iminuit-2.30.1/.ci/download_artifacts.py0000644000000000000000000000234514332717401015101 0ustar00import requests import json import shutil from urllib.request import urlopen from pathlib import Path import zipfile import tempfile organization = "scikit-hep" project = "iminuit" def get(url): return json.loads(requests.get(url).content) def get_latest_successful_build(): # get list of all builds artifact = get( f"https://api.github.com/repos/{organization}/{project}/actions/artifacts" )["artifacts"][0] return artifact["id"], artifact["updated_at"], artifact["archive_download_url"] id, date, url = get_latest_successful_build() # TODO needs authentication to work print(f"Downloading artifacts for {id} {date}") dist = Path("dist") if dist.exists(): if any(dist.iterdir()): raise SystemExit("Error: ./dist directory is not empty; please delete content") else: dist.mkdir() print(f"Downloading {id}...") with tempfile.TemporaryFile(mode="w+b") as tmp: with urlopen(url) as src: shutil.copyfileobj(src, tmp) with zipfile.ZipFile(tmp) as zip: for zip_name in zip.namelist(): fn = dist / Path(zip_name).name print("... extracting", fn) with zip.open(zip_name) as src, open(fn, "wb") as dst: shutil.copyfileobj(src, dst) iminuit-2.30.1/.ci/install_deps.py0000644000000000000000000000111414332717401013704 0ustar00from pathlib import Path import sys def install(packages): import subprocess as subp subp.check_call( ["python", "-m", "pip", "install", "--upgrade", "--prefer-binary"] + packages ) packages = [ "tomli", "pip", "wheel", ] install(packages) import tomli # noqa with open(Path(__file__).parent.parent / "pyproject.toml", "rb") as f: d = tomli.load(f) for arg in sys.argv[1:]: if arg == "build": install(d["build-system"]["requires"]) else: packages = d["project"]["optional-dependencies"][arg] install(packages) iminuit-2.30.1/.ci/release_check.py0000644000000000000000000000240414332717401014003 0ustar00"""Ensure that current version is not in conflict with published releases.""" from packaging.version import Version import subprocess as subp from pathlib import PurePath import urllib.request import json import warnings import sys project_dir = PurePath(__file__).parent.parent changelog_fn = project_dir / "doc/changelog.rst" version_fn = project_dir / "version.py" version = subp.check_output([sys.executable, version_fn]).strip().decode() with warnings.catch_warnings(record=True) as record: iminuit_version = Version(version) if record: raise ValueError(record[0].message) print("iminuit version:", iminuit_version) # make sure that changelog was updated with open(changelog_fn) as f: assert iminuit_version.base_version in f.read(), "changelog entry missing" # make sure that version is not already tagged tags = subp.check_output(["git", "tag"]).decode().strip().split("\n") assert f"v{iminuit_version}" not in tags, "tag exists" # make sure that version itself was updated with urllib.request.urlopen("https://pypi.org/pypi/iminuit/json") as r: pypi_versions = [Version(v) for v in json.loads(r.read())["releases"]] pypi_versions.sort() print("PyPI version:", pypi_versions[-1]) assert iminuit_version not in pypi_versions, "pypi version exists" iminuit-2.30.1/.clang-format0000644000000000000000000000512614332717401012562 0ustar00--- Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: true AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: false BeforeElse: false IndentBraces: false BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true # BreakInheritanceListBeforeComma: true ColumnLimit: 88 CommentPragmas: '^ IWYU pragma:' ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IndentCaseLabels: true IndentWidth: 2 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: false PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto TabWidth: 8 UseTab: Never --- Language: Json BasedOnStyle: llvm ... iminuit-2.30.1/.github/dependabot.yml0000644000000000000000000000034114332717401014371 0ustar00version: 2 updates: # Maintain dependencies for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" groups: actions: patterns: - "*" iminuit-2.30.1/.github/workflows/coverage.yml0000644000000000000000000000142214332717401016115 0ustar00name: Coverage on: pull_request: paths-ignore: - 'doc/**' - '.ci/**' - '*.rst' push: branches: - main - develop - beta/* paths-ignore: - 'doc/**' - '.ci/**' - '*.rst' jobs: coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: true - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.python-version }} create-symlink: true - uses: rui314/setup-mold@v1 - uses: actions/setup-python@v5 with: python-version: "3.12" - uses: yezz123/setup-uv@v4 - run: uv pip install --system nox - run: nox -s cov - uses: AndreMiras/coveralls-python-action@develop iminuit-2.30.1/.github/workflows/docs.yml0000644000000000000000000000262114332717401015254 0ustar00name: Docs on: pull_request: push: branches: - main workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true env: CMAKE_ARGS: -DCMAKE_CXX_COMPILER_LAUNCHER=ccache # Latest Jupyter requires this to acknowledge deprecation JUPYTER_PLATFORM_DIRS: 1 jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 # needed to get correct ROOT version # must come after checkout - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.python-version }} - uses: actions/setup-python@v5 with: python-version: "3.11" - run: sudo apt-get install pandoc - uses: yezz123/setup-uv@v4 - run: uv pip install --system nox - run: nox -s doc - uses: actions/upload-pages-artifact@v3 with: path: './build/html' deploy: if: github.event_name == 'workflow_dispatch' || github.ref_name == 'main' needs: build # Set permissions to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - uses: actions/configure-pages@v5 - uses: actions/deploy-pages@v4 iminuit-2.30.1/.github/workflows/release.yml0000644000000000000000000000653514332717401015754 0ustar00name: Release on: push: branches: - main workflow_dispatch: pull_request: paths: - .github/workflows/release.yml env: # Latest Jupyter requires this to acknowledge deprecation JUPYTER_PLATFORM_DIRS: 1 jobs: release_check: runs-on: ubuntu-latest outputs: tag: ${{ steps.tag.outputs.tag }} steps: - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: '3.12' - if: ${{ github.ref == 'refs/heads/main' }} run: | pip install packaging python .ci/release_check.py - id: tag run: echo "tag=$(python version.py)" >> $GITHUB_OUTPUT wheels: needs: release_check name: ${{ matrix.py }} ${{ matrix.os }} ${{ matrix.arch }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-13, macos-14] arch: [auto, aarch64] py: [cp39, cp310, cp311, cp312, cp313] exclude: - os: windows-latest arch: aarch64 - os: macos-13 arch: aarch64 - os: macos-14 arch: aarch64 steps: - uses: actions/checkout@v4 with: submodules: true - if: ${{ matrix.arch == 'aarch64' }} uses: docker/setup-qemu-action@v3 - uses: yezz123/setup-uv@v4 - uses: pypa/cibuildwheel@v2.21 env: CIBW_BUILD: ${{ matrix.py }}-* CIBW_ARCHS: ${{ matrix.arch }} - uses: actions/upload-artifact@v4 with: name: wheel-${{ matrix.py }}-${{ matrix.os }}-${{ matrix.arch }} path: ./wheelhouse/*.whl sdist: needs: release_check name: source package runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: true - run: pipx run build --sdist - run: python -m pip install --upgrade pip setuptools - run: python -m pip install -v $(echo dist/iminuit-*)[test] - run: python -m pytest - uses: actions/upload-artifact@v4 with: name: sdist path: dist/*.tar.gz upload: needs: [wheels, sdist] runs-on: ubuntu-latest environment: name: pypi url: https://pypi.org/project/iminuit/ permissions: id-token: write attestations: write if: ${{ github.ref == 'refs/heads/main' }} steps: - uses: actions/download-artifact@v4 with: pattern: "*" merge-multiple: true path: dist - name: Generate artifact attestation for sdist and wheels uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2 with: subject-path: "dist/iminuit-*" - uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{secrets.pypi_password}} release: needs: [release_check, upload] runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/main' }} steps: - uses: actions/checkout@v4 - uses: softprops/action-gh-release@v2 with: name: v${{ needs.release_check.outputs.tag }} tag_name: v${{ needs.release_check.outputs.tag }} target_commitish: ${{ github.ref_name }} generate_release_notes: true iminuit-2.30.1/.github/workflows/test.yml0000644000000000000000000000275214332717401015310 0ustar00name: Test on: pull_request: paths-ignore: - 'doc/**' - '.ci/**' - '*.rst' env: CMAKE_ARGS: -DCMAKE_CXX_COMPILER_LAUNCHER=ccache # Latest Jupyter requires this to acknowledge deprecation JUPYTER_PLATFORM_DIRS: 1 jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: include: # version number must be string, otherwise 3.10 becomes 3.1 - os: windows-latest python-version: "3.11" installs: "numpy>=2" - os: macos-14 python-version: "3.9" installs: "numpy==1.21.0 scipy matplotlib" - os: ubuntu-latest python-version: "pypy-3.9" - os: ubuntu-latest python-version: "3.13" installs: "'numpy>=2' scipy matplotlib" fail-fast: false steps: - uses: actions/checkout@v4 with: submodules: true # must come after checkout - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.python-version }} - uses: rui314/setup-mold@v1 if: runner.os == 'Linux' - uses: yezz123/setup-uv@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} allow-prereleases: true # pip install .[test] is not used here to test minimum (faster) # cov workflow runs all tests - run: uv pip install --system . pytest pytest-xdist ${{ matrix.installs }} - run: python -m pytest -n 3 iminuit-2.30.1/.gitignore0000644000000000000000000000103314332717401012170 0ustar00/pypy* /py[0-9]* /gammapy /probfit /iminuit-dev /root-* /dev /venv /out /.venv /.vs /build /dist /_build /_skbuild __pycache__ *.pyxbldc *.root *.so *.pyc *.o *.pkl CMakeCache.txt CMakeFiles/ pip-wheel-metadata bench/*.svg .benchmarks .DS_Store .idea .vscode .cache .project .pydevproject .settings .coverage* .ipynb_checkpoints .eggs .pytest_cache .mypy_cache .ruff_cache .nox Untitled*.ipynb Untitled*.py Pipfile iminuit.egg-info archive env MANIFEST htmlcov cover coverage.xml tests/fig/*.svg doc/index.rst testcase *venv* iminuit-2.30.1/.gitmodules0000644000000000000000000000013414332717401012356 0ustar00[submodule "extern/root"] path = extern/root url = https://github.com/HDembinski/root.git iminuit-2.30.1/.pre-commit-config.yaml0000644000000000000000000000356414332717401014474 0ustar00# To use: # # pre-commit run -a # # Or: # # pre-commit install # (runs every time you commit in git) # # To update this file: # # pre-commit autoupdate # # See https://github.com/pre-commit/pre-commit repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: check-case-conflict - id: check-docstring-first - id: check-executables-have-shebangs - id: check-merge-conflict - id: check-symlinks - id: check-yaml args: ["--allow-multiple-documents"] - id: debug-statements - id: end-of-file-fixer - id: mixed-line-ending - id: sort-simple-yaml - id: file-contents-sorter - id: trailing-whitespace exclude: ^doc/_static/.*.svg # Ruff linter and formatter - repo: https://github.com/astral-sh/ruff-pre-commit rev: 'v0.6.7' hooks: - id: ruff args: [--fix, --show-fixes] - id: ruff-format # C++ formatting - repo: https://github.com/pre-commit/mirrors-clang-format rev: v18.1.8 hooks: - id: clang-format files: "src" # CMake formatting - repo: https://github.com/cheshirekow/cmake-format-precommit rev: v0.6.13 hooks: - id: cmake-format additional_dependencies: [pyyaml] types: [file] files: (\.cmake|CMakeLists.txt)(.in)?$ # Python type checking - repo: https://github.com/pre-commit/mirrors-mypy rev: 'v1.11.2' hooks: - id: mypy additional_dependencies: [numpy] files: "src" # Clear Jupyter notebook output and remove empty cells # Override this by adding "keep_output": true to "metadata" block - repo: https://github.com/kynan/nbstripout rev: 0.7.1 hooks: - id: nbstripout args: [--drop-empty-cells] - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.29.2 hooks: - id: check-github-workflows - repo: https://github.com/henryiii/validate-pyproject-schema-store rev: 2024.09.20 hooks: - id: validate-pyproject iminuit-2.30.1/CITATION.cff0000644000000000000000000000402114332717401012072 0ustar00# This CITATION.cff file was generated with cffinit. # Visit https://bit.ly/cffinit to generate yours today! cff-version: 1.2.0 title: scikit-hep/iminuit message: >- If you use this software, please cite it using the metadata from this file and the MINUIT paper at https://doi.org/10.1016/0010-4655(75)90039-9. This software includes source code under other licenses, see LICENSE in the repository for details. type: software authors: - given-names: Hans family-names: Dembinski email: hans.dembinski@gmail.com affiliation: TU Dortmund orcid: 'https://orcid.org/0000-0003-3337-3850' - given-names: Piti family-names: Ongmongkolkul - given-names: Christoph family-names: Deil - given-names: Henry family-names: Schreiner - given-names: Matthew family-names: Feickert - given-names: Chris family-names: Burr - given-names: Jason family-names: Watson - given-names: Fabian family-names: Rost - given-names: Alex family-names: Pearce - given-names: Lukas family-names: Geiger - given-names: Ahmed family-names: Abdelmotteleb - given-names: Aman family-names: Desai - given-names: Bernhard M. family-names: Wiedemann - given-names: Christoph family-names: Gohlke - given-names: Jeremy family-names: Sanders - given-names: Jonas family-names: Drotleff - given-names: Jonas family-names: Eschle - given-names: Ludwig family-names: Neste - given-names: Marco Edward family-names: Gorelli - given-names: Max family-names: Baak - given-names: Michael family-names: Eliachevitch - given-names: Omar family-names: Zapata identifiers: - type: doi value: 10.5281/zenodo.7695764 repository-code: 'https://github.com/scikit-hep/iminuit' url: 'https://scikit-hep.org/iminuit/' abstract: >- iminuit is a Jupyter-friendly Python interface for the Minuit2 C++ library maintained by CERN's ROOT team. keywords: - Python - C++ - fitting - optimization - statistics - data analysis - Scikit-HEP license: MIT iminuit-2.30.1/CMakeLists.txt0000644000000000000000000001176414332717401012754 0ustar00cmake_minimum_required(VERSION 3.15...3.26) project(iminuit LANGUAGES CXX) if(NOT DEFINED SKBUILD) message( WARNING "You should call this through Python so that all variables are set; pip install -v ." ) endif() include(CheckIPOSupported) check_ipo_supported(RESULT ipo_supported OUTPUT error) set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ version selection") # or 11, 14, 17, 20 set(CMAKE_CXX_STANDARD_REQUIRED ON) # optional, ensure standard is supported set(CMAKE_CXX_EXTENSIONS OFF) # optional, keep compiler extensionsn off set(PYBIND11_FINDPYTHON ON) find_package(pybind11 CONFIG REQUIRED) file(GLOB SOURCES_A "src/*.cpp") set(SOURCES_B extern/root/math/minuit2/src/AnalyticalGradientCalculator.cxx extern/root/math/minuit2/src/BFGSErrorUpdator.cxx extern/root/math/minuit2/src/DavidonErrorUpdator.cxx extern/root/math/minuit2/src/HessianGradientCalculator.cxx extern/root/math/minuit2/src/ExternalInternalGradientCalculator.cxx extern/root/math/minuit2/src/InitialGradientCalculator.cxx extern/root/math/minuit2/src/LaEigenValues.cxx extern/root/math/minuit2/src/LaInnerProduct.cxx extern/root/math/minuit2/src/LaInverse.cxx extern/root/math/minuit2/src/LaOuterProduct.cxx extern/root/math/minuit2/src/LaSumOfElements.cxx extern/root/math/minuit2/src/LaVtMVSimilarity.cxx extern/root/math/minuit2/src/MPIProcess.cxx extern/root/math/minuit2/src/MinimumBuilder.cxx extern/root/math/minuit2/src/MnApplication.cxx extern/root/math/minuit2/src/MnContours.cxx extern/root/math/minuit2/src/MnCovarianceSqueeze.cxx extern/root/math/minuit2/src/MnFcn.cxx extern/root/math/minuit2/src/MnFunctionCross.cxx extern/root/math/minuit2/src/MnGlobalCorrelationCoeff.cxx extern/root/math/minuit2/src/MnHesse.cxx extern/root/math/minuit2/src/MnLineSearch.cxx extern/root/math/minuit2/src/MnMachinePrecision.cxx extern/root/math/minuit2/src/MnMinos.cxx extern/root/math/minuit2/src/MnParabolaFactory.cxx extern/root/math/minuit2/src/MnParameterScan.cxx extern/root/math/minuit2/src/MnPlot.cxx extern/root/math/minuit2/src/MnPosDef.cxx extern/root/math/minuit2/src/MnPrint.cxx extern/root/math/minuit2/src/MnSeedGenerator.cxx extern/root/math/minuit2/src/MnStrategy.cxx extern/root/math/minuit2/src/MnScan.cxx extern/root/math/minuit2/src/MnTiny.cxx extern/root/math/minuit2/src/MnTraceObject.cxx extern/root/math/minuit2/src/MnUserFcn.cxx extern/root/math/minuit2/src/MnUserParameterState.cxx extern/root/math/minuit2/src/MnUserParameters.cxx extern/root/math/minuit2/src/MnUserTransformation.cxx extern/root/math/minuit2/src/ModularFunctionMinimizer.cxx extern/root/math/minuit2/src/NegativeG2LineSearch.cxx extern/root/math/minuit2/src/Numerical2PGradientCalculator.cxx extern/root/math/minuit2/src/SimplexSeedGenerator.cxx extern/root/math/minuit2/src/SimplexBuilder.cxx extern/root/math/minuit2/src/SimplexParameters.cxx extern/root/math/minuit2/src/SinParameterTransformation.cxx extern/root/math/minuit2/src/ScanBuilder.cxx extern/root/math/minuit2/src/SqrtLowParameterTransformation.cxx extern/root/math/minuit2/src/SqrtUpParameterTransformation.cxx extern/root/math/minuit2/src/VariableMetricBuilder.cxx extern/root/math/minuit2/src/VariableMetricEDMEstimator.cxx extern/root/math/minuit2/src/mnbins.cxx extern/root/math/minuit2/src/mndasum.cxx extern/root/math/minuit2/src/mndaxpy.cxx extern/root/math/minuit2/src/mnddot.cxx extern/root/math/minuit2/src/mndscal.cxx extern/root/math/minuit2/src/mndspmv.cxx extern/root/math/minuit2/src/mndspr.cxx extern/root/math/minuit2/src/mnlsame.cxx extern/root/math/minuit2/src/mnteigen.cxx extern/root/math/minuit2/src/mntplot.cxx extern/root/math/minuit2/src/mnvert.cxx extern/root/math/minuit2/src/mnxerbla.cxx) pybind11_add_module(_core MODULE ${SOURCES_A} ${SOURCES_B}) target_include_directories(_core PRIVATE extern/root/math/minuit2/inc) target_compile_definitions(_core PUBLIC PYBIND11_DETAILED_ERROR_MESSAGES=1) set_target_properties(_core PROPERTIES VISIBILITY_INLINES_HIDDEN ON) if(ipo_supported) set_target_properties(_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) endif() # Add compiler-specific extra warnings if(MSVC) target_compile_options(_core PRIVATE /std:c++14 /Y-) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # lots of warnings from gcc, including odr violations target_compile_options( _core PRIVATE -Wall -Wextra -Werror -Werror=odr -Werror=lto-type-mismatch -Werror=strict-aliasing -pedantic -fstrict-aliasing) target_link_options(_core PRIVATE -Werror -Wodr -Wlto-type-mismatch) else() # lots of warnings from clang target_compile_options(_core PRIVATE -Wall -Wextra -pedantic -Werror -Werror=odr -fstrict-aliasing) target_link_options(_core PRIVATE -Werror -Wodr) endif() install(TARGETS _core DESTINATION iminuit) iminuit-2.30.1/CONTRIBUTING.md0000644000000000000000000000016114332717401012432 0ustar00See doc/contribute.rst in this repository or its [html version](https://scikit-hep.org/iminuit/contribute.html). iminuit-2.30.1/LICENSE0000644000000000000000000000277514332717401011223 0ustar00Minuit is from SEAL Minuit It's LGPL v2 http://seal.web.cern.ch/seal/main/license.html. For iminuit, I'm releasing it as MIT license: Copyright (c) 2012 Piti Ongmongkolkul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Note: MIT license is GPL compatible, so it is an acceptable license for a wrapper, as can be seen here: http://www.gnu.org/licenses/old-licenses/gpl-2.0-faq.html#GPLWrapper http://www.gnu.org/licenses/old-licenses/gpl-2.0-faq.html#OrigBSD (L)GPL can be combined or included in code that does not impose more restrictive conditions. iminuit-2.30.1/README.rst0000644000000000000000000001750214332717401011677 0ustar00.. |iminuit| image:: doc/_static/iminuit_logo.svg :alt: iminuit |iminuit| ========= .. version-marker-do-not-remove .. image:: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg :target: https://scikit-hep.org .. image:: https://img.shields.io/pypi/v/iminuit.svg :target: https://pypi.org/project/iminuit .. image:: https://img.shields.io/conda/vn/conda-forge/iminuit.svg :target: https://github.com/conda-forge/iminuit-feedstock .. image:: https://coveralls.io/repos/github/scikit-hep/iminuit/badge.svg?branch=develop :target: https://coveralls.io/github/scikit-hep/iminuit?branch=develop .. image:: https://github.com/scikit-hep/iminuit/actions/workflows/docs.yml/badge.svg?branch=main :target: https://scikit-hep.org/iminuit .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3949207.svg :target: https://doi.org/10.5281/zenodo.3949207 .. image:: https://img.shields.io/badge/ascl-2108.024-blue.svg?colorB=262255 :target: https://ascl.net/2108.024 :alt: ascl:2108.024 .. image:: https://img.shields.io/gitter/room/Scikit-HEP/iminuit :target: https://gitter.im/Scikit-HEP/iminuit .. image:: https://mybinder.org/badge_logo.svg :target: https://mybinder.org/v2/gh/scikit-hep/iminuit/develop?filepath=doc%2Ftutorial ``iminuit`` is a Jupyter-friendly Python interface for the ``Minuit2`` C++ library maintained by CERN's `ROOT team `_. Minuit was designed to optimize statistical cost functions, for maximum-likelihood and least-squares fits. It provides the best-fit parameters and error estimates from likelihood profile analysis. The iminuit package brings additional features: - Builtin cost functions for statistical fits to N-dimensional data - Unbinned and binned maximum-likelihood + extended versions - `Template fits with error propagation `_ - Least-squares (optionally robust to outliers) - Gaussian penalty terms for parameters - Cost functions can be combined by adding them: ``total_cost = cost_1 + cost_2`` - Visualization of the fit in Jupyter notebooks - Support for SciPy minimizers as alternatives to Minuit's MIGRAD algorithm (optional) - Support for Numba accelerated functions (optional) Minimal dependencies -------------------- ``iminuit`` is promised to remain a lean package which only depends on ``numpy``, but additional features are enabled if the following optional packages are installed. - ``numba``: Cost functions are partially JIT-compiled if ``numba`` is installed. - ``matplotlib``: Visualization of fitted model for builtin cost functions - ``ipywidgets``: Interactive fitting, see example below (also requires ``matplotlib``) - ``scipy``: Compute Minos intervals for arbitrary confidence levels - ``unicodeitplus``: Render names of model parameters in simple LaTeX as Unicode Documentation ------------- Checkout our large and comprehensive list of `tutorials`_ that take you all the way from beginner to power user. For help and how-to questions, please use the `discussions`_ on GitHub or `gitter`_. **Lecture by Glen Cowan** `In the exercises to his lecture for the KMISchool 2022 `_, Glen Cowan shows how to solve statistical problems in Python with iminuit. You can find the lectures and exercises on the Github page, which covers both frequentist and Bayesian methods. `Glen Cowan `_ is a known for his papers and international lectures on statistics in particle physics, as a member of the Particle Data Group, and as author of the popular book `Statistical Data Analysis `_. In a nutshell ------------- ``iminuit`` can be used with a user-provided cost functions in form of a negative log-likelihood function or least-squares function. Standard functions are included in ``iminuit.cost``, so you don't have to write them yourself. The following example shows how to perform an unbinned maximum likelihood fit. .. code:: python import numpy as np from iminuit import Minuit from iminuit.cost import UnbinnedNLL from scipy.stats import norm x = norm.rvs(size=1000, random_state=1) def pdf(x, mu, sigma): return norm.pdf(x, mu, sigma) # Negative unbinned log-likelihood, you can write your own cost = UnbinnedNLL(x, pdf) m = Minuit(cost, mu=0, sigma=1) m.limits["sigma"] = (0, np.inf) m.migrad() # find minimum m.hesse() # compute uncertainties .. image:: doc/_static/demo_output.png :alt: Output of the demo in a Jupyter notebook Interactive fitting ------------------- ``iminuit`` optionally supports an interactive fitting mode in Jupyter notebooks. .. image:: doc/_static/interactive_demo.gif :alt: Animated demo of an interactive fit in a Jupyter notebook High performance when combined with numba ----------------------------------------- When ``iminuit`` is used with cost functions that are JIT-compiled with `numba`_ (JIT-compiled pdfs are provided by `numba_stats`_ ), the speed is comparable to `RooFit`_ with the fastest backend. `numba`_ with auto-parallelization is considerably faster than the parallel computation in `RooFit`_. .. image:: doc/_static/roofit_vs_iminuit+numba.svg More information about this benchmark is given `in the Benchmark section of the documentation `_. Citation -------- If you use iminuit in a scientific work, please cite us. A generic BibTeX entry is:: @article{iminuit, author={Hans Dembinski and Piti Ongmongkolkul et al.}, title={scikit-hep/iminuit}, DOI={10.5281/zenodo.3949207}, publisher={Zenodo}, year={2020}, month={Dec}, url={https://doi.org/10.5281/zenodo.3949207} } The DOI and URL in this entry point always to the latest release of iminuit. You can also cite the actual release that you used, please follow the `Zenodo link `_, which offers entries for common bibliography formats for all iminuit releases. The recommended scientific reference for the MINUIT algorithms is:: @article{James:1975dr, author = "James, F. and Roos, M.", title = "{Minuit: A System for Function Minimization and Analysis of the Parameter Errors and Correlations}", reportNumber = "CERN-DD-75-20", doi = "10.1016/0010-4655(75)90039-9", journal = "Comput. Phys. Commun.", volume = "10", pages = "343--367", year = "1975" } Partner projects ---------------- * `numba_stats`_ provides faster implementations of probability density functions than scipy, and a few specific ones used in particle physics that are not in scipy. * `boost-histogram`_ from Scikit-HEP provides fast generalized histograms that you can use with the builtin cost functions. * `jacobi`_ provides a robust, fast, and accurate calculation of the Jacobi matrix of any transformation function and building a function for generic error propagation. Versions -------- The 2.x series has introduced breaking interfaces changes with respect to the 1.x series. There are no plans to introduce further breaking changes. All interface changes from 1.x to 2.x are documented in the `changelog`_ with recommendations how to upgrade. To keep old scripts running, pin your major iminuit version to <2: the command ``pip install 'iminuit<2'`` installs the 1.x series. .. _changelog: https://scikit-hep.org/iminuit/changelog.html .. _tutorials: https://scikit-hep.org/iminuit/tutorials.html .. _discussions: https://github.com/scikit-hep/iminuit/discussions .. _gitter: https://gitter.im/Scikit-HEP/iminuit .. _jacobi: https://github.com/hdembinski/jacobi .. _numba_stats: https://github.com/HDembinski/numba-stats .. _boost-histogram: https://github.com/scikit-hep/boost-histogram .. _numba: https://numba.pydata.org .. _RooFit: https://root.cern/manual/roofit/ iminuit-2.30.1/bench/cost.json0000644000000000000000000063562114332717401013142 0ustar00{ "machine_info": { "node": "MacBook-Pro-2.local", "processor": "i386", "machine": "x86_64", "python_compiler": "Clang 13.0.0 (clang-1300.0.29.3)", "python_implementation": "CPython", "python_implementation_version": "3.8.12", "python_version": "3.8.12", "python_build": [ "default", "Oct 22 2021 18:39:35" ], "release": "21.3.0", "system": "Darwin", "cpu": { "python_version": "3.8.12.final.0 (64 bit)", "cpuinfo_version": [ 8, 0, 0 ], "cpuinfo_version_string": "8.0.0", "arch": "X86_64", "bits": 64, "count": 8, "arch_string_raw": "x86_64", "vendor_id_raw": "GenuineIntel", "brand_raw": "Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz", "hz_advertised_friendly": "2.8000 GHz", "hz_actual_friendly": "2.8000 GHz", "hz_advertised": [ 2800000000, 0 ], "hz_actual": [ 2800000000, 0 ], "l2_cache_size": 262144, "stepping": 10, "model": 142, "family": 6, "flags": [ "1gbpage", "3dnowprefetch", "abm", "acapmsr", "acpi", "adx", "aes", "apic", "avx", "avx1.0", "avx2", "bmi1", "bmi2", "clflush", "clflushopt", "clfsh", "clfsopt", "cmov", "cx16", "cx8", "de", "ds", "ds_cpl", "dscpl", "dtes64", "dts", "em64t", "erms", "est", "f16c", "fma", "fpu", "fpu_csds", "fxsr", "ht", "htt", "ibrs", "intel_pt", "invpcid", "ipt", "l1df", "lahf", "lahf_lm", "lzcnt", "mca", "mce", "mdclear", "mmx", "mon", "monitor", "movbe", "mpx", "msr", "mtrr", "osxsave", "pae", "pat", "pbe", "pcid", "pclmulqdq", "pdcm", "pge", "pni", "popcnt", "prefetchw", "pse", "pse36", "rdrand", "rdrnd", "rdseed", "rdtscp", "rdwrfsgs", "seglim64", "sep", "sgx", "smap", "smep", "ss", "ssbd", "sse", "sse2", "sse3", "sse4.1", "sse4.2", "sse4_1", "sse4_2", "ssse3", "stibp", "syscall", "tm", "tm2", "tpr", "tsc", "tsc_thread_offset", "tscdeadline", "tsci", "tsctmr", "tsxfa", "vme", "vmx", "x2apic", "xd", "xsave", "xtpr" ], "l2_cache_line_size": 256, "l2_cache_associativity": 6 } }, "commit_info": { "id": "5b76d81819cfde26c08db4516f87ad8d5ddc905b", "time": "2022-03-14T18:52:11+01:00", "author_time": "2022-03-14T18:52:11+01:00", "dirty": true, "project": "iminuit", "branch": "develop" }, "benchmarks": [ { "group": null, "name": "test_UnbinnedNLL[False-10]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-10]", "params": { "log": false, "n": 10 }, "param": "False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.613999999987129e-06, "max": 2.6232000000625533e-05, "mean": 6.807627819539115e-06, "stddev": 3.8941006015191716e-06, "rounds": 266, "median": 5.8319999998168726e-06, "iqr": 1.0900000102509466e-07, "q1": 5.782999999759397e-06, "q3": 5.892000000784492e-06, "iqr_outliers": 29, "stddev_outliers": 15, "outliers": "15;29", "ld15iqr": 5.6440000006929836e-06, "hd15iqr": 6.056000000143058e-06, "ops": 146894.04687045614, "total": 0.0018108289999974048, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-31]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-31]", "params": { "log": false, "n": 31 }, "param": "False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.01999999982894e-06, "max": 0.00012303500000054868, "mean": 6.816884017796628e-06, "stddev": 2.323222675723695e-06, "rounds": 44731, "median": 6.545000000635071e-06, "iqr": 3.320000008244506e-07, "q1": 6.399999999295858e-06, "q3": 6.732000000120308e-06, "iqr_outliers": 1712, "stddev_outliers": 690, "outliers": "690;1712", "ld15iqr": 6.01999999982894e-06, "hd15iqr": 7.231999999746108e-06, "ops": 146694.58910982363, "total": 0.304926039000061, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-100]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-100]", "params": { "log": false, "n": 100 }, "param": "False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 7.054000000117355e-06, "max": 0.00016630500000047732, "mean": 8.018752700972623e-06, "stddev": 3.2906121861149325e-06, "rounds": 45354, "median": 7.604999999522022e-06, "iqr": 3.2199999999704687e-07, "q1": 7.461000000041906e-06, "q3": 7.783000000038953e-06, "iqr_outliers": 2576, "stddev_outliers": 880, "outliers": "880;2576", "ld15iqr": 7.054000000117355e-06, "hd15iqr": 8.267000000117264e-06, "ops": 124707.67428439418, "total": 0.36368250999991236, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-316]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-316]", "params": { "log": false, "n": 316 }, "param": "False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.546000000248966e-06, "max": 0.00017028099999993884, "mean": 1.109931439856433e-05, "stddev": 4.326686668004807e-06, "rounds": 38483, "median": 1.0506999999826405e-05, "iqr": 6.220000008383408e-07, "q1": 1.0136999999410534e-05, "q3": 1.0759000000248875e-05, "iqr_outliers": 1857, "stddev_outliers": 1125, "outliers": "1125;1857", "ld15iqr": 9.546000000248966e-06, "hd15iqr": 1.1693999999451421e-05, "ops": 90095.65492886187, "total": 0.4271349159999511, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-1000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-1000]", "params": { "log": false, "n": 1000 }, "param": "False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.6870999999696323e-05, "max": 0.00020322700000008354, "mean": 2.1278980280460123e-05, "stddev": 1.0796045995011676e-05, "rounds": 15974, "median": 1.8531000000265863e-05, "iqr": 1.0599999997751297e-06, "q1": 1.794599999982438e-05, "q3": 1.900599999959951e-05, "iqr_outliers": 2115, "stddev_outliers": 1376, "outliers": "1376;2115", "ld15iqr": 1.6870999999696323e-05, "hd15iqr": 2.060899999989374e-05, "ops": 46994.73315073614, "total": 0.33991043100007, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-3162]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-3162]", "params": { "log": false, "n": 3162 }, "param": "False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 3.918599999952477e-05, "max": 0.000341052999999647, "mean": 5.476941792159598e-05, "stddev": 2.465966861807974e-05, "rounds": 16070, "median": 4.4873000000222873e-05, "iqr": 8.62499999954025e-06, "q1": 4.2888000000296245e-05, "q3": 5.1512999999836495e-05, "iqr_outliers": 2870, "stddev_outliers": 2113, "outliers": "2113;2870", "ld15iqr": 3.918599999952477e-05, "hd15iqr": 6.445400000032464e-05, "ops": 18258.36457549228, "total": 0.8801445460000474, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-10000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-10000]", "params": { "log": false, "n": 10000 }, "param": "False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00012126399999967674, "max": 0.0005189279999999741, "mean": 0.0001688479985113522, "stddev": 5.476428721666543e-05, "rounds": 2687, "median": 0.0001410760000002398, "iqr": 5.87212500005041e-05, "q1": 0.00013086899999947832, "q3": 0.00018959024999998242, "iqr_outliers": 155, "stddev_outliers": 413, "outliers": "413;155", "ld15iqr": 0.00012126399999967674, "hd15iqr": 0.0002777659999999571, "ops": 5922.486548946369, "total": 0.4536945720000034, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-31622]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-31622]", "params": { "log": false, "n": 31622 }, "param": "False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00036192599999917974, "max": 0.0010299439999998938, "mean": 0.00047745339502761915, "stddev": 0.0001255235368462855, "rounds": 1086, "median": 0.0004199184999995609, "iqr": 0.00013283600000058016, "q1": 0.0003908599999995488, "q3": 0.000523696000000129, "iqr_outliers": 85, "stddev_outliers": 168, "outliers": "168;85", "ld15iqr": 0.00036192599999917974, "hd15iqr": 0.0007232020000005335, "ops": 2094.445259818821, "total": 0.5185143869999944, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-100000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-100000]", "params": { "log": false, "n": 100000 }, "param": "False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0011009369999985807, "max": 0.002529974999999851, "mean": 0.001402640759219157, "stddev": 0.00030394511879178475, "rounds": 461, "median": 0.0012860190000001381, "iqr": 0.00032229700000208084, "q1": 0.001183275749998991, "q3": 0.0015055727500010718, "iqr_outliers": 32, "stddev_outliers": 73, "outliers": "73;32", "ld15iqr": 0.0011009369999985807, "hd15iqr": 0.00200464300000025, "ops": 712.940924771568, "total": 0.6466173900000314, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-316227]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-316227]", "params": { "log": false, "n": 316227 }, "param": "False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004103880000000615, "max": 0.00699744199999941, "mean": 0.004840556282258055, "stddev": 0.00042142557346933887, "rounds": 124, "median": 0.0048290335000000795, "iqr": 0.0005937444999997155, "q1": 0.0045202749999999625, "q3": 0.005114019499999678, "iqr_outliers": 1, "stddev_outliers": 41, "outliers": "41;1", "ld15iqr": 0.004103880000000615, "hd15iqr": 0.00699744199999941, "ops": 206.5878262102374, "total": 0.6002289789999988, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[False-1000000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[False-1000000]", "params": { "log": false, "n": 1000000 }, "param": "False-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.02014899499999956, "max": 0.03069126699999991, "mean": 0.02306327500000005, "stddev": 0.0031518522647303528, "rounds": 32, "median": 0.02149305200000029, "iqr": 0.00429467100000025, "q1": 0.02059766350000025, "q3": 0.0248923345000005, "iqr_outliers": 0, "stddev_outliers": 7, "outliers": "7;0", "ld15iqr": 0.02014899499999956, "hd15iqr": 0.03069126699999991, "ops": 43.35897655471731, "total": 0.7380248000000016, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-10]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-10]", "params": { "log": true, "n": 10 }, "param": "True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.861000000555009e-06, "max": 0.00011064799999971342, "mean": 1.2904325369988345e-05, "stddev": 6.2280154244536975e-06, "rounds": 9460, "median": 1.1257000000597372e-05, "iqr": 8.969999996111255e-07, "q1": 1.0861499999847979e-05, "q3": 1.1758499999459104e-05, "iqr_outliers": 1496, "stddev_outliers": 734, "outliers": "734;1496", "ld15iqr": 9.861000000555009e-06, "hd15iqr": 1.3104999998958533e-05, "ops": 77493.39630924877, "total": 0.12207491800008974, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-31]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-31]", "params": { "log": true, "n": 31 }, "param": "True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.0087999999797148e-05, "max": 0.0008933570000007052, "mean": 1.4521875886642965e-05, "stddev": 1.048082927260062e-05, "rounds": 31439, "median": 1.158200000084264e-05, "iqr": 1.1149999994408688e-06, "q1": 1.1069999999779867e-05, "q3": 1.2184999999220736e-05, "iqr_outliers": 6311, "stddev_outliers": 2651, "outliers": "2651;6311", "ld15iqr": 1.0087999999797148e-05, "hd15iqr": 1.3857999999089543e-05, "ops": 68861.62695549459, "total": 0.45655325600016816, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-100]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-100]", "params": { "log": true, "n": 100 }, "param": "True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.0066999999835957e-05, "max": 0.00014689099999998234, "mean": 1.3911768780707706e-05, "stddev": 7.284360644200518e-06, "rounds": 21365, "median": 1.1793999998843674e-05, "iqr": 1.0229999993782712e-06, "q1": 1.1591999999893687e-05, "q3": 1.2614999999271959e-05, "iqr_outliers": 3185, "stddev_outliers": 1637, "outliers": "1637;3185", "ld15iqr": 1.0066999999835957e-05, "hd15iqr": 1.4150000000157092e-05, "ops": 71881.58571085229, "total": 0.29722493999982014, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-316]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-316]", "params": { "log": true, "n": 316 }, "param": "True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.1033000001603455e-05, "max": 0.00014430300000078944, "mean": 1.517401692263753e-05, "stddev": 7.712991478504646e-06, "rounds": 21096, "median": 1.2793000001565247e-05, "iqr": 1.4230000004999965e-06, "q1": 1.2477999999482847e-05, "q3": 1.3900999999982844e-05, "iqr_outliers": 3203, "stddev_outliers": 1738, "outliers": "1738;3203", "ld15iqr": 1.1033000001603455e-05, "hd15iqr": 1.603599999988603e-05, "ops": 65902.12763689083, "total": 0.32011106099996134, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-1000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-1000]", "params": { "log": true, "n": 1000 }, "param": "True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.186399999930643e-05, "max": 0.0001897890000002178, "mean": 1.5743009087816723e-05, "stddev": 7.027698432300104e-06, "rounds": 17606, "median": 1.3716999999857649e-05, "iqr": 1.3730000016920485e-06, "q1": 1.3452999999330473e-05, "q3": 1.4826000001022521e-05, "iqr_outliers": 1916, "stddev_outliers": 1396, "outliers": "1396;1916", "ld15iqr": 1.186399999930643e-05, "hd15iqr": 1.688700000102017e-05, "ops": 63520.25806641278, "total": 0.27717141800010126, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-3162]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-3162]", "params": { "log": true, "n": 3162 }, "param": "True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.5538999999620273e-05, "max": 0.00014090600000038478, "mean": 1.96098519289649e-05, "stddev": 7.033629237581259e-06, "rounds": 16330, "median": 1.7546000000479012e-05, "iqr": 1.7870000004194253e-06, "q1": 1.715600000018469e-05, "q3": 1.8943000000604115e-05, "iqr_outliers": 1613, "stddev_outliers": 1318, "outliers": "1318;1613", "ld15iqr": 1.5538999999620273e-05, "hd15iqr": 2.1632000001048368e-05, "ops": 50994.775667986636, "total": 0.3202288819999968, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-10000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-10000]", "params": { "log": true, "n": 10000 }, "param": "True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.8184999999680826e-05, "max": 0.00013907000000124015, "mean": 3.572925095727153e-05, "stddev": 1.084553273841856e-05, "rounds": 3395, "median": 3.183599999978526e-05, "iqr": 3.561500000248685e-06, "q1": 3.0721249999920985e-05, "q3": 3.428275000016967e-05, "iqr_outliers": 537, "stddev_outliers": 385, "outliers": "385;537", "ld15iqr": 2.8184999999680826e-05, "hd15iqr": 3.9652000001666465e-05, "ops": 27988.272163776848, "total": 0.12130080699993684, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-31622]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-31622]", "params": { "log": true, "n": 31622 }, "param": "True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.362099999890347e-05, "max": 0.00022118799999937266, "mean": 8.053470712206149e-05, "stddev": 2.237386259623731e-05, "rounds": 1376, "median": 7.234949999901374e-05, "iqr": 1.333300000005977e-05, "q1": 6.82505000000333e-05, "q3": 8.158350000009307e-05, "iqr_outliers": 173, "stddev_outliers": 170, "outliers": "170;173", "ld15iqr": 6.362099999890347e-05, "hd15iqr": 0.00010197200000128248, "ops": 12417.00672586245, "total": 0.1108157569999566, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-100000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-100000]", "params": { "log": true, "n": 100000 }, "param": "True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00017283899999931407, "max": 0.0006448110000008, "mean": 0.0002660068870056153, "stddev": 8.887120161713912e-05, "rounds": 354, "median": 0.00023938700000059043, "iqr": 0.00010831899999885763, "q1": 0.0001986719999997888, "q3": 0.00030699099999864643, "iqr_outliers": 14, "stddev_outliers": 60, "outliers": "60;14", "ld15iqr": 0.00017283899999931407, "hd15iqr": 0.000481723000000045, "ops": 3759.301164179597, "total": 0.0941664379999878, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-316227]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-316227]", "params": { "log": true, "n": 316227 }, "param": "True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007201549999997781, "max": 0.0021617169999998964, "mean": 0.0010889014239999569, "stddev": 0.0002952186780363007, "rounds": 125, "median": 0.0010181800000008678, "iqr": 0.0003412147499983753, "q1": 0.0008715085000003953, "q3": 0.0012127232499987706, "iqr_outliers": 6, "stddev_outliers": 27, "outliers": "27;6", "ld15iqr": 0.0007201549999997781, "hd15iqr": 0.0017415899999999596, "ops": 918.3567749655543, "total": 0.1361126779999946, "iterations": 1 } }, { "group": null, "name": "test_UnbinnedNLL[True-1000000]", "fullname": "bench/test_cost.py::test_UnbinnedNLL[True-1000000]", "params": { "log": true, "n": 1000000 }, "param": "True-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.006835566999999543, "max": 0.015650539000001018, "mean": 0.00975040879411762, "stddev": 0.0021127750091034783, "rounds": 34, "median": 0.009763373000000186, "iqr": 0.002199320999999088, "q1": 0.008179027000000616, "q3": 0.010378347999999704, "iqr_outliers": 2, "stddev_outliers": 11, "outliers": "11;2", "ld15iqr": 0.006835566999999543, "hd15iqr": 0.015237973000001404, "ops": 102.55980247754287, "total": 0.33151389899999906, "iterations": 1 } }, { "group": null, "name": "test_custom[False-10]", "fullname": "bench/test_cost.py::test_custom[False-10]", "params": { "log": false, "n": 10 }, "param": "False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.966000000360964e-06, "max": 0.00024564900000001444, "mean": 1.3333629878563186e-05, "stddev": 8.059901903783004e-06, "rounds": 17705, "median": 1.1383000000364518e-05, "iqr": 7.669999995130183e-07, "q1": 1.0903999999811731e-05, "q3": 1.167099999932475e-05, "iqr_outliers": 2760, "stddev_outliers": 1442, "outliers": "1442;2760", "ld15iqr": 9.966000000360964e-06, "hd15iqr": 1.2824999998883868e-05, "ops": 74998.33197018054, "total": 0.23607191699996122, "iterations": 1 } }, { "group": null, "name": "test_custom[False-31]", "fullname": "bench/test_cost.py::test_custom[False-31]", "params": { "log": false, "n": 31 }, "param": "False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.0072000000249659e-05, "max": 0.00015143200000089507, "mean": 1.2920464623972505e-05, "stddev": 6.0667386601100956e-06, "rounds": 28296, "median": 1.1435999999420687e-05, "iqr": 1.1170000000504388e-06, "q1": 1.0959999999116121e-05, "q3": 1.207699999916656e-05, "iqr_outliers": 3148, "stddev_outliers": 1756, "outliers": "1756;3148", "ld15iqr": 1.0072000000249659e-05, "hd15iqr": 1.375699999961455e-05, "ops": 77396.59749887088, "total": 0.365597466999926, "iterations": 1 } }, { "group": null, "name": "test_custom[False-100]", "fullname": "bench/test_cost.py::test_custom[False-100]", "params": { "log": false, "n": 100 }, "param": "False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.1143000000046754e-05, "max": 0.00018102599999991753, "mean": 1.3956544709495123e-05, "stddev": 8.850763497969071e-06, "rounds": 27332, "median": 1.1990999999156315e-05, "iqr": 4.919999998520552e-07, "q1": 1.1842999999345238e-05, "q3": 1.2334999999197294e-05, "iqr_outliers": 2873, "stddev_outliers": 1668, "outliers": "1668;2873", "ld15iqr": 1.1143000000046754e-05, "hd15iqr": 1.3072999999863555e-05, "ops": 71650.97241580613, "total": 0.3814602799999207, "iterations": 1 } }, { "group": null, "name": "test_custom[False-316]", "fullname": "bench/test_cost.py::test_custom[False-316]", "params": { "log": false, "n": 316 }, "param": "False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.4291999999471727e-05, "max": 0.0003033289999994082, "mean": 1.824192360940663e-05, "stddev": 1.128592405055234e-05, "rounds": 20369, "median": 1.542300000068053e-05, "iqr": 5.450000011286704e-07, "q1": 1.5228000000089281e-05, "q3": 1.577300000121795e-05, "iqr_outliers": 3139, "stddev_outliers": 1608, "outliers": "1608;3139", "ld15iqr": 1.4411000000436047e-05, "hd15iqr": 1.659399999986988e-05, "ops": 54818.7801578305, "total": 0.3715697420000037, "iterations": 1 } }, { "group": null, "name": "test_custom[False-1000]", "fullname": "bench/test_cost.py::test_custom[False-1000]", "params": { "log": false, "n": 1000 }, "param": "False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.0483999998432978e-05, "max": 0.0006008140000002271, "mean": 2.8404916538409974e-05, "stddev": 1.940288907234837e-05, "rounds": 20141, "median": 2.2700999998903626e-05, "iqr": 1.0439999993394622e-06, "q1": 2.248500000057163e-05, "q3": 2.3528999999911093e-05, "iqr_outliers": 4157, "stddev_outliers": 1463, "outliers": "1463;4157", "ld15iqr": 2.095600000018294e-05, "hd15iqr": 2.5103000000470388e-05, "ops": 35205.17297235393, "total": 0.5721034240001153, "iterations": 1 } }, { "group": null, "name": "test_custom[False-3162]", "fullname": "bench/test_cost.py::test_custom[False-3162]", "params": { "log": false, "n": 3162 }, "param": "False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 4.402500000111331e-05, "max": 0.0010989180000002818, "mean": 6.062804127025641e-05, "stddev": 4.098725536298938e-05, "rounds": 7778, "median": 4.5823000000666525e-05, "iqr": 1.1557000000550488e-05, "q1": 4.53880000002016e-05, "q3": 5.694500000075209e-05, "iqr_outliers": 1255, "stddev_outliers": 716, "outliers": "716;1255", "ld15iqr": 4.402500000111331e-05, "hd15iqr": 7.437300000034952e-05, "ops": 16494.017933754218, "total": 0.4715649050000543, "iterations": 1 } }, { "group": null, "name": "test_custom[False-10000]", "fullname": "bench/test_cost.py::test_custom[False-10000]", "params": { "log": false, "n": 10000 }, "param": "False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00011805799999997646, "max": 0.000288777999999823, "mean": 0.00014026708187140824, "stddev": 3.206076021385848e-05, "rounds": 171, "median": 0.00012519699999913314, "iqr": 2.349775000087817e-05, "q1": 0.00012187674999974973, "q3": 0.0001453745000006279, "iqr_outliers": 19, "stddev_outliers": 24, "outliers": "24;19", "ld15iqr": 0.00011805799999997646, "hd15iqr": 0.00018273300000082315, "ops": 7129.256463157646, "total": 0.02398567100001081, "iterations": 1 } }, { "group": null, "name": "test_custom[False-31622]", "fullname": "bench/test_cost.py::test_custom[False-31622]", "params": { "log": false, "n": 31622 }, "param": "False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0003327609999992376, "max": 0.0011477549999998615, "mean": 0.0003945496537657045, "stddev": 8.637925549902671e-05, "rounds": 956, "median": 0.0003578080000004036, "iqr": 4.9915000000844145e-05, "q1": 0.00034959099999998244, "q3": 0.0003995060000008266, "iqr_outliers": 109, "stddev_outliers": 104, "outliers": "104;109", "ld15iqr": 0.0003327609999992376, "hd15iqr": 0.0004750000000015575, "ops": 2534.535236454244, "total": 0.3771894690000135, "iterations": 1 } }, { "group": null, "name": "test_custom[False-100000]", "fullname": "bench/test_cost.py::test_custom[False-100000]", "params": { "log": false, "n": 100000 }, "param": "False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0010441270000001168, "max": 0.0024914440000003424, "mean": 0.0013609152873899988, "stddev": 0.0003018179004937743, "rounds": 341, "median": 0.0012594489999990799, "iqr": 0.00035873650000262103, "q1": 0.0011328457499990563, "q3": 0.0014915822500016773, "iqr_outliers": 19, "stddev_outliers": 51, "outliers": "51;19", "ld15iqr": 0.0010441270000001168, "hd15iqr": 0.0020326839999995627, "ops": 734.7995935278439, "total": 0.4640721129999896, "iterations": 1 } }, { "group": null, "name": "test_custom[False-316227]", "fullname": "bench/test_cost.py::test_custom[False-316227]", "params": { "log": false, "n": 316227 }, "param": "False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0037355100000020514, "max": 0.011600158000000249, "mean": 0.005870520244680857, "stddev": 0.0019264995299903547, "rounds": 94, "median": 0.0053474695000002015, "iqr": 0.00284201499999881, "q1": 0.004240069000001512, "q3": 0.007082084000000322, "iqr_outliers": 1, "stddev_outliers": 25, "outliers": "25;1", "ld15iqr": 0.0037355100000020514, "hd15iqr": 0.011600158000000249, "ops": 170.3426541976543, "total": 0.5518289030000005, "iterations": 1 } }, { "group": null, "name": "test_custom[False-1000000]", "fullname": "bench/test_cost.py::test_custom[False-1000000]", "params": { "log": false, "n": 1000000 }, "param": "False-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.01992837400000269, "max": 0.030484014999998976, "mean": 0.023060005529411728, "stddev": 0.0026836474675817536, "rounds": 34, "median": 0.022698909500000752, "iqr": 0.0037107550000001766, "q1": 0.020900592000000273, "q3": 0.02461134700000045, "iqr_outliers": 1, "stddev_outliers": 8, "outliers": "8;1", "ld15iqr": 0.01992837400000269, "hd15iqr": 0.030484014999998976, "ops": 43.36512403366759, "total": 0.7840401879999988, "iterations": 1 } }, { "group": null, "name": "test_custom[True-10]", "fullname": "bench/test_cost.py::test_custom[True-10]", "params": { "log": true, "n": 10 }, "param": "True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 8.789999998981557e-06, "max": 0.0007441660000004902, "mean": 1.3133151607740057e-05, "stddev": 1.2985262274528562e-05, "rounds": 21272, "median": 9.6799999980135e-06, "iqr": 5.479999991564455e-07, "q1": 9.512000001876686e-06, "q3": 1.0060000001033131e-05, "iqr_outliers": 3515, "stddev_outliers": 1608, "outliers": "1608;3515", "ld15iqr": 8.789999998981557e-06, "hd15iqr": 1.0882999998074183e-05, "ops": 76143.18557098262, "total": 0.2793684009998465, "iterations": 1 } }, { "group": null, "name": "test_custom[True-31]", "fullname": "bench/test_cost.py::test_custom[True-31]", "params": { "log": true, "n": 31 }, "param": "True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.032000001241158e-06, "max": 0.000202774000001682, "mean": 1.2148806264562728e-05, "stddev": 9.895840143008478e-06, "rounds": 31734, "median": 9.932000001100505e-06, "iqr": 4.620000026989146e-07, "q1": 9.676999997765279e-06, "q3": 1.0139000000464193e-05, "iqr_outliers": 3591, "stddev_outliers": 2027, "outliers": "2027;3591", "ld15iqr": 9.032000001241158e-06, "hd15iqr": 1.0833000001042592e-05, "ops": 82312.61394931735, "total": 0.3855302179996336, "iterations": 1 } }, { "group": null, "name": "test_custom[True-100]", "fullname": "bench/test_cost.py::test_custom[True-100]", "params": { "log": true, "n": 100 }, "param": "True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.170999998531215e-06, "max": 0.0002294269999971732, "mean": 1.2380379749494696e-05, "stddev": 1.0329272028596635e-05, "rounds": 33372, "median": 9.99099999887676e-06, "iqr": 4.6000000253343387e-07, "q1": 9.734999999011507e-06, "q3": 1.019500000154494e-05, "iqr_outliers": 4550, "stddev_outliers": 2308, "outliers": "2308;4550", "ld15iqr": 9.170999998531215e-06, "hd15iqr": 1.0885999998322404e-05, "ops": 80772.96659989892, "total": 0.413158033000137, "iterations": 1 } }, { "group": null, "name": "test_custom[True-316]", "fullname": "bench/test_cost.py::test_custom[True-316]", "params": { "log": true, "n": 316 }, "param": "True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.731000002233259e-06, "max": 0.00029858699999962823, "mean": 1.367896212417522e-05, "stddev": 1.0813466337242634e-05, "rounds": 25478, "median": 1.0877999997660481e-05, "iqr": 7.020000012403216e-07, "q1": 1.0460999998684883e-05, "q3": 1.1162999999925205e-05, "iqr_outliers": 4276, "stddev_outliers": 2161, "outliers": "2161;4276", "ld15iqr": 9.731000002233259e-06, "hd15iqr": 1.2219000002033908e-05, "ops": 73104.96154036946, "total": 0.34851259699973625, "iterations": 1 } }, { "group": null, "name": "test_custom[True-1000]", "fullname": "bench/test_cost.py::test_custom[True-1000]", "params": { "log": true, "n": 1000 }, "param": "True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.1400999998301131e-05, "max": 0.0003645020000000443, "mean": 1.8334365914677316e-05, "stddev": 1.4686574395030505e-05, "rounds": 21986, "median": 1.2191999999799918e-05, "iqr": 6.534000000613105e-06, "q1": 1.1879000002323892e-05, "q3": 1.8413000002936997e-05, "iqr_outliers": 2787, "stddev_outliers": 1954, "outliers": "1954;2787", "ld15iqr": 1.1400999998301131e-05, "hd15iqr": 2.8219000000717642e-05, "ops": 54542.38257563433, "total": 0.40309936900009546, "iterations": 1 } }, { "group": null, "name": "test_custom[True-3162]", "fullname": "bench/test_cost.py::test_custom[True-3162]", "params": { "log": true, "n": 3162 }, "param": "True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.4678000002987801e-05, "max": 0.00021816099999938388, "mean": 2.0741297327134935e-05, "stddev": 1.5083305725205552e-05, "rounds": 18108, "median": 1.5502000000111593e-05, "iqr": 1.0165000023931725e-06, "q1": 1.5300999997691633e-05, "q3": 1.6317500000084806e-05, "iqr_outliers": 3633, "stddev_outliers": 1610, "outliers": "1610;3633", "ld15iqr": 1.4678000002987801e-05, "hd15iqr": 1.784299999840755e-05, "ops": 48212.99189861878, "total": 0.3755834119997594, "iterations": 1 } }, { "group": null, "name": "test_custom[True-10000]", "fullname": "bench/test_cost.py::test_custom[True-10000]", "params": { "log": true, "n": 10000 }, "param": "True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.8541999999021073e-05, "max": 0.0002257589999992149, "mean": 3.8309295480477375e-05, "stddev": 2.1328575645327324e-05, "rounds": 2633, "median": 2.947999999847184e-05, "iqr": 4.855249998492184e-06, "q1": 2.9189000001927923e-05, "q3": 3.4044250000420107e-05, "iqr_outliers": 555, "stddev_outliers": 267, "outliers": "267;555", "ld15iqr": 2.8541999999021073e-05, "hd15iqr": 4.1689999999761085e-05, "ops": 26103.325249340734, "total": 0.10086837500009693, "iterations": 1 } }, { "group": null, "name": "test_custom[True-31622]", "fullname": "bench/test_cost.py::test_custom[True-31622]", "params": { "log": true, "n": 31622 }, "param": "True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.303400000007287e-05, "max": 0.0003410009999988972, "mean": 7.764404535792864e-05, "stddev": 3.0996005951667394e-05, "rounds": 1411, "median": 6.483900000020526e-05, "iqr": 3.5792500030495944e-06, "q1": 6.404674999860305e-05, "q3": 6.762600000165264e-05, "iqr_outliers": 307, "stddev_outliers": 170, "outliers": "170;307", "ld15iqr": 6.303400000007287e-05, "hd15iqr": 7.309700000135422e-05, "ops": 12879.287721165661, "total": 0.10955574800003731, "iterations": 1 } }, { "group": null, "name": "test_custom[True-100000]", "fullname": "bench/test_cost.py::test_custom[True-100000]", "params": { "log": true, "n": 100000 }, "param": "True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00017040299999848685, "max": 0.0005319950000028939, "mean": 0.00021622023185481127, "stddev": 6.987675584364205e-05, "rounds": 496, "median": 0.00017799749999980463, "iqr": 6.552499999834538e-05, "q1": 0.00017415550000166036, "q3": 0.00023968050000000574, "iqr_outliers": 41, "stddev_outliers": 69, "outliers": "69;41", "ld15iqr": 0.00017040299999848685, "hd15iqr": 0.00034965300000067145, "ops": 4624.914104575955, "total": 0.1072452349999864, "iterations": 1 } }, { "group": null, "name": "test_custom[True-316227]", "fullname": "bench/test_cost.py::test_custom[True-316227]", "params": { "log": true, "n": 316227 }, "param": "True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007048860000011814, "max": 0.0013792859999988138, "mean": 0.0008437566850828471, "stddev": 0.00012339195355524246, "rounds": 181, "median": 0.0007973080000027721, "iqr": 0.00012779849999944304, "q1": 0.0007587457500006778, "q3": 0.0008865442500001208, "iqr_outliers": 13, "stddev_outliers": 34, "outliers": "34;13", "ld15iqr": 0.0007048860000011814, "hd15iqr": 0.0010797920000022998, "ops": 1185.1757949648857, "total": 0.15271995999999533, "iterations": 1 } }, { "group": null, "name": "test_custom[True-1000000]", "fullname": "bench/test_cost.py::test_custom[True-1000000]", "params": { "log": true, "n": 1000000 }, "param": "True-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.007021717000000649, "max": 0.010763501999999647, "mean": 0.008429458762711945, "stddev": 0.0008034515838174789, "rounds": 59, "median": 0.008447413999999043, "iqr": 0.0012559467500015131, "q1": 0.007796427249999738, "q3": 0.009052374000001251, "iqr_outliers": 0, "stddev_outliers": 20, "outliers": "20;0", "ld15iqr": 0.007021717000000649, "hd15iqr": 0.010763501999999647, "ops": 118.63157862798272, "total": 0.4973380670000047, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-10]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-10]", "params": { "fastmath": false, "parallel": false, "n": 10 }, "param": "False-False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.569999999011088e-07, "max": 9.442200000009393e-05, "mean": 7.384942069935835e-07, "stddev": 1.3178564893478023e-06, "rounds": 151562, "median": 6.510000005732763e-07, "iqr": 4.4000000087862645e-08, "q1": 6.270000021402211e-07, "q3": 6.710000022280838e-07, "iqr_outliers": 6690, "stddev_outliers": 904, "outliers": "904;6690", "ld15iqr": 5.620000003148107e-07, "hd15iqr": 7.379999971135476e-07, "ops": 1354106.7628289312, "total": 0.1119276590003615, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-31]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-31]", "params": { "fastmath": false, "parallel": false, "n": 31 }, "param": "False-False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.08050000039384e-07, "max": 8.525150000160409e-06, "mean": 7.301177386555848e-07, "stddev": 3.304085264139116e-07, "rounds": 75234, "median": 6.574500000411376e-07, "iqr": 3.0949999896279223e-08, "q1": 6.448500000644231e-07, "q3": 6.757999999607023e-07, "iqr_outliers": 6112, "stddev_outliers": 4451, "outliers": "4451;6112", "ld15iqr": 6.08050000039384e-07, "hd15iqr": 7.222499998960075e-07, "ops": 1369642.1098347555, "total": 0.0549296779500134, "iterations": 20 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-100]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-100]", "params": { "fastmath": false, "parallel": false, "n": 100 }, "param": "False-False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.763500000062095e-07, "max": 1.0546700000091392e-05, "mean": 8.538209473740091e-07, "stddev": 4.178100397458519e-07, "rounds": 62953, "median": 7.458000000681864e-07, "iqr": 5.410000003536197e-08, "q1": 7.22100000061232e-07, "q3": 7.76200000096594e-07, "iqr_outliers": 6993, "stddev_outliers": 5168, "outliers": "5168;6993", "ld15iqr": 6.763500000062095e-07, "hd15iqr": 8.574499998914575e-07, "ops": 1171205.7464455054, "total": 0.053750590100036806, "iterations": 20 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-316]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-316]", "params": { "fastmath": false, "parallel": false, "n": 316 }, "param": "False-False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 8.770000000879463e-07, "max": 4.2351599999790325e-05, "mean": 1.135184090152709e-06, "stddev": 8.640068702973347e-07, "rounds": 195313, "median": 9.75399999703086e-07, "iqr": 5.05999999234064e-08, "q1": 9.439999999472093e-07, "q3": 9.945999998706157e-07, "iqr_outliers": 25154, "stddev_outliers": 6912, "outliers": "6912;25154", "ld15iqr": 8.770000000879463e-07, "hd15iqr": 1.0705999997639992e-06, "ops": 880914.3897226823, "total": 0.2217162102000466, "iterations": 5 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-1000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-1000]", "params": { "fastmath": false, "parallel": false, "n": 1000 }, "param": "False-False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.934000000147762e-06, "max": 0.00015526800000031926, "mean": 2.591447944351279e-06, "stddev": 3.1300665431034445e-06, "rounds": 197942, "median": 2.162000001248998e-06, "iqr": 9.599999728493458e-08, "q1": 2.1100000004992125e-06, "q3": 2.205999997784147e-06, "iqr_outliers": 25596, "stddev_outliers": 4300, "outliers": "4300;25596", "ld15iqr": 1.9669999993254805e-06, "hd15iqr": 2.3499999990406195e-06, "ops": 385884.65656034293, "total": 0.5129563890007809, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-3162]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-3162]", "params": { "fastmath": false, "parallel": false, "n": 3162 }, "param": "False-False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 4.73999999783814e-06, "max": 0.00010552999999902113, "mean": 5.680130016329278e-06, "stddev": 3.55400793831634e-06, "rounds": 121877, "median": 5.089000001845534e-06, "iqr": 7.30000024873334e-08, "q1": 5.058999999363323e-06, "q3": 5.132000001850656e-06, "iqr_outliers": 29499, "stddev_outliers": 3435, "outliers": "3435;29499", "ld15iqr": 4.94999999745005e-06, "hd15iqr": 5.242000000293956e-06, "ops": 176052.30815583322, "total": 0.6922772060001634, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-10000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-10000]", "params": { "fastmath": false, "parallel": false, "n": 10000 }, "param": "False-False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.5317000002568193e-05, "max": 0.0001715979999978856, "mean": 1.798729320889319e-05, "stddev": 7.312460171572777e-06, "rounds": 49712, "median": 1.6140999999691985e-05, "iqr": 1.1899999918796311e-07, "q1": 1.6093000002825875e-05, "q3": 1.6212000002013838e-05, "iqr_outliers": 9907, "stddev_outliers": 3368, "outliers": "3368;9907", "ld15iqr": 1.5931000000080076e-05, "hd15iqr": 1.6390999999060796e-05, "ops": 55594.80175180471, "total": 0.8941843200004982, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-31622]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-31622]", "params": { "fastmath": false, "parallel": false, "n": 31622 }, "param": "False-False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.250899999964531e-05, "max": 0.00023098600000537317, "mean": 5.8762171728307075e-05, "stddev": 1.6905532008580644e-05, "rounds": 16299, "median": 5.324499999659338e-05, "iqr": 5.850000022178392e-07, "q1": 5.287199999770564e-05, "q3": 5.345699999992348e-05, "iqr_outliers": 3407, "stddev_outliers": 1483, "outliers": "1483;3407", "ld15iqr": 5.250899999964531e-05, "hd15iqr": 5.4335000001515255e-05, "ops": 17017.750886124537, "total": 0.9577646369996771, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-100000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-100000]", "params": { "fastmath": false, "parallel": false, "n": 100000 }, "param": "False-False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0001557339999962437, "max": 0.0004167609999967681, "mean": 0.0001776748460486473, "stddev": 3.571705864297936e-05, "rounds": 4391, "median": 0.00016488499999667283, "iqr": 6.429500002624877e-06, "q1": 0.00016334399999529126, "q3": 0.00016977349999791613, "iqr_outliers": 818, "stddev_outliers": 500, "outliers": "500;818", "ld15iqr": 0.0001557339999962437, "hd15iqr": 0.0001797769999996035, "ops": 5628.258711006286, "total": 0.7801702489996103, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-316227]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-316227]", "params": { "fastmath": false, "parallel": false, "n": 316227 }, "param": "False-False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006041039999971076, "max": 0.001561467999998456, "mean": 0.000725377717692312, "stddev": 0.00016024841360708203, "rounds": 1300, "median": 0.0006513955000002625, "iqr": 0.00013348199999896337, "q1": 0.0006258485000003589, "q3": 0.0007593304999993222, "iqr_outliers": 128, "stddev_outliers": 172, "outliers": "172;128", "ld15iqr": 0.0006041039999971076, "hd15iqr": 0.0009613699999988512, "ops": 1378.5921122327284, "total": 0.9429910330000055, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-False-1000000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-False-1000000]", "params": { "fastmath": false, "parallel": false, "n": 1000000 }, "param": "False-False-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004517882000001805, "max": 0.006456591999999262, "mean": 0.005539401096491291, "stddev": 0.0003119458719998638, "rounds": 228, "median": 0.005589803999999532, "iqr": 0.0003723320000048602, "q1": 0.005370785499998476, "q3": 0.005743117500003336, "iqr_outliers": 6, "stddev_outliers": 59, "outliers": "59;6", "ld15iqr": 0.004819979000004082, "hd15iqr": 0.006456591999999262, "ops": 180.52493086904457, "total": 1.2629834500000143, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-10]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-10]", "params": { "fastmath": false, "parallel": true, "n": 10 }, "param": "False-True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.2930000014298457e-06, "max": 0.00013977399999731688, "mean": 2.9654290337888466e-06, "stddev": 3.2213711052195733e-06, "rounds": 144907, "median": 2.494000000297092e-06, "iqr": 1.3000000365082087e-07, "q1": 2.4289999984716815e-06, "q3": 2.5590000021225023e-06, "iqr_outliers": 19688, "stddev_outliers": 2877, "outliers": "2877;19688", "ld15iqr": 2.2930000014298457e-06, "hd15iqr": 2.754999997023333e-06, "ops": 337219.3327190594, "total": 0.4297114249992404, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-31]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-31]", "params": { "fastmath": false, "parallel": true, "n": 31 }, "param": "False-True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.2199999989425123e-06, "max": 0.00012292000000257985, "mean": 2.6337453622649823e-06, "stddev": 1.564083121951044e-06, "rounds": 185220, "median": 2.53599999666676e-06, "iqr": 2.0050000060223283e-07, "q1": 2.428500000206668e-06, "q3": 2.629000000808901e-06, "iqr_outliers": 1983, "stddev_outliers": 1334, "outliers": "1334;1983", "ld15iqr": 2.2199999989425123e-06, "hd15iqr": 2.9299999937393295e-06, "ops": 379687.42701079295, "total": 0.48782231599872006, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-100]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-100]", "params": { "fastmath": false, "parallel": true, "n": 100 }, "param": "False-True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.303999998787276e-06, "max": 0.00012516999999689915, "mean": 2.8794110737327086e-06, "stddev": 2.6350071267249425e-06, "rounds": 173672, "median": 2.5570000019570216e-06, "iqr": 1.4500000133921276e-07, "q1": 2.506999997820003e-06, "q3": 2.651999999159216e-06, "iqr_outliers": 9865, "stddev_outliers": 2496, "outliers": "2496;9865", "ld15iqr": 2.303999998787276e-06, "hd15iqr": 2.8699999958803346e-06, "ops": 347293.23962196737, "total": 0.500073079997307, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-316]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-316]", "params": { "fastmath": false, "parallel": true, "n": 316 }, "param": "False-True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.651000002629189e-06, "max": 0.0007230800000002091, "mean": 3.612061695701183e-06, "stddev": 4.688857260435486e-06, "rounds": 156348, "median": 2.889999997535142e-06, "iqr": 1.5100000183565498e-07, "q1": 2.8560000018273968e-06, "q3": 3.0070000036630518e-06, "iqr_outliers": 16901, "stddev_outliers": 4247, "outliers": "4247;16901", "ld15iqr": 2.651000002629189e-06, "hd15iqr": 3.2339999975761202e-06, "ops": 276850.1992062119, "total": 0.5647386219994885, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-1000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-1000]", "params": { "fastmath": false, "parallel": true, "n": 1000 }, "param": "False-True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 3.2270000005496513e-06, "max": 0.00014222000000074786, "mean": 3.86599585170078e-06, "stddev": 2.652394058101699e-06, "rounds": 139334, "median": 3.5559999957968103e-06, "iqr": 2.2399999721756103e-07, "q1": 3.4370000037142745e-06, "q3": 3.6610000009318355e-06, "iqr_outliers": 4063, "stddev_outliers": 2235, "outliers": "2235;4063", "ld15iqr": 3.2270000005496513e-06, "hd15iqr": 3.997000000310891e-06, "ops": 258665.56467205385, "total": 0.5386646660008765, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-3162]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-3162]", "params": { "fastmath": false, "parallel": true, "n": 3162 }, "param": "False-True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.1769999984685455e-06, "max": 0.00012922499999490356, "mean": 6.23081878861576e-06, "stddev": 3.2334501468683276e-06, "rounds": 112664, "median": 5.766000001017346e-06, "iqr": 2.8999999557299816e-07, "q1": 5.681000004642556e-06, "q3": 5.971000000215554e-06, "iqr_outliers": 5431, "stddev_outliers": 2834, "outliers": "2834;5431", "ld15iqr": 5.246999997154944e-06, "hd15iqr": 6.405999997127765e-06, "ops": 160492.55064632688, "total": 0.701988968000606, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-10000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-10000]", "params": { "fastmath": false, "parallel": true, "n": 10000 }, "param": "False-True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.1323000002505523e-05, "max": 0.0002611179999973956, "mean": 1.3936605927854537e-05, "stddev": 6.55507154859e-06, "rounds": 61641, "median": 1.2569999995548642e-05, "iqr": 6.752500070206224e-07, "q1": 1.2448999996195198e-05, "q3": 1.312425000321582e-05, "iqr_outliers": 4883, "stddev_outliers": 3371, "outliers": "3371;4883", "ld15iqr": 1.1436999997727071e-05, "hd15iqr": 1.4137999997387851e-05, "ops": 71753.48181448827, "total": 0.8590663259988816, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-31622]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-31622]", "params": { "fastmath": false, "parallel": true, "n": 31622 }, "param": "False-True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 3.0582000000833887e-05, "max": 0.00016446400000091899, "mean": 3.4908025296270915e-05, "stddev": 9.43187804471102e-06, "rounds": 25063, "median": 3.224499999987529e-05, "iqr": 1.5230000016686063e-06, "q1": 3.2120000000190885e-05, "q3": 3.364300000185949e-05, "iqr_outliers": 2143, "stddev_outliers": 1659, "outliers": "1659;2143", "ld15iqr": 3.0582000000833887e-05, "hd15iqr": 3.5932000002958375e-05, "ops": 28646.707784608658, "total": 0.874899838000438, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-100000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-100000]", "params": { "fastmath": false, "parallel": true, "n": 100000 }, "param": "False-True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.072600000337161e-05, "max": 0.000300341000006199, "mean": 0.00010426488576224787, "stddev": 2.267235254179405e-05, "rounds": 7143, "median": 9.734900000069047e-05, "iqr": 6.862499994042537e-06, "q1": 9.504225000256383e-05, "q3": 0.00010190474999660637, "iqr_outliers": 833, "stddev_outliers": 595, "outliers": "595;833", "ld15iqr": 9.072600000337161e-05, "hd15iqr": 0.00011222599999882732, "ops": 9590.956655151096, "total": 0.7447640789997365, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-316227]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-316227]", "params": { "fastmath": false, "parallel": true, "n": 316227 }, "param": "False-True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0002935079999986101, "max": 0.001218880999999783, "mean": 0.0003769477158383957, "stddev": 0.00010447618990144026, "rounds": 1932, "median": 0.00032598900000024855, "iqr": 0.00011434200000337569, "q1": 0.00030775849999642446, "q3": 0.00042210049999980015, "iqr_outliers": 111, "stddev_outliers": 270, "outliers": "270;111", "ld15iqr": 0.0002935079999986101, "hd15iqr": 0.0005952469999996879, "ops": 2652.887809058161, "total": 0.7282629869997805, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[False-True-1000000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[False-True-1000000]", "params": { "fastmath": false, "parallel": true, "n": 1000000 }, "param": "False-True-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0010692270000021153, "max": 0.0016584909999934894, "mean": 0.0014053659056599997, "stddev": 0.00010938705043474735, "rounds": 742, "median": 0.0014287605000014025, "iqr": 0.0001535330000095314, "q1": 0.0013364219999942861, "q3": 0.0014899550000038175, "iqr_outliers": 1, "stddev_outliers": 235, "outliers": "235;1", "ld15iqr": 0.0011212009999965744, "hd15iqr": 0.0016584909999934894, "ops": 711.5584603074398, "total": 1.0427815019997198, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-10]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-10]", "params": { "fastmath": true, "parallel": false, "n": 10 }, "param": "True-False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 4.2525000019111305e-07, "max": 6.327250000026652e-06, "mean": 5.276509057261997e-07, "stddev": 2.5985263902639337e-07, "rounds": 107262, "median": 4.5859999993069777e-07, "iqr": 2.835000003642566e-08, "q1": 4.5375000006231404e-07, "q3": 4.821000000987397e-07, "iqr_outliers": 10751, "stddev_outliers": 6206, "outliers": "6206;10751", "ld15iqr": 4.2525000019111305e-07, "hd15iqr": 5.246500002442644e-07, "ops": 1895192.4258023659, "total": 0.05659689145000069, "iterations": 20 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-31]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-31]", "params": { "fastmath": true, "parallel": false, "n": 31 }, "param": "True-False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.998500000714558e-07, "max": 8.326300000049968e-06, "mean": 7.364908693010957e-07, "stddev": 3.1494067713892395e-07, "rounds": 70597, "median": 6.688500000961994e-07, "iqr": 4.175000007933254e-08, "q1": 6.566999999790823e-07, "q3": 6.984500000584148e-07, "iqr_outliers": 4606, "stddev_outliers": 3911, "outliers": "3911;4606", "ld15iqr": 5.998500000714558e-07, "hd15iqr": 7.611999997436669e-07, "ops": 1357790.0849591773, "total": 0.051994045900049815, "iterations": 20 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-100]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-100]", "params": { "fastmath": true, "parallel": false, "n": 100 }, "param": "True-False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 6.781499997998708e-07, "max": 6.672919999992644e-05, "mean": 8.573905086876151e-07, "stddev": 4.852130215400721e-07, "rounds": 66819, "median": 7.606000000492941e-07, "iqr": 4.069999981481942e-08, "q1": 7.39200000055007e-07, "q3": 7.798999998698264e-07, "iqr_outliers": 6747, "stddev_outliers": 4465, "outliers": "4465;6747", "ld15iqr": 6.792500002461566e-07, "hd15iqr": 8.410500001332366e-07, "ops": 1166329.6827610508, "total": 0.05728997639999992, "iterations": 20 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-316]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-316]", "params": { "fastmath": true, "parallel": false, "n": 316 }, "param": "True-False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 8.33833333047096e-07, "max": 0.0006090733333330434, "mean": 1.1376584217867735e-06, "stddev": 1.7193758544463329e-06, "rounds": 174856, "median": 9.371666666406023e-07, "iqr": 5.416666700360417e-08, "q1": 9.09666666141599e-07, "q3": 9.638333331452031e-07, "iqr_outliers": 29951, "stddev_outliers": 7628, "outliers": "7628;29951", "ld15iqr": 8.33833333047096e-07, "hd15iqr": 1.0451666661026593e-06, "ops": 878998.4593349568, "total": 0.1989264009999456, "iterations": 6 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-1000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-1000]", "params": { "fastmath": true, "parallel": false, "n": 1000 }, "param": "True-False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.9029999975828105e-06, "max": 0.0001145579999928259, "mean": 2.5136941765871796e-06, "stddev": 2.748865927021821e-06, "rounds": 190404, "median": 2.117999997608422e-06, "iqr": 9.200000761211413e-08, "q1": 2.078999997934261e-06, "q3": 2.171000005546375e-06, "iqr_outliers": 31316, "stddev_outliers": 3712, "outliers": "3712;31316", "ld15iqr": 1.940999993621517e-06, "hd15iqr": 2.3099999992837184e-06, "ops": 397820.8683117097, "total": 0.47861742599890533, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-3162]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-3162]", "params": { "fastmath": true, "parallel": false, "n": 3162 }, "param": "True-False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 4.888999995955601e-06, "max": 0.0016173559999970166, "mean": 6.67323438642645e-06, "stddev": 7.125385296796051e-06, "rounds": 117814, "median": 5.28900000063004e-06, "iqr": 7.889999977805928e-07, "q1": 5.217999998308187e-06, "q3": 6.00699999608878e-06, "iqr_outliers": 18184, "stddev_outliers": 5567, "outliers": "5567;18184", "ld15iqr": 4.888999995955601e-06, "hd15iqr": 7.190999994577396e-06, "ops": 149852.3717425584, "total": 0.7862004360024457, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-10000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-10000]", "params": { "fastmath": true, "parallel": false, "n": 10000 }, "param": "True-False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.590200000123332e-05, "max": 0.00020341500000142787, "mean": 2.001629543258794e-05, "stddev": 9.9266641487268e-06, "rounds": 45540, "median": 1.691299999606599e-05, "iqr": 8.679999865535137e-07, "q1": 1.6245000011849697e-05, "q3": 1.711299999840321e-05, "iqr_outliers": 8686, "stddev_outliers": 5031, "outliers": "5031;8686", "ld15iqr": 1.590200000123332e-05, "hd15iqr": 1.8414999999549764e-05, "ops": 49959.294584148156, "total": 0.9115420940000547, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-31622]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-31622]", "params": { "fastmath": true, "parallel": false, "n": 31622 }, "param": "True-False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 5.195599999296974e-05, "max": 0.00026434200000835517, "mean": 6.409864415755342e-05, "stddev": 2.298564850533202e-05, "rounds": 6042, "median": 5.50729999986288e-05, "iqr": 2.561000002287983e-06, "q1": 5.28730000013411e-05, "q3": 5.543400000362908e-05, "iqr_outliers": 1359, "stddev_outliers": 798, "outliers": "798;1359", "ld15iqr": 5.195599999296974e-05, "hd15iqr": 5.9315999990872115e-05, "ops": 15600.954016156977, "total": 0.3872840079999378, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-100000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-100000]", "params": { "fastmath": true, "parallel": false, "n": 100000 }, "param": "True-False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00015974299999754749, "max": 0.0005250009999997474, "mean": 0.00019991409436661905, "stddev": 5.6284982081303065e-05, "rounds": 3497, "median": 0.00017131999999264735, "iqr": 4.23897500105852e-05, "q1": 0.0001695609999927683, "q3": 0.0002119507500033535, "iqr_outliers": 396, "stddev_outliers": 515, "outliers": "515;396", "ld15iqr": 0.00015974299999754749, "hd15iqr": 0.0002756389999944986, "ops": 5002.148563703153, "total": 0.6990995880000668, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-316227]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-316227]", "params": { "fastmath": true, "parallel": false, "n": 316227 }, "param": "True-False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0005987210000029108, "max": 0.001858225999995966, "mean": 0.000793979701890818, "stddev": 0.0001924912937560062, "rounds": 899, "median": 0.0007148859999972501, "iqr": 0.00027998899999914784, "q1": 0.0006326717500009238, "q3": 0.0009126607500000716, "iqr_outliers": 10, "stddev_outliers": 155, "outliers": "155;10", "ld15iqr": 0.0005987210000029108, "hd15iqr": 0.0013555880000097886, "ops": 1259.4780415904288, "total": 0.7137877519998455, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-False-1000000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-False-1000000]", "params": { "fastmath": true, "parallel": false, "n": 1000000 }, "param": "True-False-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004206049000003986, "max": 0.006451630000000819, "mean": 0.005544679136364101, "stddev": 0.0003724681762288862, "rounds": 220, "median": 0.005616597000006607, "iqr": 0.00047781199999974433, "q1": 0.005313022999999362, "q3": 0.005790834999999106, "iqr_outliers": 4, "stddev_outliers": 58, "outliers": "58;4", "ld15iqr": 0.004679873000000612, "hd15iqr": 0.006451630000000819, "ops": 180.35308724027368, "total": 1.2198294100001021, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-10]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-10]", "params": { "fastmath": true, "parallel": true, "n": 10 }, "param": "True-True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.3770000012746095e-06, "max": 8.785100000352486e-05, "mean": 2.869558150655784e-06, "stddev": 2.5634970718002163e-06, "rounds": 43843, "median": 2.5719999996454135e-06, "iqr": 6.899998084008985e-08, "q1": 2.5320000105466534e-06, "q3": 2.600999991386743e-06, "iqr_outliers": 4040, "stddev_outliers": 700, "outliers": "700;4040", "ld15iqr": 2.428999991366254e-06, "hd15iqr": 2.7049999999917418e-06, "ops": 348485.70668326365, "total": 0.12581003799920154, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-31]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-31]", "params": { "fastmath": true, "parallel": true, "n": 31 }, "param": "True-True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.389000002267494e-06, "max": 0.0002836330000093312, "mean": 2.96322942001911e-06, "stddev": 2.5824245072081864e-06, "rounds": 164881, "median": 2.6139999960150817e-06, "iqr": 1.2000000992884452e-07, "q1": 2.566999995678998e-06, "q3": 2.6870000056078425e-06, "iqr_outliers": 13447, "stddev_outliers": 2621, "outliers": "2621;13447", "ld15iqr": 2.389000002267494e-06, "hd15iqr": 2.867999995714854e-06, "ops": 337469.65160515683, "total": 0.4885802300021709, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-100]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-100]", "params": { "fastmath": true, "parallel": true, "n": 100 }, "param": "True-True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.4869999890597683e-06, "max": 0.00017010599999878195, "mean": 3.2954506166353633e-06, "stddev": 3.4040333843371385e-06, "rounds": 170766, "median": 2.7100000039581573e-06, "iqr": 1.610000168739134e-07, "q1": 2.6609999963511655e-06, "q3": 2.822000013225079e-06, "iqr_outliers": 19746, "stddev_outliers": 4008, "outliers": "4008;19746", "ld15iqr": 2.4869999890597683e-06, "hd15iqr": 3.063999997721112e-06, "ops": 303448.63763153413, "total": 0.5627509200003544, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-316]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-316]", "params": { "fastmath": true, "parallel": true, "n": 316 }, "param": "True-True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.4320000022726163e-06, "max": 0.000343454999992332, "mean": 3.290745510603073e-06, "stddev": 3.3747928953426736e-06, "rounds": 161213, "median": 2.7200000118909884e-06, "iqr": 1.4900000167017424e-07, "q1": 2.663999993046673e-06, "q3": 2.812999994716847e-06, "iqr_outliers": 19819, "stddev_outliers": 3690, "outliers": "3690;19819", "ld15iqr": 2.4419999959945926e-06, "hd15iqr": 3.0369999990398355e-06, "ops": 303882.50831852894, "total": 0.5305109560008532, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-1000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-1000]", "params": { "fastmath": true, "parallel": true, "n": 1000 }, "param": "True-True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.6120000029550283e-06, "max": 0.00016679300000532749, "mean": 3.390966656527658e-06, "stddev": 3.3982203598919475e-06, "rounds": 151424, "median": 2.901000001998e-06, "iqr": 1.5599999869664316e-07, "q1": 2.8150000019877552e-06, "q3": 2.9710000006843984e-06, "iqr_outliers": 17510, "stddev_outliers": 3331, "outliers": "3331;17510", "ld15iqr": 2.6120000029550283e-06, "hd15iqr": 3.205000012940218e-06, "ops": 294901.1598433108, "total": 0.513473734998044, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-3162]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-3162]", "params": { "fastmath": true, "parallel": true, "n": 3162 }, "param": "True-True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 3.030999991437966e-06, "max": 0.0018878150000034566, "mean": 4.191692589570426e-06, "stddev": 7.0054428267911025e-06, "rounds": 150626, "median": 3.3860000030472293e-06, "iqr": 1.4500000133921276e-07, "q1": 3.3240000050227536e-06, "q3": 3.4690000063619664e-06, "iqr_outliers": 26754, "stddev_outliers": 4427, "outliers": "4427;26754", "ld15iqr": 3.106999997726234e-06, "hd15iqr": 3.6869999888722305e-06, "ops": 238567.11307698314, "total": 0.631377887996635, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-10000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-10000]", "params": { "fastmath": true, "parallel": true, "n": 10000 }, "param": "True-True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 4.261999990262666e-06, "max": 0.00016315700000291145, "mean": 5.513823705609758e-06, "stddev": 4.4255046361270606e-06, "rounds": 128189, "median": 4.741000012131735e-06, "iqr": 2.499999993688107e-07, "q1": 4.5860000028596914e-06, "q3": 4.836000002228502e-06, "iqr_outliers": 13608, "stddev_outliers": 4658, "outliers": "4658;13608", "ld15iqr": 4.261999990262666e-06, "hd15iqr": 5.2119999907063175e-06, "ops": 181362.34551398535, "total": 0.7068115469984093, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-31622]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-31622]", "params": { "fastmath": true, "parallel": true, "n": 31622 }, "param": "True-True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 9.149999996793667e-06, "max": 0.00016548899999691002, "mean": 1.1977842146838918e-05, "stddev": 7.249386427116504e-06, "rounds": 31675, "median": 9.897999987629191e-06, "iqr": 3.599999871539694e-07, "q1": 9.802000008107825e-06, "q3": 1.0161999995261795e-05, "iqr_outliers": 5640, "stddev_outliers": 2571, "outliers": "2571;5640", "ld15iqr": 9.262999995485188e-06, "hd15iqr": 1.0703999990369084e-05, "ops": 83487.49196564681, "total": 0.37939815000112276, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-100000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-100000]", "params": { "fastmath": true, "parallel": true, "n": 100000 }, "param": "True-True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.2526999998717656e-05, "max": 0.00038498199999992266, "mean": 3.00487217428664e-05, "stddev": 1.4126930086363842e-05, "rounds": 25383, "median": 2.4766999999314976e-05, "iqr": 1.6147499977137159e-06, "q1": 2.4354999997200366e-05, "q3": 2.5969749994914082e-05, "iqr_outliers": 5157, "stddev_outliers": 2812, "outliers": "2812;5157", "ld15iqr": 2.2526999998717656e-05, "hd15iqr": 2.839399999743364e-05, "ops": 33279.285839751275, "total": 0.7627267039991779, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-316227]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-316227]", "params": { "fastmath": true, "parallel": true, "n": 316227 }, "param": "True-True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 7.126100000220958e-05, "max": 0.0013527760000044964, "mean": 0.00010187946724624525, "stddev": 4.637387629720374e-05, "rounds": 6442, "median": 7.959999999940237e-05, "iqr": 3.755599999522019e-05, "q1": 7.624799999916831e-05, "q3": 0.0001138039999943885, "iqr_outliers": 571, "stddev_outliers": 925, "outliers": "925;571", "ld15iqr": 7.126100000220958e-05, "hd15iqr": 0.0001703669999955082, "ops": 9815.520507022035, "total": 0.6563075280003119, "iterations": 1 } }, { "group": null, "name": "test_numba_sum_logpdf[True-True-1000000]", "fullname": "bench/test_cost.py::test_numba_sum_logpdf[True-True-1000000]", "params": { "fastmath": true, "parallel": true, "n": 1000000 }, "param": "True-True-1000000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00032303599999750077, "max": 0.0008806449999951838, "mean": 0.00041048534172643224, "stddev": 7.492473906070616e-05, "rounds": 1668, "median": 0.0003826869999912219, "iqr": 7.027049999663859e-05, "q1": 0.0003624620000053369, "q3": 0.0004327325000019755, "iqr_outliers": 128, "stddev_outliers": 271, "outliers": "271;128", "ld15iqr": 0.00032303599999750077, "hd15iqr": 0.0005382989999986876, "ops": 2436.1405837152874, "total": 0.684689549999689, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-10]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-10]", "params": { "numba": false, "log": false, "n": 10 }, "param": "False-False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0017344800000103078, "max": 0.0041282650000056265, "mean": 0.0021414910851063726, "stddev": 0.00034513590580946964, "rounds": 376, "median": 0.0020513134999973204, "iqr": 0.0003378595000000928, "q1": 0.00189626299999901, "q3": 0.0022341224999991027, "iqr_outliers": 30, "stddev_outliers": 66, "outliers": "66;30", "ld15iqr": 0.0017344800000103078, "hd15iqr": 0.002772308999993811, "ops": 466.9643534613771, "total": 0.805200647999996, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-31]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-31]", "params": { "numba": false, "log": false, "n": 31 }, "param": "False-False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008828080000000682, "max": 0.0020847910000014735, "mean": 0.0010923882206673027, "stddev": 0.00020940821009605564, "rounds": 929, "median": 0.0010156419999987065, "iqr": 0.00022649024999665812, "q1": 0.0009411497500018129, "q3": 0.001167639999998471, "iqr_outliers": 56, "stddev_outliers": 129, "outliers": "129;56", "ld15iqr": 0.0008828080000000682, "hd15iqr": 0.00150755599999286, "ops": 915.4254697008121, "total": 1.0148286569999243, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-100]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-100]", "params": { "numba": false, "log": false, "n": 100 }, "param": "False-False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009083310000050915, "max": 0.0019698910000016667, "mean": 0.0010831048155651986, "stddev": 0.00019561254309250845, "rounds": 938, "median": 0.0009991424999995502, "iqr": 0.00022228399998880377, "q1": 0.0009399099999995997, "q3": 0.0011621939999884034, "iqr_outliers": 47, "stddev_outliers": 131, "outliers": "131;47", "ld15iqr": 0.0009083310000050915, "hd15iqr": 0.001495941999991146, "ops": 923.2716775228888, "total": 1.0159523170001563, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-316]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-316]", "params": { "numba": false, "log": false, "n": 316 }, "param": "False-False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0011275840000024573, "max": 0.0026859690000122782, "mean": 0.0013931383106435605, "stddev": 0.0002711524370633534, "rounds": 808, "median": 0.0013117589999893653, "iqr": 0.00027960450000108494, "q1": 0.0011993314999969584, "q3": 0.0014789359999980434, "iqr_outliers": 55, "stddev_outliers": 115, "outliers": "115;55", "ld15iqr": 0.0011275840000024573, "hd15iqr": 0.0019012909999958083, "ops": 717.8038191613939, "total": 1.1256557549999968, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-1000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-1000]", "params": { "numba": false, "log": false, "n": 1000 }, "param": "False-False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001243679000012321, "max": 0.003187733999993725, "mean": 0.0015580237327586924, "stddev": 0.00029879129198301976, "rounds": 696, "median": 0.0014769430000001194, "iqr": 0.00033460450000433184, "q1": 0.0013272039999989715, "q3": 0.0016618085000033034, "iqr_outliers": 40, "stddev_outliers": 123, "outliers": "123;40", "ld15iqr": 0.001243679000012321, "hd15iqr": 0.002164116999992416, "ops": 641.8387467239438, "total": 1.08438451800005, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-3162]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-3162]", "params": { "numba": false, "log": false, "n": 3162 }, "param": "False-False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0014341560000019626, "max": 0.0033118289999976014, "mean": 0.0018275347154604706, "stddev": 0.0003623601156891203, "rounds": 608, "median": 0.0017206160000000637, "iqr": 0.0003861669999949413, "q1": 0.001543353000002412, "q3": 0.0019295199999973534, "iqr_outliers": 48, "stddev_outliers": 100, "outliers": "100;48", "ld15iqr": 0.0014341560000019626, "hd15iqr": 0.0025115819999967925, "ops": 547.1852280234453, "total": 1.1111411069999662, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-10000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-10000]", "params": { "numba": false, "log": false, "n": 10000 }, "param": "False-False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0032603289999997287, "max": 0.00596613300000115, "mean": 0.0040838711266375175, "stddev": 0.0005379164641770408, "rounds": 229, "median": 0.00399909300000445, "iqr": 0.0007170995000080893, "q1": 0.0036451789999922823, "q3": 0.004362278500000372, "iqr_outliers": 3, "stddev_outliers": 70, "outliers": "70;3", "ld15iqr": 0.0032603289999997287, "hd15iqr": 0.005591271999989544, "ops": 244.86570927211326, "total": 0.9352064879999915, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-31622]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-31622]", "params": { "numba": false, "log": false, "n": 31622 }, "param": "False-False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.012078066000000831, "max": 0.018781547999992654, "mean": 0.013415765839285245, "stddev": 0.001054360041583573, "rounds": 56, "median": 0.013215752000000691, "iqr": 0.0010431765000049609, "q1": 0.012766638999991642, "q3": 0.013809815499996603, "iqr_outliers": 2, "stddev_outliers": 8, "outliers": "8;2", "ld15iqr": 0.012078066000000831, "hd15iqr": 0.016091967000008367, "ops": 74.53916623020585, "total": 0.7512828869999737, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-100000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-100000]", "params": { "numba": false, "log": false, "n": 100000 }, "param": "False-False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.028532187999999792, "max": 0.03257806400000618, "mean": 0.030168462875001634, "stddev": 0.0010069044608002923, "rounds": 32, "median": 0.029816428499998437, "iqr": 0.0012382594999920116, "q1": 0.029552801000008344, "q3": 0.030791060500000356, "iqr_outliers": 0, "stddev_outliers": 9, "outliers": "9;0", "ld15iqr": 0.028532187999999792, "hd15iqr": 0.03257806400000618, "ops": 33.14719759317356, "total": 0.9653908120000523, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-False-316227]", "fullname": "bench/test_cost.py::test_minuit_custom[False-False-316227]", "params": { "numba": false, "log": false, "n": 316227 }, "param": "False-False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.1348924870000019, "max": 0.14091586800000755, "mean": 0.13745938849999995, "stddev": 0.002217329713866885, "rounds": 8, "median": 0.13775680399999857, "iqr": 0.0037236874999990732, "q1": 0.1352264424999987, "q3": 0.13895012999999778, "iqr_outliers": 0, "stddev_outliers": 3, "outliers": "3;0", "ld15iqr": 0.1348924870000019, "hd15iqr": 0.14091586800000755, "ops": 7.274875953634846, "total": 1.0996751079999996, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-10]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-10]", "params": { "numba": false, "log": true, "n": 10 }, "param": "False-True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001266528000002154, "max": 0.002670139999992216, "mean": 0.001511692147388548, "stddev": 0.00029771554978151555, "rounds": 536, "median": 0.001384672500002182, "iqr": 0.00022811350000750963, "q1": 0.0013347789999968995, "q3": 0.0015628925000044092, "iqr_outliers": 62, "stddev_outliers": 70, "outliers": "70;62", "ld15iqr": 0.001266528000002154, "hd15iqr": 0.0019159369999925957, "ops": 661.5103490002924, "total": 0.8102669910002618, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-31]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-31]", "params": { "numba": false, "log": true, "n": 31 }, "param": "False-True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008195010000093816, "max": 0.00237106100000517, "mean": 0.0010072394748206137, "stddev": 0.00023668967424665633, "rounds": 695, "median": 0.0008981460000114794, "iqr": 0.0001717067499953373, "q1": 0.0008661062500046057, "q3": 0.001037812999999943, "iqr_outliers": 85, "stddev_outliers": 97, "outliers": "97;85", "ld15iqr": 0.0008195010000093816, "hd15iqr": 0.001296014000004675, "ops": 992.8125584812857, "total": 0.7000314350003265, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-100]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-100]", "params": { "numba": false, "log": true, "n": 100 }, "param": "False-True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007900579999926549, "max": 0.002130019999995625, "mean": 0.0009970345534532489, "stddev": 0.00022869089032350124, "rounds": 1057, "median": 0.0008880030000000261, "iqr": 0.00017210600000083787, "q1": 0.000867814250000265, "q3": 0.0010399202500011029, "iqr_outliers": 108, "stddev_outliers": 133, "outliers": "133;108", "ld15iqr": 0.0007900579999926549, "hd15iqr": 0.0013007349999867301, "ops": 1002.9742665752958, "total": 1.0538655230000842, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-316]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-316]", "params": { "numba": false, "log": true, "n": 316 }, "param": "False-True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009590579999922966, "max": 0.002438382999997657, "mean": 0.0011908449200866893, "stddev": 0.0002753196635742493, "rounds": 926, "median": 0.0010627799999980425, "iqr": 0.00026227499999720294, "q1": 0.001015735000009954, "q3": 0.001278010000007157, "iqr_outliers": 73, "stddev_outliers": 129, "outliers": "129;73", "ld15iqr": 0.0009590579999922966, "hd15iqr": 0.0016742699999952038, "ops": 839.73990494682, "total": 1.1027223960002743, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-1000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-1000]", "params": { "numba": false, "log": true, "n": 1000 }, "param": "False-True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008996469999971168, "max": 0.002533948000007058, "mean": 0.001122879915151448, "stddev": 0.0002661797058956045, "rounds": 495, "median": 0.0009918009999978494, "iqr": 0.00022886399999322293, "q1": 0.0009561847500023646, "q3": 0.0011850487499955875, "iqr_outliers": 47, "stddev_outliers": 72, "outliers": "72;47", "ld15iqr": 0.0008996469999971168, "hd15iqr": 0.001557597000001465, "ops": 890.5671804318679, "total": 0.5558255579999667, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-3162]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-3162]", "params": { "numba": false, "log": true, "n": 3162 }, "param": "False-True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007653779999969856, "max": 0.002001369999987901, "mean": 0.0009433106150064317, "stddev": 0.00022681224343272042, "rounds": 813, "median": 0.0008336240000090811, "iqr": 0.0001813799999972332, "q1": 0.0008093120000012277, "q3": 0.000990691999998461, "iqr_outliers": 86, "stddev_outliers": 118, "outliers": "118;86", "ld15iqr": 0.0007653779999969856, "hd15iqr": 0.001264914000003614, "ops": 1060.096201708895, "total": 0.7669115300002289, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-10000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-10000]", "params": { "numba": false, "log": true, "n": 10000 }, "param": "False-True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0011349509999973861, "max": 0.002723068000008766, "mean": 0.0014135167107025514, "stddev": 0.00029743002774712714, "rounds": 598, "median": 0.0012958754999985445, "iqr": 0.0002950410000011061, "q1": 0.001206702999994036, "q3": 0.001501743999995142, "iqr_outliers": 46, "stddev_outliers": 86, "outliers": "86;46", "ld15iqr": 0.0011349509999973861, "hd15iqr": 0.0019505309999914289, "ops": 707.4553787927814, "total": 0.8452829930001258, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-31622]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-31622]", "params": { "numba": false, "log": true, "n": 31622 }, "param": "False-True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0024581879999914236, "max": 0.004871679000004292, "mean": 0.003061960565350218, "stddev": 0.00046932590081302344, "rounds": 329, "median": 0.0028868889999955627, "iqr": 0.0006882747500007724, "q1": 0.002695703249997905, "q3": 0.0033839779999986774, "iqr_outliers": 2, "stddev_outliers": 82, "outliers": "82;2", "ld15iqr": 0.0024581879999914236, "hd15iqr": 0.004499139999992963, "ops": 326.5881381087032, "total": 1.0073850260002217, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-100000]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-100000]", "params": { "numba": false, "log": true, "n": 100000 }, "param": "False-True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0048042859999952725, "max": 0.008324477999991586, "mean": 0.005830165062893427, "stddev": 0.000842987564016931, "rounds": 159, "median": 0.0056534279999880255, "iqr": 0.0014428974999987076, "q1": 0.005083976250002564, "q3": 0.006526873750001272, "iqr_outliers": 0, "stddev_outliers": 57, "outliers": "57;0", "ld15iqr": 0.0048042859999952725, "hd15iqr": 0.008324477999991586, "ops": 171.52173038197213, "total": 0.9269962450000548, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[False-True-316227]", "fullname": "bench/test_cost.py::test_minuit_custom[False-True-316227]", "params": { "numba": false, "log": true, "n": 316227 }, "param": "False-True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.022271719000002577, "max": 0.0275136759999981, "mean": 0.024295345702703235, "stddev": 0.0013508909801599129, "rounds": 37, "median": 0.023977650999995603, "iqr": 0.0018118857500049046, "q1": 0.023361240249997195, "q3": 0.0251731260000021, "iqr_outliers": 0, "stddev_outliers": 9, "outliers": "9;0", "ld15iqr": 0.022271719000002577, "hd15iqr": 0.0275136759999981, "ops": 41.160146977811245, "total": 0.8989277910000197, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-10]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-10]", "params": { "numba": true, "log": false, "n": 10 }, "param": "True-False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006247840000099814, "max": 0.0016997040000035213, "mean": 0.0007364066695156964, "stddev": 0.00013824279332687748, "rounds": 1053, "median": 0.0006690249999934395, "iqr": 0.0001570274999949106, "q1": 0.0006363307500016901, "q3": 0.0007933582499966008, "iqr_outliers": 50, "stddev_outliers": 136, "outliers": "136;50", "ld15iqr": 0.0006247840000099814, "hd15iqr": 0.0010297870000073317, "ops": 1357.9453329199991, "total": 0.7754362230000282, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-31]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-31]", "params": { "numba": true, "log": false, "n": 31 }, "param": "True-False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004155829999916705, "max": 0.0014971849999909637, "mean": 0.0005144389983598676, "stddev": 0.00012006889660948242, "rounds": 1829, "median": 0.00045067599999981667, "iqr": 0.00011892400000590442, "q1": 0.0004417722499958643, "q3": 0.0005606962500017687, "iqr_outliers": 109, "stddev_outliers": 270, "outliers": "270;109", "ld15iqr": 0.0004155829999916705, "hd15iqr": 0.0007393000000064376, "ops": 1943.8650708600942, "total": 0.9409089280001979, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-100]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-100]", "params": { "numba": true, "log": false, "n": 100 }, "param": "True-False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004419530000063787, "max": 0.0011699809999896615, "mean": 0.000541588804844375, "stddev": 0.00012835751210447753, "rounds": 1445, "median": 0.00047369000000685446, "iqr": 0.0001397294999954113, "q1": 0.00045465125000276885, "q3": 0.0005943807499981801, "iqr_outliers": 78, "stddev_outliers": 229, "outliers": "229;78", "ld15iqr": 0.0004419530000063787, "hd15iqr": 0.0008043440000022883, "ops": 1846.4192595106335, "total": 0.782595823000122, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-316]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-316]", "params": { "numba": true, "log": false, "n": 316 }, "param": "True-False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0005664549999977453, "max": 0.0013976510000048847, "mean": 0.0006828348768269093, "stddev": 0.0001516300455717845, "rounds": 1437, "median": 0.0006034110000001647, "iqr": 0.0001802785000037943, "q1": 0.000572579999996492, "q3": 0.0007528585000002863, "iqr_outliers": 62, "stddev_outliers": 223, "outliers": "223;62", "ld15iqr": 0.0005664549999977453, "hd15iqr": 0.001024354000008998, "ops": 1464.4828990676883, "total": 0.9812337180002686, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-1000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-1000]", "params": { "numba": true, "log": false, "n": 1000 }, "param": "True-False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007363069999968275, "max": 0.0021546970000088095, "mean": 0.0009467173763704371, "stddev": 0.0002562169552203185, "rounds": 821, "median": 0.0008324180000016668, "iqr": 0.00023939500000125236, "q1": 0.0007829792500011479, "q3": 0.0010223742500024002, "iqr_outliers": 64, "stddev_outliers": 107, "outliers": "107;64", "ld15iqr": 0.0007363069999968275, "hd15iqr": 0.0013873550000056412, "ops": 1056.2814467754251, "total": 0.7772549660001289, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-3162]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-3162]", "params": { "numba": true, "log": false, "n": 3162 }, "param": "True-False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001129839000000743, "max": 0.0024871709999985114, "mean": 0.0014112488782049412, "stddev": 0.00025772909993452935, "rounds": 468, "median": 0.0013277479999942443, "iqr": 0.00030073650000161933, "q1": 0.0012109054999953628, "q3": 0.0015116419999969821, "iqr_outliers": 27, "stddev_outliers": 88, "outliers": "88;27", "ld15iqr": 0.001129839000000743, "hd15iqr": 0.0019648090000004004, "ops": 708.5922373040004, "total": 0.6604644749999125, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-10000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-10000]", "params": { "numba": true, "log": false, "n": 10000 }, "param": "True-False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0028462549999943576, "max": 0.005148325999996928, "mean": 0.003433433589905115, "stddev": 0.0004043515901989944, "rounds": 317, "median": 0.0033321929999914346, "iqr": 0.0006182132500072157, "q1": 0.0031049022499907153, "q3": 0.003723115499997931, "iqr_outliers": 2, "stddev_outliers": 91, "outliers": "91;2", "ld15iqr": 0.0028462549999943576, "hd15iqr": 0.004794410000002358, "ops": 291.2536310415824, "total": 1.0883984479999214, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-31622]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-31622]", "params": { "numba": true, "log": false, "n": 31622 }, "param": "True-False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.01161169799999584, "max": 0.014282819999991148, "mean": 0.013063198207316943, "stddev": 0.0006028859771067187, "rounds": 82, "median": 0.013191876000000491, "iqr": 0.0005937240000122301, "q1": 0.012847469999996974, "q3": 0.013441194000009205, "iqr_outliers": 7, "stddev_outliers": 22, "outliers": "22;7", "ld15iqr": 0.011996899999999755, "hd15iqr": 0.014282819999991148, "ops": 76.55093217829928, "total": 1.0711822529999893, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-100000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-100000]", "params": { "numba": true, "log": false, "n": 100000 }, "param": "True-False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.03272018700000956, "max": 0.03617866599999786, "mean": 0.03391822135483881, "stddev": 0.0007924347345359764, "rounds": 31, "median": 0.03377913299999591, "iqr": 0.0007900052500069421, "q1": 0.03340289824999587, "q3": 0.034192903500002814, "iqr_outliers": 2, "stddev_outliers": 7, "outliers": "7;2", "ld15iqr": 0.03272018700000956, "hd15iqr": 0.03596168900000407, "ops": 29.48267804312029, "total": 1.051464862000003, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-False-316227]", "fullname": "bench/test_cost.py::test_minuit_custom[True-False-316227]", "params": { "numba": true, "log": false, "n": 316227 }, "param": "True-False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.11665477299999338, "max": 0.1410759789999929, "mean": 0.12520272274999478, "stddev": 0.00810219504828115, "rounds": 8, "median": 0.12357879749998801, "iqr": 0.010663498500001367, "q1": 0.11885160949999829, "q3": 0.12951510799999966, "iqr_outliers": 0, "stddev_outliers": 3, "outliers": "3;0", "ld15iqr": 0.11665477299999338, "hd15iqr": 0.1410759789999929, "ops": 7.987046751345843, "total": 1.0016217819999582, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-10]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-10]", "params": { "numba": true, "log": true, "n": 10 }, "param": "True-True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.000514675000005127, "max": 0.001299927000019352, "mean": 0.0006025002745481143, "stddev": 0.0001336977721421544, "rounds": 1548, "median": 0.000543470499991372, "iqr": 0.00010868399998287259, "q1": 0.0005201235000100723, "q3": 0.0006288074999929449, "iqr_outliers": 153, "stddev_outliers": 211, "outliers": "211;153", "ld15iqr": 0.000514675000005127, "hd15iqr": 0.0007927520000237109, "ops": 1659.7502810268716, "total": 0.9326704250004809, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-31]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-31]", "params": { "numba": true, "log": true, "n": 31 }, "param": "True-True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0003904719999923145, "max": 0.0009447790000081113, "mean": 0.00044771645565514363, "stddev": 9.136295565787653e-05, "rounds": 1556, "median": 0.0004084115000040356, "iqr": 6.77675000133604e-05, "q1": 0.0003944184999937761, "q3": 0.0004621860000071365, "iqr_outliers": 168, "stddev_outliers": 214, "outliers": "214;168", "ld15iqr": 0.0003904719999923145, "hd15iqr": 0.0005640329999891946, "ops": 2233.556500702436, "total": 0.6966468049994035, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-100]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-100]", "params": { "numba": true, "log": true, "n": 100 }, "param": "True-True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00039467700000273, "max": 0.0010728569999969295, "mean": 0.0004754076685305402, "stddev": 0.00010500805596300418, "rounds": 1967, "median": 0.0004204650000190213, "iqr": 0.00010018425001590003, "q1": 0.0004143244999923468, "q3": 0.0005145087500082468, "iqr_outliers": 145, "stddev_outliers": 320, "outliers": "320;145", "ld15iqr": 0.00039467700000273, "hd15iqr": 0.0006664209999769355, "ops": 2103.457866152952, "total": 0.9351268839995726, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-316]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-316]", "params": { "numba": true, "log": true, "n": 316 }, "param": "True-True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004328759999907561, "max": 0.0010588549999965835, "mean": 0.0005392366092147661, "stddev": 0.00011845867843780345, "rounds": 1172, "median": 0.00047436049999305396, "iqr": 0.0001410179999936645, "q1": 0.00045806500000367123, "q3": 0.0005990829999973357, "iqr_outliers": 47, "stddev_outliers": 191, "outliers": "191;47", "ld15iqr": 0.0004328759999907561, "hd15iqr": 0.00081333899998981, "ops": 1854.4734962564867, "total": 0.6319853059997058, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-1000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-1000]", "params": { "numba": true, "log": true, "n": 1000 }, "param": "True-True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00043979399998761437, "max": 0.0013313549999907082, "mean": 0.0005350957644579634, "stddev": 0.00013075402531963296, "rounds": 1660, "median": 0.00047016950000511315, "iqr": 0.00013194699998564374, "q1": 0.0004477095000083864, "q3": 0.0005796564999940301, "iqr_outliers": 105, "stddev_outliers": 242, "outliers": "242;105", "ld15iqr": 0.00043979399998761437, "hd15iqr": 0.0007777449999935016, "ops": 1868.8243608374873, "total": 0.8882589690002192, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-3162]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-3162]", "params": { "numba": true, "log": true, "n": 3162 }, "param": "True-True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00046590800002377364, "max": 0.0010717620000093575, "mean": 0.0005515500011639458, "stddev": 0.00011455680487290001, "rounds": 1719, "median": 0.0004965059999904042, "iqr": 0.00012479274998611345, "q1": 0.00047282225000344624, "q3": 0.0005976149999895597, "iqr_outliers": 94, "stddev_outliers": 270, "outliers": "270;94", "ld15iqr": 0.00046590800002377364, "hd15iqr": 0.000787972000011905, "ops": 1813.0722471030408, "total": 0.9481144520008229, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-10000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-10000]", "params": { "numba": true, "log": true, "n": 10000 }, "param": "True-True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007520370000122512, "max": 0.0018421880000119017, "mean": 0.0009149970662489864, "stddev": 0.0001907750093467647, "rounds": 1117, "median": 0.000823462999989033, "iqr": 0.0002045154999876786, "q1": 0.0007893734999910862, "q3": 0.0009938889999787648, "iqr_outliers": 71, "stddev_outliers": 159, "outliers": "159;71", "ld15iqr": 0.0007520370000122512, "hd15iqr": 0.001302224999989221, "ops": 1092.8996790115202, "total": 1.0220517230001178, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-31622]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-31622]", "params": { "numba": true, "log": true, "n": 31622 }, "param": "True-True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0021368330000086644, "max": 0.003999949000018432, "mean": 0.0026084402773717845, "stddev": 0.00037383043636695523, "rounds": 411, "median": 0.0025082939999947484, "iqr": 0.000464154500001257, "q1": 0.0023317954999839685, "q3": 0.0027959499999852255, "iqr_outliers": 11, "stddev_outliers": 128, "outliers": "128;11", "ld15iqr": 0.0021368330000086644, "hd15iqr": 0.0035078079999948386, "ops": 383.37086291566595, "total": 1.0720689539998034, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-100000]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-100000]", "params": { "numba": true, "log": true, "n": 100000 }, "param": "True-True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004990885000012213, "max": 0.007896475999984887, "mean": 0.005972209641024269, "stddev": 0.0005900366215827988, "rounds": 156, "median": 0.005957894000005126, "iqr": 0.0007728875000054813, "q1": 0.005514118499988285, "q3": 0.006287005999993767, "iqr_outliers": 3, "stddev_outliers": 54, "outliers": "54;3", "ld15iqr": 0.004990885000012213, "hd15iqr": 0.007816135000012991, "ops": 167.44221320209618, "total": 0.9316647039997861, "iterations": 1 } }, { "group": null, "name": "test_minuit_custom[True-True-316227]", "fullname": "bench/test_cost.py::test_minuit_custom[True-True-316227]", "params": { "numba": true, "log": true, "n": 316227 }, "param": "True-True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.01949758699998938, "max": 0.027939285999991625, "mean": 0.021289639764706506, "stddev": 0.0017427119903350153, "rounds": 51, "median": 0.020739848999994592, "iqr": 0.0015701012499675926, "q1": 0.020108637500015902, "q3": 0.021678738749983495, "iqr_outliers": 5, "stddev_outliers": 9, "outliers": "9;5", "ld15iqr": 0.01949758699998938, "hd15iqr": 0.02410944599998288, "ops": 46.971203414055786, "total": 1.0857716280000318, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[10]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[10]", "params": { "n": 10 }, "param": "10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006447549999961666, "max": 0.0015930299999808994, "mean": 0.0007842420807876833, "stddev": 0.0001565645130149, "rounds": 1015, "median": 0.0006999699999994391, "iqr": 0.0001715167499725112, "q1": 0.0006756515000105878, "q3": 0.000847168249983099, "iqr_outliers": 61, "stddev_outliers": 147, "outliers": "147;61", "ld15iqr": 0.0006447549999961666, "hd15iqr": 0.0011045630000126039, "ops": 1275.1164780594431, "total": 0.7960057119994985, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[31]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[31]", "params": { "n": 31 }, "param": "31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004511540000180503, "max": 0.001408961999999292, "mean": 0.0005259686660196399, "stddev": 0.00010568538228575217, "rounds": 1545, "median": 0.00047737200000597113, "iqr": 9.500899999892454e-05, "q1": 0.0004575827500090668, "q3": 0.0005525917500079913, "iqr_outliers": 135, "stddev_outliers": 227, "outliers": "227;135", "ld15iqr": 0.0004511540000180503, "hd15iqr": 0.0006951860000015131, "ops": 1901.2539426876422, "total": 0.8126215890003436, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[100]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[100]", "params": { "n": 100 }, "param": "100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00045346900000708956, "max": 0.0013854369999819482, "mean": 0.000554866174465344, "stddev": 0.00013699137067027308, "rounds": 1731, "median": 0.00048286000000530294, "iqr": 0.00011051450000110208, "q1": 0.0004782202499953314, "q3": 0.0005887347499964335, "iqr_outliers": 179, "stddev_outliers": 264, "outliers": "264;179", "ld15iqr": 0.00045346900000708956, "hd15iqr": 0.0007564699999988989, "ops": 1802.2363698121922, "total": 0.9604733479995105, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[316]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[316]", "params": { "n": 316 }, "param": "316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004975850000050741, "max": 0.0015226000000154727, "mean": 0.0005956076732426517, "stddev": 0.00014400037339921823, "rounds": 1622, "median": 0.0005278789999891842, "iqr": 0.00012384700002598947, "q1": 0.0005052779999914492, "q3": 0.0006291250000174387, "iqr_outliers": 144, "stddev_outliers": 219, "outliers": "219;144", "ld15iqr": 0.0004975850000050741, "hd15iqr": 0.0008150140000111605, "ops": 1678.9575502876341, "total": 0.966075645999581, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[1000]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[1000]", "params": { "n": 1000 }, "param": "1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004520509999963451, "max": 0.0012797220000209109, "mean": 0.0005659766371160534, "stddev": 0.00014320245033526549, "rounds": 1692, "median": 0.0004979195000061054, "iqr": 0.000115224500021327, "q1": 0.00047633049999262767, "q3": 0.0005915550000139547, "iqr_outliers": 203, "stddev_outliers": 252, "outliers": "252;203", "ld15iqr": 0.0004520509999963451, "hd15iqr": 0.0007654270000045926, "ops": 1766.8573831872677, "total": 0.9576324700003624, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[3162]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[3162]", "params": { "n": 3162 }, "param": "3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00040641699999355296, "max": 0.0014257770000085657, "mean": 0.000509190936292067, "stddev": 0.00014181213943027505, "rounds": 1915, "median": 0.00043356099999414255, "iqr": 0.00011474950000689432, "q1": 0.00042845974999039527, "q3": 0.0005432092499972896, "iqr_outliers": 186, "stddev_outliers": 275, "outliers": "275;186", "ld15iqr": 0.00040641699999355296, "hd15iqr": 0.0007153869999854123, "ops": 1963.8998433122338, "total": 0.9751006429993083, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[10000]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[10000]", "params": { "n": 10000 }, "param": "10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00043939399998293993, "max": 0.0011787109999943368, "mean": 0.000532945294524735, "stddev": 0.00011164931986661854, "rounds": 1735, "median": 0.00048139100002231316, "iqr": 0.00010011325001357818, "q1": 0.00046285599998441285, "q3": 0.000562969249997991, "iqr_outliers": 167, "stddev_outliers": 290, "outliers": "290;167", "ld15iqr": 0.00043939399998293993, "hd15iqr": 0.0007132650000016838, "ops": 1876.3651922131537, "total": 0.924660086000415, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[31622]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[31622]", "params": { "n": 31622 }, "param": "31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.000692094999976689, "max": 0.0016611030000035498, "mean": 0.0008298776604989758, "stddev": 0.0001619579016758851, "rounds": 1081, "median": 0.0007468939999739632, "iqr": 0.00018415425002871189, "q1": 0.0007206242499862014, "q3": 0.0009047785000149133, "iqr_outliers": 50, "stddev_outliers": 177, "outliers": "177;50", "ld15iqr": 0.000692094999976689, "hd15iqr": 0.0011827239999888661, "ops": 1204.996890022001, "total": 0.8970977509993929, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[100000]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[100000]", "params": { "n": 100000 }, "param": "100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009025119999819253, "max": 0.0018434059999776764, "mean": 0.001093183470524098, "stddev": 0.00018948897883235276, "rounds": 916, "median": 0.0010175925000055486, "iqr": 0.00024105599999302285, "q1": 0.0009530935000015006, "q3": 0.0011941494999945235, "iqr_outliers": 29, "stddev_outliers": 141, "outliers": "141;29", "ld15iqr": 0.0009025119999819253, "hd15iqr": 0.0015616629999897214, "ops": 914.7595321035878, "total": 1.0013560590000736, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_sum_logpdf_parallel_fastmath[316227]", "fullname": "bench/test_cost.py::test_minuit_numba_sum_logpdf_parallel_fastmath[316227]", "params": { "n": 316227 }, "param": "316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0022540200000094046, "max": 0.004824810000002344, "mean": 0.0028190955069646068, "stddev": 0.00044183862244312174, "rounds": 359, "median": 0.0027121580000084577, "iqr": 0.0005951160000137179, "q1": 0.0024769562499855624, "q3": 0.0030720722499992803, "iqr_outliers": 10, "stddev_outliers": 96, "outliers": "96;10", "ld15iqr": 0.0022540200000094046, "hd15iqr": 0.00398796899997933, "ops": 354.72370394315794, "total": 1.012055287000294, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[10]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[10]", "params": { "n": 10 }, "param": "10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006169539999802964, "max": 0.0013400910000029853, "mean": 0.0007354356790245874, "stddev": 0.00013036012440391771, "rounds": 1025, "median": 0.0006735409999976127, "iqr": 0.00014174899999375157, "q1": 0.0006452930000051538, "q3": 0.0007870419999989053, "iqr_outliers": 60, "stddev_outliers": 158, "outliers": "158;60", "ld15iqr": 0.0006169539999802964, "hd15iqr": 0.0010006649999922956, "ops": 1359.7382184752116, "total": 0.7538215710002021, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[31]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[31]", "params": { "n": 31 }, "param": "31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00045015799997827344, "max": 0.0012866180000230543, "mean": 0.0005365436358944543, "stddev": 0.00012836141443097246, "rounds": 1744, "median": 0.00047820700000045235, "iqr": 0.00010994799998798044, "q1": 0.0004574595000121917, "q3": 0.0005674075000001721, "iqr_outliers": 136, "stddev_outliers": 221, "outliers": "221;136", "ld15iqr": 0.00045015799997827344, "hd15iqr": 0.0007330510000258528, "ops": 1863.7813089198849, "total": 0.9357321009999282, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[100]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[100]", "params": { "n": 100 }, "param": "100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00046435999999516753, "max": 0.0014027260000091246, "mean": 0.0005565170250606008, "stddev": 0.00013389062863757158, "rounds": 1237, "median": 0.0004945350000014059, "iqr": 0.00011656950001537325, "q1": 0.0004753962499890463, "q3": 0.0005919657500044195, "iqr_outliers": 84, "stddev_outliers": 146, "outliers": "146;84", "ld15iqr": 0.00046435999999516753, "hd15iqr": 0.0007677450000187491, "ops": 1796.890220727941, "total": 0.6884115599999632, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[316]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[316]", "params": { "n": 316 }, "param": "316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004767350000065562, "max": 0.0010502730000041538, "mean": 0.0005557864736837383, "stddev": 9.341290116534625e-05, "rounds": 1615, "median": 0.0005062649999842961, "iqr": 6.809850000877304e-05, "q1": 0.000500083499993309, "q3": 0.0005681820000020821, "iqr_outliers": 217, "stddev_outliers": 259, "outliers": "259;217", "ld15iqr": 0.0004767350000065562, "hd15iqr": 0.0006703820000097949, "ops": 1799.2521361162785, "total": 0.8975951549992374, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[1000]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[1000]", "params": { "n": 1000 }, "param": "1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004586219999964669, "max": 0.001172613999983696, "mean": 0.0005524427758412109, "stddev": 0.00011277084009062057, "rounds": 1664, "median": 0.0005010604999853285, "iqr": 9.5973499981028e-05, "q1": 0.0004800764999970397, "q3": 0.0005760499999780677, "iqr_outliers": 179, "stddev_outliers": 269, "outliers": "269;179", "ld15iqr": 0.0004586219999964669, "hd15iqr": 0.0007208290000164652, "ops": 1810.1422332426894, "total": 0.919264778999775, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[3162]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[3162]", "params": { "n": 3162 }, "param": "3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00038899599999808743, "max": 0.001106687999993028, "mean": 0.0004695797848955093, "stddev": 0.00010632279095631717, "rounds": 1920, "median": 0.000415307500006179, "iqr": 7.069250000313332e-05, "q1": 0.00040906750000146985, "q3": 0.00047976000000460317, "iqr_outliers": 260, "stddev_outliers": 275, "outliers": "275;260", "ld15iqr": 0.00038899599999808743, "hd15iqr": 0.0005861009999819089, "ops": 2129.563563351688, "total": 0.9015931869993778, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[10000]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[10000]", "params": { "n": 10000 }, "param": "10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004541559999893252, "max": 0.001393481999997448, "mean": 0.000576431029412094, "stddev": 0.00016425272729781457, "rounds": 816, "median": 0.00048226399999862224, "iqr": 0.00015625100000704606, "q1": 0.00047502050000503004, "q3": 0.0006312715000120761, "iqr_outliers": 66, "stddev_outliers": 127, "outliers": "127;66", "ld15iqr": 0.0004541559999893252, "hd15iqr": 0.0008694260000083887, "ops": 1734.812924661441, "total": 0.4703677200002687, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[31622]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[31622]", "params": { "n": 31622 }, "param": "31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006344500000068365, "max": 0.0016135670000210212, "mean": 0.0007772023883264803, "stddev": 0.00017813848871515344, "rounds": 1285, "median": 0.0006859529999871938, "iqr": 0.0001660530000222593, "q1": 0.0006688909999894577, "q3": 0.000834944000011717, "iqr_outliers": 110, "stddev_outliers": 185, "outliers": "185;110", "ld15iqr": 0.0006344500000068365, "hd15iqr": 0.0010847110000042903, "ops": 1286.6661438769652, "total": 0.9987050689995272, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[100000]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[100000]", "params": { "n": 100000 }, "param": "100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008010539999929733, "max": 0.0022210260000008475, "mean": 0.0010672760456803586, "stddev": 0.0002877242619050517, "rounds": 1007, "median": 0.0009236479999970015, "iqr": 0.0003022327500019628, "q1": 0.00088111500000565, "q3": 0.0011833477500076128, "iqr_outliers": 74, "stddev_outliers": 160, "outliers": "160;74", "ld15iqr": 0.0008010539999929733, "hd15iqr": 0.0016387120000160849, "ops": 936.9647187785687, "total": 1.074746978000121, "iterations": 1 } }, { "group": null, "name": "test_minuit_numba_handtuned_parallel_fastmath[316227]", "fullname": "bench/test_cost.py::test_minuit_numba_handtuned_parallel_fastmath[316227]", "params": { "n": 316227 }, "param": "316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0018499210000015864, "max": 0.004200620999995408, "mean": 0.0022775608804356355, "stddev": 0.00037805549420293413, "rounds": 460, "median": 0.002145488500005399, "iqr": 0.0002891255000037063, "q1": 0.002060043000000178, "q3": 0.0023491685000038842, "iqr_outliers": 36, "stddev_outliers": 55, "outliers": "55;36", "ld15iqr": 0.0018499210000015864, "hd15iqr": 0.0027852329999973335, "ops": 439.06619954269985, "total": 1.0476780050003924, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[10]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[10]", "params": { "n": 10 }, "param": "10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00028420900000014626, "max": 0.0008445459999961713, "mean": 0.0003479935256570441, "stddev": 8.193483762795691e-05, "rounds": 2397, "median": 0.00031339099999172504, "iqr": 4.8590500014711324e-05, "q1": 0.0002999247500028446, "q3": 0.0003485152500175559, "iqr_outliers": 348, "stddev_outliers": 321, "outliers": "321;348", "ld15iqr": 0.00028420900000014626, "hd15iqr": 0.00042177200000992343, "ops": 2873.616680402048, "total": 0.8341404809999347, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[31]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[31]", "params": { "n": 31 }, "param": "31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0002551640000092448, "max": 0.0010490439999841783, "mean": 0.0003081439760683613, "stddev": 7.846546720246586e-05, "rounds": 2340, "median": 0.0002789315000057968, "iqr": 3.9101999988133684e-05, "q1": 0.0002670349999931432, "q3": 0.00030613699998127686, "iqr_outliers": 340, "stddev_outliers": 287, "outliers": "287;340", "ld15iqr": 0.0002551640000092448, "hd15iqr": 0.0003652430000045115, "ops": 3245.23624559888, "total": 0.7210569039999655, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[100]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[100]", "params": { "n": 100 }, "param": "100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.000267385000000786, "max": 0.0008799059999944348, "mean": 0.0003238323639140989, "stddev": 8.990359949664036e-05, "rounds": 2616, "median": 0.0002826215000055754, "iqr": 6.883249997713392e-05, "q1": 0.0002701845000103731, "q3": 0.000339016999987507, "iqr_outliers": 271, "stddev_outliers": 367, "outliers": "367;271", "ld15iqr": 0.000267385000000786, "hd15iqr": 0.00044231399999716814, "ops": 3088.017478899249, "total": 0.8471454639992828, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[316]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[316]", "params": { "n": 316 }, "param": "316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0002733890000001793, "max": 0.0008168150000074093, "mean": 0.0003298011725664967, "stddev": 7.497849278677978e-05, "rounds": 2486, "median": 0.00029053299999759474, "iqr": 5.076999997299936e-05, "q1": 0.0002866750000123375, "q3": 0.00033744499998533684, "iqr_outliers": 324, "stddev_outliers": 355, "outliers": "355;324", "ld15iqr": 0.0002733890000001793, "hd15iqr": 0.0004142679999858956, "ops": 3032.12991093406, "total": 0.8198857150003107, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[1000]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[1000]", "params": { "n": 1000 }, "param": "1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00030172299997843766, "max": 0.0008848319999970045, "mean": 0.0003798759886840202, "stddev": 9.481835510859718e-05, "rounds": 2386, "median": 0.00032567249999715386, "iqr": 0.00010039599999345228, "q1": 0.0003187549999950079, "q3": 0.00041915099998846017, "iqr_outliers": 154, "stddev_outliers": 376, "outliers": "376;154", "ld15iqr": 0.00030172299997843766, "hd15iqr": 0.000570160000023634, "ops": 2632.43803185412, "total": 0.9063841090000722, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[3162]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[3162]", "params": { "n": 3162 }, "param": "3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00035379999999918255, "max": 0.0008948260000067876, "mean": 0.0004093662588432514, "stddev": 8.74659813714349e-05, "rounds": 1781, "median": 0.0003644489999885536, "iqr": 6.840875002467328e-05, "q1": 0.00035715699998917216, "q3": 0.00042556575001384545, "iqr_outliers": 229, "stddev_outliers": 289, "outliers": "289;229", "ld15iqr": 0.00035379999999918255, "hd15iqr": 0.0005282380000153353, "ops": 2442.8002513585407, "total": 0.7290813069998308, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[10000]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[10000]", "params": { "n": 10000 }, "param": "10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006233320000035292, "max": 0.0016100530000073832, "mean": 0.0007169718373211462, "stddev": 0.00014036103764686689, "rounds": 1254, "median": 0.0006401134999975966, "iqr": 0.00014293599997472484, "q1": 0.0006274890000099731, "q3": 0.0007704249999846979, "iqr_outliers": 97, "stddev_outliers": 214, "outliers": "214;97", "ld15iqr": 0.0006233320000035292, "hd15iqr": 0.000985245000009627, "ops": 1394.754923340287, "total": 0.8990826840007173, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[31622]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[31622]", "params": { "n": 31622 }, "param": "31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0017984259999934693, "max": 0.0031719259999931637, "mean": 0.0022157871553666916, "stddev": 0.00030705215548166345, "rounds": 354, "median": 0.0021333315000049424, "iqr": 0.0004940940000039973, "q1": 0.0019429609999974673, "q3": 0.0024370550000014646, "iqr_outliers": 0, "stddev_outliers": 121, "outliers": "121;0", "ld15iqr": 0.0017984259999934693, "hd15iqr": 0.0031719259999931637, "ops": 451.30688549122385, "total": 0.7843886529998088, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[100000]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[100000]", "params": { "n": 100000 }, "param": "100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004520018999983222, "max": 0.008775570000011612, "mean": 0.005380861803278567, "stddev": 0.0006082198985246072, "rounds": 183, "median": 0.005286898999997902, "iqr": 0.0005016057499744875, "q1": 0.00504591650001629, "q3": 0.005547522249990777, "iqr_outliers": 10, "stddev_outliers": 30, "outliers": "30;10", "ld15iqr": 0.004520018999983222, "hd15iqr": 0.006321036999992202, "ops": 185.84383627743398, "total": 0.9846977099999776, "iterations": 1 } }, { "group": null, "name": "test_minuit_cfunc_sum_logpdf[316227]", "fullname": "bench/test_cost.py::test_minuit_cfunc_sum_logpdf[316227]", "params": { "n": 316227 }, "param": "316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.01902835599997843, "max": 0.023534320999999636, "mean": 0.02005255944680737, "stddev": 0.0008857244094260912, "rounds": 47, "median": 0.019740104000021574, "iqr": 0.0009997244999908617, "q1": 0.01945873849999913, "q3": 0.02045846299998999, "iqr_outliers": 2, "stddev_outliers": 10, "outliers": "10;2", "ld15iqr": 0.01902835599997843, "hd15iqr": 0.02198451499998555, "ops": 49.86894578982102, "total": 0.9424702939999463, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-10]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-10]", "params": { "log": false, "n": 10 }, "param": "False-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009500509999895712, "max": 0.0021751660000006723, "mean": 0.001163103485426069, "stddev": 0.0002163732143692876, "rounds": 892, "median": 0.001063496999975655, "iqr": 0.0002513774999783891, "q1": 0.0009969680000097014, "q3": 0.0012483454999880905, "iqr_outliers": 43, "stddev_outliers": 151, "outliers": "151;43", "ld15iqr": 0.0009500509999895712, "hd15iqr": 0.0016263640000033774, "ops": 859.768724391432, "total": 1.0374883090000537, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-31]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-31]", "params": { "log": false, "n": 31 }, "param": "False-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006618170000081136, "max": 0.0013512219999824993, "mean": 0.0007760414820512503, "stddev": 0.00012780869805370098, "rounds": 1170, "median": 0.0007192424999971081, "iqr": 0.00013883399998348978, "q1": 0.0006903830000055677, "q3": 0.0008292169999890575, "iqr_outliers": 64, "stddev_outliers": 184, "outliers": "184;64", "ld15iqr": 0.0006618170000081136, "hd15iqr": 0.0010405230000003485, "ops": 1288.5909105744934, "total": 0.9079685339999628, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-100]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-100]", "params": { "log": false, "n": 100 }, "param": "False-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006952620000220122, "max": 0.0014686420000202816, "mean": 0.0008397515719299828, "stddev": 0.00015518254979093076, "rounds": 855, "median": 0.0007648550000283194, "iqr": 0.00018832924998690714, "q1": 0.0007313414999998713, "q3": 0.0009196707499867784, "iqr_outliers": 30, "stddev_outliers": 160, "outliers": "160;30", "ld15iqr": 0.0006952620000220122, "hd15iqr": 0.001216068000019277, "ops": 1190.82837523212, "total": 0.7179875940001352, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-316]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-316]", "params": { "log": false, "n": 316 }, "param": "False-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008643740000024991, "max": 0.001995728999986568, "mean": 0.0010439097798508438, "stddev": 0.00020806135760371145, "rounds": 804, "median": 0.0009451905000048555, "iqr": 0.00019835750001107044, "q1": 0.0009114770000024919, "q3": 0.0011098345000135623, "iqr_outliers": 67, "stddev_outliers": 125, "outliers": "125;67", "ld15iqr": 0.0008643740000024991, "hd15iqr": 0.0014084320000051775, "ops": 957.9371889234358, "total": 0.8393034630000784, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-1000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-1000]", "params": { "log": false, "n": 1000 }, "param": "False-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0010225190000028306, "max": 0.0026591009999776816, "mean": 0.0012434683702419432, "stddev": 0.0002772054801049433, "rounds": 867, "median": 0.0011282440000002225, "iqr": 0.00020816350001950923, "q1": 0.0010788477500014437, "q3": 0.001287011250020953, "iqr_outliers": 97, "stddev_outliers": 111, "outliers": "111;97", "ld15iqr": 0.0010225190000028306, "hd15iqr": 0.0016033560000039415, "ops": 804.2022008211022, "total": 1.0780870769997648, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-3162]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-3162]", "params": { "log": false, "n": 3162 }, "param": "False-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001305465999990929, "max": 0.0028778389999786214, "mean": 0.0015743717098670453, "stddev": 0.00031583569333025095, "rounds": 679, "median": 0.0014391480000028878, "iqr": 0.000270756250003501, "q1": 0.0013738869999997405, "q3": 0.0016446432500032415, "iqr_outliers": 71, "stddev_outliers": 96, "outliers": "96;71", "ld15iqr": 0.001305465999990929, "hd15iqr": 0.0020530059999828154, "ops": 635.1740149627367, "total": 1.0689983909997238, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-10000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-10000]", "params": { "log": false, "n": 10000 }, "param": "False-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.003588719000021001, "max": 0.006967398000000458, "mean": 0.004346541895197051, "stddev": 0.0006198113371817329, "rounds": 229, "median": 0.004060890000005202, "iqr": 0.0009249262500006239, "q1": 0.003895881749997443, "q3": 0.004820807999998067, "iqr_outliers": 4, "stddev_outliers": 47, "outliers": "47;4", "ld15iqr": 0.003588719000021001, "hd15iqr": 0.006245973999995158, "ops": 230.06795381519382, "total": 0.9953580940001245, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-31622]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-31622]", "params": { "log": false, "n": 31622 }, "param": "False-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.012513622000000169, "max": 0.01677481799998759, "mean": 0.014605974288135655, "stddev": 0.0009040166266761113, "rounds": 59, "median": 0.014678333000006205, "iqr": 0.0013619759999912162, "q1": 0.01391518524999924, "q3": 0.015277161249990456, "iqr_outliers": 0, "stddev_outliers": 19, "outliers": "19;0", "ld15iqr": 0.012513622000000169, "hd15iqr": 0.01677481799998759, "ops": 68.46513490115439, "total": 0.8617524830000036, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-100000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-100000]", "params": { "log": false, "n": 100000 }, "param": "False-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.032298643999979504, "max": 0.037699446000004855, "mean": 0.03393516844827728, "stddev": 0.0009654127119240813, "rounds": 29, "median": 0.03381888599997751, "iqr": 0.0006604002500054662, "q1": 0.03351382150000859, "q3": 0.034174221750014055, "iqr_outliers": 2, "stddev_outliers": 6, "outliers": "6;2", "ld15iqr": 0.03256087400001206, "hd15iqr": 0.037699446000004855, "ops": 29.46795450637479, "total": 0.984119885000041, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[False-316227]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[False-316227]", "params": { "log": false, "n": 316227 }, "param": "False-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.12719934200001148, "max": 0.13136711900000364, "mean": 0.12872532262500158, "stddev": 0.0013783641940866545, "rounds": 8, "median": 0.12850404099999935, "iqr": 0.0015317520000053264, "q1": 0.12779113349999704, "q3": 0.12932288550000237, "iqr_outliers": 0, "stddev_outliers": 3, "outliers": "3;0", "ld15iqr": 0.12719934200001148, "hd15iqr": 0.13136711900000364, "ops": 7.768479267386787, "total": 1.0298025810000127, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-10]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-10]", "params": { "log": true, "n": 10 }, "param": "True-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0013268200000027264, "max": 0.0027703669999823433, "mean": 0.0015558359545456246, "stddev": 0.0002398404314984047, "rounds": 550, "median": 0.0014608724999902734, "iqr": 0.0002616170000067086, "q1": 0.0013864539999985936, "q3": 0.0016480710000053023, "iqr_outliers": 32, "stddev_outliers": 81, "outliers": "81;32", "ld15iqr": 0.0013268200000027264, "hd15iqr": 0.002041799000011224, "ops": 642.7412845668847, "total": 0.8557097750000935, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-31]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-31]", "params": { "log": true, "n": 31 }, "param": "True-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008524710000017421, "max": 0.0023565159999918706, "mean": 0.001070813328124783, "stddev": 0.0002734924517447499, "rounds": 960, "median": 0.0009472470000133626, "iqr": 0.00023539750000622917, "q1": 0.0009057919999975184, "q3": 0.0011411895000037475, "iqr_outliers": 83, "stddev_outliers": 127, "outliers": "127;83", "ld15iqr": 0.0008524710000017421, "hd15iqr": 0.0014967170000090846, "ops": 933.8695865424164, "total": 1.0279807949997917, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-100]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-100]", "params": { "log": true, "n": 100 }, "param": "True-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008614839999836477, "max": 0.002530946999996786, "mean": 0.0010834494570856042, "stddev": 0.00024397184166669071, "rounds": 1002, "median": 0.0009715845000073386, "iqr": 0.00025357599997732905, "q1": 0.0009158640000066498, "q3": 0.0011694399999839789, "iqr_outliers": 62, "stddev_outliers": 141, "outliers": "141;62", "ld15iqr": 0.0008614839999836477, "hd15iqr": 0.0015542489999802456, "ops": 922.9779879994801, "total": 1.0856163559997754, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-316]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-316]", "params": { "log": true, "n": 316 }, "param": "True-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009960589999877811, "max": 0.003216543999997157, "mean": 0.001349540059023644, "stddev": 0.00036189012498504935, "rounds": 881, "median": 0.0012199869999847124, "iqr": 0.00043317675000054123, "q1": 0.0010779427499869598, "q3": 0.001511119499987501, "iqr_outliers": 34, "stddev_outliers": 123, "outliers": "123;34", "ld15iqr": 0.0009960589999877811, "hd15iqr": 0.0021940579999863985, "ops": 740.9931949137347, "total": 1.1889447919998304, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-1000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-1000]", "params": { "log": true, "n": 1000 }, "param": "True-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009383240000033766, "max": 0.0024742819999801213, "mean": 0.0012518140994157772, "stddev": 0.0003125229195674502, "rounds": 513, "median": 0.0011416589999839744, "iqr": 0.00033568399999239773, "q1": 0.0010188847500032239, "q3": 0.0013545687499956216, "iqr_outliers": 36, "stddev_outliers": 75, "outliers": "75;36", "ld15iqr": 0.0009383240000033766, "hd15iqr": 0.0018581129999972745, "ops": 798.8406589019096, "total": 0.6421806330002937, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-3162]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-3162]", "params": { "log": true, "n": 3162 }, "param": "True-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007931719999874076, "max": 0.0022585739999954058, "mean": 0.0010533879853709153, "stddev": 0.00027790488354070586, "rounds": 957, "median": 0.0009487769999907414, "iqr": 0.00028883100001309003, "q1": 0.0008526302500015959, "q3": 0.001141461250014686, "iqr_outliers": 68, "stddev_outliers": 130, "outliers": "130;68", "ld15iqr": 0.0007931719999874076, "hd15iqr": 0.0015812840000251072, "ops": 949.3178333981886, "total": 1.008092301999966, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-10000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-10000]", "params": { "log": true, "n": 10000 }, "param": "True-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0011688759999799458, "max": 0.002916024999990441, "mean": 0.001509200726087309, "stddev": 0.0003141009604528609, "rounds": 690, "median": 0.0014224404999936269, "iqr": 0.00037800399999809997, "q1": 0.0012661419999915324, "q3": 0.0016441459999896324, "iqr_outliers": 32, "stddev_outliers": 108, "outliers": "108;32", "ld15iqr": 0.0011688759999799458, "hd15iqr": 0.002214564000013297, "ops": 662.6023846361103, "total": 1.0413485010002432, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-31622]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-31622]", "params": { "log": true, "n": 31622 }, "param": "True-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0024861429999987195, "max": 0.004981973000013795, "mean": 0.0030995408549860473, "stddev": 0.0004135482973252876, "rounds": 331, "median": 0.0030435200000056284, "iqr": 0.0005594307500089712, "q1": 0.0027622864999941044, "q3": 0.0033217172500030756, "iqr_outliers": 4, "stddev_outliers": 110, "outliers": "110;4", "ld15iqr": 0.0024861429999987195, "hd15iqr": 0.004232782000002544, "ops": 322.6284300758157, "total": 1.0259480230003817, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-100000]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-100000]", "params": { "log": true, "n": 100000 }, "param": "True-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004802079000000958, "max": 0.013973354000000882, "mean": 0.006184715731707305, "stddev": 0.00131114337082781, "rounds": 164, "median": 0.005878464999995003, "iqr": 0.001183939500009501, "q1": 0.005392125499994904, "q3": 0.006576065000004405, "iqr_outliers": 8, "stddev_outliers": 16, "outliers": "16;8", "ld15iqr": 0.004802079000000958, "hd15iqr": 0.00848663800002214, "ops": 161.6889188412137, "total": 1.014293379999998, "iterations": 1 } }, { "group": null, "name": "test_minuit_UnbinnedNLL[True-316227]", "fullname": "bench/test_cost.py::test_minuit_UnbinnedNLL[True-316227]", "params": { "log": true, "n": 316227 }, "param": "True-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.02254614800000354, "max": 0.03322082799999748, "mean": 0.025007343810812387, "stddev": 0.002478186561594418, "rounds": 37, "median": 0.024372866999982534, "iqr": 0.0023638517500330636, "q1": 0.023315686249979706, "q3": 0.02567953800001277, "iqr_outliers": 3, "stddev_outliers": 4, "outliers": "4;3", "ld15iqr": 0.02254614800000354, "hd15iqr": 0.030401066000024457, "ops": 39.98825335330622, "total": 0.9252717210000583, "iterations": 1 } }, { "group": null, "name": "test_RooFit[10]", "fullname": "bench/test_cost.py::test_RooFit[10]", "params": { "n": 10 }, "param": "10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006122679999975844, "max": 0.0009010500000101729, "mean": 0.0007050892857145234, "stddev": 0.00010758060558618865, "rounds": 14, "median": 0.0006504324999951905, "iqr": 0.0001380970000184334, "q1": 0.0006222669999829122, "q3": 0.0007603640000013456, "iqr_outliers": 0, "stddev_outliers": 3, "outliers": "3;0", "ld15iqr": 0.0006122679999975844, "hd15iqr": 0.0009010500000101729, "ops": 1418.2600987712071, "total": 0.009871250000003329, "iterations": 1 } }, { "group": null, "name": "test_RooFit[31]", "fullname": "bench/test_cost.py::test_RooFit[31]", "params": { "n": 31 }, "param": "31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0004892839999968146, "max": 0.0015550309999809997, "mean": 0.0005778007936199647, "stddev": 0.00010770752459401756, "rounds": 1536, "median": 0.0005270945000006577, "iqr": 0.00010376050002491866, "q1": 0.0005090164999899116, "q3": 0.0006127770000148303, "iqr_outliers": 121, "stddev_outliers": 230, "outliers": "230;121", "ld15iqr": 0.0004892839999968146, "hd15iqr": 0.0007688059999964025, "ops": 1730.7002881303192, "total": 0.8875020190002658, "iterations": 1 } }, { "group": null, "name": "test_RooFit[100]", "fullname": "bench/test_cost.py::test_RooFit[100]", "params": { "n": 100 }, "param": "100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0006665639999994255, "max": 0.0012955530000056115, "mean": 0.0007882812602365763, "stddev": 0.00012215875083451973, "rounds": 1099, "median": 0.0007301910000023781, "iqr": 0.00015063824998406972, "q1": 0.0007054642500179398, "q3": 0.0008561025000020095, "iqr_outliers": 41, "stddev_outliers": 184, "outliers": "184;41", "ld15iqr": 0.0006665639999994255, "hd15iqr": 0.0010834070000100837, "ops": 1268.5827387294269, "total": 0.8663211049999973, "iterations": 1 } }, { "group": null, "name": "test_RooFit[316]", "fullname": "bench/test_cost.py::test_RooFit[316]", "params": { "n": 316 }, "param": "316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0011175200000081986, "max": 0.00218862200000558, "mean": 0.0012993575508343548, "stddev": 0.00017844516878629842, "rounds": 659, "median": 0.0012324679999835553, "iqr": 0.0001928562499955433, "q1": 0.0011757307499991043, "q3": 0.0013685869999946476, "iqr_outliers": 37, "stddev_outliers": 98, "outliers": "98;37", "ld15iqr": 0.0011175200000081986, "hd15iqr": 0.0016609360000074957, "ops": 769.6111046246442, "total": 0.8562766259998398, "iterations": 1 } }, { "group": null, "name": "test_RooFit[1000]", "fullname": "bench/test_cost.py::test_RooFit[1000]", "params": { "n": 1000 }, "param": "1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0023462180000137778, "max": 0.0036021269999935157, "mean": 0.0027190710953850436, "stddev": 0.0002960786807391795, "rounds": 325, "median": 0.002624744999991435, "iqr": 0.00035847350000750566, "q1": 0.0025032794999972907, "q3": 0.0028617530000047964, "iqr_outliers": 12, "stddev_outliers": 93, "outliers": "93;12", "ld15iqr": 0.0023462180000137778, "hd15iqr": 0.0034125629999834928, "ops": 367.7726565139303, "total": 0.8836981060001392, "iterations": 1 } }, { "group": null, "name": "test_RooFit[3162]", "fullname": "bench/test_cost.py::test_RooFit[3162]", "params": { "n": 3162 }, "param": "3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0070529690000000755, "max": 0.009920332999996617, "mean": 0.008050764816514068, "stddev": 0.0005535654462759453, "rounds": 109, "median": 0.008048930999990489, "iqr": 0.000883497000010891, "q1": 0.007585992499997474, "q3": 0.008469489500008365, "iqr_outliers": 1, "stddev_outliers": 42, "outliers": "42;1", "ld15iqr": 0.0070529690000000755, "hd15iqr": 0.009920332999996617, "ops": 124.21180133703047, "total": 0.8775333650000334, "iterations": 1 } }, { "group": null, "name": "test_RooFit[10000]", "fullname": "bench/test_cost.py::test_RooFit[10000]", "params": { "n": 10000 }, "param": "10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0241574460000038, "max": 0.02698788999998669, "mean": 0.02565058709090677, "stddev": 0.0007058901130612385, "rounds": 33, "median": 0.025619065999990198, "iqr": 0.000895872749978821, "q1": 0.025234184500000367, "q3": 0.02613005724997919, "iqr_outliers": 0, "stddev_outliers": 12, "outliers": "12;0", "ld15iqr": 0.0241574460000038, "hd15iqr": 0.02698788999998669, "ops": 38.98546245573084, "total": 0.8464693739999234, "iterations": 1 } }, { "group": null, "name": "test_RooFit[31622]", "fullname": "bench/test_cost.py::test_RooFit[31622]", "params": { "n": 31622 }, "param": "31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.06533745100000488, "max": 0.07018297199999779, "mean": 0.06782916825000267, "stddev": 0.0017636218885062626, "rounds": 12, "median": 0.06757253799999319, "iqr": 0.0033303670000179864, "q1": 0.06616526499999509, "q3": 0.06949563200001307, "iqr_outliers": 0, "stddev_outliers": 5, "outliers": "5;0", "ld15iqr": 0.06533745100000488, "hd15iqr": 0.07018297199999779, "ops": 14.742919982657472, "total": 0.8139500190000319, "iterations": 1 } }, { "group": null, "name": "test_RooFit[100000]", "fullname": "bench/test_cost.py::test_RooFit[100000]", "params": { "n": 100000 }, "param": "100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.23750098700000422, "max": 0.2524962930000072, "mean": 0.24434892280000325, "stddev": 0.00610208358833709, "rounds": 5, "median": 0.24614085199999636, "iqr": 0.00932900350000665, "q1": 0.2386875890000013, "q3": 0.24801659250000796, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.23750098700000422, "hd15iqr": 0.2524962930000072, "ops": 4.09250832187416, "total": 1.2217446140000163, "iterations": 1 } }, { "group": null, "name": "test_RooFit[316227]", "fullname": "bench/test_cost.py::test_RooFit[316227]", "params": { "n": 316227 }, "param": "316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.7698972659999868, "max": 0.7902549499999907, "mean": 0.7843643233999898, "stddev": 0.008318801216263792, "rounds": 5, "median": 0.7876884430000075, "iqr": 0.008084058500003266, "q1": 0.7812198569999822, "q3": 0.7893039154999855, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.7698972659999868, "hd15iqr": 0.7902549499999907, "ops": 1.2749177520788968, "total": 3.9218216169999494, "iterations": 1 } } ], "datetime": "2022-03-15T15:06:02.637206", "version": "3.4.1" } iminuit-2.30.1/bench/plot.ipynb0000644000000000000000000065467314332717401013330 0ustar00{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ ".benchmarks/Darwin-CPython-3.11-64bit/0003_a7f9e06fd44a98dc1caf03c110caf57e8dbf69c3_20231221_103807_uncommited-changes.json\n", "benchmark results\n", " 2023-12-21T10:48:12.673733\n", " Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz\n", "\n", "UnbinnedNLL\n", "UnbinnedNLL_log\n", "nll_numba_stats\n", "nll_scipy.stats\n", "nll_numba\n", "minuit\n", "minuit_numba\n", "minuit_log\n", "minuit_log_numba\n", "minuit_parallel_fastmath\n", "minuit_parallel_fastmath_log\n", "minuit_cfunc\n", "minuit_UnbinnedNLL\n", "minuit_UnbinnedNLL_log\n", "RooFit_legacy\n", "RooFit_legacy-parallel\n", "RooFit_cpu\n", "RooFit_cpu-parallel\n", "RooFit_cpu-implicitmt\n", "RooFit_codegen\n", "RooFit_codegen_no_grad\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:53:57.574600\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:53:58.121446\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:53:58.788049\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import json\n", "\n", "from pathlib import Path\n", "\n", "with open(\"root.json\") as f:\n", " root_data = json.load(f)\n", "\n", "paths = []\n", "for p in Path(\".benchmarks\").rglob(\"*.json\"):\n", " paths.append((p.stat().st_mtime, p))\n", "paths.sort()\n", "fn = paths[-1][1]\n", "\n", "print(fn)\n", "with open(fn) as f:\n", " data = json.load(f)\n", "\n", "print(\n", " f\"\"\"\\\n", "benchmark results\n", " {data['datetime']}\n", " {data['machine_info']['cpu']['brand_raw']}\n", "\"\"\"\n", ")\n", "\n", "variant = {}\n", "for d in (data, root_data):\n", " # override ROOT results with root_data if any\n", " for k in tuple(variant):\n", " if k.startswith(\"RooFit\"):\n", " del variant[k]\n", " for b in d[\"benchmarks\"]:\n", " params = b[\"params\"]\n", " n = params[\"n\"]\n", " n = int(n)\n", " name = b[\"name\"]\n", " name = name[name.find(\"_\") + 1 : name.find(\"[\")]\n", " extra = []\n", " for k, v in params.items():\n", " if k in (\"n\", \"lib\", \"model\"):\n", " continue\n", " if isinstance(v, (bool, int)):\n", " if v:\n", " extra.append(k)\n", " else:\n", " extra.append(v)\n", " if extra:\n", " name += \"_\" + \"_\".join(extra)\n", " for key in (\"lib\", \"model\"):\n", " if key in params:\n", " name += f\"_{params[key]}\"\n", " t = b[\"stats\"][\"min\"]\n", " if name not in variant:\n", " variant[name] = []\n", " variant[name].append((n, t))\n", "\n", "for k in variant:\n", " print(k)\n", "\n", "names = {\n", " \"Numba vs. SciPy\": {\n", " \"nll_scipy.stats\": \"handwritten NLL scipy.stats\",\n", " \"nll_numba_stats\": \"handwritten NLL numba_stats\",\n", " },\n", " \"Overhead\": {\n", " \"minuit_UnbinnedNLL\": \"iminuit+UnbinnedNLL\",\n", " \"minuit_numba\": \"iminuit+numba\",\n", " \"minuit_cfunc\": \"iminuit+numba.cfunc\",\n", " },\n", " \"RooFit vs. iminuit+numba\": {\n", " \"RooFit_legacy\": \"RooFit [legacy]\",\n", " \"RooFit_legacy-parallel\": \"RooFit [legacy, parallel]\",\n", " \"RooFit_cpu\": \"RooFit [CPU]\",\n", " \"RooFit_cpu-implicitmt\": \"RooFit [CPU, ImplicitMT]\",\n", " # \"RooFit_cpu_NumCPU\": \"RooFit [CPU, parallel]\",\n", " \"RooFit_codegen\": \"RooFit [Codegen]\",\n", " \"RooFit_codegen_no_grad\": \"RooFit [CodegenNoGrad]\",\n", " # \"RooFit_codegen_NumCPU\": \"RooFit [Codegen, parallel]\",\n", " \"minuit\": \"iminuit+numba\",\n", " \"minuit_parallel_fastmath\": \"iminuit+numba [parallel, fastmath]\",\n", " \"minuit_parallel_fastmath_log\": \"iminuit+numba logpdf [parallel, fastmath]\",\n", " },\n", "}\n", "\n", "for title, subnames in names.items():\n", " plt.figure(constrained_layout=True)\n", " plt.title(title)\n", " for name in subnames:\n", " if name not in variant:\n", " continue\n", " d = variant[name]\n", " n, t = np.transpose(d)\n", " ls = \"-\"\n", " if (\n", " \"parallel\" in name\n", " and \"fastmath\" in name\n", " or (\"NumCPU\" in name and \"BatchMode\" in name)\n", " ):\n", " ls = \"-.\"\n", " elif \"parallel\" in name or \"NumCPU\" in name:\n", " ls = \"--\"\n", " elif \"fastmath\" in name or \"BatchMode\" in name:\n", " ls = \":\"\n", " plt.plot(n, t, ls=ls, label=subnames[name])\n", "\n", " plt.loglog()\n", " plt.legend(\n", " frameon=False,\n", " fontsize=\"medium\" if len(subnames) < 4 else \"small\",\n", " ncol=1 if len(subnames) < 3 else 2,\n", " )\n", " # plt.title(\"Fit of normal distribution with 2 parameters\")\n", " plt.xlabel(\"number of data points\")\n", " plt.ylabel(\"runtime / sec\")\n", " fname = title.replace(\" \", \"_\").replace(\".\", \"_\").replace(\"__\", \"_\").lower()\n", " plt.savefig(f\"{fname}.svg\")" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "py39", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/bench/root.json0000644000000000000000000023251014332717401013143 0ustar00{ "machine_info": { "node": "MacBook-Pro-105.e5.physik.tu-dortmund.de", "processor": "i386", "machine": "x86_64", "python_compiler": "Clang 14.0.6 ", "python_implementation": "CPython", "python_implementation_version": "3.11.3", "python_version": "3.11.3", "python_build": [ "main", "Apr 6 2023 09:05:00" ], "release": "23.2.0", "system": "Darwin", "cpu": { "python_version": "3.11.3.final.0 (64 bit)", "cpuinfo_version": [ 9, 0, 0 ], "cpuinfo_version_string": "9.0.0", "arch": "X86_64", "bits": 64, "count": 8, "arch_string_raw": "x86_64", "vendor_id_raw": "GenuineIntel", "brand_raw": "Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz", "hz_advertised_friendly": "2.8000 GHz", "hz_actual_friendly": "2.8000 GHz", "hz_advertised": [ 2800000000, 0 ], "hz_actual": [ 2800000000, 0 ], "l2_cache_size": 262144, "stepping": 10, "model": 142, "family": 6, "flags": [ "1gbpage", "3dnowprefetch", "abm", "acapmsr", "acpi", "adx", "aes", "apic", "avx", "avx1.0", "avx2", "bmi1", "bmi2", "clflush", "clflushopt", "clfsh", "clfsopt", "cmov", "cx16", "cx8", "de", "ds", "ds_cpl", "dscpl", "dtes64", "dts", "em64t", "erms", "est", "f16c", "fma", "fpu", "fpu_csds", "fxsr", "ht", "htt", "ibrs", "intel_pt", "invpcid", "ipt", "l1df", "lahf", "lahf_lm", "lzcnt", "mca", "mce", "mdclear", "mmx", "mon", "monitor", "movbe", "mpx", "msr", "mtrr", "osxsave", "pae", "pat", "pbe", "pcid", "pclmulqdq", "pdcm", "pge", "pni", "popcnt", "prefetchw", "pse", "pse36", "rdrand", "rdrnd", "rdseed", "rdtscp", "rdwrfsgs", "seglim64", "sep", "sgx", "smap", "smep", "ss", "ssbd", "sse", "sse2", "sse3", "sse4.1", "sse4.2", "sse4_1", "sse4_2", "ssse3", "stibp", "syscall", "tm", "tm2", "tpr", "tsc", "tsc_thread_offset", "tscdeadline", "tsci", "tsctmr", "tsxfa", "vme", "vmx", "x2apic", "xd", "xsave", "xtpr" ], "l2_cache_line_size": 256, "l2_cache_associativity": 6 } }, "commit_info": { "id": "a7f9e06fd44a98dc1caf03c110caf57e8dbf69c3", "time": "2023-12-08T18:17:55+01:00", "author_time": "2023-12-08T18:17:55+01:00", "dirty": true, "project": "iminuit", "branch": "develop" }, "benchmarks": [ { "group": null, "name": "test_RooFit[legacy-10]", "fullname": "bench/test_cost.py::test_RooFit[legacy-10]", "params": { "backend": "legacy", "n": 10 }, "param": "legacy-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007005090010352433, "max": 0.0008599779976066202, "mean": 0.0007565715703614322, "stddev": 5.8255153846422144e-05, "rounds": 7, "median": 0.0007506270048907027, "iqr": 8.358725608559325e-05, "q1": 0.0007088404963724315, "q3": 0.0007924277524580248, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.0007005090010352433, "hd15iqr": 0.0008599779976066202, "ops": 1321.752018149818, "total": 0.0052960009925300255, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-31]", "fullname": "bench/test_cost.py::test_RooFit[legacy-31]", "params": { "backend": "legacy", "n": 31 }, "param": "legacy-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007951469888212159, "max": 0.0246911450085463, "mean": 0.0010871820886024068, "stddev": 0.0008561111953296545, "rounds": 835, "median": 0.0009501390013610944, "iqr": 0.00025586775154806674, "q1": 0.0008877167492755689, "q3": 0.0011435845008236356, "iqr_outliers": 58, "stddev_outliers": 8, "outliers": "8;58", "ld15iqr": 0.0007951469888212159, "hd15iqr": 0.001528937995317392, "ops": 919.8091198186672, "total": 0.9077970439830096, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-100]", "fullname": "bench/test_cost.py::test_RooFit[legacy-100]", "params": { "backend": "legacy", "n": 100 }, "param": "legacy-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001465353008825332, "max": 0.0031573739979648963, "mean": 0.0018546975041212406, "stddev": 0.0003273572769928595, "rounds": 605, "median": 0.0017449940060032532, "iqr": 0.0003884627512888983, "q1": 0.001618071495613549, "q3": 0.002006534246902447, "iqr_outliers": 26, "stddev_outliers": 123, "outliers": "123;26", "ld15iqr": 0.001465353008825332, "hd15iqr": 0.002596771009848453, "ops": 539.1714809438977, "total": 1.1220919899933506, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-316]", "fullname": "bench/test_cost.py::test_RooFit[legacy-316]", "params": { "backend": "legacy", "n": 316 }, "param": "legacy-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0032979569950839505, "max": 0.05757506699592341, "mean": 0.004563227288206297, "stddev": 0.003781750715640262, "rounds": 222, "median": 0.004000909502792638, "iqr": 0.0006613579898839816, "q1": 0.0037921530019957572, "q3": 0.004453510991879739, "iqr_outliers": 17, "stddev_outliers": 5, "outliers": "5;17", "ld15iqr": 0.0032979569950839505, "hd15iqr": 0.005578388008871116, "ops": 219.1431495390355, "total": 1.0130364579817979, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-1000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-1000]", "params": { "backend": "legacy", "n": 1000 }, "param": "legacy-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.010332684003515169, "max": 0.018995074002305046, "mean": 0.012094848250695655, "stddev": 0.0016413108299880804, "rounds": 92, "median": 0.011847519490402192, "iqr": 0.00158826750703156, "q1": 0.010941118001937866, "q3": 0.012529385508969426, "iqr_outliers": 5, "stddev_outliers": 13, "outliers": "13;5", "ld15iqr": 0.010332684003515169, "hd15iqr": 0.014917556996806525, "ops": 82.67983022792231, "total": 1.1127260390640004, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-3162]", "fullname": "bench/test_cost.py::test_RooFit[legacy-3162]", "params": { "backend": "legacy", "n": 3162 }, "param": "legacy-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.030854668002575636, "max": 0.036186438010190614, "mean": 0.033038362357079416, "stddev": 0.0015019388526836975, "rounds": 28, "median": 0.032942849495157134, "iqr": 0.0023444729959010147, "q1": 0.03170173599937698, "q3": 0.03404620899527799, "iqr_outliers": 0, "stddev_outliers": 10, "outliers": "10;0", "ld15iqr": 0.030854668002575636, "hd15iqr": 0.036186438010190614, "ops": 30.2678440653921, "total": 0.9250741459982237, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-10000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-10000]", "params": { "backend": "legacy", "n": 10000 }, "param": "legacy-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.09650715500174556, "max": 0.11421739299839828, "mean": 0.10395916340348776, "stddev": 0.006496043950645579, "rounds": 10, "median": 0.10251897050329717, "iqr": 0.011454138002591208, "q1": 0.09812275200965814, "q3": 0.10957689001224935, "iqr_outliers": 0, "stddev_outliers": 3, "outliers": "3;0", "ld15iqr": 0.09650715500174556, "hd15iqr": 0.11421739299839828, "ops": 9.619161671384234, "total": 1.0395916340348776, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-31622]", "fullname": "bench/test_cost.py::test_RooFit[legacy-31622]", "params": { "backend": "legacy", "n": 31622 }, "param": "legacy-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.2844333589891903, "max": 0.2985705949977273, "mean": 0.2936104517953936, "stddev": 0.005509503900663688, "rounds": 5, "median": 0.29422829700342845, "iqr": 0.006075020992284408, "q1": 0.2913954867472057, "q3": 0.29747050773949013, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.2844333589891903, "hd15iqr": 0.2985705949977273, "ops": 3.405873305548617, "total": 1.468052258976968, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-100000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-100000]", "params": { "backend": "legacy", "n": 100000 }, "param": "legacy-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.050909273995785, "max": 1.2431965580035467, "mean": 1.1157275094010402, "stddev": 0.07547845712817663, "rounds": 5, "median": 1.0837585300032515, "iqr": 0.07891360225039534, "q1": 1.0725963722507004, "q3": 1.1515099745010957, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 1.050909273995785, "hd15iqr": 1.2431965580035467, "ops": 0.8962761889207459, "total": 5.578637547005201, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-316227]", "fullname": "bench/test_cost.py::test_RooFit[legacy-316227]", "params": { "backend": "legacy", "n": 316227 }, "param": "legacy-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 2.9033515580085805, "max": 3.029330438002944, "mean": 2.976277193799615, "stddev": 0.04967547250975799, "rounds": 5, "median": 2.9731256230006693, "iqr": 0.0720617669976491, "q1": 2.9463962472473213, "q3": 3.0184580142449704, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 2.9033515580085805, "hd15iqr": 3.029330438002944, "ops": 0.3359902102140448, "total": 14.881385968998075, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-10]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-10]", "params": { "backend": "legacy-parallel", "n": 10 }, "param": "legacy-parallel-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.3718831489968579, "max": 0.37906355000450276, "mean": 0.37514686600188724, "stddev": 0.0026443324202783535, "rounds": 5, "median": 0.3752416710049147, "iqr": 0.003173609253281029, "q1": 0.3733612677497149, "q3": 0.3765348770029959, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.3718831489968579, "hd15iqr": 0.37906355000450276, "ops": 2.665622695072626, "total": 1.8757343300094362, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-31]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-31]", "params": { "backend": "legacy-parallel", "n": 31 }, "param": "legacy-parallel-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.31850098200084176, "max": 0.3294463159982115, "mean": 0.3235686325991992, "stddev": 0.004683913790956048, "rounds": 5, "median": 0.3250305789988488, "iqr": 0.00780199549626559, "q1": 0.3189168967510341, "q3": 0.32671889224729966, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.31850098200084176, "hd15iqr": 0.3294463159982115, "ops": 3.0905344314962964, "total": 1.617843162995996, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-100]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-100]", "params": { "backend": "legacy-parallel", "n": 100 }, "param": "legacy-parallel-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.31695572499302216, "max": 0.34992367099039257, "mean": 0.33083485599199774, "stddev": 0.014172496402985964, "rounds": 5, "median": 0.3257616349874297, "iqr": 0.023998363758437335, "q1": 0.3194357109896373, "q3": 0.34343407474807464, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.31695572499302216, "hd15iqr": 0.34992367099039257, "ops": 3.0226561134301644, "total": 1.6541742799599888, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-316]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-316]", "params": { "backend": "legacy-parallel", "n": 316 }, "param": "legacy-parallel-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.30671836900000926, "max": 0.3206368000101065, "mean": 0.3135507946019061, "stddev": 0.0054269156824407845, "rounds": 5, "median": 0.31319186800101306, "iqr": 0.008314376256748801, "q1": 0.3094648089972907, "q3": 0.3177791852540395, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.30671836900000926, "hd15iqr": 0.3206368000101065, "ops": 3.1892759234421053, "total": 1.5677539730095305, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-1000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-1000]", "params": { "backend": "legacy-parallel", "n": 1000 }, "param": "legacy-parallel-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.30811516899848357, "max": 0.3450653059990145, "mean": 0.3218996348034125, "stddev": 0.017060317740722444, "rounds": 5, "median": 0.31202193700300995, "iqr": 0.02879128075801418, "q1": 0.30886282975188806, "q3": 0.33765411050990224, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.30811516899848357, "hd15iqr": 0.3450653059990145, "ops": 3.1065583550932283, "total": 1.6094981740170624, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-3162]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-3162]", "params": { "backend": "legacy-parallel", "n": 3162 }, "param": "legacy-parallel-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.2922349319997011, "max": 0.3044901539979037, "mean": 0.29808675600215795, "stddev": 0.00498016733637895, "rounds": 5, "median": 0.2968873030040413, "iqr": 0.008073935248830821, "q1": 0.294361689753714, "q3": 0.30243562500254484, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.2922349319997011, "hd15iqr": 0.3044901539979037, "ops": 3.354728044317275, "total": 1.4904337800107896, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-10000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-10000]", "params": { "backend": "legacy-parallel", "n": 10000 }, "param": "legacy-parallel-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.29546002500865143, "max": 0.3344733609992545, "mean": 0.31599222820368594, "stddev": 0.01585648495187206, "rounds": 5, "median": 0.31112540900358, "iqr": 0.024563671002397314, "q1": 0.3060482175023935, "q3": 0.33061188850479084, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.29546002500865143, "hd15iqr": 0.3344733609992545, "ops": 3.164634793977934, "total": 1.5799611410184298, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-31622]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-31622]", "params": { "backend": "legacy-parallel", "n": 31622 }, "param": "legacy-parallel-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.3346969919948606, "max": 0.3590786599961575, "mean": 0.3445257168001262, "stddev": 0.011484672678500056, "rounds": 5, "median": 0.3390739810129162, "iqr": 0.0206852892479219, "q1": 0.33504641849867767, "q3": 0.35573170774659957, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.3346969919948606, "hd15iqr": 0.3590786599961575, "ops": 2.902540946109233, "total": 1.7226285840006312, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-100000]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-100000]", "params": { "backend": "legacy-parallel", "n": 100000 }, "param": "legacy-parallel-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.5947874940029578, "max": 0.6609520100028021, "mean": 0.6185228212008951, "stddev": 0.026775051782847687, "rounds": 5, "median": 0.6055552910111146, "iqr": 0.03549876425677212, "q1": 0.6009627974926843, "q3": 0.6364615617494565, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.5947874940029578, "hd15iqr": 0.6609520100028021, "ops": 1.6167552202171724, "total": 3.0926141060044756, "iterations": 1 } }, { "group": null, "name": "test_RooFit[legacy-parallel-316227]", "fullname": "bench/test_cost.py::test_RooFit[legacy-parallel-316227]", "params": { "backend": "legacy-parallel", "n": 316227 }, "param": "legacy-parallel-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.1974406770023052, "max": 1.758303728987812, "mean": 1.3421673655946507, "stddev": 0.23696034971691565, "rounds": 5, "median": 1.2422643039899413, "iqr": 0.22097694649346522, "q1": 1.20129012174948, "q3": 1.4222670682429452, "iqr_outliers": 1, "stddev_outliers": 1, "outliers": "1;1", "ld15iqr": 1.1974406770023052, "hd15iqr": 1.758303728987812, "ops": 0.7450635633335844, "total": 6.710836827973253, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-10]", "fullname": "bench/test_cost.py::test_RooFit[cpu-10]", "params": { "backend": "cpu", "n": 10 }, "param": "cpu-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0014671549870399758, "max": 0.002871106000384316, "mean": 0.0016200299061642125, "stddev": 0.00017847356951943092, "rounds": 116, "median": 0.0015764940035296604, "iqr": 0.00013952550943940878, "q1": 0.001514359493739903, "q3": 0.0016538850031793118, "iqr_outliers": 8, "stddev_outliers": 11, "outliers": "11;8", "ld15iqr": 0.0014671549870399758, "hd15iqr": 0.0019183289987267926, "ops": 617.272555398515, "total": 0.18792346911504865, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-31]", "fullname": "bench/test_cost.py::test_RooFit[cpu-31]", "params": { "backend": "cpu", "n": 31 }, "param": "cpu-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.000819156994111836, "max": 0.021386360996984877, "mean": 0.0009683774074458569, "stddev": 0.0006830980065490508, "rounds": 923, "median": 0.000924173989915289, "iqr": 9.77397539827507e-05, "q1": 0.0008766409955569543, "q3": 0.000974380749539705, "iqr_outliers": 51, "stddev_outliers": 1, "outliers": "1;51", "ld15iqr": 0.000819156994111836, "hd15iqr": 0.0011226000060560182, "ops": 1032.6552357696462, "total": 0.8938123470725259, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-100]", "fullname": "bench/test_cost.py::test_RooFit[cpu-100]", "params": { "backend": "cpu", "n": 100 }, "param": "cpu-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007978200010256842, "max": 0.0024681819922989234, "mean": 0.0009230493377304445, "stddev": 0.00016120479451367775, "rounds": 518, "median": 0.0008574754974688403, "iqr": 0.00010985099652316421, "q1": 0.000835560989798978, "q3": 0.0009454119863221422, "iqr_outliers": 45, "stddev_outliers": 53, "outliers": "53;45", "ld15iqr": 0.0007978200010256842, "hd15iqr": 0.001110733996029012, "ops": 1083.365708769976, "total": 0.47813955694437027, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-316]", "fullname": "bench/test_cost.py::test_RooFit[cpu-316]", "params": { "backend": "cpu", "n": 316 }, "param": "cpu-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.00099500099895522, "max": 0.002214982989244163, "mean": 0.0011722189005684974, "stddev": 0.00018187967594588428, "rounds": 593, "median": 0.0011077739909524098, "iqr": 0.00015127825463423505, "q1": 0.0010567337449174374, "q3": 0.0012080119995516725, "iqr_outliers": 51, "stddev_outliers": 74, "outliers": "74;51", "ld15iqr": 0.00099500099895522, "hd15iqr": 0.001455343997804448, "ops": 853.0829860489577, "total": 0.695125808037119, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-1000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-1000]", "params": { "backend": "cpu", "n": 1000 }, "param": "cpu-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.002000612992560491, "max": 0.0038917310012038797, "mean": 0.002274001059866148, "stddev": 0.0002445097657628164, "rounds": 450, "median": 0.002214209504018072, "iqr": 0.00018441998690832406, "q1": 0.0021369380119722337, "q3": 0.0023213579988805577, "iqr_outliers": 36, "stddev_outliers": 63, "outliers": "63;36", "ld15iqr": 0.002000612992560491, "hd15iqr": 0.0026014140021288767, "ops": 439.75353294640144, "total": 1.0233004769397667, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-3162]", "fullname": "bench/test_cost.py::test_RooFit[cpu-3162]", "params": { "backend": "cpu", "n": 3162 }, "param": "cpu-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004249673002050258, "max": 0.007217341990326531, "mean": 0.0048226268934271, "stddev": 0.0004421533143299928, "rounds": 151, "median": 0.004714020004030317, "iqr": 0.00040734924186835997, "q1": 0.004532697752438253, "q3": 0.004940046994306613, "iqr_outliers": 9, "stddev_outliers": 23, "outliers": "23;9", "ld15iqr": 0.004249673002050258, "hd15iqr": 0.005642948002787307, "ops": 207.35587100111962, "total": 0.728216660907492, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-10000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-10000]", "params": { "backend": "cpu", "n": 10000 }, "param": "cpu-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.013100060008582659, "max": 0.016508283995790407, "mean": 0.01379366944858138, "stddev": 0.0006386432630538987, "rounds": 58, "median": 0.013608618995931465, "iqr": 0.0006548930105054751, "q1": 0.01336961699416861, "q3": 0.014024510004674084, "iqr_outliers": 3, "stddev_outliers": 14, "outliers": "14;3", "ld15iqr": 0.013100060008582659, "hd15iqr": 0.01510237599723041, "ops": 72.49702508296991, "total": 0.80003282801772, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-31622]", "fullname": "bench/test_cost.py::test_RooFit[cpu-31622]", "params": { "backend": "cpu", "n": 31622 }, "param": "cpu-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.047107987003983, "max": 0.05519401498895604, "mean": 0.049077301788584965, "stddev": 0.002272480384790934, "rounds": 19, "median": 0.04849759400531184, "iqr": 0.0024033869995037094, "q1": 0.047323406499344856, "q3": 0.049726793498848565, "iqr_outliers": 1, "stddev_outliers": 4, "outliers": "4;1", "ld15iqr": 0.047107987003983, "hd15iqr": 0.05519401498895604, "ops": 20.376018313064492, "total": 0.9324687339831144, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-100000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-100000]", "params": { "backend": "cpu", "n": 100000 }, "param": "cpu-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.12987463500758167, "max": 0.14339014800498262, "mean": 0.13448679714305659, "stddev": 0.005007674720867423, "rounds": 7, "median": 0.13209983200067654, "iqr": 0.006055870253476314, "q1": 0.13186249274440343, "q3": 0.13791836299787974, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.12987463500758167, "hd15iqr": 0.14339014800498262, "ops": 7.435674142319545, "total": 0.9414075800013961, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-316227]", "fullname": "bench/test_cost.py::test_RooFit[cpu-316227]", "params": { "backend": "cpu", "n": 316227 }, "param": "cpu-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.4676898799953051, "max": 0.4770243910024874, "mean": 0.4736688425997272, "stddev": 0.003529541322922611, "rounds": 5, "median": 0.474255337001523, "iqr": 0.0030081709919613786, "q1": 0.4726006752534886, "q3": 0.47560884624544997, "iqr_outliers": 1, "stddev_outliers": 1, "outliers": "1;1", "ld15iqr": 0.4742376070062164, "hd15iqr": 0.4770243910024874, "ops": 2.1111796049567224, "total": 2.368344212998636, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-10]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-10]", "params": { "backend": "cpu-parallel", "n": 10 }, "param": "cpu-parallel-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.000668169988784939, "max": 0.010772941997856833, "mean": 0.0007794888897890063, "stddev": 0.00031843733182223926, "rounds": 1150, "median": 0.0007282524966285564, "iqr": 6.929201481398195e-05, "q1": 0.0007105459953891113, "q3": 0.0007798380102030933, "iqr_outliers": 130, "stddev_outliers": 35, "outliers": "35;130", "ld15iqr": 0.000668169988784939, "hd15iqr": 0.0008838160138111562, "ops": 1282.8919220012, "total": 0.8964122232573573, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-31]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-31]", "params": { "backend": "cpu-parallel", "n": 31 }, "param": "cpu-parallel-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0009122519986703992, "max": 0.00226244299847167, "mean": 0.0010482984794189538, "stddev": 0.00015547836700138782, "rounds": 962, "median": 0.0010011695048888214, "iqr": 0.00010027299867942929, "q1": 0.0009656089969212189, "q3": 0.0010658819956006482, "iqr_outliers": 86, "stddev_outliers": 90, "outliers": "90;86", "ld15iqr": 0.0009122519986703992, "hd15iqr": 0.0012183829967398196, "ops": 953.926786724212, "total": 1.0084631372010335, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-100]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-100]", "params": { "backend": "cpu-parallel", "n": 100 }, "param": "cpu-parallel-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007350749947363511, "max": 0.001863379991846159, "mean": 0.0008269642522303109, "stddev": 0.00011026228501073631, "rounds": 1142, "median": 0.0007954455068102106, "iqr": 6.893000681884587e-05, "q1": 0.0007721489964751527, "q3": 0.0008410790032939985, "iqr_outliers": 108, "stddev_outliers": 111, "outliers": "111;108", "ld15iqr": 0.0007350749947363511, "hd15iqr": 0.0009453940001549199, "ops": 1209.242113311445, "total": 0.944393176047015, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-316]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-316]", "params": { "backend": "cpu-parallel", "n": 316 }, "param": "cpu-parallel-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001102002992411144, "max": 0.0025494020082987845, "mean": 0.001277589783393064, "stddev": 0.00020050402170423458, "rounds": 711, "median": 0.0012095629936084151, "iqr": 0.00013596451026387513, "q1": 0.0011654922418529168, "q3": 0.001301456752116792, "iqr_outliers": 76, "stddev_outliers": 82, "outliers": "82;76", "ld15iqr": 0.001102002992411144, "hd15iqr": 0.0015073660033522174, "ops": 782.7238547134964, "total": 0.9083663359924685, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-1000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-1000]", "params": { "backend": "cpu-parallel", "n": 1000 }, "param": "cpu-parallel-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001947208002093248, "max": 0.026661908006644808, "mean": 0.002474250720781611, "stddev": 0.0012592933691523047, "rounds": 415, "median": 0.002282087007188238, "iqr": 0.0004096262600796763, "q1": 0.0021398869939730503, "q3": 0.0025495132540527266, "iqr_outliers": 35, "stddev_outliers": 4, "outliers": "4;35", "ld15iqr": 0.001947208002093248, "hd15iqr": 0.0031644420087104663, "ops": 404.16275990175404, "total": 1.0268140491243685, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-3162]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-3162]", "params": { "backend": "cpu-parallel", "n": 3162 }, "param": "cpu-parallel-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004864135000389069, "max": 0.007666377001442015, "mean": 0.0053891585104335355, "stddev": 0.000473195254738816, "rounds": 147, "median": 0.005266398002277128, "iqr": 0.0003113054917776026, "q1": 0.005115893753099954, "q3": 0.005427199244877556, "iqr_outliers": 17, "stddev_outliers": 22, "outliers": "22;17", "ld15iqr": 0.004864135000389069, "hd15iqr": 0.005920135998167098, "ops": 185.55772632480134, "total": 0.7922063010337297, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-10000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-10000]", "params": { "backend": "cpu-parallel", "n": 10000 }, "param": "cpu-parallel-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.014344871990033425, "max": 0.018350030994042754, "mean": 0.015482226793618135, "stddev": 0.0011242937805976386, "rounds": 58, "median": 0.015050748996145558, "iqr": 0.001431675991625525, "q1": 0.01467892900109291, "q3": 0.016110604992718436, "iqr_outliers": 2, "stddev_outliers": 11, "outliers": "11;2", "ld15iqr": 0.014344871990033425, "hd15iqr": 0.01826805000018794, "ops": 64.5901919233095, "total": 0.8979691540298518, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-31622]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-31622]", "params": { "backend": "cpu-parallel", "n": 31622 }, "param": "cpu-parallel-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.040180248994147405, "max": 0.05163722299039364, "mean": 0.04289198528775679, "stddev": 0.0031649917132922493, "rounds": 21, "median": 0.04152488900581375, "iqr": 0.002441354747134028, "q1": 0.04107215250405716, "q3": 0.043513507251191186, "iqr_outliers": 3, "stddev_outliers": 3, "outliers": "3;3", "ld15iqr": 0.040180248994147405, "hd15iqr": 0.04876860199146904, "ops": 23.31437897525911, "total": 0.9007316910428926, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-100000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-100000]", "params": { "backend": "cpu-parallel", "n": 100000 }, "param": "cpu-parallel-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.14871835500525776, "max": 0.16018856200389564, "mean": 0.15196209816834502, "stddev": 0.004485295401590702, "rounds": 6, "median": 0.15004983450489817, "iqr": 0.005101219008793123, "q1": 0.1488323919911636, "q3": 0.15393361099995673, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.14871835500525776, "hd15iqr": 0.16018856200389564, "ops": 6.5805882654514996, "total": 0.9117725890100701, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-parallel-316227]", "fullname": "bench/test_cost.py::test_RooFit[cpu-parallel-316227]", "params": { "backend": "cpu-parallel", "n": 316227 }, "param": "cpu-parallel-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.45470694699906744, "max": 0.46212191399536096, "mean": 0.45817346739931963, "stddev": 0.002640144979663871, "rounds": 5, "median": 0.45809548599936534, "iqr": 0.002312164240720449, "q1": 0.456926146754995, "q3": 0.45923831099571544, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.45470694699906744, "hd15iqr": 0.46212191399536096, "ops": 2.182579462045656, "total": 2.290867336996598, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-10]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-10]", "params": { "backend": "cpu-implicitmt", "n": 10 }, "param": "cpu-implicitmt-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007200959953479469, "max": 0.001797903998522088, "mean": 0.0008133133315610716, "stddev": 0.00011703830866325536, "rounds": 1070, "median": 0.0007792219912516885, "iqr": 7.482500222977251e-05, "q1": 0.000754313005018048, "q3": 0.0008291380072478205, "iqr_outliers": 102, "stddev_outliers": 109, "outliers": "109;102", "ld15iqr": 0.0007200959953479469, "hd15iqr": 0.0009425540047232062, "ops": 1229.538433952143, "total": 0.8702452647703467, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-31]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-31]", "params": { "backend": "cpu-implicitmt", "n": 31 }, "param": "cpu-implicitmt-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0008245380013249815, "max": 0.001914356995257549, "mean": 0.0009253558771507371, "stddev": 0.00012110792391076515, "rounds": 1050, "median": 0.0008875455023371615, "iqr": 7.933400047477335e-05, "q1": 0.000862483007949777, "q3": 0.0009418170084245503, "iqr_outliers": 92, "stddev_outliers": 107, "outliers": "107;92", "ld15iqr": 0.0008245380013249815, "hd15iqr": 0.0010611149918986484, "ops": 1080.6653144940296, "total": 0.971623671008274, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-100]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-100]", "params": { "backend": "cpu-implicitmt", "n": 100 }, "param": "cpu-implicitmt-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0007356760033871979, "max": 0.0020696200081147254, "mean": 0.0008372390935366984, "stddev": 0.00013132055339564906, "rounds": 1059, "median": 0.0007916689937701449, "iqr": 7.000749610597268e-05, "q1": 0.000777236509748036, "q3": 0.0008472440058540087, "iqr_outliers": 114, "stddev_outliers": 103, "outliers": "103;114", "ld15iqr": 0.0007356760033871979, "hd15iqr": 0.000952778005739674, "ops": 1194.4019429094747, "total": 0.8866362000553636, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-316]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-316]", "params": { "backend": "cpu-implicitmt", "n": 316 }, "param": "cpu-implicitmt-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.0010497159964870661, "max": 0.002325473993550986, "mean": 0.0011809460886370378, "stddev": 0.00014962243321875958, "rounds": 824, "median": 0.0011355685055605136, "iqr": 0.00010644949361449108, "q1": 0.0011011159949703142, "q3": 0.0012075654885848053, "iqr_outliers": 61, "stddev_outliers": 79, "outliers": "79;61", "ld15iqr": 0.0010497159964870661, "hd15iqr": 0.0013689659972442314, "ops": 846.7787053294934, "total": 0.9730995770369191, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-1000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-1000]", "params": { "backend": "cpu-implicitmt", "n": 1000 }, "param": "cpu-implicitmt-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.001790890994016081, "max": 0.004143363999901339, "mean": 0.0020498482750351188, "stddev": 0.0002869803341444723, "rounds": 502, "median": 0.001965461007785052, "iqr": 0.00019754499953705817, "q1": 0.001890444997115992, "q3": 0.00208798999665305, "iqr_outliers": 43, "stddev_outliers": 51, "outliers": "51;43", "ld15iqr": 0.001790890994016081, "hd15iqr": 0.002386910011409782, "ops": 487.840984222536, "total": 1.0290238340676297, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-3162]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-3162]", "params": { "backend": "cpu-implicitmt", "n": 3162 }, "param": "cpu-implicitmt-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.004783964002854191, "max": 0.007459753003786318, "mean": 0.0053213926825619855, "stddev": 0.0004159361645062317, "rounds": 164, "median": 0.005223456500971224, "iqr": 0.00032539849780732766, "q1": 0.005080420502054039, "q3": 0.005405818999861367, "iqr_outliers": 14, "stddev_outliers": 26, "outliers": "26;14", "ld15iqr": 0.004783964002854191, "hd15iqr": 0.005913358996622264, "ops": 187.92073046534685, "total": 0.8727083999401657, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-10000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-10000]", "params": { "backend": "cpu-implicitmt", "n": 10000 }, "param": "cpu-implicitmt-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.014872005995130166, "max": 0.020700373002910055, "mean": 0.017060837692009622, "stddev": 0.0012039184978595925, "rounds": 55, "median": 0.017030836010235362, "iqr": 0.0011959252515225671, "q1": 0.016383821250201436, "q3": 0.017579746501724003, "iqr_outliers": 3, "stddev_outliers": 15, "outliers": "15;3", "ld15iqr": 0.014872005995130166, "hd15iqr": 0.019847458999720402, "ops": 58.613769033647515, "total": 0.9383460730605293, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-31622]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-31622]", "params": { "backend": "cpu-implicitmt", "n": 31622 }, "param": "cpu-implicitmt-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.045840309001505375, "max": 0.05520169799274299, "mean": 0.04762188742001614, "stddev": 0.0021407254240015878, "rounds": 19, "median": 0.047332203001133166, "iqr": 0.0016499667508469429, "q1": 0.046292393999465276, "q3": 0.04794236075031222, "iqr_outliers": 1, "stddev_outliers": 2, "outliers": "2;1", "ld15iqr": 0.045840309001505375, "hd15iqr": 0.05520169799274299, "ops": 20.99874772245348, "total": 0.9048158609803068, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-100000]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-100000]", "params": { "backend": "cpu-implicitmt", "n": 100000 }, "param": "cpu-implicitmt-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.14228589199774433, "max": 0.15501050600141753, "mean": 0.14729090083468085, "stddev": 0.004172174887266756, "rounds": 6, "median": 0.1466384650047985, "iqr": 0.000986426995950751, "q1": 0.14609282500168774, "q3": 0.1470792519976385, "iqr_outliers": 2, "stddev_outliers": 2, "outliers": "2;2", "ld15iqr": 0.14609282500168774, "hd15iqr": 0.15501050600141753, "ops": 6.789285653988897, "total": 0.8837454050080851, "iterations": 1 } }, { "group": null, "name": "test_RooFit[cpu-implicitmt-316227]", "fullname": "bench/test_cost.py::test_RooFit[cpu-implicitmt-316227]", "params": { "backend": "cpu-implicitmt", "n": 316227 }, "param": "cpu-implicitmt-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.47016523098864127, "max": 0.48012216700590216, "mean": 0.47380304760008585, "stddev": 0.0042034478505916205, "rounds": 5, "median": 0.4724877050030045, "iqr": 0.006576268260687357, "q1": 0.47033784124505473, "q3": 0.4769141095057421, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.47016523098864127, "hd15iqr": 0.48012216700590216, "ops": 2.1105816120542378, "total": 2.3690152380004292, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-10]", "fullname": "bench/test_cost.py::test_RooFit[codegen-10]", "params": { "backend": "codegen", "n": 10 }, "param": "codegen-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.06683230800263118, "max": 0.06993486700230278, "mean": 0.06841488259669859, "stddev": 0.0012513390334097122, "rounds": 5, "median": 0.06871401699027047, "iqr": 0.001999333002459025, "q1": 0.06731868824499543, "q3": 0.06931802124745445, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.06683230800263118, "hd15iqr": 0.06993486700230278, "ops": 14.61670271211217, "total": 0.34207441298349295, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-31]", "fullname": "bench/test_cost.py::test_RooFit[codegen-31]", "params": { "backend": "codegen", "n": 31 }, "param": "codegen-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.06590226799016818, "max": 0.07333107000158634, "mean": 0.06887715066235008, "stddev": 0.0020692905383103664, "rounds": 12, "median": 0.06835134499851847, "iqr": 0.0022804895052104257, "q1": 0.06750148299033754, "q3": 0.06978197249554796, "iqr_outliers": 1, "stddev_outliers": 3, "outliers": "3;1", "ld15iqr": 0.06590226799016818, "hd15iqr": 0.07333107000158634, "ops": 14.518602909435163, "total": 0.826525807948201, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-100]", "fullname": "bench/test_cost.py::test_RooFit[codegen-100]", "params": { "backend": "codegen", "n": 100 }, "param": "codegen-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.07552436999685597, "max": 0.14266879399656318, "mean": 0.09213821891656455, "stddev": 0.02006523749108669, "rounds": 12, "median": 0.0857936385073117, "iqr": 0.013452628503728192, "q1": 0.07952348499384243, "q3": 0.09297611349757062, "iqr_outliers": 2, "stddev_outliers": 2, "outliers": "2;2", "ld15iqr": 0.07552436999685597, "hd15iqr": 0.12208131900115404, "ops": 10.85325950250402, "total": 1.1056586269987747, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-316]", "fullname": "bench/test_cost.py::test_RooFit[codegen-316]", "params": { "backend": "codegen", "n": 316 }, "param": "codegen-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.07084199499513488, "max": 0.08963498999946751, "mean": 0.07476126369035158, "stddev": 0.004867411834158928, "rounds": 13, "median": 0.0732175820012344, "iqr": 0.0028022569968015887, "q1": 0.07226451049791649, "q3": 0.07506676749471808, "iqr_outliers": 1, "stddev_outliers": 1, "outliers": "1;1", "ld15iqr": 0.07084199499513488, "hd15iqr": 0.08963498999946751, "ops": 13.375910874672071, "total": 0.9718964279745705, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-1000]", "fullname": "bench/test_cost.py::test_RooFit[codegen-1000]", "params": { "backend": "codegen", "n": 1000 }, "param": "codegen-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.07296148099703714, "max": 0.0846795780089451, "mean": 0.07856812483320634, "stddev": 0.0038187833260300784, "rounds": 12, "median": 0.07784744999662507, "iqr": 0.00633002749964362, "q1": 0.07513087899860693, "q3": 0.08146090649825055, "iqr_outliers": 0, "stddev_outliers": 5, "outliers": "5;0", "ld15iqr": 0.07296148099703714, "hd15iqr": 0.0846795780089451, "ops": 12.727807900760235, "total": 0.942817497998476, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-3162]", "fullname": "bench/test_cost.py::test_RooFit[codegen-3162]", "params": { "backend": "codegen", "n": 3162 }, "param": "codegen-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.07991708199551795, "max": 0.09413949798909016, "mean": 0.08559422174706317, "stddev": 0.003555874212433865, "rounds": 12, "median": 0.08569041099690367, "iqr": 0.00419082601001719, "q1": 0.08289551599591505, "q3": 0.08708634200593224, "iqr_outliers": 1, "stddev_outliers": 2, "outliers": "2;1", "ld15iqr": 0.07991708199551795, "hd15iqr": 0.09413949798909016, "ops": 11.683031629811051, "total": 1.0271306609647581, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-10000]", "fullname": "bench/test_cost.py::test_RooFit[codegen-10000]", "params": { "backend": "codegen", "n": 10000 }, "param": "codegen-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.11125191500468645, "max": 0.131547947996296, "mean": 0.11652122374835017, "stddev": 0.007206100756245227, "rounds": 8, "median": 0.11275007849326357, "iqr": 0.008202141005313024, "q1": 0.11186637199716642, "q3": 0.12006851300247945, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.11125191500468645, "hd15iqr": 0.131547947996296, "ops": 8.582127511462556, "total": 0.9321697899868013, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-31622]", "fullname": "bench/test_cost.py::test_RooFit[codegen-31622]", "params": { "backend": "codegen", "n": 31622 }, "param": "codegen-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.23037348099751398, "max": 0.24697742798889522, "mean": 0.24114297199703288, "stddev": 0.006732287118619689, "rounds": 5, "median": 0.24329604199738242, "iqr": 0.009211855507601285, "q1": 0.2369634017450153, "q3": 0.24617525725261657, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.23037348099751398, "hd15iqr": 0.24697742798889522, "ops": 4.1469174561401045, "total": 1.2057148599851644, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-100000]", "fullname": "bench/test_cost.py::test_RooFit[codegen-100000]", "params": { "backend": "codegen", "n": 100000 }, "param": "codegen-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.6001459550025174, "max": 0.811777016002452, "mean": 0.6747652078018291, "stddev": 0.08091696200007821, "rounds": 5, "median": 0.6460077130032005, "iqr": 0.07558948950463673, "q1": 0.6321563847486686, "q3": 0.7077458742533054, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.6001459550025174, "hd15iqr": 0.811777016002452, "ops": 1.4819969797460106, "total": 3.3738260390091455, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen-316227]", "fullname": "bench/test_cost.py::test_RooFit[codegen-316227]", "params": { "backend": "codegen", "n": 316227 }, "param": "codegen-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 1.8010034800099675, "max": 2.0892695580114378, "mean": 1.92036267920339, "stddev": 0.1077377377820376, "rounds": 5, "median": 1.9017413690016838, "iqr": 0.12847684175358154, "q1": 1.850720329748583, "q3": 1.9791971715021646, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 1.8010034800099675, "hd15iqr": 2.0892695580114378, "ops": 0.5207349688834937, "total": 9.60181339601695, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-10]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-10]", "params": { "backend": "codegen_no_grad", "n": 10 }, "param": "codegen_no_grad-10", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.010190108994720504, "max": 0.025696373006212525, "mean": 0.012253358521537966, "stddev": 0.002824272706262127, "rounds": 92, "median": 0.011197070503840223, "iqr": 0.001678156499110628, "q1": 0.010761483994429, "q3": 0.012439640493539628, "iqr_outliers": 9, "stddev_outliers": 9, "outliers": "9;9", "ld15iqr": 0.010190108994720504, "hd15iqr": 0.01678557100240141, "ops": 81.61027837733472, "total": 1.127308983981493, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-31]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-31]", "params": { "backend": "codegen_no_grad", "n": 31 }, "param": "codegen_no_grad-31", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.010589262994471937, "max": 0.016498710989253595, "mean": 0.011839018053887162, "stddev": 0.0012027574405917138, "rounds": 93, "median": 0.011505026996019296, "iqr": 0.0011304999970889185, "q1": 0.01103748725290643, "q3": 0.012167987249995349, "iqr_outliers": 9, "stddev_outliers": 11, "outliers": "11;9", "ld15iqr": 0.010589262994471937, "hd15iqr": 0.013878323006792925, "ops": 84.46646465512106, "total": 1.101028679011506, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-100]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-100]", "params": { "backend": "codegen_no_grad", "n": 100 }, "param": "codegen_no_grad-100", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.010526666999794543, "max": 0.015157608999288641, "mean": 0.011656077519198593, "stddev": 0.000787832060219564, "rounds": 81, "median": 0.011498309002490714, "iqr": 0.0006766655060346238, "q1": 0.011210065244085854, "q3": 0.011886730750120478, "iqr_outliers": 6, "stddev_outliers": 13, "outliers": "13;6", "ld15iqr": 0.010526666999794543, "hd15iqr": 0.013068179003312252, "ops": 85.79215420907346, "total": 0.944142279055086, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-316]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-316]", "params": { "backend": "codegen_no_grad", "n": 316 }, "param": "codegen_no_grad-316", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.01137653698970098, "max": 0.013352230002055876, "mean": 0.0121299539154484, "stddev": 0.0004041635551083039, "rounds": 71, "median": 0.012051107987645082, "iqr": 0.0004939007631037384, "q1": 0.011813542991149006, "q3": 0.012307443754252745, "iqr_outliers": 3, "stddev_outliers": 18, "outliers": "18;3", "ld15iqr": 0.01137653698970098, "hd15iqr": 0.013094114998239093, "ops": 82.44054404249842, "total": 0.8612267279968364, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-1000]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-1000]", "params": { "backend": "codegen_no_grad", "n": 1000 }, "param": "codegen_no_grad-1000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.013053673988906667, "max": 0.02356622899242211, "mean": 0.014778493820826884, "stddev": 0.0022501301992051, "rounds": 67, "median": 0.01409292800235562, "iqr": 0.001543123013107106, "q1": 0.013505486745998496, "q3": 0.015048609759105602, "iqr_outliers": 6, "stddev_outliers": 7, "outliers": "7;6", "ld15iqr": 0.013053673988906667, "hd15iqr": 0.018043802003376186, "ops": 67.66589424632232, "total": 0.9901590859954013, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-3162]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-3162]", "params": { "backend": "codegen_no_grad", "n": 3162 }, "param": "codegen_no_grad-3162", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.019105512998066843, "max": 0.02910914400126785, "mean": 0.02083919196156785, "stddev": 0.0023238479786721277, "rounds": 25, "median": 0.020141758999670856, "iqr": 0.0008154914939950686, "q1": 0.01981114775480819, "q3": 0.020626639248803258, "iqr_outliers": 3, "stddev_outliers": 2, "outliers": "2;3", "ld15iqr": 0.019105512998066843, "hd15iqr": 0.022097530993050896, "ops": 47.98650551538777, "total": 0.5209797990391962, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-10000]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-10000]", "params": { "backend": "codegen_no_grad", "n": 10000 }, "param": "codegen_no_grad-10000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.03955670598952565, "max": 0.04542348100221716, "mean": 0.04166008686099138, "stddev": 0.0016294170234124933, "rounds": 22, "median": 0.04113661999144824, "iqr": 0.002047046000370756, "q1": 0.040531354999984615, "q3": 0.04257840100035537, "iqr_outliers": 0, "stddev_outliers": 7, "outliers": "7;0", "ld15iqr": 0.03955670598952565, "hd15iqr": 0.04542348100221716, "ops": 24.003790566657575, "total": 0.9165219109418103, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-31622]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-31622]", "params": { "backend": "codegen_no_grad", "n": 31622 }, "param": "codegen_no_grad-31622", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.09108170800027438, "max": 0.10447667400876526, "mean": 0.09457751549925889, "stddev": 0.003919609694759334, "rounds": 10, "median": 0.09392885849956656, "iqr": 0.003891891989042051, "q1": 0.09179762600979302, "q3": 0.09568951799883507, "iqr_outliers": 1, "stddev_outliers": 1, "outliers": "1;1", "ld15iqr": 0.09108170800027438, "hd15iqr": 0.10447667400876526, "ops": 10.573337592145103, "total": 0.9457751549925888, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-100000]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-100000]", "params": { "backend": "codegen_no_grad", "n": 100000 }, "param": "codegen_no_grad-100000", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.3220408360066358, "max": 0.34582003600371536, "mean": 0.33433468620060014, "stddev": 0.010814202779697189, "rounds": 5, "median": 0.33366848999867216, "iqr": 0.020301168740843423, "q1": 0.32463605050361366, "q3": 0.3449372192444571, "iqr_outliers": 0, "stddev_outliers": 2, "outliers": "2;0", "ld15iqr": 0.3220408360066358, "hd15iqr": 0.34582003600371536, "ops": 2.991014816213242, "total": 1.6716734310030006, "iterations": 1 } }, { "group": null, "name": "test_RooFit[codegen_no_grad-316227]", "fullname": "bench/test_cost.py::test_RooFit[codegen_no_grad-316227]", "params": { "backend": "codegen_no_grad", "n": 316227 }, "param": "codegen_no_grad-316227", "extra_info": {}, "options": { "disable_gc": false, "timer": "perf_counter", "min_rounds": 5, "max_time": 1.0, "min_time": 5e-06, "warmup": false }, "stats": { "min": 0.8641546050057514, "max": 0.9343273810081882, "mean": 0.8891137668018928, "stddev": 0.027782482951162507, "rounds": 5, "median": 0.883118365003611, "iqr": 0.03537458126083948, "q1": 0.8686111387432902, "q3": 0.9039857200041297, "iqr_outliers": 0, "stddev_outliers": 1, "outliers": "1;0", "ld15iqr": 0.8641546050057514, "hd15iqr": 0.9343273810081882, "ops": 1.1247154608762393, "total": 4.445568834009464, "iterations": 1 } } ], "datetime": "2023-12-21T10:21:33.110016", "version": "4.0.0" } iminuit-2.30.1/bench/test_cost.py0000644000000000000000000002076014332717401013650 0ustar00from iminuit.cost import UnbinnedNLL from iminuit import Minuit import numpy as np import numba as nb from numba_stats import norm, truncexpon import pytest from numpy.testing import assert_allclose N = [int(x) for x in np.geomspace(10, 1e6, 11)] # N = N[:-5] def make_data(size, seed=1): rng = np.random.default_rng(seed) s = rng.normal(0.5, 0.1, size=size // 2) b = rng.exponential(1, size=2 * size) b = b[b < 1] b = b[: size // 2] x = np.append(s, b) return x # we inline following functions to profit from parallel=True,fastmath=True @nb.njit(inline="always") def mixture(x, z, mu, sigma, slope): b = truncexpon.pdf(x, 0.0, 1.0, 0.0, slope) s = norm.pdf(x, mu, sigma) return (1 - z) * b + z * s @nb.njit(inline="always") def logsumexp(a, b): r = np.empty_like(a) for i in nb.prange(len(r)): if a[i] > b[i]: c = a[i] d = b[i] else: c = b[i] d = a[i] r[i] = c + np.log1p(np.exp(d - c)) return r ARGS = (0.5, 0.5, 0.1, 1.0) @nb.njit(inline="always") def log_mixture(x, z, mu, sigma, slope): log_b = truncexpon.logpdf(x, 0.0, 1.0, 0.0, slope) log_s = norm.logpdf(x, mu, sigma) b = np.log(1 - z) + log_b s = np.log(z) + log_s return logsumexp(b, s) @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("log", [False, True]) def test_UnbinnedNLL(benchmark, n, log): x = make_data(size=n) fn = log_mixture if log else mixture fn(x, *ARGS) # warm-up JIT cost = UnbinnedNLL(x, fn, log=log) benchmark(cost, *ARGS) @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("lib", ["numba_stats", "scipy.stats"]) def test_nll(benchmark, n, lib): x = make_data(size=n) if lib == "scipy.stats": from scipy.stats import truncexpon, norm def fn(x, z, mu, sigma, slope): b = truncexpon.pdf(x, 1.0, 0.0, slope) s = norm.pdf(x, mu, sigma) return (1 - z) * b + z * s else: fn = mixture def cost(x, z, mu, sigma, slope): return -np.sum(np.log(fn(x, z, mu, sigma, slope))) benchmark(cost, x, *ARGS) @pytest.mark.parametrize("n", N) def test_nll_numba(benchmark, n): x = make_data(size=n) @nb.njit def cost(x, z, mu, sigma, slope): return -np.sum(np.log(mixture(x, z, mu, sigma, slope))) benchmark(cost, x, *ARGS) @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("numba", [False, True]) @pytest.mark.parametrize("log", [False, True]) def test_minuit(benchmark, n, log, numba): x = make_data(size=n) if log: def cost(x, z, mu, sigma, slope): return -np.sum(log_mixture(x, z, mu, sigma, slope)) else: def cost(x, z, mu, sigma, slope): return -np.sum(np.log(mixture(x, z, mu, sigma, slope))) if numba: cost = nb.njit(cost) cost(x, *ARGS) # jit warm-up m = Minuit(lambda *args: cost(x, *args), *ARGS) m.errordef = Minuit.LIKELIHOOD m.limits[0, 1] = (0, 1) m.limits[2, 3] = (0, 10) def run(): m.reset() return m.migrad() m = benchmark(run) assert m.valid # ignore slope assert_allclose(m.values[:-1], ARGS[:-1], atol=2 / n**0.5) @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("log", [False, True]) def test_minuit_parallel_fastmath(benchmark, n, log): x = make_data(size=n) if log: @nb.njit(parallel=True, fastmath=True) def cost(x, z, mu, sigma, slope): return -np.sum(log_mixture(x, z, mu, sigma, slope)) else: @nb.njit(parallel=True, fastmath=True) def cost(x, z, mu, sigma, slope): p = mixture(x, z, mu, sigma, slope) return -np.sum(np.log(p)) cost(x, *ARGS) # jit warm-up m = Minuit(lambda *args: cost(x, *args), *ARGS) m.errordef = Minuit.LIKELIHOOD m.limits[0, 1] = (0, 1) m.limits[2, 3] = (0, 10) def run(): m.reset() return m.migrad() m = benchmark(run) assert m.valid # ignore slope assert_allclose(m.values[:-1], ARGS[:-1], atol=2 / n**0.5) @pytest.mark.parametrize("n", N) def test_minuit_cfunc(benchmark, n): x = make_data(size=n) @nb.cfunc(nb.double(nb.uintc, nb.types.CPointer(nb.double))) def cost(n, par): z, mu, sigma, slope = nb.carray(par, (n,)) return -np.sum(np.log(mixture(x, z, mu, sigma, slope))) m = Minuit(cost, *ARGS) m.errordef = Minuit.LIKELIHOOD m.limits[0, 1] = (0, 1) m.limits[2, 3] = (0, 10) def run(): m.reset() return m.migrad() m = benchmark(run) assert m.valid # ignore slope assert_allclose(m.values[:-1], ARGS[:-1], atol=2 / n**0.5) @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("log", [False, True]) def test_minuit_UnbinnedNLL(benchmark, n, log): x = make_data(size=n) cost = UnbinnedNLL(x, log_mixture if log else mixture, log=log) m = Minuit(cost, *ARGS) m.limits[0, 1] = (0, 1) m.limits[2, 3] = (0, 10) def run(): m.reset() return m.migrad() m = benchmark(run) assert m.valid # ignore slope assert_allclose(m.values[:-1], ARGS[:-1], atol=2 / n**0.5) try: import ROOT as R if R.__version__ >= "6.30": @pytest.mark.parametrize("n", N) @pytest.mark.parametrize( "backend", [ "legacy", "legacy-parallel", "cpu", "cpu-parallel", "cpu-implicitmt", "codegen", "codegen_no_grad", ], ) def test_RooFit(benchmark, n, backend): x = R.RooRealVar("x", "x", 0, 1) z = R.RooRealVar("z", "z", 0.5, 0, 1) mu = R.RooRealVar("mu", "mu", 0.5, 0, 1) sigma = R.RooRealVar("sigma", "sigma", 0.1, 0, 10) slope = R.RooRealVar("slope", "slope", 1.0, 0, 10) pdf1 = R.RooGaussian("gauss", "gauss", x, mu, sigma) pdf2 = R.RooExponential("expon", "expon", x, slope) pdf = R.RooAddPdf("pdf", "pdf", [pdf1, pdf2], [z]) data = pdf.generate(x, n) parallel = False implicitmt = False if backend.endswith("-parallel"): backend = backend.split("-")[0] parallel = True if backend.endswith("-implicitmt"): backend = backend.split("-")[0] implicitmt = True print(backend) args = [R.RooFit.PrintLevel(-1), R.RooFit.EvalBackend(backend)] NumCPU = nb.get_num_threads() if parallel: args.append(R.RooFit.NumCPU(NumCPU)) if implicitmt: R.EnableImplicitMT(NumCPU) else: R.EnableImplicitMT(1) def run(): mu.setVal(0.5) sigma.setVal(0.1) slope.setVal(1) z.setVal(0.5) pdf.fitTo(data, *args) benchmark(run) assert_allclose(z.getVal(), 0.5, atol=5 / n**0.5) assert_allclose(mu.getVal(), 0.5, atol=5 / n**0.5) assert_allclose(sigma.getVal(), 0.1, atol=5 / n**0.5) else: @pytest.mark.parametrize("n", N) @pytest.mark.parametrize("NumCPU", [0, nb.get_num_threads()]) @pytest.mark.parametrize("BatchMode", [False, True]) def test_RooFit(benchmark, n, NumCPU, BatchMode): x = R.RooRealVar("x", "x", 0, 1) z = R.RooRealVar("z", "z", 0.5, 0, 1) mu = R.RooRealVar("mu", "mu", 0.5, 0, 1) sigma = R.RooRealVar("sigma", "sigma", 0.1, 0, 10) slope = R.RooRealVar("slope", "slope", 1.0, 0, 10) pdf1 = R.RooGaussian("gauss", "gauss", x, mu, sigma) pdf2 = R.RooExponential("expon", "expon", x, slope) pdf = R.RooAddPdf("pdf", "pdf", [pdf1, pdf2], [z]) data = pdf.generate(x, n) args = [R.RooFit.PrintLevel(-1), R.RooFit.BatchMode(BatchMode)] if NumCPU: args.append(R.RooFit.NumCPU(NumCPU, 1)) args.append(R.RooFit.Parallelize(NumCPU)) def run(): mu.setVal(0.5) sigma.setVal(0.1) slope.setVal(1) z.setVal(0.5) pdf.fitTo(data, *args) benchmark(run) assert_allclose(z.getVal(), 0.5, atol=5 / n**0.5) assert_allclose(mu.getVal(), 0.5, atol=5 / n**0.5) assert_allclose(sigma.getVal(), 0.1, atol=5 / n**0.5) except ModuleNotFoundError: pass iminuit-2.30.1/binder/postBuild0000644000000000000000000000004414332717401013334 0ustar00python -m pip install iminuit[test] iminuit-2.30.1/doc/_static/bench.svg0000644000000000000000000035013214332717401014202 0ustar00 iminuit-2.30.1/doc/_static/bench2d.svg0000644000000000000000000012125414332717401014431 0ustar00 iminuit-2.30.1/doc/_static/demo_output.png0000644000000000000000000021453514332717401015462 0ustar00‰PNG  IHDR€|€q ¨iCCPICC ProfileH‰•—PSé€ÿ{ÓC@¤„Þézè½ÙI€PB »²¸+Šˆ4EÐ¥ˆ‚kd­ˆb[•b]EDY ¢¢ò.0wß¼÷æ;ÿ=ßœœÿ”î?s™Â “a )‚tQ°§ =2*šŽX@$ä­Çæ¤ ™¾‘9ýwùРi}Ïx:Ö¿ÿþ_E–ËKã"ËM㤠| Y£¡(ÔAÄ®µ:]8ÍíË‹î›æøYæØFƒŸÐ`W„åÀ“ØlQ<$:b§gpâ‘8$g„M\¾a!ÂŽ))©\„#¬ø 6Òt|Fìwqâÿ3V“ÍŽ—ðl/3‚wã§ “ÙkÿÏãøß’’,žË¡‹,R‚È+xºgäÌú’R}$,ˆõ˜c>wƆÄ^asÌIsžc.ÛÍG²7ÙßwŽãø,IœtVèóÒÜCæX”,É'reÎ1[4ŸWœ&±'ðX’ø™ ¡sœÁ÷Ÿã´¤ŸyW‰]$–ÔÏxºÌçõôž’ö]¿|–dozB¨—¤wö|ý<s>fZ¤¤6.ÏÍ}Þ'Lâ/Lw‘ä&JüyÉž{ZFˆdo:òAÎï ”œa"Û;pŽp¾ÈCaÀX3`•Î[“>݈kªp­ˆŸNg"7ŒGg 8&‹èæ¦æLß×ÙÏá]ßÌ=„høy[êl:¸:o‹Ù@Ók$íļM©OÖ €sBŽX”1k›¹K@2H…J@ h}`ŒÔf ì3R­7¡ ¬R€¬ëÁ rÁ.°”‚ pÔ‚càhgÁ%pÜw@7xúÁxÆÀ0 A"CTH R‡t #Èb@Ž;ä CQP  1´ÚåBP)T ÕA¿@g KÐu¨ z @#Ð[è3Œ‚I°<¬ ë‹aÌ„}àPx9¯‚3á,x'\ WÁGá&ø|î†ûáWð8  ¤P4”ÊÅ@¹¢PѨ8”µ•ƒ*BU¡P­¨Ô=T?jõ ESÑt´1Úí…CsЫÐÑyèRt-º ÝŽ¾‡@¡¿aÈŒÆÃÂDbâ1«1Ù˜"L5æ4æ ¦3„ù€ÅbiX=¬ Ö …MÄ®Ãæa÷c±±]ØAì8‡SÂáp86.—+ÁÅ]ÀÝÅ á>â¥ðêxs¼>/ÀoÅáàÏãïâ‡ñ“ A‡`G p k ù„ÄVÂmÂa’(KÔ#:C‰‰Ä-Äbbñ ñ1ñ”””¦”­T_j³T±Ôq©kRRŸHr$C’+iILÚIª!]$= ½#“ɺdgr49¼“\G¾L~Jþ(M•6‘fIs¥7I—I7Iß•~-CÑ‘aʬɔ)’9)s[f”B èR\)lÊFJå ¥—2.K•5“ M‘Í“="{]ö…NNWÎ]Ž+—%wHî²Ü EÕ¢ºR9ÔmÔÃÔ+Ô!y¬¼žQ>Wþ˜|§ü˜‚œ‚¥B¸Â…2…s ý4M—Æ¢%Óòi'h=´Ï T0ðìXаàî‚ Å…ŠÎŠ<ÅÅFÅnÅÏJt%w¥$¥ÝJÍJO”ÑʆÊAÊ«•(_Q](¿Ð~!gaΠªÀ*†*Á*ëT©ÜRWUSõTª–¨^VU£©9«%ªªWQ§ª;ªóÕ Õ/¨¿¤+Йôdz1½>¦¡¢á¥!Ö¨ÔèÔ˜ÔÔÓ Óܪ٨ùD‹¨ÅЊÓ*ÔjÓÓV×öÓ^¯]¯ýP‡ ÃÐIÐÙ§Ó¡3¡«§¡»]·Y÷…ž¢K/S¯^ï±>YßI•~•þ}¬à É`¿ÁCØÐÊ0Á°Ìð¶ldmÄ7ÚoÔµ³Èv‘`QÕ¢^c’1Ó8øÞxÀ„fâk²Õ¤ÙäõbíÅÑ‹w/îXüÍÔÊ4Ùô°é#393o³­f­foÍ Í9æeæ÷-È›,Z,ÞXYò,XöYQ­ü¬¶[µY}µ¶±Y7XØhÛÄØ”Ûô2äŒ<Æ5[Œ­‹í&Û³¶Ÿì¬íÒíNØýeolŸdÄþŽ%¼%‡— :h:°*úéŽ1Žû4œØNUNÏœµœ¹ÎÕÎÃLf"ó(󵋩‹Èå´Ë„«ë׋n(7O··Nw9÷0÷R÷§šñõcžVžëþò—˜_zNøœh;É8ÙpJçTùiêéœ&¨imÓXsBsKTK×ï3m­ö­§5ùµæ¬ÆÙ²s çòÏÏgŸºyaü¢ðâè¥øKƒm+Û]޼|¿=¨½óŠÏ•kW=®^î`v\¸æpíìu»ëgn0n4ß´¾ÙtËêÖé߬~;ÝiÝÙtÛævËÛ;­]KºÎßuº{éžÛ½«÷Y÷ovûwwõ„õôõ.ëíïãö½xüàÍÃŒ‡“6?Æ<ÎyByRôTåiÕï¿7ö[÷Ÿp¸õ,äÙ£AÎà«?Òþø2”õœü¼hX}¸î…ù‹³##w^.}9ôJøjr4ûOÙ?Ë_ë¿>õ—ó_·Æ"džވÞL½Í{§ô®æ½åû¶ñÀñ§R>LNä|TúXû‰ñ©ãsÄçáÉÕ_p_Š¿|mýæóíñTÊÔ”-bÏŒ(dÁqq¼­€õÄ¥³óôŒ@³ÿfü'ž¹gÄ€:DM]~Î쟞A6@A8Y¡Î¶°¬¹ÙwfNŸÊQ¶˜Yšùv—ìÛ þ!³3üwuÿSƒé¨–àŸú_G ÇË"’°VeXIfMM*‡i’†D € ASCIIScreenshotXOЦÖiTXtXML:com.adobe.xmp 785 640 Screenshot ÂK@IDATxì¼ÅÇÝH§tw+]R*ŠŠ¢(¢(ˆõAÅ@ADQT¤ ‘TD¤¤»Séîøïw`®{ï»õú=Þ9|ÞÝÝÙ™Ù™ßìÎüæœ3C²B… ]E@PE@P$ƒ@ò$SS­¨" (Š€" (Š€A@  ¾Š€" (Š€" $1”&±×ê*Š€" (Š€" PßE@PE@P’J“XƒkuE@PE@P¨ï€" (Š€" (I %€I¬ÁµºŠ€" (Š€" (Ôw@ˆe’'O.mÚ´‘Úµk|RÕªUMœŒ3š8”>ø `üؼñÊ+¯È믿›Ð¼E@Pâ”ñü|}¼"pÍ#>}ziß¾½\¾|Y-Z$çÏŸPç^xAR¥J%Ë—/—M›6IÚ´iÍ_„ˆq/_>I:uñÄîK=WE@Pb%€1 §f¦G²çK[·n!ÑK/½$h1Ç" Ç\œÿºQÎ;gòhÛ¶­üöÛo2fÌi×®4iÒDfÏž--Z´ýû÷K÷îÝ%wîÜòüóÏKÞ¼yM>Û¶m“>}úÈéÓ§ÍuŠ)ä¹çž“råÊ ¦ê ˜pýQE@¸¶PÀk»}µv 7J¦L™¤B… žRåÏŸ_råÊe̾ž@ç¤`Á‚Â=¿À¾}ûJñâÅeýúõ²sçNéܹ³dÏž]0×"¼lÙ²ÉwÜ!»ví2¦f dòZ¹r¥lß¾]J—.-o½õ·Œàëwà 7ÈdõêÕR¯^=É™3§½­GE@PkÕ^£ «ÕJxàÿW¸pa¹ï¾û¤G¦€:tK—.ÉôéÓ ÁóWêæÍ›KºtéÌ¢4|H«V­äˆÂgµxh÷¾ûî;Y±b…@>‘-"çË2eÊȪU«¤wïÞ™2ôïßßœë" (ŠÀµ‹€j¯Ý¶Õš%@æÏŸoHä ‚Æê_4o˜u æYXòG¼É“'ûnÉ7/^¼(3f̺uëÊ›o¾)ï¾û®-ZÔ<—û•+Wæ`ȧ9q~X€râÄ {©GE@PkÕ^£ «ÕJ˜Œ;V4h`Vã§ üòË/=¦\¥>uê”°€„¸:$Mš4¢BÝ‚‰xøðá&Ï:|ø°û¶Ñ*@þn±Ïp‡é¹" (ŠÀµ…€j¯­öÔÚ$plÆ®¢$$T˜ZCË¢(Š€" (Š@  0@ÖG(Š€" (Š€"P˜ZCË¢(Š€" (Š@  0@ÖG(Š€" (Š€"P˜ZCË¢(Š€" (Š@  0@ÖG(Š€" (Š€"P˜ZCË¢(Š€" (Š@ pÀpŸ]¶lY)Y²d„臖¹sçz“%K&ÕªU“:uêȹsçäï¿ÿ– xÝ¿ýöÛeݺu²~ýzO8'2d¦M›Êï¿ÿ.ôºÝ‹† J•*UäôéÓ2oÞ\þøãOxtNx~Ÿ>}¤pá¦sL•*•$Ož\~üñGùꫯLÖéÒ¥“~ýú å§\¤!Dô£>ò<¾qãÆf¸|ù ”Äûúë¯å‡~ˆTOd=Q8EBwß}÷Éäé§Ÿözöã?n&®ÜG }£F’S§N™¾`ôèÑ^ñãó¢I“&Ò±cGSú,ú\ú×=z˜ºù–íƒ>¬Y³Êùóç=é|ãèuÌ  AÇ ŽšKÌ!#&`::G÷Ÿ%«·ÞzËhÆ>ýôSyàäþûï—iÓ¦ 3Uˆ[Р½òÊ+î X9¯W¯ž!“&M’N:™?Hç­·Þêy3|Èß7ß|cÊMÙwìØ!¤Í’%‹‰q¥Ã=zô¨<öØc†2ˆ´mÛÖ¤%R8q<ÕE@ˆ7øÞ;tèôù¥J•2÷'L˜ ‰üQ(Ê~ìØ1éܹ³<øàƒ2dÈa"Û¦M›ujß¾½!DE@HzÄ f•Œ3ÊÔ©SeÖ¬Ybµd_~ù¥1¥–(QÂÌRmÉüùóËwÜaƒbåˆésò·ß~kòg¼téRCT ˜£ÕäQö9s昰‚ šcƒ L4h=1µ :Ôh ›5kvQE ^ ÿiÞ¼¹-ZÔo9˜Ø=óÌ3æ ‚e…t”/¾øÂ„sm \Ïž=å©§ž’O>ùÄôwÞy§½#ÇÌ™3ËÚµk¥Ä’:\Vè·rçÎíõ \Vn¾ùfc"Þµk—×=½P¤@´}CÁ„ï ‚¦ÍWz÷îí ¬‚à‡rã7š+¾t˜Tƒ ZÄbÅŠù²{÷n£ô½ ñ³äÏÞỒùùçŸßb¯^½L§ŽÖ™4$oÅŠ&þAÈ’%KÌ‘|1u[’NOb=QxCBI{ñÅ¥K—.†<¹ûŸ7ʶmÛ-àöíÛ…þÁG –úú#®‘_~ùEòåË'Ù³g7æXH~Óô%X/^lâ¹n»í6CÐÜaîsÌÒ¾‚æ—+hþyäÓþúë¯6Ø_xáS7ëóÏ?ïuO/E i #³íûï¿ï…„oöìÙÆÌzá£óŠäß¼wÞyÇøâJpÚ>tèßh–Ìù½é Ät‚VpòäÉžP£P´‘¶c…ؽú꫞8tìÔÏj6í H¢u‡Ǧӣ" Äô#cÇŽ5äíÉ'ŸôÒðQªåË—?pÊ”)òv×]wry¤? O¤Ï`‘¡ïÀ¿KAêÔ©!VEú4&©Á׈%®ãÆ“?ÿüÓ“¤Q£F†b…¡,*Š€"4ˆt¾ &US '"#hý&Nœ(tªø²`š &˜_£#˜jZ´haÌ!ãÇ÷dÅ,ò‰œ?¾dÊ”Éøÿ½þúëòÒK/™Ù?DÏv´ž„Î ufµ3NQE Þ€°áº‚%¢råÊ!ËÙÃÏwáÂ…†ü‘’æ«YÃÇØö“ô <&þ„É3Qú+ú1& , ÃT ùÄ Ÿl|÷ïßoü°£’¿¦Qk!€tvø·øÌ¡˜CèŒþý÷_Qü†¡y«U«–4lØPŽ9â7NLÒÑcªÙ³g¼ñÆ^Y¶jÕÊtÒîUø}z£ù#ÞÌ™3Mtö%¤£gûœ°©Ë=÷ÜcL=ø!áÄ1õGP ,ìZ´hQHHY°V¿~}3‘d§¬Õ«W7;D¥Bäç«1 •åÅõÒÊ^¦X °  á[½zµI©õúeg?Xtª(Š@ÒA ÚÐWkæºþýû +iYùÆÊ:„tt”#GŽ4×Ì!üït¬ÌX=Ëý?Ž˜ÌÂøðÙ™¯ïY˜rðb&Íj9V2ó|‚‡ó´û1éÛ·¯Ybgåh qÂv—7œ8a[£(Š@, àþVÝÙ³¸MßÙÊÊŠ¿¾jĈÆG«“]òc‰ùÕJ gØûî#+…ù‹ŒÐ7AæXÁlW óL¬ôÁ$2å ”‡†+Š@âC ÚÿHd«\¼xqÓ9ZóhdÓÇW|ö&Ä;˜?"ÿõ¤2ؾZáĉ¯:êsE úàïŒå!>‰.*XXØf&>Ë}4¯ô¹vÚòZ©IœÀk8­‡" (Š€".JÃEJãÅÉãêAúE@PE@P„€À„ÑZ E@PE@Pâ %€qµ>HPE@P„€À„ÑZ E@PE@Pâ %€qµ>HPE@P„€À„ÑZ E@PE@Pâ €Aë’õ8k}" (Š€" (qŠ€jãn}˜" (Š€" (ñ€Àøo-" (Š€" (qŠ€À8…[¦(Š€" (Š@ü# 0þÛ@K (Š€" (Š@œ" 0NáÖ‡)Š€" (Š€"ÿ(Œÿ6Ð(Š€" (Š€"§(ŒS¸õaŠ€" (Š€" Ä?÷ ·h*T’%KFˆ~öìY™ûì3™2eŠ9ú-°*Š€" (±ˆ@Œ˜€€Û´iãõùsË/¿übîwìØÑ ô+´7íÛ·÷D;wîœ9G»åOn¹å|âÄ ·£öøã φDA2GŒ!2dvíÚùÍ“ò·bÅ ¹çž{„ôÞW_}ÕèС†üíß¿ß']»v5äAù uh¶ÐÞ!O?ý´W;Ð.”Ç1@VÑêYò¡z÷Ýw þòË/åÞ{ï5Ï6l˜ÑBãSìóŸ}öYÓþù§@b5jä·XáÄ…-‡'ÔûÄû»aÃÏäÀo5PPE@ˆEb„F¦|˜IÑò`þb D£ç+h™š6mêŒMTL 4g?ýô“XîôéÓ ¡C3åOn¿ývsÀ€æøï¿ÿ iÐÊaBF²eËf4TcÆŒñ—…!Ÿ~ú©p-j®\¹üÆó Äì‹)ó:‚Fo÷îÝR¥Jߨæš|1­/Y²D>ì7(PÀ˜¾mžC î“&M2AôgÍše®S¥J%ÕªU³ÑiÜ„ ò‹©Þ-ÄÅÄË}Èk·nÝÜ·½Î³fÍ*`Ì3üI¦L™ ^¾íÛ·›6@óIùn»í¶I¶¡â„û>Íœ9Óhoy¯UE@P¸F e\?Ð>m¾~øâ'g͉˜1mÎ}+hæ j§N²Aޤñ%îHþÌÆhî}ôQw4Áç|óæÍ^áös"dÑ]–¿þúKn¾ùf)]º´!%<òˆÑ¨Õ­[×&ó_|ñE¹á†Lþø:B “”t0±~xî8ëÖ­3~ÜóM>|¸;‰×9‘úº5„•+W6q l¾iu[4¹hOÑêⓈ&Žk¢ ^={öôh‹)"76Ž=Ú7{yæ™g¤|ùòƬûý÷ßG¸Æ¤Ö ïþÙ³g·Ažc¸ñÃÁ6œ8á¼Oà„Ô«WÏ wO¡õDPE@ˆEb„b.üæ›o¼Š¹cÇYÒë†ëbÙ²e†èaNµÛ–æÍ›WöîÝ+hpÐÆýþû¹²ð:E£h¡…]$á•ÀÏ~o4š*Bœ={öxÝÚºu«¹¶ZÃ@‹$0×Bþ }ûö5iÐ*aÂ…ó´£¾Ïf ÂbiXa!þ™‹- èËHÜ|ùò™$ëׯ·I/&Dܽ­å·Û´i“°¨ì1#£…ƒL‚áv!ÐøñãM»ZŸJˆ%ZAÒG´·?a€¸ý-¹¦ísæÌÉ©—„?l!˜‘ÁŸBzŸÀ¬räÈáUV½PE@Pâ!€ø—áÐîLs¡„Áq“ ®!“­Zµ’|PúõëgüxÑ:¡ $G·Ö0P¼@áhwlL,&€úˆQêÔ©½n¥OŸÞ\"~6²5Õ¢%cáƒ[ÐzA1¥b~u š<¦ n澆„¹å‰'ž0¾Á´Ä·Z³C‡y’SG0w þš,:±á˜¼·lÙbú°zBƒ@¶Ñ&Bl™@â!û<ð€@´(?æ]ˆ½?!.Äj^-æ6mb«Ø0ŽáÄÛp⸟ê}cû ¸Óé¹" (Š€"ÛÄdÀ¤- VK†0Ÿº3æªU«¤jÕªFÄ¢e íž;mTÏÑ8Aþ(nm˜ož¬Bö%/E‹5Ñpî&6u„X|A¦¶3±¤ÌÞg‘ fgHVžx˜YÀj/:L®¬fÿ9L ˆ]¡Ì‚ÁÄú­Í›7Ïk{LÇV7räÈ€Y åC{Y³ä‚ár*4†hÃBiÿx]©Ì‚‘}ûö™g£I­S§ŽYUì^ÝÌÍ;î¸ÃĨ¢ñäÙ¾{ARFH.÷íÂŒ:x|iOKú(¤ ›}Ѧ±q2$ 2†IÕ½Ÿ"Xƒ/šÕp†ÕR4¯¾„,‚¡^ì È*i ¤‹x¤±Ä -#‹zôèaüö8‡Ù}!¶˜1!CÐØš&Ð _žÍ–3¸à#éosgLóóçÏ7&æ.]º˜ÅYtƒ€!â›G¨ø¤ Ûpâ„zŸx cøn|ý9¹§¢(Š€" Ä6Ñ&€+÷ûï¿ß«¬h£ €V+…¶Œ?rÈ¢|úÜ‹?|IÚ?þhV“²eF8‚ö-”Î_>R­$Vðù‚b†°Ø86cîÔ©“g¡ [Áà¯è+¾uâ>FCª o`Fáú/¢9dñ«‹ñS$äÔ {Õ‘§%C6<Ð"©‚lýõמh:6Èf‘¤ÓÊêÕ«½êŠéÓ6¤Í(ÏÆͯ¶»a%.+´ù?»„ûö±äó7xó㙘¹Ù.ˆ?´‰cÇŽ5[â§o¡â“&lÉê}âYµjÕâ’ð›Hú£(Š€" Ä0ÑþŸ@b¸< 6;‰¿E!˜:Ñ⸠M¸• OVB- 7-Ú8¶oŒù+W¸ùØxhbÑö±r×WÐTAŒ)/¼`ÏC³E}ü‰%ÒÀPoßtOö^´šK÷}y‹oÓ†ƒm8ql~þŽì[ˆÏ" cTE@P¸F@ `\#ž@Ÿ‡Æ !få‰'&ÐR^ÅBsùÞ{ï™ÕÞh˜UE@P¸F Îÿ'¸® >/<ÐÊñ6û®>/µÆŠ hSùU”üE5«(Š€"“¨0&ÑÔ¼E@PE@H¨04’QPE@P˜D@ `L¢©y)Š€" (Š€"P˜I‹¨(Š€" (Š@L" 0&ÑÔ¼E@PE@HÜú¹‰75NõÑ"*Š€" ( mz$¸2i’6ªLÚí¯µWE@P$ˆ€À$ØèZeE@PE@HÚ(LÚí¯µWE@P$ˆ€À$ØèZeE@PE@HÚ(LÚí¯µWE@P$ˆ€À$ØèZeE@PE@HڤȒ%Ëkþ ¨Ý®‰¿à$véÒ%Yûç I‘"…¤Ë”!BÝ·¯Þ,Gþ=(YrgpÏ0güTY6{‘”¾±‚\8w^†té#/\”‚eŠº£yÎ;yŽzq°©PB2\—ÑnON;!—¬‘”©SIºŒém°×qËòõrpÏ~É–7gXÏt'§Œîøzžðà™5ög9qø¸Ú»_îÞ'—.^”t™3H²dÉÂ.°ûÝ ;Q#îßùl_½I8ºÿÿsP²çÏ%—/]6ߣ½G½Ò¤Kkþ|ióº.GVI‘*ânW|ë¬ógÏK¦l×ù&x=æµå쩳’¿DÁ€qbúƉÃÇdäsïJþ’…$söðËê.ÇÆÅ«eÂ[ŸHõ›ëlÿ5ó—ɤÁc¥ZóÚî¤Î7-]+? ûJ*5ª0¯‰¢õ÷÷ø]ë·ÉžM;$Çõ¹½nÓÿ­ûk¥¬ú}©dp¾— Y2y÷·Ìøâ')_¿j¤ë>ÿëž|ôDHDìB©H’'O.~!Ë•û<áU*:‰¡]ß’úw7“ÂQ &û¶ï•·ï1Q._¾,gNœ’sgÎLrÞ¹GtæÔi¿qv®Û&>Õ_ª·¨¡\$8vàˆ¼÷ðk&íÐÅã%œgšÈW"ßVϼ#“‡¡0—®CzÈu9³F¸ç/Àýîú»“a‹¦Î“©OŒe¦l™åíé#äÂùóÎ{qÒ9lÙ­TköqùãûY2sôOro¯ÎR»uãy2Cª*6¨.ßíá>€ÅSÿŽo?鹿ùïu’³`Ïu\œ\8áJàôQ•㇎™<œÎ `ô+æ.xŸç¯ú’íšGšÍ8È͘¨¿;û‹ž?ôüúÅ&˜>Ò §>m» xñ^}7èKiñÈrk—»L”’5ÊÉØ7>’e3+J•&5m2=*‰%€!šÁcÒûc¥]χ%mútžØ´³A«ą́##©Ò¤–ãûG&IÀ¸‹§ý!­ÿw¿£Èâç¯ÉsÍ5'ÙgF6¾yˆþ$H^ÿqˆdË—ÓL8ÖÌ_.Ÿ¾ðžÌ0MnòÞYÞ,¹²É›S†-Ûot“·Ô5uÚ±f‹©Ïç=‡š÷B‡¤N›Ú¿{oŒ_8}Ô$s?sïoÇ^ýAƒ¾dú|/辟ÏW:ñŸ-»¼ÈvbÂáôñSÎĽìÛñ”­]YÐzºeâÀÑæò­iJ&GÛúû7Óå›w>—ru«HáòÅÍ;V»õMfr¥Мž'F”†h5Ì!ÀÕ¿ÿíeYòË|)Pºˆä-VÀä°ê·¥òǤ™r`×>É[ôzixo )Z©”ßÜ¿xù©Üø©äü!»7î0Íæe률“'ƒ[¸ò×äߤ郷{¢cæ›=nйÆÝOšvl%%ª•5ù¡9øøÙÒüá; .¶ áæië¡Ç¨!@»òΡÜ·c¯W&ý4WVÌY,Ç•2µ*JÃ{n–ôŽéËŸœ;}VfŸ"ëÿZen—º¡¼ó®ß,iÒ§•ESæÉúE«äþÞ]̽CšÐ÷£A±ß¾ä)“KóN­ýe©0êT¼jã*ñÑ3ïÈèW†ËÀßFyåÁ$mëŠ R¤bIOø~gðß¾f³çÚß ÚÃù“f›[ßì뀪FëEÀ¥ —èc޾.WVipws)]³¢‰kßë·Ö“9ηu}©Br糸aN_ýÇ2I›!1!ÖmÓÄ£EÃÌ9åãoe‹Ó¤ÏœQ*ßt£ÔkÛT’%ÿÏ\dÿ!óúG²‹ïÍiÇ›;·‘œþÓFòM£µ<´÷€ùîø¾Ý÷M]?+[" þsyÙ:UÂÒ ¯œ»Ä§t™þs=Á”:oâ ±ýW67É´O¾“»žÈ£-Åe…÷c‡ƒ{Çõ¥ÆÍumšHåôÏ4×Ùòäp´k7JÍÛÚÛX+ÆôþP ò­žjoâQÿ¯ú~*õîj*åëUõJ{âÈ1ãVóÊÄwåï ¼ V™…S~—»_ìdò#!m4{ìSv RÞ!ƒ¿|ú½ðŵ6Ø@B@„¾{˜§¬`šEûf;¨õ Wʈg8K&ÓiÓ™c‚=üÏ›ÄëHüCŽ_rdß!Öí-Ù¶r£ÔjÕPR9š‹O^ì?ÐÄï·¯~1¾]6>‹˜/ßw« 2G÷3ñ1\6k¡|Ýï3)V¥´ä*˜Wƽù±@&­ø‹ÿãÐñÆïóág=‡È ‡^uüc2šNrõËÒˆ\vþQŽcØìÓÑÓÙⓆØ2„›§'#=‰|ÚœÉDÐ HE޹MÛþéžÏ^zߘúl{dr1ʹ÷ëç?I‰êeÍ߯Ž?Ô¨Wâ£q†Lòþ#hÉy–Í\h®¬gŽùÙñ[õO.M¤(üàãÇ@ Ùss…Ê3$ãïfzå:Ò,ÉãLÒðã $…œÁ>¯3©A*7¾ÑËç¢v`׿RµY-9ºï° {¢¯!Qĵïõ7ý?3¤’ÕË ¾Ä£_&s&L•ru*RøµcF…$Yþd?Cþ˜4AŒ¾yç3ùýÛ_ímsßçÉìø+Vp´œø/yìMãÞÁMÌ™cß!ôWL ù~¹tÿa¯<ìé™]p¾ËZw4–k·¿>{?Ðqí‚åFfïCw~Ã!v[¤¶“áOö7ín]Xð¤,Ç5ÚØSGO-¤ÁìúÖÝÏâ é…ÌQ—e3ÿ² xÄŸµJÓš2Ã!ìo䛟9} 3™¹JÊ݉³;Úð®Cý»@à'‹*WÌ“$¹ãÿMùÏÖ]ž0È7²yÙ:O˜ž(‰Õ†Ñj½Ï{ 5[Ƭ™=5du<1¼—  AïÙì1Ùâhª9³Ù`òç³SÖyé6¬—ãŒ~Åd‹æþPRóö¦ãgÅD0hTu:ÄP SˆÛ©ßÓÆ±œs:ç¿]`,×þ„ø¹ å“:Ž ä™Z¤dõrF»A\ü%¿î?ê Ä"ƒpó¤#V‰<½oÊ”ÓrDj4½UšÖ2á õÝ ÑrÇÓ÷ÉMZš0Í~í{˜ Ÿ[¶®ÜdÞý§?~ÕhÞ¸Ç;0¸óëFËV´ò÷Vg2S¡~5CøÑ8b6¼óÙ‚?!$­ôW¾wÞöœ ߎ[ðuE‹Lì ¼kÃvÉêúæê;Ú¹Ož$wàgË,˜SJ(±ƒ&ñŠ;ïÌ1“ƒ&¡žÊëNoà°Íêäp%Ü&ï¤ â‚Æ"É÷òÔˆWŒö‡w“•é œ¶ÍMf>?äÕö¹Ž^¡¸„L¬ˆïªx¾]ÞÕ…?ÿf´âËg-2$׎`0Øó¨§]IÍ RÊ|Â!Fnq¯¶ß",ÌŽÈε[Í‘6¸¾Tace@+¸qñ3‘¬Ð ZßÞ¢ŽË…kŽßÑ?î§H™B*4¬”žt4wˆÛü‹æ-§%܇ü[ÈÊí ‹V{= ³6ZL´œ”…²æ+^Ðñ·üÓ!´ûäôñ“†|‡3‰åy¾Ðkó:– & hx#+iÒ¥1IΟ;ç•ô¼Ó·»Ýi¸ÉÊqȰŠ"˜PFëaÖ¨Õª‘1³õæ#žõ¤œï¬8ÿÖHÁäÄ€hÉ'BÌ$¾‹8X„®àçóþ£o˜Žm"æ\h;èʇAËbÄIž2ø«@ü˜–ØÈ3¦Ë˜ØóÃ_ Æ©n¶¼Àd‹ óÌ©+¶JéÚ*­–[›e18똑}ßÞ!4@çN_É«\ÝÊÂ÷ €xA–Иmp´9ŽŠ kØìüÓeLgL«~o Dƒ†ä/QÈ+ĦA»òû×ӥѽ·˜#hñ˪¤Hå­¦þnñ}¯Yõ¤Lýß7éÃr`«<:è9³íÕ÷ÎV,ÞþÄhè­•Á¤OõßsÜš¬³Wɯo¿iÁ$í+—/^2A¾ñ­ÿ¯o|{ –È¥«é9§o<{Æ{¢{öê»p%îEfñ„9¹úcë}Éñ Þ³u‡1#gÊêVgâÀâ ÄýN^Mð&mZó΢A¾.Èž€87ìv0Gþ=$ÙóåòDEËÊ—ß¾þÅ܇p² ±yÚïÁúüÜçl½éóÚGCòì½ç-WŠ˜˜ž´W1dëž£ÎÆÏSœþì¬CÎÑÒ±­ŒõÝóÉÞs‰ïž[SÙ{ò×ß+Œß( 3< ‰l¹ÑÊá×ÇöTLhÏ–ßmú+2†Œ²}ÌÚEm\Û|Õ_jÜRWx£›×VÏû[&¼ý‰ ]<Þ+<©^üúù¦êM;¶JP¬ú}©,žú‡t|ûÉ€åÚ·}¯ü»}¹ùòe9ãþsgÎŒ솿ôŸ÷*Õo®#åëU –Tï%p>zf€œ=u:B)ïzá!©w³áþ.œ¿ ëþZiÞ1÷R˜oY:fÊ.Î7âOÜßÑÅ åôñ“BQéõ;Š ’šFˆ_-´°-š2OÊ×­*U›Õ²AzôA`ÛÊM>! ãòàžý²dúü Ð]ÒTiRKñýÝA‘:÷—žç©T2Rùh䄇@þ%wá|Òþ•GMáö9“†ïÞ#ß¼ó™ToQGÒgÎð O%Ê_²ôþáý(?Ý_zýŽ¢ §&Tâ DOsäÏ%ãúŒ”¢•KI–\Ù¹qÉ,îX³Y ”)*5n®+%k”óÿÐÞŽq¤4ïÔZþüqŽ1•uHB½¶MåúR…=i0…Lw´kh#³åÉ!UšÜ(5ooh\भqk=™3nª“®ÜùìŽYê„Lûä{Ù²l½¤H•RJT/+-n-)S§2éFõx_*5®!›ÿ^'—¬•Be‹ÊOß'hËþø~–‰CÙÝZ»þ•yŽYtÃÂUf¬qK=)[»’‰ûÅËÈúE«Íùð'û ZÀÕÊšë¿~š++æ,–c‡ŽJ™Z¥á=7{JÌihÌ’%O.Ëfþ%7=ÐRª5«-ÏXàÔk®úç€,]DZt¾SrÈcòóý V×™£’ù“f{ÊUÎ!ñ Ú5÷Í"Â5õ©Üø£Äb\ëŽF2óËÉröäi|ÿ­†ÐMö•ìX·Uò»^Z=uŸdË›ÃäeÓ®PBƾñ‘ ûí«_œ¼–MrƬ™#~v 4q¾‹Õ¯ô#|3|÷ô|ÄdEZh»—–ìùrEÈM6}ZGò£/höP+I6‰¬‰Y$Žî?lÞý»žHrÌcLç|ë©Ò¦–¥¿ü)é¯Ë ·?q¯œ?{N¦Žœ(ÇqúÊòrÛ÷H*§Ÿr§O.~G‘À^£* DëhA|d`wI—1Œ}ý#¹|éŠùƒÎÌ-ø yìM9~ø¨ÔnÝXN=!C»öqÖw4Ï9¦¤µ®Ÿ~G’;¨¶C0v®ÝêøŸ½!CróÖÝÏ›kˆaæYœŽp„!KÜ?üïAY6k¡|Óÿ3CHJV/O°Œøß@C¢ª6¯%Å«––_>ý^¾<ÖÜãgÍüå‚9…çÖrše³É»_‘™c~6¤ÂË ²Þ!{ˆõ‚üAüŸêçÜ_iÎËׯ*×9eË‘?§CœnôäÙÎÀ3ÆÁ,GÜR©Q ùÓ!cŸ½ô¾ˆH¸{ãv™üáצ>®Ü΀ á‚ tHiÓŽ·ËÝû佇{ ¾uþ$X] •/.yr†P.48áõ:ôÏAÕbüãÐñ¦×åÌ*Ÿõ"ƒzU2dÉ(uÛ4‘Õ,HŸ›>m†t湄£Ñ  vàµqõ˜8àûG8ïÛ’«`^É[ôÊ{ê[ñ­-ć~c½CÐpÈ’;»ùÆ!z)R¦SŽuåoKM2úžéŸÿhüSy²Á™xmY¾Q²:é|åÒÅ‹æ]%MñjeL_0gü4§`¢†ê_|ó‹Ìõ¹ÓgMÿvæä“¹ýÖ×ÿµJnhYßé» “őϽkÈm…Õeö¸)b]IÜéõ;Š òWHX$z ¦û­‰³síCÌ*ßt£'».ï¿è!78h7ø3 eu4†È…s-Ü"ç¬#—Fnpˆ\Ûç;šóËNA¼úÝ{f¶ÙdÐA“Yê†òòç³åìé3ò˜¾’.Sz“†™ûôÏ~pîW0Z;fõä¹èøþ|7h´Ñ,ÞÔ¡¥ +S³¢ôkßC¶­Ü(Ū”6a™²e–g>éí!FK§ÿ)„¡±D{Y¡^5Ùºrƒ£)8ïÑ`š„ÎO¨º¯ZÆ8Û/Ÿ½ÈS.›6²ÇNýž£ñi}“õúÖCô9Ñ~˜f ( ˆì A+ò…`¦à·Û½à,ÊØêÉ­P¡²ÅL'/Ÿ•-Ž9£€³ˆÁ.¾°áîãVÇZ¤bI‘dáF™«‹+0‡"/Oä™9£að%š&ÒÕvìÛ±WzŒëgüÎf gÔ+@IDAT˜?iÎÕ‘?࿇Ưe×vžÁ„ëŒcº¢îVÜ[>ä+VÀ£Å«Ò¤¦âÛC’Öñ§ $ø%¡ ¸µË]æÖˆgÓš@·D¦®Á´°îqÒã×î·b‘(T®¸üýëŸ^îÛW_±ä/QȘv+8>¶,¤ÂŸø7»I&gÄÍ>Ú«¶yÚ#}&cˆ"«—|ZWÎ]bV-G¥±yÇ×Q¿£øB^Ÿ«D ÿª¯¨åï©ò:ĦM÷+¾_îÂÔlÕЬÈå,¤`f=kìÏÆA0ùÞÙF‚•ÃÛ»¯ú2äÍ&}Ð㿇鉸¬Ú &¤A–:ƒ fXVÁ²#:By •ú~bª°8dÀý½dÜ›#<Ùæq[lvÈ+ LØ8_AÒ}ãcC÷nÞ)SF|+¯ÜÒMönÚéIç{2éýqòòÍÝœ‘« Yܹþ ÑÆÑÞW©kîBWÒá¬_æ%&w´8Q•ĉ)üÿx7qùÀßï“Þ3d̺r„ó­¸kϪ~:±Ëæàå΢.úò±þ¶¬žçY˜K™1éâ>+‡ËׯæÎÎë¼pÅf ¯(/þ‚,°b¡EÚ iÍ¢²Èö/^ˆã ýŽâp}œ"ü§"ŠÌâ2‹dÉ"ú¶ñüíZ˜Õªl­`…Õ l|ÊJ¶ï1~b-¿[êÝÕÔFñ{d!Á÷ƒ¿4ƒûý½»8>|¥LÜokàl¯²ÊtÚ`v-ç8…[ñW>¶iî, `å/æS4ÚßâÙŦõçSgïqL‘"¹Øü 8Û zÞY±û•Ì¿ºM +Û¿ü˜' ‹J–9$‡ÕÁlºÌv.÷¿ÖÅl–ýeï ‘Åw®Ã{4ž$ö…¸e×»Ïà.}LÞ¤!¿lùrzžeO©+ÛÑàøŽ/&$”í2"ˆÓ̾x$wêX |Ó¸ÍjöÜצ']g5ó˜×>2¾boNæY%í›§^'löíøÇ¼Çöݤ´ø°>èhå dH¨ož#öAK×eð òÓ° 2ðÁ—ɶ’ãÜ®çï)Û£ h­”s|eÙ.‰w;¤uÌ¿; T&¼ålXïìH€ð¼nÃzÍb¸ý‹-«=FøhmÜßÑծӓƉãû­“Ìû¾«¿õ“^¿# ´ă@²B… yï™rµìÏMì—xj‰’bÆdAG0Œ`J~iÂ;f«’“GŽ{9‚»Ó²%š#¶CWØó 9|ðbRN?嘴S4C£%Áäm:žiû”“޲¸Ãƒ•‹m_ØÃ,ŽäN]ÉRæå‡¬1|Å2.\0{œÅpÖš]E Ô·â[l4çi?רxGù.y}ýh)CTúß²ÇÕµ~GÁ‘ئGðzWˆc­0ª8…CZÜyCŠÜ«Ý÷8÷×iûÆñ½f±˜&<Ú¥|Ÿg¯ýù'2 ±¢92‰ æ;éÎ+œº†›—;ߘ%›—­×Rž9yZΜ8¯e¸VþyÏ¡²ê÷¥×jõ´^Š@¢A e¢)©TP®)6,Z-ãß)uî¼Inâ^IŸ9ƒœ8|L¾xùüÈkÒÖ'&,>*Ýþ•Gãã±Iâ™K¦Ï—"•J&‰ºj%„Œ€ÀÚ:›–®•¿&ÿ&;×n‘âUËHÝ6M$OÑë=¥ý{ÆYðã\Góv@ –."-:ß)9 ä1÷w­ß&¿~þƒìÙ¼Kr\ŸKÞÓBJÝPÁ“6TÞžˆWOöïüGæMœ!¯‘lysHùzU¥æí }£y®çŒŸ*ë­’»žÈÄ÷ÜÐEÀ…ÀŒÑ?Jþ¥ísJÊÔ©ÌŒY3Ëý¯u•þ÷õp´DKä†[ë›ðKÖ7ƒk6K2E¥ÆÍu¥drréâEùü ¹±e©ÜøOî¼ÿ‡ÿ=(w¿ØÉ˜”§}ò½lq´Š)R¥”ÕËJ‹‡[{ž9ªÇûR¡~5Gë¸Î¼ã]¿ +æ.–³§ÏÈ-¶5yb–”Ç¡½dÂÛ#å¦-Í7ûÏ–ÝR©q ©y[C¹.gVO™øîþü»l]¹Qò»^ê¶m*%ª•õºì›÷D¼z²ê·¥òǤ™r`×>Éëô ïm!E+•òD;°ë_™÷ÝLÙ°p•dÊvTjTCj·nÖý=›vʤ÷ÇÈotÚÙ½q‡ü0d¬<ôöÓ’.Szñ‡[΂y$P¹Žî?,c߸bVÿí«_sÿROþî²æ.œOjÜROÊÖ®ä)«ž(Š@Ì# &à˜Ç4Ú9nsˆ÷}Ø  Z˜‡tySŽì;dòÆOŠÎ·`Ù¢Ò´ãír`÷>yïáÞráÜy9ûß÷’\¾,Òâ‘Ö’!sFùàñ·MçMâPyûþØ#2ä±7eý_+¥úÍu$KîìN'>B¦šäÕ\Ïý“L|w´!EEÀ—tËòQºÁCÄlkêDÝÈ~—ë®”Ï ×e’z‘DsúÞïÉagBˆðžG_QµY-3CÛj¿ÛP÷O;æoêtáü“?'ü »xáJ˜?Ü‚•+m†tI¿Ñä—¿d!sž:mSöaÝÞ6Dâ‡|øT?!/E@ˆ=T{ØúÍùí{^ŒÎâ–Ÿ?úFÊÕ­"ú?#É’%“Z­Éëw<íhæJóN­…Á$S¶ÌF‹F£B½jŽVaƒœ?{Þ´¶˜¬ZýÎs{ùlú•þöVQ˜G@ `Ìc4ÇÊn;0Ùˆ'œð@k^á^JG»gÿ¦’5®Ìöét{}3P–ü2ßG¶Ï(ì >O:ˆÚKÈÒ_ÿ”5,“O_lÇçG÷‘ìWÄ`yÛçÙãGKãDO•&•¹”¯`®rÓž™¼ï}½V@€9òç|Í‚ >~Hª4©½¢¥N{åú’cîÅÓ-ï<.‹¦þ!w÷xÈÄg5ä¨ãÊP±a5ACåO‚‘Œpó@o%…c–¶rùâ%sêþží=Žá|óîøœ³zMZ¡²Å¤håR&•l7…y8„º(o¸/n¡Ê回볧®ô#n|ª6­é˜­sÏÉÿÃÒ_z S¨! _VÔp‹µT fœEE*–”ÛºÝãyΉ#Ç=ç8¤gÉ•Mnír—ùÃ騖åë¥pÅމ)¹0Ûç¿ÁWnéæ Šó¤e×»CæíyÈÕ“BåŠËßÎÀÊ@Œé Ù¾úŠ™9‰BWc‰4pš4¼÷féwoÝ{˜Xs'‚ž(>°`á‡Èðžº'Eû¶ï‘7Ût—û{w‘ok`HÎVÇ´ ɳ²eùó.ÛÅ#, A¶túŸÆü[±auw‰};öJqý¿3óâüIsÌy8?ÑÍbQÃßÏV–ÍZh4ó,võÍÛ4öÈ¢,u<2àYtüÐQcF¶÷ –+& «~Á#ü ÷nÙe\JBÝ·ûßm{L_C¾w‡Þê)T¹lù.8m`…z ñkÙµÑîÎÄóŒãzâ&Õ6¾E fÐE 1ƒcŒæ‚Ïßo_ÿâ hSeïæ²Ø!o/5yÔøãñ Iï“—oîæ¬X\mÞÎõWœÕsÌ++ç,‘7u–?˜mîíZ·Í”-·c2BBåm"¹~ª4¹Ñ,2×g¤1-w­¯ú|X h³3GÞyƬüÅYu©¢C ÕSí”J>töþC› ñãýÚõ-ãÆÀâ¤f«†æÝÇÇ”î³ÆþlÞoÞe+¸"ðþónBÓ:&a$sŽ+&P´ƒÿlÝí¿Ù滲éÂ9ÆDuÚÜ$‹§ýaüÚ¨ßö§/¼''Ž\Ù4²ß%šL̸Lú¶;+£G¿2Ì«*U›Ö2ß? ¶¸¿bÎbù [_'þ/Ô}Vâ"3WÈ7 >&ø• öª\¤… cö%_ü+éK éú~âìz°ÕYü±JÜßKƽ9"Ø£ôž" DÕFÀp“³˜ñ5™ø «wWS9uü„³’p’q$'N“n“Æ÷Ý©Ñäáð>¤Ks ùêøö“F‹Â Ê]¶9çÇæ?M;¶2¾‚œ‡Ê›8nA3Á¶? › |Ù˜“+9Ú•v=vGs«\™Kà‹ÈÀþƒ³„UÊ,fQQü!±ê6¬—ÙZäó^C=QÊÖ®,ìÃg;ltúøI£áû~ðC[>~·y—=‰œ´kÜGhåúR…E ­ÍÊ_\%Øv¦Qû[ ´q8â“ç¾ÓäWßéyù¶mže|ŸOŒ?1å­ïôKø»Å·På"mgç‚1¯}dò}sÊ0ãGüØ ç ÁÄ„Œ”¯_UÚ¿ü˜9×E@ˆ’*T貿¬Ÿ›ØÏ_°†Å1˜~Ó;š6k~u?ó¾<é­^|…™5~@þH'ñƒåí›×8š§qV4ú+‹¿ø¦„‹ï1ÿ%"¦`»@Ä_ZÜü½ïþâºÃØ_¾ Î/Q•˜ÈƒgŸt¾K| í¤Ð·<‘ù.YÔ‚¹Öšy}óâšïLS¤¼âÂá'Ø}¶ë9IäàæKö|óq_‡* _.8Ûɸw ýéã§œº¤ôwž‰ý|`›‰½ Zþk %€×XƒjuE@PJ^›$õyÛ=’:ZE@PE@P’J“@#kE@PE@p# Іž+Š€" (Š€"P˜Y«¨(Š€" (Š€%€n4ô\PE@P$€@ÀUÀI îZEE@PE@P’$ªL’Í®•VE@P¤Œ€À¤ÜúZwE@PE@H’(L’Í®•VE@P¤Œ€À¤ÜúZwE@PE@H’(L’Í®•VE@P¤Œ€À¤ÜúZwE@PE@H’(L’Í®•VE@P¤Œ@Š,Y²¼–ØÈ;·´hÑBöíÛ'§OŸö*~±bŤaƲnÝ:¯ðÄ|‘7o^iÞ¼¹ßú&Ož\î¼óNI:µüûï¿A«ù /Èí·ß.3fÌ/>nÚzœ;wN>ìU„ìÙ³Ë-·Ü"û÷ï—S§NyÝ‹ï [î²eËŠïßùóçåСCñ]ÄH?ß~_ÁÊ߬Y3)]º´lܸQÒ¥K'Ÿþ¹\ýõò×_Eúy1‘ Q£FR­Zµm5kVÙ¹sgL<"ÁäA]Ë—//6lð[¦ HÓ¦MåÌ™3räÈéÔ©“<÷Üs2wîÜý¥ß b8ðZüFBAdëì¯?#mt¿™è¦UþÈÜ·ýÅ®]»„úú ßå»ï¾+”mÛ¶ùÞyÝô!…¶Î¾}>×ëׯ—ªU«F«Îáéã?–ë®»NV¬XNt¿qRú Mà7Þx£´oß^š4i"]»võ*mË–-¥~ýúòý÷ß{…'æ‹´iÓšúæÏŸ_† âU•zõê™{ãÆ“åË—{Ýó½È—/Ÿ0 &DIŸ>½©doóæÍ^E,Q¢„¹wàÀ3ˆyÝŒç [nÅ “Ø´i“¿[ :Ì~_ˆ.]ºD(k¡B…ä±Ç3á?ÿü³¤H‘BR¦L)`_òÈ#߉¯ìÝ»WæÏŸïœ¨¯Ÿxâ Sþ={öÈÒ¥K#Ôåé§Ÿ–"EŠ˜ÁaëÖ­Ú‡vй¿‘P8Ú:ûëÏHÝoÆ_ú#FÈÌ™3å믿U¼½oû‹Õ«WûU¼¤I“Æô£"þÒÇW]mùmíµû8eÊñWfwœ˜8g,gLŽ$Jh+œ+W.y衇ä³Ï>³A×ä‘Nüرcrà 7D¨š±Ë—/Ë?þážÄ¿üò‹0#»–$gΜR°`AÙ±c‡Wµxàs}éÒ%sX]!ßgÏž•‹/Æ:½zõòKzý•9Ö …$jHßzë­òûï¿Ô´ …yþùç3*²ÍQA÷éÓÇc aÐÆl…I…8˜ìÞzë-¹ãŽ;¤V­Z& ³ìAƒ™s~Pó>øàƒ‚©bö믿Êĉ=÷cãä·ß~´›hÃ0»!©R¥’¢E‹×Ý»w7åÃ$ŒÆ Õ;ÒW “?þ¸ðïÞ½ÛÜ®Y³¦Ñø`."-róÍ7ó+dÃØ±ceÉ’%æ^|þ„*4Á˜J0)6LV­ZeŠŒ&•:ÒÞ˜,–-[&ƒ6ƒbº}_}õUI–,™!ê˜M™¥ú駆0.^¼Ø¼{¼§¼w¨óig\èä0{3pNž<Ù”½T©RòÒK/É´iÓŒÜjÌÍXøìñ½Xá«X±¢¹dâaå£>’yóæÉ˜1c¤]»v¦l”¹U«VÆ=aÁ‚2zôhó½Ø4ݺu“*UªÍ!ï ÷W®\io›É] 6ôD ó$nÚ†þ€ºcÖÆíàï¿ÿ6ï}ý†¿¶³÷ãâX¸paðÑYéСƒ=õ[·n-·Ýv›1hë|üøqc6?yò¤q qkŽBÕ?Ô7äyx˜'¶L¼Söá} ô®{wìû7{ölóñ Ñ/ZéׯŸéüi·mœ¸8úûfø®qÓAc‹«ceGÛC;ÓŸcbDlú?þøCz÷îmªW¯.Ÿ;îî~Ý܈Ç´Ñ”1”þͶ5$­B… †ˆ9R2dÈ`,=Ln0'oÏžw6T]©?µ,.!p—™q‡ñ‡ö{ñÅM1èzôè!S§N5ÛPccÕ“O>)|óà6a„©N¢^ ÅLî•W^|.Z·-ËöíÛMçÂ@k%[¶l†àÐñ@Ð*¾÷Þ{‚i•NŸ™V:uÌGI:¾×^{Í?krÅÍ@›b f›6m<Á/zÿðÃ&Œ¦F¦ž¼tÔ…ÎΟСdÊ”Ét„ö>$„0«ª¿é¦›ÄšÖ ÁÜç¥ÅÏ2>%T¹ QŠ9sæ˜A’N2ˆ 0À?:Ø-[¶˜ö}æ™g̽Øh_H¤‰ ßTëŸÊ»GÒññ.1P1¡¼Bì ¹¦>>mÔ¶m[¡3$Nl  Ê é³‚¿)︹SØ!tVÔï‚xø¡á·Æ»dåå—_–Æ›N‘AÉß1ª M¤HüÂÍ_Û Eá[¢ß lG5e%ÌŠ¿¶³÷ââH_†Üÿý^£¯b’ëÌDø Y±uÆO‰~‘É"x[ C8õö ÙçDæhËäþFµY¨wǾLâ!‹-ŠP;^D¸‡þ¾™»îºË´ Z^¾ù·ß~Û &ݼsîwЦGia]xW9§oH(BÅŸ}m[C‚¨„þ·sçÎF‘ƒÛ  ò¸Ó‡[W_×X¸Ë Ga2R¼xqóQˆ ãìO?ý’S¯ÿþR²dI£üa\£/‰w8QkÑR}ñÅffûì³ÏÊÀ½Ú?‰ï¾ûÎtâVkFÇå«&g1 鑞={šY1Z:@ff\©R%cfÅ¡š—ë©§žòhÉ>ùä³Ã1¯BÄг¾råÊžñÑBógÕëh ™A2#Dî½÷^Cxñ¢â‹†„/^b>`êÊ óúë¯{Ê“'"“PåB«Dy!ú,úöÛo¥Aƒ†hA¨ø Àˆº ܳÕö¥Ì´‡[ 4–ìQpôí˜qŒ~ôÑG=Éî¾ûn3é 3DÃÍû‡‹áV HdÚÜ­•ödƒ'ãÇ7$«¢}(3ßžïwäûè÷ßßónŽ5ÊóîBÄi#È“)„A{èСF³Î»¬ }~™ ®æñÍ7ߨKsÄÇí"â7ß¶a÷ÿýïí8ú޻ɷí¼Ë„mÑ«[·®Ç¼ÛÐYüÆ»v€‰Z0¡ÎhÀ˜à’Í>î$ .4m¬þ´_°o(Ðs#û0™EÜmλcŸÏ÷æ91Iß¾}Ídz¢Mç³ÚKÆ(>2·ùš>mýã\|j¾ÂÅš¾÷mA4º³fÍòhÙѰ3ó•„VWVºÛ‚>íƒ>ð-¶é?Q*1qÇšÆX ¹§/ 5æ0® $ ³c€Û#<(’‰šRWœÐs-«…ÜÂK†–­¤ÎÛjÜñÜäȮڄü!t”.\0³d®Ë”)cÞŠ]XA§IüØÔÅ0ê¹víZ3s Ã¶‚iM$3û1“ެP—Œ3šdn-"á˜cK03£‰u  K|Ã)fLåLh[I“&y|B¬VmšRîY?·¨¶/åFcì»:._òÇ=kÎáÜÖA‹wá}â]¬]»¶—\ l`Ñà ÄLAÇ™ÃDJÜe¤ uš'× +øï¡)´¤2TÚtî#¤Èw…»ïªdw™lZß¶¡ „¹Û²¢ åÛ£lˆ»íøV|}@™´Å¦™‘…_LXøYáËà‚9ןÆËÖÕyùa®Ñð#áÔ?Ø7d2ñóÕoÄÝfá¼;öÑîtLFxÈ+~uqOÂL`<ýX«Ä€oßöKÇîò€ÆÌM:ˆIØ-_~ù¥1;ºÃâãœoƒ÷ùçŸÌqÍš5æÈ÷™†#(z¨—®qa¡BÿéÃl¼˜8R;!$?ú @¸Ìâ¬!ŒÛÖ•*Ô˜C¿‹0™µÂ˜Å÷]IôÐÀŽ™)¹É*rœŸy!0¯ùn/bÁsû2¹Ïí}÷‘¼H¡fiäMÇH;aãFçˆ/æ@|D0â‰üꫯcK˜Aáç|- §\L L ˜X¤€Ï# ³ML^hè(@YDaŒjûB$Ýš&wù941p¿o¶n¾ˆ½ÆTgÅÝ&6,6Žt4L:è¤Ðüò\&"¡ õr×ÙZÊh'p5fºH¨64‘|~øƒµÑýáæ.'qð¿òýŽ!Vˆ-;çî¶£ìvÒÈ=„ï06…„ra6DÓÌ€®Âw]©°o(P£ú¸Ëjñöîð|w}¸f\°×jm{ÙI?ñâS|ËݲÐO»û òsOj¢›tÒû~sÑÉ Ül[’í볤::Ï”–‰…µòŠcÃéèËéã°:Z 5æ  ¦>nÌ,y¶yDõxM@:kœc1{XÖ lCgÆ=´@çVË`"ù H~(¶AÐâŸá;hD2ëÑy5ƒqž³„$ø9b…Ä/_o,vhxC9ŒùX«­–¥HLÈ5A‚Žsí¨ ³³œiXñŸÀ™š ’—‹Žíœ(c[ðgÃoŠ¢î­_Ð~P¯råÊ /ùÁ¦Ø‹JÀ“1¦t·ÐÙ‚«øg …ÃÈ í^êNç¡Ê…ï’g 3åâóæ›o‚ˆ ¤™Y²‘Eµ}! ¾dglKÐÃÅ…÷˜v`2ƒ©‘sH·õë 7Ÿ˜ŠGçÊwÅ{€@’£+hÌùc‚ÆD„šy™ ƒ?¬ =íoZ(Â)þ¾7œÖñ_£Ìvu|°ôqyòa`p@Ó„PõçYÁ¾¡@õ‰o$œw'Ðóã#Ü_1Mc¡ˆi¡§ÿç]…\¸µî1ý,ùaIa²ê–p5Òî4áœÇw]Ã)£;Ž>W \høÃ¯øá‡6ýM0NÁBF¬ìÆ/›~À˜DIi XÂLÏš ÐV°]¾^€‡™¶ tK8Š% Ê+fÝ4‚j×.Mwçç˜Hyù1²ÀÅ uÃ\G¹Øö†ò¢ú¶¦SâÙ:pŽ)”ŽÇo'pM ¾sVp¢†âGbW‡I1-¶MíÑ¿ ³íª\,ô¡=0—#¤Çªê§OŸn4~ bäÙÖ)²íkËÆBþÜq µÿš­“MÇv4`ޝ¦ ò‡¬û.øp·¥MSG['›¤Î‹Ù*p ±éÂ)îï¼óŽ™¤àzÀû‹;ƒõ¯ Õ†þÊn¾«bñ›rkíÂ)àwŠ [/— ·ß/Ï÷m;eŠí0ZLòn?(÷sé³;~¨úó¼`ß;/Îí{ÕoÄ·ü¡Þßø¾åa @›¬Î¼ë֙߯ Tfw¸¿¸6Œº`Ý`ÒOŽ&ÝZvb³žämËñôÊdë`ãùƱ×îû6 ÷ì¹û~°º2éã/6Å–%Pà.3¾ÝôŒÛ,!-[^1>á^ƒ""§@9Á¸€ “Óð!d\¶åˆj]“9æÐÿ6óŠj. <d mLϺÐÂѨ֙:!ÀÀËñÀtèåt—3Üøä‰öƒÎ+!I°raªÂÄk§}ËMZüùSÄwûb Tvߺ$ÖkÌ8´Q bª c»Þ˜¥™,%´÷>¶ëmóUÿPßÍ'6Ž¡ÞØxfBÏ“þœE"¾>’ ½ÜQ)ßµX×Pc÷±šÄ„¦Ì“ŒÊË¥iE@PE@¸VHÔA_«¢õRE@PE 6P›èjÞŠ€" (Š€" $@”&ÀFÑ")Š€" (Š€"›(ŒMt5oE@PE@P J`£h‘E@PE@ˆM”Æ&ºš·" (Š€" ( €A³—Š" (ÿgï<Àœ¬Ò6ü½Jé ".RDX,XPWWl¨«€Ķ® º® ©¿kW@ÑUQÅPE@štÒ{‡áŸç¸_Ìd’™d&“I¹ßëÊäûN?÷ äÉ{Ê@Hl:³8Ððဠ$9`’0݃ @€D¸‡ @IN˜äL÷ @€@ ` î!@€@’@&ùÓ=@€ HH„{@€ ä —/_¾w°>)òˆÀ`É­~ýúvýõ×[íÚµmÅŠvðàÁ éŒœ@ZZšµlÙÒ®¹æÓùŒË—/ϱœÆCežuÖYÖ¶m[;ñÄmÏž=¶uëÖLå–,YÒÎ;ï<»âŠ+¬Q£F¶aÃÛ±cG¦4©|“ã@6ÇsŒuìØÑN=õT[»v­íÚµ+0‰5hÐÀÉi§fE‹µ5kÖdIsÔQGÙE]dGŽ±Í›7g‰'€ àOàСCþ·î:íØc=’%4# ’ƒ ï¿ÿ~kÖ¬™>|Ø .쾘ºwïî„`°² Ÿ€„ÚK/½dåÊ•3  „ùÞ½{íŽ;îp÷ÁJÊi<Š/nO=õ”I¨L™êùòË/íí·ßvE–-[Öž{î9+]º´óÞ‚¡C‡ÚرcƒU›Ra91„qî¹çZ—.]Ü¿ ʼn÷ðáÃí¿ÿý¯/éÝwßm-Z´°ôôt—Nã²råJ{øá‡}iÎ8ã ûûßÿîÆlÊ”)ö /øâ¸€ #/AÿùÏvâoîܹvÓM7Ù½÷Þë¾À|ðÁ`m ,B·Ür‹o½õ–ãûòË/›'þ d:u²[o½ÕvïÞm7ÜpƒI@¦²…ÃØŸD´nß¾Ýn¿ýv'7mÚdûÛ߬R¥J.i­Zµœø›5k–c|ã7šž<êMš4qin¾ùf»ë®»²xjýë†<¯Ô¢<ýúõs^ M~óÍ7N´èK-ž­^½zöꫯšÑ‹/¾hC† ±ž={š¦Øz÷îíî_yå7%çõCbéùçŸ÷nÝ{çÎí™gžÉ­›ÓO?ݶlÙb_}õ•+òûï¿wÓ‡ž(¬'œñÐ/ï¾ûξþúk—]žÛyóæY¡B…Lž?Y†gØÖ¯_o&Lp÷ò:6Ìyž4ý˜Êc>­ZµrÜÞ|óM'¢÷ïßï>oâ-Ñ-«X±¢Í™3Ç…{y¿ýö[wéý;ÒôðøñãCŠ/ï€ œäYV®\ÙvîÜé¦%½Ê¦Nê.µF*žMÓªeÊ”±«®ºÊV¯^í^jóÀMýš6mš+VÌ®»î:«P¡‚ëJµjÕ|^¯oú‚Vúü0MÅ/[¶,SÑ‹-rSÁj[ …3šv”ðõ¬aÆÎû¤5€Þ?‰ û`&¯T*[8ŒýùwÜqîvúôé¾à%K–8¾Kyþž|òIß¿#MÏ뇅Äù?üàòéÇÉ믿î+ƒ @€@n D¶Ó#H-QëÖ­Ë£M 2ï‹/SdÞLœ8Ñ^{í5×2yüJ•*e÷Üs[wÊ)§¸im­q7n\L[_µjU7%ûÛo¿eª×Û ¦ýôÓnCŽÖž>ñÄng¶vlc€ hÈó&Q"¢óá´qB¦£`ž}öÙh¶3_Êò­¢Ã*§L™2öúë¯ÛÌ™3íÉ'Ÿ +O"%zøá‡í”SN±Ã‡;ÆGޱûï¿ß–/_´bp '¸ôiii&8.>ø vÚi–žžn*Oc·nÝ:»÷Þ{`TÁµjÕ²¾}ûÚQGe[·nµ[n¹%h}©xÁØí·ßîX©¿âúî»ïÚG}´ûÌtì½q›?¾=ú裾ô§žzª=ðÀ®¬ýû÷[‰%l÷îÝîßÒöíÛ]ÞgžyÆêÔ©cŠ—H×X~òÉ'6lØ0_9\@H¿+ –š¢6¬/Ånݺٖ-[ Œä®]»¬C‡I)þ$$þfÏžíúxçw:ÑÖ³gÏ ¼¯¸â 'þ¾ÿþ{ç5’ð—_~q^¾&Mš¸<ò:Iü-\¸Ðy å]5j”U«VÍ.¼ðB—FžÃ~ýú™¼Xò ¦²•-[Ö‰_‰2yaå”—[Ÿ9yƒYïÞ½]ð}÷ÝçÒI€7hÐÀÚ´iãK®±”'·sçÎvÝu×Ù«¯¾j¥K—¶öíÛ»4­ZµrâO"óÚk¯u¯;v8¢¯. dˆô»h©K jPîæ¯¿þÚî¸ãŽ|§©/ÊÁƒÛûï¿oÿùϬqãÆ¾:_yå»þúë}÷0/¼ð‚/­<8š&öDT¯^½ì¡‡²wÞyÇÅ)—NuÈ“YªT)_™š‚S½ŠS;þñøâòëBÓ‡òÒɤwM#Ž3Æ4å®éà@Óô¤Ò=ÿüó¾¨ÇÜ]wìØÑ½×«WϽñž4#FŒp×ò6ÉN>ùdça¼ùæ›Wʦè‰6yH_{í5Ó Mʯ¼qýë_³P‘`”0”èÓt½ÆcÀ€Î#«)w™òJXúé§nzXaW¥=þøãuë¦Ý7oÞì>oºWúiÓ¦¹¶„žJ‡A©G ÒïŠÔ#D=Q€PEùmòŠháš5kl„ nZRN*ÙÑGmòlÉ$ 5•Y©R%›1c†›>»í¶ÛL_̚Δi½ Ä`ýúõmúôénúMžÌ[o½Õ–,Yâ^Çwœs©+½¦ôyäWÆO?ýä„€ÖfÝxãŠÎ7S½Z?¶gÏ_Þ:ÇO<Ñæ]H¨hJ×ß$*dâ!›8q¢[g&A-Vê§ç±’ ‘IàjšÙ¿^‘‚êÖ­ëz­q÷LÞSqõ³®wo\ô¹òLâM^C}NeʫϤ~Lx&Ñ-a¸téR¤8¥ñÆO5rBrÆ ^6Þ!¸ï¨H¾+@–ºŠD«ëò†Äš5kæ¾ÿýï;̇~hš"Ó”Y`4]&$Aç}QþßÿýŸÉ[éoZ›%Ï¥ÖWIÌÉ£7nÜ8{饗\2y|j×®í®õÅüÞ{ïÙØ±cMS2}AË+øÖ[o¹ûüø#Á¸Cdž§È¿^‰ ­É|ñÅ]”DºL¬dâ!Ñ×§O¦?b*•,© LÑ?ú± þBL(4}[µjÕ,T´þR¸FSÞÜíRmݺµisŽ6+襩K•¦€å=•€ùöÛoØ;çœsìoû›I¤ˆö}ûö9†„ü~%®ÞçÇ?ÎóšzãäÅi½³Š+^¼¸õïßß}ž´ID"0д[ð ØÛo¿Í= â"ý®Hq\)Ýý„€Ÿþ¹a:2CS–šºÕ"|-¤—Pó7}Jœù›v Z G'0Þÿ^ë5­¬<ƒ^‘”á_^¸×Û¶mË"2½)ÉE‹e)Fíùç?ÿigžy¦µhÑÂMËc¤5„7nt鵉AMy?½~hW©<™bŠÌŒUÇãh‡„š¿à“ Ó’„@Óô°¬NÆzJíüõ¬B… >Þ^˜ÆAâO¿ÞµæÔËëÅëýì³Ï6­Å”'¸GþQ\Cp"ý®[êˆÚÀX!ÔÔ—¦'å!ÑŽImZî¼óÎËÒM½i“„vºÊ´.®Ê’.’oñ¾ÄS×®]ݱ„fà™m‘”NÚÕ«W›Ä«·qCyÚ¶më²ú{+½²´‰Ek§Nê…v–Ê#ªé_oêXÜä‰Ò‘#žI8ûéŧò»¼n2í¨öLÞ8y/^ìùÞµ†TvþùçûÂä5®X±¢ûñà ̸0×´°¦ëüñGÿ(wÝ´iSßR-iÈïY@ "ý®HˆNÑÈ|!p@y>´ÞjHÆN^yUä‘‘ù{XÚªW¯îÒHÄU¬XÑ®¾új›3gŽíÛ·Ï•ÿøã;-ÆŠ— öìùçŸ7Õ£ô+V¬°O<Ñþýï{ѼC€bJ`Lq\e‡voÞ<÷®?Š÷¦'}Ir¡©ÙN8Á†꼓'O¶‘#GšDq 5jÔÈŽ9âŠÿì³Ï‚ @‰?™D¤æÊ•+ݽþ¬_¿Þ]ksÉÎ;Ýñ•W^éÊÑts:u\< @AXÔ  N ”¼˜Ö&ª}þùç¶nÝ:“ÓT·¦Â;tèàÖùIøú›Ö@ª¯… ö Ä`Óމᚦ_~ùeWæÆÝÄpó’ @æv@IDAT€ X˜T¼ÌÝ»w»4lØÐ×­_KTÓúE­»{ôÑGíºë®³#F¸iÛóÎ;/K—<¯ž6¼xv÷Ýw{—¹z׆mÑ:À¿ÿýïöÈ#˜6D""sU1™ @!à &•ƒµVMvÕUW¹ ÚüѲeË„E¢Ý½U«Vµ!C†Øüùó­Aƒ®/º´±cǺ Z'yÆg8o ÖñåE¬y;©µEF´6PSÀy)3°ÝÜC€"!€0ZI–ÖZØ_ŒhZTÓ¦:&æöÛo·Ž;ÚÒ¥K¶÷Úp¡>é(˜§Ÿ~ÚäÙ=z´-X°ÀõI}÷ᅫºÑ¦Ž_ýÕíÚíÚµ«/.üÓºˆÿýñ÷Ø*LkU—¦žu´Žà²eËü³r @ˆ)‚Ž)îάP¡Bncˆ6Û0‘X½17í«#`¼ ÁÚ¯¹š¦3fŒÛ%­4òÜI<¾ýöÛnóH°|á„i-¡Ž‡ÑzD € P€IŸºãŽ€D¯„žvïnٲŭݓhÔÔ­¼¡»v튻6Ó @€@¤€‘#}ÒÐÓBn¾ùf«[·®›îÕaÙ:B&ðÌÀ¤A!@ i “vhé @N€M Á¹ @€’–0i‡–ŽA€ à€Á¹ @€’–0i‡–ŽA€ àB> DÇ``È 9sæä%;yœp !ÜB€rG` € $,` ‡ @¹#€Ì7rA€ „%€LØ¡£á€ @ w€¹ãF.@€ °€ ;t4€ äŽ0wÜÈ@€–@Ès¶G1hxÉ’%í /´ºuëÚØ±c-§óîÒÒÒìì³Ï¶ÓO?Ý~þùg?~¼9r$SK£•Fm;çœs줓N²íÛ·Û_|a«W¯ÎT—njÔ¨a]t‘•-[Öf̘a&LÈ’¦uëÖÖ¬Y3Û»w¯Mš4É~ùå—,i€Æ{Ú´iöÝwßÙ™gžé> … ñû+ûë_ÿj½{÷6y²$B*V¬hò¾É4 [¦L'XmÀ€nÊUS¨z±6y"e+W®ÌTµ ÚhU«Vuëû~ûí·LQkÖ¬q÷òdF+ Ôf‰è3Î8Õ¯6uìØÑ]{‚X‚YuJX«Ý}š~æ™gœ˜v‰þh YÂQJ°ÈH0kú¼V­Z™2Ö¬YÓÝ~–2%†Oâr°·y@äÑòßÅ*ï•LÞ3yci{öìqÕ•*U*SµjKà®^%صk—K¸¡Æ»—W3ZiT‘„³^wÝu—i“‰·áDSÔÚ,Ó´¹^|3gÎtaš.×Z?M1Â…y´ÛYbQ^Ë÷Þ{Ï æ=LÞg%ð³êÝ{ñaG2@€@TÄ0˜Š¤§7ùeK–,qE{Ó©^=š¶–—'Ð$î$¾ªT©’)JG°Èäý‰V•·uëV»ûî»Ýº¿Ù³g›6qhcˆÖîyÓОˆõÄŸò}óÍ7NÀ6lØP·>Óq%7Þx£[³j—³/1A Hài¼W¬X‘)ÞóüÉ‹A€bM î`$¼õnÚüàÙñÇï]Fý]ëädmÚ´ñ•-q'¨ÍÁLO»„%Â<;ùä“ÝQ0žØVíüíСƒ›ª•'PÞ¼öíÛ»jµûTæMGkC‹gÞ4´75­pmR¹óÎ;ݱÖ\zmõòð>¦M›º 5ú1àÙðáÃÝy€ùùƒÅ«‹w@€@ „€%Úéú§?ýÉ®¾új;묳Üôg`'£u¯ ?þø£Ipê•SN9Å}ôQW¼·£Síй{:ˆY¦]¸Z¯Ø«W/“ðÓZF­ÍóŸjVÕsî¹ç:/ ˜hZW;O%\uV¡Ìk§¦€Õ~mFЙb9nÜ8—Fkï¿ÿ~7U¬ƒ‹µÃùÒK/u¯@o¦ËÀŸl ôìÙÓÞ£G7â­ƒµñªf‹H@ÈGqµ0”—É?ÜóúyL´“µ[·nnç°Â´~Ð_^šh¾«>MKhé%Q¨Ã‘×­[çªÑn`­½Óf ÙäÉ“M mÌxàœÐÒ.bïX˜h¦Ñq#Ú"Qçí:ÕšÉ'žxµEäåS:Míz›lä™ÒaÕ¿þú«K'Áçy,ulŒ¿8p SÛýã¸N@OSß>}úسÏ>ëv©?õÔS!ÏŽ ^ ¡€ èHš'h—ªÖáÉ# Óª„àüùó³T'(aèoT5²yóæe‰óÒE+Ú¦c[4튇꒗Pm<áçµ#ZïÞfžh•—èåHhË+«>#‘O‰”é!@ ¤€¡:HxÁ@F—=0º<) €@*Hè5€©ú(huᤗX8p *TÈ>l§žzªÍŸ?ß}ôQ_™á¤ñ%θxì±Ç¬bÅŠvðàAûꫯ|QõêÕsqE‹uq-[¶´Ž;ÚË/¿lãÆó¥»õÖ[€TÀo¿ýfßÿ½/Ž @€@¬äëðäÉ“íšk®ÉôE«ŽQOî ¼õÖ[Nü;ÖæÎk?üðƒMš4ɉ©Ü—:gÙ²eí–[n±íÛ·[§NœpÓ¦MÖ¡Cç ÌnúÞ½{»¬÷ÝwŸ+KýhРó¾ye†“ÆK{ã7:ñÌkwÇwXáÂ…­{÷î®®Ûn»Íô4.]ºxÙMQy7nÜè 〠Pò,åñèÙ³§½óÎ;îõÔSOY… \_Ž;î82dˆ5iÒÄ׷믿Þ ä¦Ÿxâ ÷eÿæ›oúâ_{í5÷¥Ù¯_?—FM?þãÿ°aƹ—¾ÐýMBAehºRùåÂrO`ðàÁvÕUWY«V­\!šÊ—@Ó¸å‡i:TâIc·k×.7-úüóÏ;ÏS …“^"QSÄ}+V¬°ôôt0`€ó^z饮ÈpÒxu«,å[¸p¡­\¹Ò ö½Ë+¨)ë ¸0MÿjŠØßû­4òHêsŒA€ ’@ž ¦Ä$ð¦NjÓ§O·ºuëÚÓO?íú¤/X½Ê•+çî%þ4µ¨5eZ_VµjU»üòË}ñJ¤/ɶmÛº©À™3gº/q‰AM©Í˜1à „³Î:Ë­éRzå¿úê«mÏž=® %J”pS‰<‡VtrgsæÌ±-Zdʬ{=3YSŸÑ6}fd?ýô“¯h -‰¶:uêøÂ¼‹pÒŸxâ‰.¹>“ž©íò,}ôÑ.(œ4^^yö4=ýøã{A™Þ'Nœè>Ç7Ýt“U«VÍ.¼ðBkذ¡-[¶Ì—N"züøñ¾{. @E ÏkkÕªe[¶l±þýû»>hŠM_|Á좋.rÓ|šÓ—»¼‡o¼ñ†•.]:Sr-Ž÷¼|<òˆÉ%¡9{ölç>|¸|òÉ6jÔ(·¹dèСîZ…¨=jË9çœãK¦‚¹É‘€’7ÞF“pÒèGŠÖñéGÉgŸ}–¥-^@Ÿ>}LAôo@ŸI-ЦýÑÆmBÁ @ñB ϰoß¾vÉ%—Øyç禂›5kæ¼rÿüç?3õÑû"üB–( 4ï Záþ×ét¯#\´VM"bݺu¶uëVç­ ––°œ h|´æRëæüÍ[÷¦iûhÛªU«Üæ ­—ó>'ªCbmÍš5Yª '½¦ešBÖÎ_Ï´>uÇŽî6œ4o:–Fžk™¦xµfQ?¾øâ ÷™“×[Kü=~ZGyíµ×ºÔß~û­ËË@€@<ÈÓ@¯¡©Bsqï½÷ºc/´NL_ºÞF¯“òÜijQÑ[ƒ¥/ÒFyIrõ®µi}×]wÝÿýnJ9W‘ÉG iÓ¦öá‡fòZiÚýÌ3Ï ê©óeÌå…·qBk9=Ó yùôy ´pÒ{^äóÏ?ß—]Ÿ7­1ÕY8iäQ–÷N2•¥×QGå–"è¨yúýôSW§Ö€ê‡…¦cÃI¯Ï¤Ž!’h•§îçŸv;™UØ+¯¼âÊ '>ßöä“Oº¶h÷¹g:+QÓÊÚà$a¨#äÁþæ›o¼d¼C€â‚@ž ¾¨uL‹¾`ÿõ¯¹éKUÇmÈãçMßêZ¦/aí¦ÔÑŠÚ¡)‘è7âeüQ¹9™WöK/½d>ø Ûù«<Ú),–{òÒŠ«Öµ=ûì³n'·Ž÷ÑÆšü2-%ÐôiçÎ]z‚†Ž ò>;òkŠXÓÂú9¥W!Z§'vh‡^ú±¡ãŠü§•ÃIØgï³ç®%©Úý«—LV}Üü,¿Y\C€ò›@Ú±Çûû£òX“¦|õe-Ï_(Ó“ôä})J(Êtè°¦’åñÉ‹éœ6ya¿lÃ)3Ø4c8ù’=„¸Î²Ó±+z¢K¤æí²$ŸÖÊ#ì­9ôÏ«ðÀÙ¥÷òÊÓœñ9·_~ùÅ ÊòNš,™‚¨òþIdææ³¤H‚ @Q'5NËt „žÄŸv÷VªTÉ}ÙòÉ'z8.0œÑ‹ įވ.üq{çw¬eË–¬KŒˆ‰!@F@O#Û¶m›Í;7XtÒ‡åJŽ3Æúöík .tÏò=óÌ3í™gž±ã?> °ûî»Ï”^vÁØóÏ?Ÿ%M8óæÍ3=Y"---œä¤ @! ìØ±ÃV­Z2>Ù#"€#FŒ°k®¹Æn¹å»ãŽ;ìСCöÅ_Øå—_n|ð5jÔÈÇLé”þÙgŸµ’%KÚË/¿ìò>Ü—&œ‹æÍ›»dz–00b¤ @ ;ýúõ³×_=»$I±=z´•-[ÖºwïnuêÔqpŠ/nuS¦Lñ À!C†8ñ§ð«¯¾Ú¥kÕª•zꩦ¸N:¹0þ@€ Ä–@Ä›@J•*eÕªUó‰?5÷Œ3Îp­–0ôlèСVµjUŸøS¸¼ƒuëÖ5Åa€ @C bغuk[´h‘M˜0Á×â>úÈ]{BP7ëׯ·ÓN;Í—Æ»Ð:AÅa€ @C â)`MçŽ5ʺvíj»ví²ôôtçÙûù短fÍš¾^üöÛoÖ¦Mß½w¡4'Nôn³¼+®wïޙ·lÙ’éž@€ ܈XŽ;ÖzöìiE‹µóÏ?ßm™}ÜãS~øáëÒ¥‹íÛ·Ï®½öZ_/.ºè"wýÀ¸tšú½çž{L:¼8_b. @€bF â5€:9»X±bn§®·[·V­Zöâ‹/Ú]wÝåkx½zõÜnßûï¿ß´6Pvúé§»0Åa€ @C b¨fj·ïÃ?ì6y*TÈ=£Wz ´³Ï>Û~üñG—NqÞ“CÓq@€ ;¹€j^ùòå­iÓ¦aµá&A€ ˜ˆx `LZE%€ @ùF˜oh)€ Ä'`|Ž ­‚ @ùF˜oh)€ Ä'`|Ž ­‚ @ùF˜oh)‰O@OóéСƒ{éH' €’ƒ09Æ‘^@ ß|ðÁ¦@ÉC˜ñ§È:uêXݺuÌ”˜@€ ˜ȳ”øÛ½{·Ýx㙽víZkÑ¢E¦0Ýœp ¦8 € @ `D<ØL À5jXË–-3E­[·ÎÚ¶m›)L7ò~óÍ7Y½€‰'Zàôð®]»¼hÞ!ÐŽ×^{ÍWÛo¼a%J”°¦M›ú¸€ Ä$'8cÆ ?~¼=ðÀYzäÈKKKË®0Åeg:uʽpáB4hP¦0n ü# M]}úôÉTÁ믿nz).ØZàL‰cpóå—_úNèÖ­›Õ®];µR ä '(ïŸì®»îÊB£J•*¶zõê,á S\(“'1ЛøÕW_!C#Q&пÿ,âÏ¿ ÀråÊ™DWA[¿~ý\â¡-Í‚ú!DB Ok‡nMš4±Zµje©S"Ož»@[¹re¶00=÷€@ì,_¾ÜÕ™S=zô0¥Å @ 1 äZêx—eË–ÙwÜ´çšÆ={¶M:5SüâÅ‹-pŠ7Sn # u;wî̱~­Ë0aBŽéH@ñI ×SÀÞôïßÿþ÷ =»âŠ+lÀ€Ö¹sg7E¬Åã£G¶jÕª™â0@ þH†kxÃ%E:@ñG WpÍš5îì¿‹.º(d*UªäÒÜ~ûí¦é"Yýúõ]˜â0@€ ‚!+¨c_rÚÉ«î4jÔÈ&MšT0=£V@ bzÔcàîßP…„z,d¨ô„C€@üÈõÀøé-¢E@¢®qãÆV¨Pèÿt”“Ò £Er Äž@èÿåcßj„â€ÀÛo¿m¥J• Ù’Ò¥K›Ò`€ ¸€‰;v´ùB@Oú˜3g޵jÕ*Kù SOÉ‚†@ E˜PÃEc!zd£Žyùâ‹/|~üñÇ.Lq $6`b­‡@¾¨^½º¯|á„A€@r@&Ç8Ò @€ 6`بH@€’ƒ09Æ‘^@€ ° ÃFEB@€ rõ$äè:½€bM@Ï÷lðàÁÞ%ï€ cxc œê Êôñ!C†ØîÝ»S}‡ Pà€>4€ Ä–0¶¼© € 8` € @±%€Œ-ojƒ @NXàC@ @€@l cË›Ú @€@@øÐ@€ [ÀØò¦6@€ Pà€>4€ Ä–0¶¼© € 8` € @±%€Œ-ojƒ @NXàC@ @€@l cË›Ú @€@@øÐ@€ [ÀØò¦6@€ Pà€>4ˆ”À„ ìÕW_õeëÛ·¯Íœ9ÓwÏ dO˜=b!8#Э[7kÓ¦9Òײ7ÞxÚ5kf}úôñ…q@¡ C³!ˆ3½{÷¶„l•âý…aÈ„D@HqÀÿÐ}$ Mñ†ãá»é¦›lÛ¶m‰Ò-Ú @ @ ;•B‘׳·cÇÖF —ô€@Ê@¦ÜÓa$&åË—‡ÝpmÁ @ 4`h6Ä@qD N:a·&’´aJB@ID˜DƒIW Ìš6mv÷"Iv¡$„ D€I4˜tE ==ݼW~µ¡]»vÖ¸qcKKK˶ŠË/¿Ü€Ù""€€!ù@y&ðÜsÏYáÂ…­B… y.+»Þ~ûm+]ºtÈ$µjÕ²!C†„Œ'€~'køÈ#¸_ã¥J•r¿ÈO9å \x=wî\kÙ²¥U®\Ù½t­0 €@nȳ7gÎkÕªU–ìòüÍž=ÛÊ—/Ÿ%Ž@ÈL HæÛðî:vìhï¿ÿ¾éÐÕSO=Õ-Zd?ýôS¦Ì7n´öíÛ›ŽdèׯŸ+V̆ æÂÆoÇsL¦ôÜ@‡€6xèÇæG}dûÛß\–+VXíÚµÃÉN@È ±üì³ÏœøÓs8o»í6±mÛ¶Y`Ž1Âyû>ùäÓÚ™ÄbÆ MqwÞyg–<@ñGàë¯¿Ž¿Fe´(»©à¸l0‚ G"€¯½öš5oÞÜ'þBõE"¯jÕª>ñ§túå^·n]`(h„C Î4iÒ$ÎZDs @ "^øë¯¿Zƒ œˆÓÙË–-kgu–Mš4)S{Ö®]k-Z´È¦›N8Á‡A€  ˆàªU«¬^½zvÍ5×XëÖ­í©§žrëû´Áãûï¿÷õbݺuÎãç øß…¼€Š e'N´*UªdzuèÐ!TrÂ!  gó0À¦M›æZ;yòdwÏ3{`ðh" ”"ž>räˆÛü¡ ×]wƒrÆgØÙgŸmO?ý´ý÷¿ÿÍ3¨gŸ}6SÚõ÷Ì3Ïd ãH 3gδK/½ÔV¯^íkðš5k¬[·nöÆoØ[o½Å¹}>2\@ˆ ˆ`µjÕ¬hÑ¢>ñ§f6kÖÌM{¿î¦tÁžÝ©0Å…2yõò·¯¾ú è„k$yøÎ9çÛµkWÐëX(ß2kÖ,Žo Jˆ@@ùC â)àêÕ«‡lÉÁƒ}qJ7uêTß½w¡5„Ù•á¥ãH|òòíܹÓ4sÌôô•+WºY…`ñ„A€@þˆXÞrË-¶eË{çw|-š1c†[ÿW¿~}_˜Òišçã?ö…-Y²Ä/^lŠÃ ‚%0|øpó^ùÕÿÿÙÕ1nܸ좉ƒ (ˆx ø¢‹.²FÙõ×_ot:ÐYG¾ìÙ³Ç:uêäkž—îž{î± 6X‰%Ü—ŽQ,yç´!Kºç—ÉûŽi/@±#±¬X±¢}ðÁvûí·ÛÀ]KåùÓÓ=´+Ø3ÿt=zôð¥S^Åa€<eÊ”ñ.y‡ ˆXªMòžû¬­á¦ –—0@ ñ 虽:ÚIkýBY¡B…Üáò¡â ‡ èˆx `ô›@‰€@²Ð4svâOýV|~NC'+[ú@ /€y¡G^@ [zx×®]ƒ¦‘çO¦xÿå#A@Q%€Œ*N ƒ@ÁÐf¬´´4w6gÁ·Æ¬ÿþöÉ'Ÿ¸ÇFú·Gëþ®øx°Æ;nòZb€’0ÙG˜þA ȸcÇ÷Ä 5§mÛ¶¶}ûvS8@±'€Œ=sj„@Ê(Y²¤ë{éÒ¥S–‡ €ñ0 ´€ Ä0†°© € Ä\ § €@|Ø(ݦ/Ûl³Wo³RÅŠØQ%‹Z¹ŒW•r% ¤Á÷ÝwŸ{â‰*ï½÷ ¤ T @ Þ ãmDhÀÁÿô¼÷ÀakÜýó=X»x£‹›»f»Í\¹ÕšÖ®2m4#Þÿ};ñÄ£Y$eAHhL'ôðÑx,;÷ÛÓ£çÛËß,v 9œ~$¬­Ü¼Û®~i’Ý:ø'[²>¼ç‡U0‰ @ ,xÃÂD"@ÀŸÀ¾ƒ‡­ßW ì͉¿º`MûæÆ&,Xoz]Ò´†u¿´‘U*S<7Å€"$€ŒÉ!ê¦-Ûb÷ð³­Ùº7j(>›¹Æ&.Ü!ÛÍkF­\ ‚ à˜Î…P@ €€¼~|8Ë:¾ò}TÅŸWÍö½íá3¬ó?Úúíû¼`Þ!@  ó*EB ÙìÞÈ:½þ£˜º2ß»6iÑF»¤ÿ·6oíö|¯‹ ¤*`ªŽ<ý†@˜6ïÚoí_þÞ¦/ßf޼'Û¶ç€uøÏ÷öãÒMy/Œ @ `$@5[÷ØU'ÙÂßvxA1{ב2ߘbãç¯YT@ U Se¤é'"$ ñwõKZï·'œÑK~(ã|ÁÛ†üd£f¬‰^¡”@†äCd!°#cCƃ~´;sÞŒ±ã—oL/Yú¡ý¶iÜëvpû†,eæ%àÁ3mÆŠ­y)‚¼€ àGèƒK@ÀLgúi'®kÎÎÒ÷ï¶5ï>dF°›Vþž4ý°m›6ÊV ¾Ë' ³+#Ü8yo<¥@½‘á¶•t€0F‰6B FÒ±;ßšj³Wm˱Ƶöµ½«çM—~`Ÿ†{WÎ Ÿ›@£È»öÊMvò@€€  .!êúþ÷û.ã@æœLS¾ûÖÌÏ!Yš­Ý?‡4‘E/ß´Ûþž!P1@È`Þø‘ICàË9ëì–‡ÕŸð<{GìÐŽQ_¨£aþýéܰÚI"@Nœ ¡H)K7ì²>˜vŸE°ÉãÐöèã2dÒ¯vè˜?Ù®]»Üë裻í$„ c0¤:CéGìöŒ£Vöf<ê-?¬P‰ÒùQ¬=úß…¶í@š•.]Ú½ò¥’€BW¯^m·Ýv›{=: –[@‰C`âŒ-…@¾óË:[‘ÃŽßÀŠKÖ>)0(ä}ñÊuCÆå%B§»cèTÓáXÚ AƒL/ €@"@&òèÑvDÀ’õ»".¥ü)—Y¡b%ÍÒÒ²Í[ñ¬ŽÙÆç5rÁºÖ'cã @‘@FÆ‹ÔHéS¿¹µBÅK[•‹ïµBE‹‡%k5¶ü€jÿûSVØ„Ñ_g˜[6äƒ €‰0J´Q$°|ùrëܹ³mܼٕº3ãH—mÓ?¸†Ò'´°×>i%k6Ê”WžÁJçÞb5:>ž)°i•­ÿ¼_æ¨HïrXiq‘¤ÿdúj›¼dS$YH @ e Svèéxª¸ñÆ3öld³iãHºظÂ=Ë7QÙ<0|SÁ‰:x´ˆ)`LqS †À¶mÛlÕªUv$ãY¿Ù[ší]½ç÷f_Wôc×oßgO~üùÄѯ!$.`âŽ-‡@&y}úô±¯¾úÊ…Ï;×î½÷^SøÌ™33¥ }“ñø¶žòºœ‚‹þÓJ›·v{Ø ð6Åè]öÑGÙ€7À@IH˜„ƒJ—R€ÞÉ'Ÿl½{÷¶ß~ûÍؾ}»õïßßj×®m‹- ŠŽxItëõIx^Lm†iÒ¤‰Û³{÷n×m=í£[·nvÎ9çD œí‡R0ÕFœþ&yø.½ôR7Ŭs6÷ýóŸgö•%,’§|dÉ'3Wn5=á$;“hÖq8;wî šlÞ¼y¦u“â‹AH6ÀdQú“räõ“×*Ôú¾ôôtÛ±ó·Hù*Ù³ÉØ R¨X‰˜á’}£rûøgs³}Lœ¼|… …þ/ððáÃ6gÎçEÍ}+È @ > ‰E³ôå$«Y³f,ª£¤o¾ù&¬þj‡oéN·Ý‹§dM/ñ—ñT*ßgù9\µÝCYëΧ5[÷Ú[“—‡,ýÛo¿ ç¡ãs0@ÉF ôÏß=Õ"s%øjÓ¦M–Z„~æ™gZ­ZµÜK× Ã èøå—ð@®tî­î)î9¾~MÐÓ<ôT=Ý#?­P±R^Æß_ùYÊN߿ۺ÷èi áªZ¹r¥›òÕfHDÝÏ?ÿœßM¥|@1'k ¦²3-Doß¾½K2~üx+[¶¬=õÔS.ì믿¶ªU«f—8@ LÕªU³uë²_ïæU´\e7Å«'u,xƒÞ³=ãy½×f¼:xI’â]O4Y÷ñ¿íÐŽ¾þìÙ³ÇmöÐ.ß'Ÿ|ÒžÓÅŸÿü眒@ áäZöêÕ+ÛÎjw¼}?üðƒµhñ»WaøðáV±bE÷ŸðC=”m~"!ðœvÚiöé§ŸšÖú…´ ¯}ñcêdŠNËfý[¦„ v#ÏŸ;Öq`óµéãÿø‡ûºaÆì¹ed®S§N`ÜCHxO‡Ûc}!xâ‰>ñçå«[·®û²òîy‡òF@ÞølÅŸŠÏ8ºÒ¹·ä­¢ɽmÚ¨ß=O6 eÚüQ©R¥¹•)SÆršíUá€â™@® ¦põŸ£¼Z¸víÚLý\¿~½{è|¦ÀŒ @Åa€@t4mÚÔì Ëò¨· ÏŸ¬|óK-ŽwqÉáÏÞ•9Ÿ(Á¬µ“7Ýt“+-p7°wÿâ‹/âÌ7Ñ€@bÈ•¼í¶ÛLÿ1ê´| :½_wÝu™HäÛõ«°ìàĉ³l0ùë_ÿš©ln Ì:uêdZk«CŸý­H™£­ÚX¥ónõNêëýë—„Ý?qûä“O¬F™ò´lÙÒf̘aŠÇ $#ˆ×êÑRGu”E—.]ìî»ï¶Ú¨Q£ì²Ë.sqòD;—LaY¼¾Ò~¿øòË/3…LŸ>ݺwïž)Œ@ 3Ö­[›v¸^Õá:ûøƒw­xµ¬Ö ÏeN”wÅ«ÔËxžqx;£å=-_¾¼µk×Î4h` ,°®]»rö_ |Nè"R@ÄÐ_üyð®ºê*'ýõW/È´3Q_F¦0Å…2ýòÆ J6mÚd›7ÿ±a¡~ýúyêþ¼5¿?7­Pá<•“¨™‹dìt¶UÙ·^S¼òúIüyV¸pjòòúÏ; Zr5ˆHG¼ÈŠ+拪^½ºM:Õwï]H$*ƒþ   SzEr¦ß¹ÿ¸š›!þÖlÛûG@ ^éX=Ñ$;ÓÀ^x!»$ÄAHjQ€¯½öšƒtì±Çú`ÝrË-¶fÍûøã}aK–,±Å‹›â0@ úžûr~ô M°uÖa¥óoÿ½ÕÿÛãëÂÿáF7íë ç€@Šˆx Xë÷¼c4«SògÏžm§Ÿ~º]|ñÅ>|]t‘5oÞÜî¹çÓY[%J”0ذaCSD—À´å[lâ¢?>Žné‰UÚQϳ╳Mß¼ži= 6ÅsþmÖªË͉Õ!Z @ Ê"€wÞy§{Œ’y>tèÛ,Axë­™wêÀg=£´GöÜs¿/D—ð{ï½÷¬\¹rQîÅAÊcý?Å+×µ·MãÞ°mÓþkÅ*T·Ú·¾â’¼öí»éìã¬há¨L‚øWË5 „ ±|饗ÂëlÂÆEBäšÀ„ëmÎêm¹ÎŸÓþ{[w°÷§¬°Î<.%ºN'!øãÄÀî!¸"ðî»ïÚ™gžé^»víÊÔ¶g¿Xé>¡o2ŽŠZ=ì÷Ú1kL¾uå?ã–Øáô#ùV>CˆgÀxÚz¶¶^þöÙ¬5¶ð·þA ½oíÓ+?mãÎ}öñô΋ÉÏP6 $€,@øT hxaì¢h“’e¼ôÍ"KÏð8†c&LÈt‚ÁC=dC‡ '+i Ä`Ü ‚@ø´ëwÙÆÌÓÁáç&åš­{íóY™ŸcŒJ·nݬM›66vìX_´ÎlÔ£â¾më/}`¸€‚0!†‰FB 8׿[<‚а ügÜâŒÇV†NÞ¿÷¼s¥ÐÒžyº”gPÈÄ $`"m…€ëvØäÅœûç‡$W—‹×ï´±s šWg†#î† b3gÎ Z€â‘0G…6A ¯‹÷/ La%yy\ðu”€áÚÈ‘#ÃMJ:@N âs ¼Å4° ;ö™vÿbÑ! g(Þ(KašÞ ×ð†KŠt€@<À£@ !w~XÎv2Ë)ùæŒÃ¡­iÓ¦A!ï#I²" ĈÀ¦D“Àˆ©+3Š+Í"óTVá²­Ê¥ÿÌSyßÁÃYšP§N,a¡€¡ÈÄ#<€ñ8*´ 9ؽ?«XÉ!K¾F—mÐʼW¾VãÂ%êºvíšm­… ¶³Î:ËÚµk—m:"!Ä`<m œÀ–]™§‚{÷îm7Ù®êÕ«Û°aÃBÆ@  ãqTh P`æ­Ûž©îòåËÛœ9s¬W¯^V¦L_\É’%wpöìÙÉT±¯.  `§j@ þèÉ*Û÷ÌÒ0yçÏŸï ÿðÃM‡DK b€0ÑFŒö¦,XŒå?ôô#6ì‡eù_5@(@À„OÕˆ„À„"INÚ<6™cvò€¬€@à˜$šMKÎX›•ü#°i×~û|ÖZ»¬Yü«$£äN:ùÊ×ãä0@±"€0V¤©y ðÊ„%yÈMÖÜxý»üg¾oß>:t¨­^½:7M$ \À˜ktd„@llܹß>ž¶*ê••¬Õ$êe&Só×î°+¶Z³c+$S·è  GÈqN@}ËKô'wä“À2‡Lú5C6 æ€@Â` 8á‡$3ÃìH-ÐáýrÎ:Óz@ €@²@&ÛˆÒŸ¤"0zöÚ gÒ%U'ã¸3éGŽØ‰¿Æq i Ü@掹 #GŽÌô Y=m¢OŸ>¾²ßžÌyt>tñþO+ìÀ¡ôªj!äÖæWJ…@Žtˆv€*ôÇï°¹sçš^_ýµ=;è· !Ç‚”©¶é…EFàèV‚fÐSA>ùy•µ?íØ ñBHDÀD5Úœðô1‰?YzzVïÒ¤I“ì†;™µ¹×¥‰äOéãO‰$9iÿG ;nƒ3¦€|T d"ð‡ë!™zE_ ǶmÛf={ö̱…‹§Ž·½+ç䘎ùO`é†]6yɦü¯ˆ Ĉ0F ©™3gÚÎá=×wïª_¼l¼0¡GÂ`€’…0YF’~$ &„ÝVϸåû÷lë÷ïûò­û°ORzÕß5ïw÷õsëO™úžW+T¢L^‹°ñ ÖÛÚm{Ã*ç7Þ°F¹×¡C‡ÂÊC"@±$ÀÀXÒ¦.dhݺu¦¾ÙA)^¥®­|·ظ"S²½kæ9¡Tþ”ˬҹ·dŠKÔ›Mß ²mÓ?Íh~𝠷®sp×¢ÉVíÊV´\e_\¸•Îí’Á¨K¸ÉC¦Ë8Æ>Œà‰,óæÍ Y€ šÀ‚êO9uêÔ »Ï»—NË"þ\f©‘ Û6m”{¹›þãúáÄŸ:ñ{ßü»#¼áóçýƒ äzô¬5R/•Bˆ6`´‰Rr صk×ìS¥²¢ªÛÁ­k³O—»eÒ»9¦‰÷[&½“c÷®žg;~ù&Çtù™`÷þÃùYÎ Îñ=’´9ãE cG‘\l‰qw¨€@B@&Ä0ÑÈT$P,cp¸¦Ý‰j%kŸvÓ‹WŽŸ~î;ÈzÀ°Ž„€@Ü@ÆÝÐ üNà¨ÆçY±JÇfœŠ’ý?ÓŠgutÃDæ¦>dkiiޅ޽‰›¸hc¼4…v@ˆ˜@öß,<ÃêÕ«M/ ˆŒ@•Kî5m e%k5¶ÅS¨Ìq®>¨/¡¬PÑ&ñdßf AHTy€§Ÿ~º¥eü:ïÓ§OZä~æ™gZ­ZµÜKב<!K@ Áî%ü»ú¢C­×ó½I+\ÔÊ6>×êüýMÇ"ž:¹~Ç~žOB[ ˆäIöèÑÃZ´h´Â¹sçZ›6m¬L™2¶xñb[µj•µlÙÒ…)ƒ@*8ãŒ3¬X±bv÷Ýw‡ìî'ÓW…ŒS„6„hcHå‹þ(£v—ÿXÎA¦Ž„ëêØ_~³;÷'\»i0 \ À={öØý÷ßow¡ì«¯¾²O<1‹‡°nݺ¦8 07½mÚ…€HÔÏ‚üSV$jói7 Âr%|ðAkÞ¼¹]sÍ5!Ñ­[·Îš6mš%þ„N0Å…²õë×[àkÛ¶m¡’„&ðÞˆ‡DÀb•jg¬S¬ík¶¦%1@‰D H¤}ÿý÷í£>²ï¾û.Û¬k×®5=ó4ÐöñÇûî-ZdçœsŽïž $+µÛöÚÄEá?#Y9$R¿´ù¦öÍ35YSÀ_Ï]o4®š)<»›åË—Û½÷ÞkcÆŒqÉ&Mšä–ÓèÉ0ÁþßÌ®,â ä†@D@mäèÞ½»=òÈ#n]_v–.]ÚvìØ‘%‰ÂÊ´iäçŸÎôz饗B%' KàÝ–Ž£„¾L d3ˆNBhÒ¤‰9Ò´œF¶ÿ~5j” 2dˆ ã ü$‘ðõ×_wÿAmÞ¼9è±/: ¦W¯^®½U«V zöŸÎT\(kÖ¬Y–¨ ð’dB@B8œž±vì§• ÝÿÉK6š<ºÕË—ü#0È•<—]v™Oøù'IOO·;wÚ=÷Üc­[·Æè‡k@ ê"€… r¿ZõË5Њ2=ê@IDATz÷îí‚<X¥J›>}z`2Ó€ŠÃ ʾœ³Î¶í }þ_*³Iľ˓ûÖ÷Ëì¡‹fÛ|=ûY"/;Û½{·)]°ÿg³ËG HD4,qw$ã:ÿ×øñã]}€ ÷L¿b׬Y㎊ñÂtþŸÎTT&ð>;G“nø?øi…8”žm¿¦M›–m¼"å 7n\ŽéH@ /"òFR‘μúê«ÝNán¸ÁŠ-jS¦L±K.¹$äÙ‘”OZ$*›wÛK7%jóiw»ö²Ñ³×Z»?× ‘ÂÜâ‘~9y ý’r @ W"ò†ªAëU‚ÙðáÃípS[¶l±‹/¾Ø†A • ¼óÃòTî~R÷=§3«U«–Ôý§s€@âȳPâ/”=ýƒ~' )ÂSW‚#I L[¾Å–oÚ²w§vš}úé§nš7T"­µ¾ôÒKCE@ *¢âŒJK()@àóYkMS…XòÈîH˜þýû[©R¥²í¼Öz›ê²MH$ <@æY!)÷¦,4 éŒÀ‡SW…|2ˆy~ñÅ]äéó7ï~ðàÁAŸ¢äŸ–k@y%ù ¼–F~@ $ÅëwÚŒ[CÆ‘øÒ÷ï¶e£ÿcwïéëÌù矟éH—N:ÙŒ3²LójÚWáŠÇ ä7`~¦|üÀ°ÉËa‘Änß`+ßcÛ¦²ÍþxÞùĉÝÉ;wöõ^ÏI×9íÛ·waçwž»öüt_&. D‘0Š0) ¡ÊX×õÉôU¡¢ Oë?{ÎíÜœ¥'ZÓ'Ó#Þ´ƒ €ñ0 ´!é ¬Ø´Çö<œôýLÕÊë·oÍ|³#Ùí=))U9Ño@ ~ ãg,hIXº1ûÇ%q×S¢k‡¶¯«Ÿ;vì° &„•–D€ò“0?éR6þG`óNžû›Ì†ý–…Ý==ƒ PЀ=Ô$<"å*‡ÝƒA(hy~HAw€ú!MšžÛºõ÷£Z6lhõë×ÏSñGŽÉS~2'â•ëÚN—ccË–-›í““r,€€¢D%“<®¼òJ×™ ä¹SÛ÷ «ŒjWv+‰â“@ùS.³³ÇÚÍ;½³ÙÒ·oßøì­‚RŽSÀ)7ät8–¶îÎyí_á’GYéz§û^±luE@•Kîµ"e*f-0-Í…ÝtÓMÖ­[·¬ñ„@(À€N•ÉO`æÌ™váÅ—Ù–U‹]gwÍ›`ë>yÜô¤,9 h¸öÍ/Zùæ—Z¡e|,Y³¡õð¦;ÐÈ &€,à úä# ›5kfc¿øÜ7˜~pŸí^ü£-ÿÏͶwåœäë4=r /m•λÕ*µþã©ÕÛ?f+K7€ ¸"€Œ«á 1‰N@›H¼G~ ²LBpÝÇåÚX¸T9Ó+Ù-Ùú9iñF[³uo²ýƒˆ›@h°hjüЯ´Œ5_!wÿfì N?°×6~3Ȫ´l=XÙ­L¯¤· ~ÇÝõvRuS›ÁGL]aÝ.81©úEg Ä%€0qÇŽ–Ç!Y³f…~í=¸uß—©@`øO«,cRa¨é#‚0!†‰F&Hñåž›¢Q#°qç>??¼GÆE­R ‚ ‚0‚!)Ö­[‡¥X¥cÃNKÂä!ðþ”•ÉÓz$4`B7'Ÿ|²e,̱YÅ«Ÿc$ïn0y1@MXÐ#@ýIEà†{{fý’Íãß2Äa¡b%옌£B°Ô# 5€xSoÜé1â‘0G…6%,é5­Ò¹·üÞþ žÀBE‹[•‹ï3‡¥&÷~\ÁfÔzz ¸"€Œ«á 1‰L@S{šâÓsakuêŸñh·Ó2¦ƒÿ'–V¨°•>át«Õy`Æ{‹Dî&mÏ#ß?'óX Ù!ä0oüÈ 2ø{Ç|è±`Õ®ènÅ«çâËžôw_´\e_z.R—ÀSV¤nçé9 €q1 4"Ñ hÙß»S{Â!0.ã86ƒ„CŠ4€@~@æYÊM)±»3¥<•§xÄÔUy,…ì€rO˜{vä„€À?­ô]sp ÿiE¶ÆÃ)ƒ4€rK€gç–ù ð?[w°¯çþDD`ÍÖ½Vx×þˆò€@´ £E’rR–Àð©lþHYt}\%J”°|0/Õ‘€€#€þG wïÞÖ¾}{Ë.»Ì ໼عï }ù˺À`î!yåIÎÎú÷ïoú|b€¢E-’”“°¶mÛfMš41yY6lØàëÇ¢E‹¬[·nÖ¦MSš@û0ã7MáaÈ+ž ’W‚ä‡"%€Œ”铎@§NlΜ9!û5a„ Þ6„DFD„Æd#¤ã„0@±"€Œiê‰K3gδÿþ÷¿9¶MSÁJëÙÏ+¶Ø²M»½[Þ!'ò$4'ƒä "™!ˆäjÈÒ¥KmÕª?þ³*W®œ5kÖ,hÅÛ·o·•+Wº¸Úµk›Òbˆ#GŽ »)€M›6uéß›ü«I?ì®Ó » B ·'/³.çŸífPy ‡ )ˆ ÖCiJÌßJ•*e<ð€õêÕË?ØFŒa×\sM¦°áÇÛÕW_)Œ`kûBµeùòå.J›?† |Æ6MnEÊU¶:·¿* á)L HÙJõ~í¶½¦gJŸS¿rDùH @ 7"ž¾ð í½÷Þ³_~ù%ã9–GlôèÑÎû§jcÇŽõµAÞ‰?‰½Å‹;¡Ò(Ì*Í— òåˇ]«çý5cN?v>¦£šüÅêüýM÷ŠÄCüî+R=† „@Ä𡇲:X£F\ƒõ£®]»ºë¹sçú:1tèPwýØcY½zõ¬fÍšÎCX½zuóâ|‰¹€@h×®]Ø5שSÇ¥}/é°™‘02ã篷;y>pdÔH ä†@Ä0X%S¦LqÁmÛ¶õEOš4ÉZ·nmúÓŸ|aºÐ½â0Äyõ.¿üò›¢9J;{õ6[øÿí|TUöÇOBB!$„!tQCéâº*MtaEPÀÞu×ÿ¢.t]vWp»‚d•&]]zgé½$BH!•TÒ‡ÿ;7¼É”÷fÞLf’™÷~çó™ä½{Ͻïžï›rÞ-ç^Êsªp‡€IUY°ëœ;EQ@\"àò@¹vyàŽ;hÿþý"`®¥³—––F;v”ÕÍÿ¹'pË–-æsÛ¥pòÜ+[]œƒ€'Ì›7†Jü^¶”ÀÀ@2™L4`Àâ@¼,?îÁ%#{žÀ‚]ç饻o¢:ž¯5‚€À5n;€¼D–§Ÿ~Z ËçüŸ@völ…Ó8OMxR~ÿþýÕ²‘'Àó¹Wšç¨.]ºTÌoå‹ôèуyä šÏ‹J+hå¡ |¯ȹRJ¿J;ÌÜ×¹…×®ŠA@Àí!`^¯M›6QóæÍ)::šÌDÃÃÃwO`óÔ¤}ûö”’’bõZ°`š:ÒAÀcØœ={¶¹¾¸¸8³ólj«$ç@x›ƒx›0êpÛ”Ññ<¿W_}Uœ®[·NN&^ì¡4tËiœ§&111dûjܸ±š:ÒA Æ,ÜXc×Â…ŒM`·´7ðù,7ö»Öƒ€w TÛäæq^Ó¦M­ÂÀðÞª<ׯ°ÐúKŒ{ 9þDàHr¿ëOMF[ýœÀüX âç·ÍŸ&à²Èó–’ŸŸO/¼ðeddÐ-·ÜbÎ;v,Ñœ9sÌiÜCÈ çA@ÀŸü+3ýév颭Ëö'Si¹I¶Àß#àò"V­Z‰ð.ìì]¾|™V¯^MìrÀç?üÐl!Çä´×_]Lª¦­[·Š4΃€€¿àIùk_t«¹-ÇT}&ܪ… K  ¸œVL¡Q=[– ð—{ÿþ÷¿SÆ éĉÂ?~<­ZµŠx‹7[á4Þ"ŽÄììlzðÁõlËá|‰ÀÿKr»'& 8„ä—/Ù„¶ø»ý£¡h%€€ßp¹:W„Fø+ÊÀ¼‰þÚ|´ÛÏ ð¼S>Op¹ÐÓ @} àËxk®Ôœ"_n"Ú¦s w%êÜB˜ PàÖu\ÓoÄíLô›¶¢¡ú$Àñ'¥«ð(8€ʼnÊôD€{þv&dèÉ$Øâg ãwSÂW/Pnnå0ð´iÓhâĉŠAöýÌ44@ – À¬å€Ëû.Ÿ¢çÅwïŽþ[–¶v¥.ÿ€J3“ÌÆ–””ï]ݺuk:tè9  à*8€®ƒ¾aüz̽Ð/†C½F gßJÊ?¶±²~…ñß‚‚6lz½vP1èŸ@ýßcXè&+%Ø÷×Mt(VMÙÛïÎû°sP~î „€€€;àºC e@@ÀKJÒÏ’©ÔùÊó€€Ú¼y³—ZjAôN Þï0ìó(²Üt1/ëòîÅ¢Þrézíñ Å5ÁÍ(0¤>‘äà9î8p #䀀*8€ªhaD_R4;{ûÂÊyYל=E%é›Cw@@ º¢ïŸLŽ¢?שS‡bcciòdI n€è4Ñ' ÓUÚ(mý¦$%éç”’­Ó$çÐTrEzi›Ãe]g PE ìÆ;(ªÏ˜Ê…žÀèëšS\\\U€€‹àº êú%ðóÑTʹRªh`YŽrÏ ’rIÚY¥d¤€KØŒyø}ª×òVópp4<Ùc=õÑêÚµ«KõA@, À´¤cCøÏ.õ^¾àÈë4³ ‰n¯YŠ àˆ@½Ö(fÌXWš(ID×û¨Éà§hÍÉ*-79*Š<pH Èa.2AÀLŸ>ÝÜÊ7ß|Ó|ìÊABZ>í;—­Z„‡äŠ’©æWfPPxci˜=dƒ@õpOõÚ#éî-«WJƒ–@ÃÞzýþ¿ÿýV­ZEC‡uÛ¨ïvTõþµøã{võ4ì4˜röþDåùYRÞU»üÊ„«=dŠJ’AÀ³îN„èY¤¨  ECÀ†ºÝ0V‰@Aq9­8"²xÈ­~›.âcVç^½æ½)zøÌ‰òÁµIúMîz’¸<j‚ÀÁó—)^깆€€€;àºC etE`ɾ$**s¾ïoH³öÔúñÙb~ú• )ì†Û©Õ„YyÛp]q1¾O`¾Eϵï·-ð%p}én -5N€ÃúÅíLÔ|]î äIø ;ß#Ê5lBÍG¾AìB@ ¦ pϵ–‡—šn® àûàúþ=B ½H`G|%e!nŸ£j/`çoÙ¾d/^Uƒè•@½ÞYØ¥‰@ÜΪÅš @ |ŒÀ‚]‰>Ö"4@ÀÀô‡»„6z…÷ü©íüá• ¢Rð^²/Q=„‘.‰*At@ n"Lp€+sÿÜ»J@ÍÀbšáŒ«€€žÀÔÓÝ„-š ðÜ)^ý =øEÚÆ0-·X¦À"°†@ã2¾E`åÁâøÐ“´œýë­¿éÁØ PCàÖh\Æ·ÌێžuGКêø~Ïy*,ÁCMu9¢<…@£ÜiØi&pà|6ñÞ¿ÐbiZ;ÐB JÐÑ„ÍÐÕí„1æn?K< gà:#„|]ȹRJk_Ô•M0d¼dí¼¿eø  N :äèÀ¢Ýç©Â„ÞZ˜tÀ›À@œ€èôD`æHéév§Róh?C+A€€%8€–4p¬k+¤Ð/©9Eº¶ÆøÆAH˜÷Þ{ºuë&^  `\p{ïýÞòÍ›7‹±U«V [V¯^-Î9]Iæ¬?£”Œ4Ðõ'.QJöU»:D©©©ªùÈÐ?8€ú¿Çº´pÖ¬Y4hÐ :|ø°•}|Îéœo)›O¥Ñ¹ÌBË$ƒ€ßh:øIо…Ejj3/vÔ ¨©(èš@]ß^}ǽS¦LÆ]µ y!Ÿs>ëÉ‚‰ñ2 ü÷G᱃I~imÿ’}É ­ô@À€àð¦û»Éo¿ý6:~ër>ë±MÉ¡}˜/Xàqp`è¸ØñÆ8w–‚€k‚\S¯Ô>pà9r„.]ºDmÛ¶¥»ï¾›š4i¢XUJJ íÚµKäõîÝ›Z¶l©¨‡DÐJ`Æ d2™ªsþÆ…Î'˜ûç2õK€·<|jÀ T'0@¿FÂ2·¸ìvéÒE8–W»é¦›hÆŒ4|øpËdZ¼x1=šÂÃÃ)44”222èǤQ£FYéá\!PPP I=??_ÌûÛ$Íÿó†5lêjQ'xŒ@VA ­:tèŽoAEE  ŽÇÑŒlР}ñÅtêÔ)âùVìÐ>}š&MšDEEU!6xþ;ìì%%%Qzzº’ã4˹Y —@8$ã0_Îd½Ï6ž‘Þ§rŠçþ7îÿ(µ}öjûÌמ«5€`1ˆ ¢JЗÀ;vÐÓO?MÜëÇÂϵJLL¤³gÏš‘|÷ÝwâxúôéY¹rmÚ´iÔ¢E ’óÌÊ8ÜvÛmš´c»t£åûS4éB ôJ€CïŒÏЫy° @ÀM.;€J×iÓ¦H ªQÞ¾}; 8:tè`U„Ï9î˜7oqO´ÚBNçü㦺{ ”]ødC¼®ì1 Õ'På±U£®µk× gOîäªÒÒÒ¨cÇŽvµò"-[¶Ø¥Ë Û¶m£ÒÒRùTüDZßp26l)ͬ_¿>}¿d9ý߶ˆg ÀöžË¢糩{›(A Ú ÏéãÅ›6m²BÊ ÒŠ_Nã‚ÂwÞ)ÎCÃÂiþÄ?3ð[¦+Øv&ƒŽ_ÈUÈQNЧ¹sçRyy¹²RAüš€Û=€¼ß*ï¶°lÙ29r¤^ìÁ Cl…Ó8OM‚ƒƒí²êÔ©c—†P#ðÞó”[T¦–t0,O¥Uñ×Öz `IÀ­@îõãýV¹çOÉùã tîÜYÌõ+,´Þ5!!AäY6Ç à)¦«ôå–ß¬àÞ¿K?VϘ¿h1}üñÇ¢B“ÉdU±ksÊ”)tèÐ!«<œ€ø'8€þyß ÝjÛÞ¿ÈÛ†QÌß#îÝ€€¸G kûBâÕÀŽ$00\ÙÞQ]Ȩ]ˆX»üqu7ÌÙ`½ò·^›.nÔ‚" –JÒÏYž*sÏàÞ½{ó à_Ðè_÷Ëð­ýñIt6£Àðd¼ÓGæÆ¯)%î59‰’çMiZwѪǸxñ¢ù:8ð_pý÷Þ®åEeô¯ŸOÎn jÊrÓ)iîË”³o¥ §qžç.0$Ì®¼ZBll¬ZÒAüˆ@?ºYFoêçã)»1ÉŒþ>€ýUÒ×΢ò¼Œª›#ÎK“vÀÑ"a7öÒ¢FƒÖ¤%ß&зïZw@z^1}½õ7ð¸F (é(%sÊ£0~7±®3ir×SX7TÚ1Dy!ˆ¼]8#‰|ðpýã>¾•®9A¥åÖ¡)\‡âx?T×ëC ¨=Zœ?¹uZxp<Àè!¯P`pˆ\ÌêË–-iåÊ•nílUN@|‚@Ÿ¸ h„#'.æoûæ®dïXD 3†ÓÕŠÊ­­2ÖI¾ƒxþŒ@@Ë<@ævãÔö¹¹Ùc†Ôh¢££iæÌ™täÈêÚµ«÷†…UÍ|ôÑGE°èÄÄD³@|—@ß½7hÙ5Ó–;¾RƒÅ«!Ù´î=Ižû’¦¡1Û²8_ $õØiWtyAH“ÁOQݦmEõƒïþØ!$22RœçääPçÎéwÞ±»@ Ü4A™À·«¶Òá¯^£‹‹§)+8Hղ걲x€ÔKxÖAMÈß%ÀÎÏ×SÎÓâ$ª•çt“´vêÝ•«]ÙsQEÔ>lWû÷-P [TFÛÎÔÄ" i(¸¸P¡Hÿ Àóõêµî$õd¯Â»ávioì"ÝV¬?q‰v&d’+ +ºžh#êpz]ãí"À;~””¹ö%0´ju¢³&‡4kçLù àÓxõnãÍmŒê;Ö¡ó×èö©á­w™õµ¼¹ô0uê¬}ßíj©: µD=€µ—U'p>«xÏßêHH³öÞ„Ê ²ˆ¤9Iޤnt{GÙÈ]ˆºónÙ“œ}…â:Rxx8åç[/ Qª ¤€ïô¦ % PIà­¥G¨‚'US¢‡LqêüÕkK c±µU5Q£¸AÌÙOÿþü§ÖŽ1‚à:ŨUpk?.nK`Ù¾dÚõ[¦m²[ç8€î³CIÈÙ·’L¥WœîÞÐÃàQx€Àó—=P ª¨)n'%%ÑÙ³•amù“’’B»víöôîÝ›Z¶lYS¶á:>JÀ¤²ÍÏý#âÝœoW”tÔáf÷>j:š^%Ðà¦>^­ßQåËö'Ó_ò‹©i¸òÎ;ŽÊ"@ æ ¸ì¾óÎ;G¿ýö›¹µWU†ëfÍšE´C‡Lǧ™3gÒäÉ“Íeq`<óvœS4ÚT\(¥;wþ # N ´yºnDåâªÚ@ÁÛÄMYx€þó̵qy\@ÀEn ÿþ÷¿N £ž¿Í›7 çïÅ_¤Ó§OÓ±cÇè›o¾iœ1&½ç²è‡=çiÖN1])1("Z)i µH`ÏÙ,š¯ð€Ç‘n¹åñJOO¯ÅâÒ 2—@Þ|Μ94nÜ8¹Åÿ‹/é/½ô’9ÿñǧ-ZœgÎÀ!ä•ѤûI¥Ã˜êF·×À!€‚›PpD3 ºP¨i3Öž ¤,îÍ·–“'O¿ ¾AÀePk³÷ìÙCÜCÈÿ–Âçœ1×¾?H«~m 4ŒLa7ö²M¶9¿JÑC¦Ø¤á@ÀW””›ÄƒžIíIÏWŠv€€Á ¸<P+¯ÔÔTêÔ©“zÛ¶mé×_µK—¶mÛF¼pÄRŽ9byŠãZ ŸŸ/®ZZzmwÛ·óm>•æ´Tôý“)uÙûT”|LZ"-±ø ¥&¿{ÆíÅ׿ºÄéõ¡  @@p]ºáÏ+ì »Ks6ÄÓKw[wØ)"@ Öxͼxñ"±³g+œÆyŽä…^°Ê.++³:ÇIÍàùšãÇ'^õÍÂs9#""èÝwߥI“&ijÈ™Kùô7i»7çoíÇÄÁže¹ðýR¯ß}ÿ$ ¯˜1PÞ± ”»w•d$ G0²ûPЏmD5‡~%‡ àA꟩9ÎР›£)6&ƒ×CU ž"àµ!àèèhJNN¶k'§qžšôëײ³³­^K– çF—7Óy÷ AƒìzdóòòÄJî‰':½<½·—J®äSâçOX9rav?{¼õ§óppÃ.¿*u¨É৪éüÉWÚ P!…{zaþ^Ê/Æ|MðÆ5@ÀU^um‡r¹qœæÈtÕè{‡À¡C‡ÄŠm®Ýd2)^dÞ¼y$oé&+´oßž5jDS§NIÓW£s™…bX×T"yVSY‘ØN%É ~HàbN½øiá—¶M½ðšÈ{Ænݺ• ­Wƒqü@Oí'«÷›S›ö½ýöÛèøíÁùJÃÀ999¢é<çï{)ä msú$ÍõãmÞ,‡‡©#@À?ìŒÏ ¬çuûGËÑJÐ7Ç¿ðÕ°ý‰'ž ¢¢"úç?ÿi®…ÿ$$$çA|›À™3gT{þä–sÏ Ï ”>9ÿHÃ>¼ê—¥$]9ð³È´ù㊮MQœ‚ø(_%úhËÐ,0.—@^ ­Îä—ÐY>ç]BdéÛ·/q/¿n¸áêØ±#=ZœsÄ· ¸¯+11ÑΘõÇÓˆãþ±ðâ­b*.Ъ ='P–›N¼Ð+mõGæ–ò Þ!JéÁѬ„¯rç ìÔiÝ­[7óžÁ@¼OÀeƒ;óK«ÀáÓJÊ·ôøkqGŒaÕð¼k½~–‰u›µ§Àº¡ÒA±e²â1‡„€ø7îõçxžŽ>ó<}„# ð6qš'àòpÍ7Wt‡/¾©W¯žx-X°@µ ~ —õ222ÌzÜËKuêÔ1§Yð ?É˲æðERryÛ¶¨¾Ž·ä:¢úŒA¨&þƒ€(B;•çñ÷‰ãõ¿EÀr ÉóÏ?/¾°PÐo>šî7àúÍ­r½¡ÅÅÅÄ/g¢¦G7ß|³bñ°°0Zµjq`o–½ç²èµÒÕŠrqn;ï/ò¶áÂÁ™ "{ s˜¯PI >J 4í¬æ–qÈ)KÑòe©c÷Àt›!Jñܾ£GÒÌ™3ÍŽ÷úñÜN¾áab–„´|6aúÛP*/Èi¹׉ÀÏFîák5a…ÇÞ%'QývÝ)æá÷E gs"@üš@Y^ºæö[öj.Ej€Xm„ú¯`òäÉtï½÷ C;tè VrË·3 J¨× {)m«ý0sy^¦XÈÛºÉ"ÍŒºc´|Jz=äpoßàF-(¨a3³>@|ŸεÊuí:jU…€€ Àô L£UUTZA}²OîT1½rþOæú/ˆÃA¸*݇P›§>/WËB@ ö„ÝØKÓÅëÖ£öQJ¶ú.Aš*‚€€Ëຌ ˜€IÚ¹ãYiŸÏSk¿q „Wæî[áT ú À=€<¯×™D™B—Ë‚è‘/vRF¾óùÊÎêC>€€vpµ³ò[Í+WÔŸ®m·êÓjäÔ%‡i˾ãŠ1¾”êÀJTú%Õ÷«ù¾¶–òœ`9ìSª´gðØ/vQfvŽPã]¤ Þ%л|k¼vŽ®ÏQöy±†,O?ý´Èm9Ùš D=ö˜¬FÍš5Ó¡ÿÏ?¤¥û’©<7Í\ÖÙ;CÀÎêD>€€ï £èû'Só‘S­æù6ìò{±Œ@Yx±Ø†7‡Ò≤S§NQDD}üñDz þƒx˜€Ë =|}TçAìüõïß_¬Üµ­öÈ‘#Ô¹sgZ¹r¥ÈâÝJ½Î"ôó\åûSDõZw²½ŒÊy…D·SÉC2€€ž Ƚ|rD€ÆýÆQúf“sö­¤Ì_“´¿¨9òòòˆ q˜˜¹sçZåá@ úÐX}†>SYrØ%1™LTPP@cÇŽ/>æ4%‘#ô[æñœ?y_9¯^«X»/n9¯êÿUóPOUŽ@ŒN€·‹Îƒ¸öcËdÞ¼yVçmóq à8€îqó¹R<¤ûÝwß9l×Ué öâÅ‹âÅÇŽÄ6Bÿ®„LEõ&ƒŸ¤Àà‡N`hÌÍÔ0v°by$‚—@öiÈצçO‰Ç"…€x–@Ïò¬µÚ,ç÷yª<ôRaºJ/Äí¥¤¬BÅjyµ_ôW$'0T1Ÿ¿ø«bAŒM ,û¢jÏŸ%•à).ÏÀ@ϱ¬Õšl·SòDcΞ;GÏ~·—6ŸJ£ûŠ—R½<ǧísßÏå¹¼g)]-/¥ºMÛPdÏT{þbž®TÒ@ D 4+Y³µüË»± \9¢Ð³gOúðÃ5ס¤8gÎâ=ÑY6l¨ Z¯¤‹4Ð8€:¹›ò£'ÍÙ’^N\ª\é[¯ug‡UóŠ?^Õ—l£ô9®ï©êüGµ ~A@ŒM€ç%ÓÁrwvÏž=KìzB6nÜHÁÁÁž¨ u€€ßÀ°ßÜ*Ç å}yÃÃÃ)0Ð3·4(´>0Å8¾(rA@ ´FàEþøévÚŸQ«¡(€€%Ïx –5â¸ÖÌŸ?_ue¯Ü¨I“&¿œIÓû&;SA>€T‹ÔmÒFZ¢òS$- ¬JMîzŠŠÊ*èño÷ÐʃªuM¨$€!`½xà/ëÅ_TŒñ7bÄzûí·Í+YåÅQRœ.9v—Y  P Í~ÿ¢béæ½E©KߣÒÌóvùA ¢Ä"³àˆf"¥½úýÊÊ-ç¹¹¹ve\MÈÊÊEœEFpµ^胀¯Pyìòõf£}j&L˜@ÇŽ£©S§šUúõëGË—/'í)^ð™Ó† bÖ‹¼}$ÅŒý"onNÀT—?P6ìrxYæzÙ¹kýøl©—ïIªU9í„çóyëÇ?±ÚE„ÃÆ$ÌN¹Yé¢IŸþ9µiÓ†6oÞ,Î]ùà ç88þ´iÓD±òòr)"M€¦Ý\¹tAÀW À¬æùì³ÏH~U³*oÛ¶­•øÌ3Ï÷Ú §?ÁœÜèöÉr¢µ9  àeüà)/6 ŽŒ¢ìÊraÑTqå„kÿ“““Ŷ–0Z«ðÃp·nÝÄòm~8æ•vÆ– ÎõF`5ïè_þòzþùç)??¿š5Õ|qÞ€ýëNÖü…qEp;~j«…å¡Û—^z‰´ÄCeÇŽ÷@çsrYÛ¦ðŽJ–Óelóqz PwÑ –íK¦¡³¶ÐÅËEn”V/½7î/}¹Ö­¯®„p@ÎÞŸœjóö–ÿúÈùŽ!ÜÃÇìj[aÊRš#-çá?èTó.ò¼–Ë—/W³¦š)ν~ÿ·ä°×Â)4ºã5c® `e¹éd*Õö ºhízýí+Ô2JýÔ• ù<·ClA@@ÐèÆ]å!„)S¦ˆ Ã……•[¤q4zw'#»Ñ·Š|¿ç<Ý÷Ñf¯9n5 …@@Àr)°¼VÉÍH#N\R-‚¹}ªha0pݸἪ–‡lÅÉȶuxãüra)ûb'½µì–TöXzã:¨@9r$u4šæn;k[ÎA@@7ØÉc°NX#aSØõ·YûJ!c?{‚ ãwÛÙ\”t”’ç¾D%égéóMñÔ÷ýÿÒ«íéîû+‡ƒƒ‚‚ˆ¿s]ùž·»@ÀÀtáfñCll¬èsVŒçúÉ!b”t¯\¹B£F"Ž^Ï"/ ±Õ•ŸF¿ûî;Û,«óô=?ÁA@@À¨Ò×Î’b^Q5ßTZLik*ƒE—”›hÑîóôñO }iÚ E ‹·;..N8k¼šôéÓ‡’’’F𝍍 }ûöG¯w&+V¬Û9Ô PÜ'Óad‚€€Nð°ÚvqU&^¥ÒŒóŠ=„&“—µåtz•:Ž@@ǰˆÊÍåhñ¼Ø‚eÀ€f-Ž!µ|ùrzôÑG7žXܱcGÚ±c‡¹Œ'œm[$y¥Tvù¢'.…:@@ÀŸÓÜfÖå9…¶Âá²øÕºqèCöhåpWÛòž>çß¡óçÏSdd¤Õï;×áyç<2Åÿ»téâSCÝrÛØ.žÏ£mïPïÆòþµ}ò <'ZtëÖx¿øÜ2ü Oæ9{œïêº߸öÅ ¨F"‡G€€€€ T‹®Šý§Æ€¿'Y·:RaºJ‡’.Ó§Ò6s~¹‹ºOû™&|½›¾Ú’@Ç.ä’ÉÍ%ÅÜÉ El‡”ʰ£È  GŸàžF­×uT—+yÜáÂóäy1¤š°ƒÊQ0XâAÞ©¶ªÖ5kÖˆI¬œÂŽÒ!Cª2}èˆWäª=qÉÍä|Û.iµy þå…Š,j¿MJÕYêò±Ü6^,ÂmTn«³*ü(/<±l›+v²m<ªñ<¯:€ìüpÏZ‡Äb žsÀç¼xÂ×ÄQÌ>­mÍ*(O…¤9#G“sèPùíÔjÂ,Ê=°–òŽü*ªiØõ^Š^òlÚ|ä",Áå=K©øâi ¨LîøEÞ6ÜÝžõ[?>›òŽn Ë»SÅ•\ ޼Ž"ºzZÛ=Ð3þÞ¬×:VúÎ]/}÷®¦†ÇÞ%F×kÝÉeÓsö­¤ìí ­â Ö­OQýÆRda¢>^€’½c±®,¿IKg4¥hiã¶zRïë›PÇðúêý?ÓžÛd5ñŸ^DhéˆY)(œ°.÷ÜÙv2ð&7ÖÕºØ)ã!Wîu³^42wî\³#ÈÓ xzÛM x§ªI“&™‹r'ˆí´*ÞÛVCÎæ†áÀLÀkàÏ?ÿ,œ=K‡oñâÅ4zôhêÕ«Ý{ï½æFøÂx>vì˜Ó¦´ˆ‰¡S©y”rù %gI¯ìÊ×ÉÔ\JË-¶+ÏŽ[Ã.÷˜Àˆ®÷IÎ_;;=~r-ÉH` 4çOé)•Eþr+8-uK /úàs€€@þÞeçLvJ ;Î_š4:“lcUÅ׎8Øt憯¨4í,5ü$¥,ü?_ÐV±;|ìD²³Ø©S'ÅßSnæ¾òrYGÿå^NG:Ès€×@öò9Ê+¯¼bnï|Ѿ}{ñàkààÁƒß°æÆ_;¸r]w6ËþCg«g{ÞâÎ{=C¯»QÚÐܹ^TïѶÕã@@À†€–ïS›"æSÞNNÉù3+HyÇ6PEQž¢óW©wUüãÝG‚›H½ˆìüU¦UæWý-,ȧÝGϨî %kò\t•¢äüÉ:üŸƒ9JEqq±ÓéMK–,sÜÕ¦Añð2GºØ¾}»å%쎹G255Uõ·T®ÿ›o¾ %¼ñbJ ÿÚaöX‚×À'NˆÀ•áááV½ñƉó|M†Nx™>Ÿ·Jò²¤Ï§É¾yÒ“QPƒÆÕ÷û<')¡Í;8Ѩ̮߾‡Gõ4U%Ð!àF͉_îŠÎå1G :¤üÂßö:½„©´ˆJ³ì÷{·-Xš•"FˆTƒZs{‚B(9ÃùªÝÉQl}ÃMtêÈAÛËX÷ïߟ¶nÝj•¦tÂÎ;Ÿ²§¤Ãi¿üò‹Z–9Wÿj¹./¦lÛ¶­¹ü@Ù^+ÀÃÊïðªتU+»–s;‡Žä³Ï>³ÊvÖMl¥ìæÉííÓâ·ÆI¯ïç~N{wl¥ÌôKÔ¤ÙuÔ³Ozxâ³nÖŒb  þFàŽµÓâ‘]¯£'ç~Dk–.¢Ý[7Rҹߨ~XpÏý4ä¡1T—K#58€ÜúàŠ+´rö[”š2ž–.˜+ý®mFµnw=|duïÕ‡þüÌ£t®LMÏʦž˜D·ôL?}ÿ?´_´¢clzhÜÔá–X±¨²këFµÐ:c\Òk`‹-W!ñÊ$ÎS“~ýú‘mw){{Î`TX]ê%9,½Þ{CúË/€€€ Ü|óÍtòäÉ7}È Þⷨן^$âW5äviNü®I¿môWÞAdPŸÛiëúuÕ¸Š{Eï¼½G¥íУC¸W JU‹€×A7oÞ\Õä<€€ø*{î¹GSÓ7n¬¸zVSa%ž3/Çñ³É²:ÕºÂWË -:¼:˜ÃËh‘¨¨(§›*p=Z®«åzÐqŸ€×@^UËKÛ¹ÇÏRâãã‰ó  ü|~l üIDAT à«8ä OYªS§Žb9ó9~‡mq´“Ôˆ#4Å¿?¾¦Es¯AƒOmÆ68vÄ,ã÷)é³}¼«ש&ì$²Ë!cxõ±3¼M¤v xÍ|ðÁ…eï¿ÿ¾ÙÂÙ³gÓ… HÎ3gà@@|ˆÇÆ[¹r%ñP°’p:çó´%våýßmcé±óÇáQØSÛËΜ9“8è²á¶ñ‚I^T©$}úô¡U«V)e)¦qÛÔœ@v49¶;Š\'×­$·Þz«XMܹsg¡'ô©ñPªi5K @ÚžE1(ѹsç>]hi¦¼Èõ×_OAAAtúôi‡µ:å9€¼ÉöͤVé   à ÜãÆAŽyD«­–„‡imW¨òî²³;M¶N×ÃÁ•y„ŒEÖÑ2ô+ Xüáë°s)·ëà—»½kÜ&ùÅN¦\Ûl)|MÖóËzkú˜î¯¿þšx—2Y¸·“ã,A¼ê2@~B:{ö¬`ÉA ‡w}ç 8€Fx+ÂF¨9Fwƒ¼Ú‡ÏÛmBý    `d^›hd¨°@@@|™@_¾;h€€€x@/@E•    àËàúòÝAÛ@@@@À àz*ª_&ЗïÚ   ^ Ð PQ%€€€ø28€¾|wÐ6ð8€^€Š*A@@@À— Àô廃¶€€€€x}+8O´ùâÅ‹¢š„„ ðD•¨@@@ÀÀ233©´´Ô°üÂLMM7¨C‡†½Q0@@@À³BBB<[¡Õæ`¯^½hýúõÔºuëéÜ·o3†Ž=J¡¡¡~t;½ÛÔ;3^}õUz衇¼{!?ª}úô锘˜H_ýµµÚ»MÝ¿?=üðÃtèÐ! óîÅü¨ö¾}ûÒ¤I“hÔ¨Q~Ôjï6õoûÅÇÇÓ·ß~ëÝ ùQíü¹á÷Ž6lèG-÷nS @Ï=÷œønñԕΟ?頻ü²¿p\£påÇöíÛSýúõkôÚ¾|±   jÖ¬Ýpà ¾ÜÌm[dd¤x€Iö´´4qŸŸðð𪠃áócÿÀçÇž K²ðç‡ù@* xãócôïm,Á§ @@@ F Án8Ì8€x€€€€€Á´iÓæª’ÍçΫ‘J×®í49쌂¨ã› Ó@@@´0’ˆ!`íï h‚€€€€.ÀÔÅm„     @í¬     º P·F€€€€€vp5°zçwèŽ;î«¢ÄN'N¤µk×j(­O¶ýÿø 4HìC#FŒ ;vèÓ`VýüóÏôé§ŸÒ /¼ Ø0#I\\=Z|Vø?ŸYŒþ~Pº÷¼mâ£>J±±±â}Ò±cGz饗(99YIÝ0iòç†cš6mJ¼u ÇBªð÷)¿6oÞ\•ˆ#· ÀÔˆŽ·åùç?ÿI›6mûæääÐ!ChñâÅkЗÚÞ½{é‡~ ûüòKñ¾k×.ñ¥µgÏ}ë‚5l;;ß|ó ¥ô¡ÊJ=öõîÝ[|Nn½õVqÎéF#¿Ôîù‚ (77—^|ñEñ>á÷Ë'Ÿ|" ¯\¹¢VL÷é)))ôöÛoÓ?þ(¿¶mÛÒŸÿügš2eŠîm×bàË/¿,ÂJÁùÓBK›ÂÀhà”MQQQVš‹-¢Gy„&L˜@sçεÊ3Âɯ¿þJ÷Üs•©gΜ¡›nº‰žxâ â§|#ʨ{÷îÂt¹÷Œ |ïù31mÚ4³¹ü€pöìY:}ú´9ÍHF~?¨Ýç#GŽPçέ²ù!þ^}øá‡­òŒ|"ǣ㸼F–uëÖÑ<@¿üò‹èäïÔz ÂÀx«ÿVjëü±%wß}·0ˆŸÒŒ(¶Î3èСƒøP¦§§‰°YvþŒ€ŸÊù`èСV¦óç„ÓúÔnÔ÷ƒÕ›ÀæÄÖùãlù¡áÂ… 6ÚÆ>íÙ³'………‚dý믿No¾ù¦á9x†€Ý ÊÃ: „UªRSSE^=¬täs9ß*' p€ÀC¿}ô‘µ’ÎxÛ?uêTY]s¦ÕÜ¥|ãJÇ×´Úì¯ý+9񻄿 XðÀ“Sy¢»¿Kuž¼ù œ¿¤þóŸÿÐØ±cý…¹ýÕab®Ä ÑÑÑ-u–ï°02uK€GU222DDv.òo s7neffÒ²eË éòïJQQ‘èæÛ‡Hî9¶äeô÷Ž;öÎ|ï½÷ÜádWF^ðÀó4þýïÛåûSÇärWdçCŒ5ÊÝj|®\ݺuÉSïŸ3Î ’<þ1çf²ð z9_NǨ_¿>qx-'çOùýÀ¡rä¸wFtvx\Én9‚­S¨L©j0PŒ“tye#‡1ªÈÎ?¡êÉù3êý¬ŽÝ image/svg+xml iminuit-2.30.1/doc/_static/interactive_demo.gif0000644000000000000000000236644214332717401016427 0ustar00GIF89aîÊ÷1Uªÿ$$U$ª$ÿHHUHªHÿllUlªlÿUªÿ´´U´ª´ÿØØUتØÿüüUüªüÿ$$U$ª$ÿ$$$$U$$ª$$ÿ$H$HU$Hª$Hÿ$l$lU$lª$lÿ$$U$ª$ÿ$´$´U$´ª$´ÿ$Ø$ØU$ت$Øÿ$ü$üU$üª$üÿHHUHªHÿH$H$UH$ªH$ÿHHHHUHHªHHÿHlHlUHlªHlÿHHUHªHÿH´H´UH´ªH´ÿHØHØUHتHØÿHüHüUHüªHüÿllUlªlÿl$l$Ul$ªl$ÿlHlHUlHªlHÿllllUllªllÿllUlªlÿl´l´Ul´ªl´ÿlØlØUlتlØÿlülüUlüªlüÿUªÿ$$U$ª$ÿHHUHªHÿllUlªlÿUªÿ´´U´ª´ÿØØUتØÿüüUüªüÿ´´U´ª´ÿ´$´$U´$ª´$ÿ´H´HU´Hª´Hÿ´l´lU´lª´lÿ´´U´ª´ÿ´´´´U´´ª´´ÿ´Ø´ØU´Øª´Øÿ´ü´üU´üª´üÿØØUتØÿØ$Ø$UØ$ªØ$ÿØHØHUØHªØHÿØlØlUØlªØlÿØØUتØÿششUØ´ªØ´ÿØØØØUØØªØØÿØüØüUØüªØüÿüüUüªüÿü$ü$Uü$ªü$ÿüHüHUüHªüHÿülülUülªülÿüüUüªüÿü´ü´Uü´ªü´ÿüØüØUüتüØÿüüüüUüüªüüÿ!ÿ NETSCAPE2.0!ù ,îÊÿI QB Aƒ&<¨¡Ã†J\HñáD‹#f¼¨£ÇŽ 9ŠÜHòãH“%C¦<©¥Ë–0YÊ\IóåL›5c漩§Ïž@y ÝIôçP£Eƒ&=ª%‘ tcËÁ$‘$iͺU’’Ú4¤jµD›[Y«FE‰ÄÃ$·jI%¨mnÍ©bO–¨‹´¯Â6’HÜBâ&ÒÞ¶’°m  ÇŽB~lprdÊ“%c®¼YsæÍ—-sþ,Ú3eÓ¡;ƒ}z5jÖ©I«.íº6íÛ³sËÞÝ7ïØ½uÿ »øëã¶…_n<9q侇Kg]yóèÔO¿n½úsíÙ±sÿÿ.Þûvóể3m‘ÈPsæ¡vªªÆŸÌÄŠ¼—-“ŒUaü]¡‚†Ý4fIŒvüU \ÕSGwn‰H€ -à­wÞ|ïÿíw߀ÿ-xà„nxሮxâŒ/îxã?.yä”Onyå˜_®yæœoîyç .zè¤nz騟®zê¬ûÝ„ÞRÀbCýNéð”$`u0îgâ8í©˜‚y¿^º .€(ZNà|ÎýóÑO/}õØS¯ýõÛ[ï}ö܇ÿ}÷à/~ù蓯þùë›ï~úìÇÿ~ûðÏ/ýøÓ¯ÿýûÛïþü àÿúÀ °€$ ¸@:0 ŒàÁ J°‚Õs›²€ÅÁ z°ƒË£àú\ š‡ y½K!ïV¨Â²ð….Œ! g(ÃÒð†6Ì!w¨Cml-êêIíÿ´5Dj]HdË™NøÒ8Rƒb¡85*¶ÆŠ—Á¢A´8.J±ŠS #ÇxE1–‘ŒY4cѸE5¶‘]tcáøÅ3Úqw|cç¸Ç:âñz$éÇ@r‡,$"©ÈFzñ‘rtd$!IGJöÑ’„Äd"5ÉHNJ²’“ %(GyIQJÄiIZ*‘f¶¥)m•—ÙÐ&ÝȼÚ…‰=ä¡.sÉË]ú²—Àü¥0ƒIÌa³˜¼|×1—‰L$NKDaT–焵њqĦµ En.ëšuìf8¿™ÍqzóœæL§ŹNrnSàl':å ÏrÒóžņ̃=õùÿN|îóŸýä';êÎÔ =hA:O‚6T¡M¨DJQ†Ös¢õ'F#ZQŽfÔ¡íhH? Ñ‘zô¤&M©FªA~ð¥.é¤ ²R’’ –›1¡4›ÉSfú´§@ý©PƒJÔ¡µ¨H‘2ŸÉ¬àI,‰A|*» ¥L%1"Ô̤)µJJ®–²«³k'·Ö¯šÕ«h-kZÇ*ÖOžU­peë[åºV·ÖÕ“x%+]ãjW¾æµ­k_÷JØÁníIlÔTÙJXº’±¨lìfØ4âT3ÁåQ7›ÔÎrö³ž -hG+ÚÒÂð+¨-AjW«ÚÖ²öµ®-lg+ÛÚÿÒö¶¶Í-nw«ÛÞòö·¾¦ò6Ã<>¶Ó¸z<î8‘ËÜå:W¹ÐM®t›]êN÷¹×­.v­ËÝízW»àÍ®x»^òŽ÷»ç-/zÍËÞõºW½ðM¯|Û_úÎ÷½÷­/~íËßýºú p~Ü_˜Àþ5ðM«¹$&!š5­„IKá [¸Â¾°†3Ìá {x˜WeˆW2óD½¶²~51Š »â«øÅ€…±`[LcßÕÆ)ޱŽgŒc÷ØÅ;¾qsÌã!ûØÈ@.²’…¼d"38 ˆ"Üá*øÊVÎ2–·¬å.sùË^n•KU•‚´¦(E³™Kªæ6ŸùÿÍl†óF×4¦-éDyYs˜ÁLêQ›ºÔ¨>µªSÍêU)Ä IÍe“\W‘ÕÉ·nò‘uMk'ûz×Oþu¯-ì\›ØÈ¶²]ì3;ÙÏ^¶³§kjó:Úyu€n¹SW·úÛÞ7¸Ç-îr“ûÜ<35l_š"XÁð~·¼Ùày×›ÞñÆ·½ó}ï~óûßû¸¾îoœàG¸Á~ð†3üáçýt€BÝíºB8LCÌÍqt{¼ã ÿ¸ÈC.nX ĉØÿŽb²¢ˆD „IT¼¸ò>Âüå$p„#ëEBÊÍæÖþyÊ«Môk½ÙE?¶´“Žt£3ÚG‡úÓ—îôª+}èVoz°%Enóð)D° Šö— ìcJTÆ^³¯=c'ÈØ]ሸψ_,zSUs$¶»]*~§Þ¥’„‘žä‡O<â¯øª›¸ ¦ô£! G4Š!håuNù§¡ò §)6/ ÅÀ<’pD$6OÊ»B”oz [ÜB¶ˆÄ@$¡.âž³º½-´q‹À†kćOE¸H(¤wD‚$~ãø¬ýðÑÅ$àžø´Ò´ÿä9MþM›üç¿ú~ö£ÿýëwtùáïþø_šþòoþñûwzÿþ§h\§S_W­€qS! EÐ ®`}‰ð PŸ÷€­ j`} (w®§qdR•#Ú° ·2‚ ÛpµgÛS ²ŧ¶÷gA&¼7xQÑI0w¯ÀHI°wv‘|ƒgQ0IØxŒ×„Lø„N…P(&²Æ`RgG2—s­0!ÐŽPŠ _Xwj €OAwOQyOQ–ç…²à e3—s®cu{PäáÇ{Tô{³b%·°|1|á}VA¿7!nH"ÿ‚f !" n v5ws­aˆ$À‡Šá}’p uTwu¤ˆu¦8u¨¨u¬˜…©˜u®ØŠ¥(‹«‹¶8‹·X‹.¦m]¢VCtwnð€à › hŒq†dçè ÊØzecÁ(#Úð`7(ˆ*ˆm‚|È‚tñ`$° þÁ{ªE‚.’® ìè RâqØeÐ"×H݈%÷8#…ü8…ýøþ^öx“Q\']Žs:wz`Hjp‡`Xg"Y² DEŽ`Œs’z³G0ç©PÁ5‡Ø‡½E€Xm+ÞWµ×uõ’|Á\HÿmW’8'c†¥‡QÅ×}áç} -©{©pL¹”N qM •O¹pT•U9•V™•X¹•RÙ•Wé•M9€·Kwj`‰°sïp§zp' H ¸say&"ˆÛPx((%äŽßx_A|ò‚R~âx"I óXð UÕzs©"õh¢ˆ™å~Ù™ù™žš  bɃUQbªvÖç %e(‘d¨yYyip†Y†( ®à–sB‰E°…É2†ó2*È“¹S”×è‚nÁ‡À7/IÃÃ7*|H Œ£çf±Žf7H`‘ið‘xÿd’ÇىċH‹§¸žªÈž°ˆ‹ð©‹ò鞯XŸêÙžøùžó™Ÿö‹èu:”± ² ±à„a`HgY‰à ` vIZy˜s`"X%)r™gQx2‚¶Ç2˜)(ƒà÷/0&)¢yq_ÑzºzôÈ—…×¶G| *š<:š=ú£>¤FB”Sü·P^؆p'"`·¤ J†m÷‘˜×vEP‡KJÚt¥p7h­YSC ¢â„ˆ•¤mç¤Kêšj‡‰GÞ7„îVp €qÚsút*§xz§zj§|:¨{ê§u*¨yÚ§€j¨GJ¨z¨„ÿ*– ñ‹+$;6v™kÁ‡'úKù(¤œ ¤žÚ© ú©&R…WØŸu¤¦1—ªqt†–t‰ªJ5w±Út¹75Þ'ж¦rº:5³ÊHmê\¦ºŸúIŸ÷9¬üY¬ÁJ¬¹¨¬ñɬš¬Çº¬Ñº‹X¸,ªØ*ªÙº­ÚÚ­ÜúSDê –#ÅG5·¦åÊ•é^!©®ZI®ðú•òú®óê®ö¯ôš¯÷Z¯øº¯úÚ¯{_Ž a÷­Þz°›°»° [#¤zšºˆ‰Ðj¬«t½ Ÿ‹¬+­»±Í:­Ïê±!˱[²"ë¬( ²8öŸ¾X° û² ³2³4šáÿº`ŠŠ¨š¨ŒÚ³V„‰¨š³ ¹³D;¨>[´…*´Gk´<Û´H»¨NË´O«³R[µI»´Wµ‹6°©3ûµ5¶`;¶b»j«³¦‹ŽAœ{VR2²”«¤´íjªK²'«²zÛ±xÛ·mk²~ ·‚›²|û·y[¸PÄ‹Sæ²0TŒ8T\r¡2äDX"º‚$úw0´£eK¶žÛ¹ ›x7;®òê!Ò×vôjMÞGˆ‘1[¹‰(^~ˆ`­YwèšoÖ—Cû¯üú»¾¼þ:¼+¼ÅK¼À‹¼Æ›¼Ç+•\^Ë;­× Avkm·vdxgGvd0ÿâ¦J%¾>t$äKH€Žã "0X"ó#ÖK'i×½7•vÛ;'rG¥kǽr÷ye v廾Œ©Lz÷¹º|À9ô°$¦‹ °z gy2' øysâ¢:W}€F‘ ||A”Û kû}³Ë{ÛÇFiæèHü}q«ß‡«!º}£8|)ì% ~:|Gü‘Á œ+פÇ1Ÿ×˜”g®zqû}ÑIÞgÃk 9Ê5³‚ø'ˆK¸€k¸ Ƈƃ»·fLÆcŒÆeŒ³9u­9$£'£©‹%êØE†v¼›n€Å˜"é‹ö.F˜&1œ'X{üÿ±‚‚&¿§"é+ƒÃ\r+ïR!ºRƒª!ÛZ›¸X!#³ivi ijðÇ è <È€@H–'"Å ¨(pvi š{"Â×’œ™||8‰IŽch1|T‘© œÀ̼ÌÎ$£ySK‡9*!PyU v”G‡lh‘§†‰Obª%pN…i»§ £h˜2ˆÍyÎÞ4Γµ,•6áEµÛE¬HZGß\0g‘%€ºmד멟Gv¯¹Œ¥—¦s‚ºÓ·Q\ã*5‰”ä9+‰È%Ú N8 ºòÑS«´Z µ%µ(mµ+µ)}ÒTëÒ,Ó-ÿ]Ó4}Ó&mϽ)D™ò«z§—p§+ ¹£€¨Ë"·GŽù2(‚˜'ØÉ뜘q{/²Ôô!é;Q ~-(¼2¼˜)2Ê¡Ž¹ ý`²€€D mð…ÊÈ ºLJ"¹Ë$Â5TýÉe±Õ}-ÝøÉ˜Ù̆ý̈}Ø[š Qª[†âÙ‘u7*yz:7v’hз›ˆ|µRƒx$»RÔÂpÑS=“v´‡žM¢ÝEÎ7„œÈÂ)¹Nò{cÐŽÁ“]wáLÐ(s²žc"êXÑ «ø }±Xô{PT|pƒ2%©”P4+Í9ÒoúÅl¼ÆÜÿýÝiÜÝb<Þg ÞmìÝá=¬Š Ç7T#‚—QQŒÚlI¹híCPÍ{ b"• Ö_ÝÈ‚MŽÂ|¼§ÌQ¢¾0ÉÕ±ÿm%>|¨¢(’×gmŒy}ßqHe°›Íáhvw="~ÕfRžh™Ž;X¢,ùàŠØ0þâ‡ÍúúšVtÍ•8‚­ÞÙ·W(H|U~¡Î¼·Ô’K"”g ²p Ö—;†aQyz‘! ,Ø*©ö( «g½'Â×*Þš·÷ëQëöè,9à1Þî2îî_ËÀ§šïiºÈGtø‘§ççØ+s™ÜjwèSÓšÛ­E¼7,l "·RDðœÑES`E˜¸¤Ùl¦>Ùï­ç§Ûï…G5M}s’ñœ}ðQ‘Ý•Þ0Þäÿ­Æ3/Þåóè-ó7¯ó4¯I,K…Ÿ.…a-â(ÈÕ¤fíðþîJŸôLÏLÑœÓÈU‡(Ϻ iZ„RiÔºuÄ{U$ìê`üDY€f\jGO[¡ÚöÉr®ßT‡Z_SÈõö/=÷3 õ2}÷6m÷y¯Ò8Í÷zß÷0ý÷‚ï÷XëéÆíÞŠø,¢øMßøKÿøŽ_Cg[¤ÕŠu®Šò8GJ%ŸÜD¦`^åù|´© ¯«Pœ»ÚÌmJÊ…ó5oÞ9û¯ïú;/ûµ?û¦ÎÅü›~ý˜žýš®ýÎÿÏýØ¿ýàßýáÿýþeøÆ$Áþê_üì¿þ-$ï‘Aï¦z±w[õS“±Ú´ùsCF­`€D $h‚I€pH€D† I„¨HB"Fˆ=jt‘ãŇv,y0¢C† [²4 ó£B—1U~|y3cÎ…6{âôÉShP¢@î,ŠôhÍ¥2•>e ÕiTªS­ê¬ŠõêO©Z½rÍ vëЦ_Évk6iسl׎}«¶lZºmáε+mÞºqûâõËW`' ,A"q‰.?^ YrdÊ“-WÆ|YsfΛ=wýYthÒ£M—F}ZujÖ«]·†ýZvlÚ³ÿmׯ}[wnÞ»}÷þ[xpâÃG®¸ñäà g,(fÏéÒcZÿX‚ÅÄ«§„N]¼wñ3¯‡€$±yö ¥«w^~AŒë3ÚWˆ¥ugÁ.>‰ø  °(Àèæ“¬½ï<œPÂø,\Ãò.Œ°Ã =äðCC$1CMÅ7T±E_TF WŒ±Æ]´QÃO”QÇ{äqÇRH4G$—ô±É ™|ÒÉ k.¿–K´F‘ʼnޓÌ[PCâ–6pCb›3!k# Ѹ#‘4ãNµ:Ks³>Í’°E’Ç$±ÅÍÅ´±å6B'[3ÿK‡HKLEu4RH'•´RJ/µ4SL7Õ´ÓM—3p †œ,0¢JHCΊ𮚣<‘À3H?a=U±@ŸâéÕ]HÌQ‰ª/’"2B©×/7O Œ0êO1Y’ ‚<hãmK‚Ð6,²µU¾’$`j#P½ÜúêÕŸÒM0y÷2u^véµ÷.|÷½·_}ý]÷_&ø/~6à„.5ß‚>øáz#^Xb‡+^˜J˜&ÃRÓ8e)¢ZȈÐ.díJ&yäM–MPøH{ùµCQK™2"V¹äÉny±jyöÙ•9k¶Ì m¶17m½ MPÙŒvº¶$’¨,ÿ‰˜›Z2¨=åšS¯»ûk±Ã&{l³ËF[쎫’0}šîm‹BhÄY¸t¤#qü‹ ïH0JânÃiÃÅÄ<´ 6´ÑÖBm1rm'Hm4—ØÆI¸ÅOÅÕÆË‚"·ÜO󸓄Kj1ÂÛp7$v5."¹õ»çt(o¼)A»ñNƒ ÝKWLÄ4ótÈ)éÆm‰¤ nÝ P‡$—Þ H¸'W¹+úÞrìË×ÖÍ`-/4ôÃ/0þ¸å‡»þñçÇß~úï×?þÿß_ý'Àþ€D  x@&\`(ÁV‚Ä )xA fpÿ|;Ì¢®ä˜MÅ),ÓŽ#b!§$œ)®hCêv¦4È n…êö™$hk1Ù*Ÿl±Ç´i‹‰Ä6lц$š tcÝ­H`ÄD!¡[·°¢g TU)Ʈࢱrø1G$Á ®0ƒ…–„/ÖL¯hÄÔn·*YœéjZÓ†J·ÇĨ[…Òøt Å”iMš[Œ7$hnjQ;M¶lá†FÚqiJÛ Œæ¥$8ñ@PËâÙD™6RŽÒ”¥Då)U™JV®’1Ž Uª'( b"Ù’È6r·2p„ІvBp·›ÉUŽ(Bd­¢( +Á÷`´ü”®![ÿ+Á"×¾åIÂ"ÙÄ\O”—faZDˆ#\1L5p±!hàˆðŰñ$P¦úH`·ˆL$ç$JZE¥ñÉ[KT‰ô"9‚líz ‘! =ƒÀëb‹ÏÖ–w 7”)ÅÄl9±‘^L¤ #)JMšR‹Qì¤--©KYÒ™¾”¦+Å©LsSžªT¦ ¤eÖf©8 N2Ž„žJÐ W(Æ„¨’ UÑ R1ÙÒä¶°šÈ#*&‰‘^bÂEFª‰2Ê+MâÄ»¸Bq:“[I€ÔÅ0uŠ9tjë# E쬋ZÛdÍAY2‹,A¶A5Å2“ƒäÿc°)3Bž•ˆ‰qhêðIW¶Ò³ígEZÒŽÖ´j Úö)é;KA†9»Ä@Än²Í¥2CªbêGAã$4³¥ÈseÓK™Ó†tû¹Ð-ȸS‘@2LìÍõ²HCœÞOع☼3gv â ½„ æ¤DäŸl16±ÍÛEA'º‡>4{…²N÷LÒ^%AhœàʤûêUÉá×qmm£´`é&˜H®e0„aOØÂÆp…3ü` w˜ÃNˆ¡ta‡ØÄ#Þð‰¬b ‹xŪtb™ZIÁ FõYÞ”ºÃ~:bp5¼kR%Œ¾7«‰½l!oÿáɯŠŠ>̪dÖÃVv4k] ^·Ô·ªÐd®p ÌÙWT -Ëdv•Z4m8­[L›ä{«l5á@KëcÉ™ÉþPL¤±íM*;pîói]ZF/Úцô£%})P=F–0ÑØNáÛ€^¤uI‰9Ý5`··©*‚9k;•6‰é‘µq3µÍQšCZ‰?FÂ@´–„­¢97¬‰')AÐK5í† ·ÓñÝ!CW$vÓJ•1{âˆD8«!ÃTÕ±¦RP„¤ë[”ÞÔÝ)¶ytKÔ!I`E>ÊM©w É%ç³úÁEÒ*æ›$^ñ®cÉU¶Îö{’l×{pƒß÷~øe¿yð¿üä?úÍŸþó·Ÿýï_üÕ?÷Ë¿þô‡ÿGbl¥Ðøò–Ÿf@Ú³ÿ3ÀDÀTÀdÀ­J[Yª%‘û8“#9«@úhâø’ë@h¡çû@ ¹Ì@ ô@ÄÀ¼@<ÁÁTAdA¬Á´ÁŒýS¹ôAüÁ Â!Â"$Â#4BKɼž +1't±c1‹B*œÂƒÂ+|ÂãB)ÌÂ/ìB+C/ C,,Ã-$Ã4Ã3¬Bÿ3TC7\Ã7DÃ8¤C8´Ã9<¹*¡þ[9$ôÃ$üÃ@ÄAÄB$ÄC|@X²´aÉ4ÔAG„DÔ q¹ÁJ|DIÌÁHœALÄÁN´DM„ÁMÅP$ÅLäÄO<ÅKES˜F”¡êCD”EC¤ÅY´ÅZÄÅ[ÔE?\ÂÃp›ûÆü FûÆb$ÆcÄ?dÆddÆetFclFh|Fe”Æj¤ÆkŒFlœÆläÆmŒœ±XÌÅqÜÅr$Çs4ÇtDÇuÔ&ˆ ,EOTÅyDÅU¤GPdE{¬Ç}ôÇ|LE}H|¼G~È‚üG„Hƒ H·àAXTLjdlj”ÈŠ¤Èÿ‹´HDìÅžÐ6ÔÂ6ÄÃÉ‘üÈ’Ã:I“ôÈ“¼C’dÉ”|I—\É™”C™¬I•¼É˜ÄI”´IžÜÉ–üIp´4ÿËHŒ4Ê¢DÊ£TʤdÊOQÄÄ4”;È~\È„¤J…ÄÊ«ÔÊ©äʆ$È­ôJ†üÊ®˰´J²Ë´dEWD È Ê¥„˦”˸¤Ë¹´Ëº„HÊб„JHŒiK˜¤ú‹¾HKˆ‹0WtEv5c"Ihƒ±9“]ñ>ˆ@9.ú!xõµï:vµ¾óH@‘X$ð>ÿ€å×? .[ÀWyÑŽUQeQ ÙY5Ù’F¥ÔáHO’ Å«) Þ@‚€•ºz«[¨îˆ1±„ZÈ9Üø Õ[ˆq­[ÈÙZ@Œ8`WIZáxÚ¤mÌè“¥5,ØèÙJ]ZÉhƒ¤õÚÙ“ïÑ…ØŒ¡…Ú?s®]Û6Ö$(Z³ÍZk­Ö»µÛÑâQÒlH¹£$\Ü…+®û ¬øª§˜¢Äti- $€J°¸%KЉ°\׃H$ÐÃ"1AÈYÊeWÌÕ…s1”J] Ðí‰S=ž®MWIÝÊ]Ýmÿè“t©„)§mX×J8 J¤ˆÏÛy)Ø-Ú=Õô@[ÕµQÕ^] Ö_Ý^aíÕïõ^îVOõÍ *SMÙ¹žë98“§Û¥yŒ?+½#,Òi_ã`×:ÑÙ?‘ÛÄiƒ¢¥ÜâØßå©…@[[¹õ7 `iežUœµ´ ÈY×H‚\ˆMÊ…%"¨ v]·Z¨[ÐP\­µÈÙÞ% iÂÛÎ[ƪá{¶a|V§|Gó­JĸœÇ@ˆCQ £‰>‚?^èy¨PÕæc\ÄðÚÿ.®Ü\@ãœÍbé} Öå e1>^Å€]ŠÞßt‰,㎞‰àâ8Ð…X×~¥ ‰€éÌU鯸âïa‚>^–˜½å乨Ðe\8v q‘\ÏõݰèÚG^W:^ Š`ˆe&c< _ò½jðÖòÝê¬_­ß-ÖôåÅ[e©‹&+«ÄPå=›åË$æyÜÐ8àu+ZÅÈÃ’ÛiFfþïi$ÚM‚¤5—š­ÚÙ0Û,†àoVa¿N&fÄ&\øÚÒì Ž¬ÎPZ N[1Éb€ulËXæÖç|FíÓæT†Ç_|Ì碉ÏA.Èj=mjpµ¯ðH›mâÿ ù\å颥ã&W@Ë%CÖ}*0°“…s“þàˆ]&¸ãi6näFefîC ¡çÆØeöB–Ýv“d .]§=]àÞ`7ÁÜÇý¥AŒúÓ]“v3]¶mÝeNì(Û·Ùë… ]î(Zшnñ&=Y’…ð‘•ðŸp”p ÇðŽ=e®YØ{"ÊP¬@"©[š—™;3 7`ƒç^“}e‚]Öà%Âæ>´&ü}ìk¾å`Å8]?¬À“ ÷ŒnN‚žõ¤Wï/q‚kf9HÚÅ{ºÏ8]¹Ýì€ñ°\7;dŒzk$]¨%ŠXÛÿɘòÊhîÐ`à&PòÅXà>yŒ×]¢6¸e0WíÔÖó<½ý‰ÒÌÇr㙄FŒé™™…ÈBYXv{(ˆ)U1)Ú»¶I×§…]¥Þo„>è‹ –ÝP·…Ò½µ¢Ý阥ˆÈ‰lòkNËeׂ ˆ&ðA'”Еé‚àŽýt(–uU_mÝ…àQ‡l2œ&e–/vÕ³d°xž³ˆcYOàí+ÚJ0žut®®°æjr÷êîE÷rÇê®fwsOȇ$ëàt<@[Ï~/‡ ÇC‚ÑæŒEìc Ç;šÄæ z·¥; <‡™*/ ~çó=‡øÿ‡_mæhmÖêdI é Ș¾øx‰ÃÓ9æ5>Œ5´sùŽçh™äP Có«.ù'޾…¨Ym’ìð‰:^ê _ßùžŽ–Öµ‘㑈Ç!W%áy–”¿xRÆäMöäRe©¯úQ¶z¨ú¬çú <_JT^Ó[N²ß”6a9‚w”i’øˆwû¶ON~¾4FÈù9‹aÙJJ$‘pUŸ†>Ö$ER™¯ Žvh#- ¾—•€GÍ]ÕŸv㛞¸æ›‹ê˜Yj–!m÷uw÷ÎçüÏkÐÿêÑOw­ëÅXÙ·W}¸_ýÖgýVÂÖ WœŽUy¿1zšGïÿœÿ‘öàùÈ·Û¯SŒU¯Œ°} ßšyRùÙ¿p ¯ðç—þè§~Ù¯~è·~òÛp×çþ×ïþï÷þ²ñs„tÑ/ýÍýô'}uWÿó÷üögÿõ?÷øwó‡ xG}±ÿýþˆ$h° ƒ 2\è°!ć#Rœh±"Æ‹3rÜè±#È"C’,àb!)Sp’’‰0UΔ óeÌ™8mÒ„És§ÎšA}ÍySèQ¢Iöd téO¤M£*Z”ªS©O­B½êµ+X®b·’Õj¶jY´g³ªmËö-Ö¸_Ç®•6-ܹxíÒuËw¯ÞºýÎ{Wðaÿ‰ ÷e xñ_Ä#+ž\˜²cÉ-C¾ì¹3hË-Wö”)0€É‘ªI®nÍúµëذgË®Mû¶íܸwëîÍû·ïàÀ‡ /Nü¸ñäÈ—+™ÚtÌ”2Yºd:Ý:Mž×µg*Ý;öïDÅç$¿5â‡+ž8ã‹;Þ8äsdo ;±)æf®©æsþ¹§¡o.ºç¤ƒ>:ꥧ~ºê­³þºé±¯.»ë´Ã>;îµ§4Q£9ð’?¼ðżñÉ#¿QÕÑÑ$]¯|ÿ-÷ôÒŸ÷õ~g_=ö{w8÷Ú{/>øÛ›?~øéŸ_>úëSï¾õíóNøòÊÛ_?þÿ÷ëŸ?ÿûû¯å,§3Ÿ¹ìg9ëÙˆÀÞL dà(ÁRЀ, w–Aj°ƒü +¸Á^Ѓ$!/8¿¡Q®.ü _(ÃÒp†6 XótuÁ±¯‡ïk}?!~ï‡D$Ÿ“8D%q‰Nl"‘øD)FQ}Ad"³H"¾¤^¿«!o(Æ0’qŒf,#?Àç‘ %¹»îâÇ9Ú®Žo´£ñHÇ;ò1}Ü£ ÈAê±4¤ ù©ê„Š…_<#¿ˆ“4R’™¤%3YÉM¾0‡» @ôªØ@@ Øa N£Å$¡H8Ï)eKÿ¡”à•ñ™å,ÙS˪” ì±E$`‚î”2Šù™e1WY\’`˜GùN2sÙÌk!S@¥¬åwf©žjÂ’m§$L’ù¡«åDœbfP JtÆÇœáœf2‰‚„l‹V<â=í ?Q^qŠùôç>•Y¾ùy1JrPÁEà9L!PN-¶¡ mŒDÁœE‚[L´ iC6@¥¤à–xènj‰Khâ(@irHjR˜þÆ›ð  ‡;$¦ÅQ‚XÊSŸÞ†·8©nR Ml½B)¬ Lr²ªš¼jñÖHš…‰°3RhÂ;¹SJº ­L—ƒIPÿÔO fcR" X'lMêId£Dë˜æ*1%³¶¸Ä..‘‚¨Ä“.-€..a‰;lâ‹í`«R[l"±)˜ w¤` Æò©±)‘Cd7á†rç¡Ú9lK+ V¡˜v-8a‰%ÜPOJaw°é.V[JÄ¢h8¡ SˆBÐ.·« Tnr™]ç"÷¹Òµ®ÈV˜«.§H€N*ä´æ%éÌZÞˆ x¥ê@òª÷.¤M^ñ›×ŒbD¾ɯ6$qlØb!ŒÈ†G‚Òõæ4*XïH^J€Ï¢4»ˆj?K’œ6¦¾,PÛ« §à¥ÿfƒQŠ‚[Èaº ªDˆ:áo4Œ‚]¼ø ø˜ªUÓŒÕ5+Γ;¬N?m‚„…JANpÁXåPg74!%*гå°Úú”@µ…-äÌQ]&‘8t€…ÂVíHÒ A ­‹H$Õ£ ìiH3%‹6´6ÚHà&§,.,“$\"щì.X,KgIö‘•ÃXͺÒÏZ“B)Ð…« _&³m¸„T4Imø±¾ˆd‡™„e·ñ¥ÃæÿÉ0ÕóØgãZÕ2A-b‰²mÄZBŸ­ö.Ú}‰$àÙʶD Né] ÷JEú^idîËc3[·ñ}$›w Ý»°EdYÄ Xâ’°¶.n1j+Û×¥tCÇ-1VŒ5²Ø55¨!$ÜB¾Œ³@õ óòŸ¥yÌ:søq¾%à®pzP¥t R˜B˜› …—¤SðïDìëÑ6¬V •ÚP È!x娪 b߃°AµHBM‚«·ÑŽÈÕ³n «¸ ½¨{ íÞƒP#óÕÄpí05I°Ä&z:¦FB L=HˆËL’lBN ²äÿQ< wG8ÞK½C_À7]ô(FmŽìë»!Á%@ÁáoJMl‚ê´Ï«&.Ñ2«@Rpr$R TÒ„Èm€1E ]ô~Ml(ßò¢ÇN°¼j’e$¤ ø>ôKo  Vž¤ñvB”CßÓ8¸! I°éñ’‚¦Ò4å ÑÆ6\Ïæý«¹ÿ´Ò*M¸Q"é””@(] @H”N)A(€¨Q4G L$A¤ÝLäUÛÕO°QpÔ{Õ‚-ˆ”6È <\u‰ N@£@$XOØB-T5´Z9‘@o!…=›¤@$À.TܠОL8ÿÁ.|V1]\ ¤DceS¨À.Èx­T^! Jì‚ÌŸ|¡/]‚”’¾\ [XÈd”k ÅìB8=Û¢e}Öo}¡€Jœ:ÑÚ&à„öÊžàÖ%e€¦aL@!NL\–—<[bdIÂ%…%xa \Âî‚/ÕXX¡bé•LÀ>p¢ù!-&R-΢-æ".î¢"õ¢˜h—ïI|J]0”$£Ä_’MÁFØ¡ÁU Ô þ „NÔD½Ý@ŒA`ãDI^m\iàE=5"X”5FAØBØBÞ&ÌA,ÿUå‘ÙÑÄ<‘)ˆeØjPÞñEL¥@î­†…5A €!ÔÞè9c HAdkHSYÂIДMÕ#ç•€$^ žQIBD’1•.О앞‘„àÙBØ”ò½X èõe^HnÔSEY¡X¼¡ÔF‚˜¯Ô^HºÀå¥ä.lI¢˜‹ßùÿ]%ÿee¾¸8…’@éÔg)à@„¡‚WNü+vG.!A N”L´Ë­‡¡©ÚFÕÂwÔàupT{õ¥“m`ÛqZ|È¥/}‡:Â^µ0  …+®åÄmBž])ÙC1‹ž’##*Ö—|ÿˆ…•âJ‘×­)Vµ! \Bbß&ØL¸)ÎD@á0IÓy0\ ¬Tp1Å bLÈîÉDo½›@V*šagJA”Ô&è ðSt& ôfg&Ylv&ine®KÄÁÞÂlÁÄ"áŽWdy—.(A(Nß.4 VYñaN$[’ÇÊœÍíî§ê'€êÜ h€v AÐ GˆMß] HxAX3šGp#lCj”8„\jã4¶Õ@dƒ.8†Â[yèB”]†D‰’[•c¡B0B5ˆÔA0‘]¢ö=•„¶Á-ÌÝE‘M_E^êÁT,^ÿ„ôÝ$J1Óy˜-hEŒ™GYìÂñ™dL:ß‚¡…º¨- hC,XùÄP’€l‚3ni„dàAŸHå„mÂ%Dô9äAø(BÄLÆä%ôéü9”àIâ)MEi5ÆØsîãD†›’Wù™BZiíäï‘%ýEÞ¥.Ä™-D”¶©V†*VŽj’ Ö@—X€ž5R}ÕÊA˜•@‚Á„bà[HB#È*_ªÄD]À`]Ê¥Ùñ„ÚBø’\kD‚€É 0%k ’œSôjüªJ Z$k$àE)A>D "­T”eÁjnª![iÜ›´¦L8¢³9ÿâÙ™,@4ò…#@JÚ°_ŸqhËÙjTáüEÁÂ'e,e½\\´µŸMhÆa¹öa-áy‚ê%l‚¬Ô&§q–ô™«¤¤o¦†a 8Â Ž‰vÊÁ&€~¡îý`"ž&lëAGË šWÔ›(äJý+Û¼% !´Í¡b-lj6 ÆgÉÆb¥¢ÄJ°Ÿ´‚@Ô#ìħÉ"u¡juµ-Û¾íu¹mÜÂíÚέÝÖ-Þº!#•Æv=Òr$c, „šø—Rm„}áÄþMÊ¥D¨BÈã [}ãÖý%ä²ÿãDè‚DZ7JÔÕ9®¬%„$äƒ$•ÀîEJ­”:¥¦.™î„-lÞ~n*².) Ä-dÜìbŸïjCÕMDˆ'æê‚ï/™M‚A¸ÅîäB¬X•öÊ-xÔñή¹ D»‘ÙïReˉéôþnåÕ©5/>FB’ýî.ØT›ÚB*Þ‚ëê‚óníf\%óºî6¬ET#ÞBŸ’€oQóF–ã^oE\ûVJÅû¦äzðìæ^™10öa©³‘YSí‚ëZ‚/TUC5øþ%*©®°¨¶°•œÄÐaQ°ÀÏ!\üœYÀwÄá6…{Ùè®@K!ÉÙÿ(P”¶×Zq·ñ^©¯T$è©Äµœ´¶œ…4Ù°O Ü–yW&ë€Äa³µ‘wÁ±t š­Iÿ\N Á¸2ÅZhÎÕ0ã1ßœ1÷ç0³õý°0D°GycGùÆÞ½†Å Çíªpmø¯´‡ž=èAþÆ5 [oJ%­ ØÿòÆ“9³ Çÿ3<‡©¶Ñåè"£Lá`Í…Xe…>wEÔ‚$ÔB$´@³A 9–?÷ kZÑÖB» ª1 7 …×µÉ3ô>/ë/¿EJTtUôVgݱ‘–˜¨’w`ûÙÉG÷àVô³M´ÁD—Ö0bg!gDóó>óâ-ú">÷4Pÿ´PóôPûôŸcL$¨0Bu{w©T5ôè§*ýWkòL„Û™„€,$A†KëWëÕ0]ÓŸû2R2¢qÈg:ˆ`É yÔy£¬caÆ„¡j)‘@T#Èù}È÷8:°G­ÖßH‡bÚR{ž÷LôGµ\¢@5ÐÂnˆ™Œ7+ú¬RÈœ‹ ¥““|H©Óa–GŸS ¤¸m’Ï©į]€¡ž«º›+…b&ˆÈ—ˆD)¢YìDËÄ÷\÷vr3;r[O]Ä„ïF…ï”ÁAd;Á@\{¸B"A¶o·ĵ—{õRAÄb£eÿ„$¼¸C4¹5:u^‘x|ÕGTs¾{à-ø˩ﶛ°vë×lȽß_¼çmä×FHo~ídôv¸”-9G\ô¾ÿ—A¼ FÄ{G$¼Ã3D^!üÉüB´éˆcBDB6¬®F¸ßÁ[ãE$XD÷FÉ[ÄÏ»<λüÏ?Y±Ä¡AÁW9Ó x6&ÝmH‚#D‚#È‚#dx\½#¸AÈ‚+`=Ö§LàjJA,D8Bp}„€ÕS½,¤Á\¼ ‰¦^,›œF˜6”G£O<ª±+ñ~”Zl±ï¹ ¢šüf ªer±šø ÚD>Ä‚$Å„bJÿB\/Á>®â©õy &kâǧZÍÄ(âûœ¯÷¥#¾a]zâoœŽŸ8ËG±L0>h{e,f^Ø}&/Ål¥Ãç·WY šŽo«£Õ¾^i ôí῾¹–äÛBJh ôÿ%¤¹ë^™ð}·—ÞǨJ ù\:Ìëš/=M¾¨ü¥Ñv†aÕ¾Mþ-DÜL´ëêG@ÜÒfK›@I$J,h+ ‰$ @rËÖCˆDòµ!¢ÃŽ#~ìhqãH‘!!‚ô˜Ò$K”%_ª$)óäJ˜6iºÄÙòæLž9{ÖôógQ¢Gw"š”éR§B¡ê|*•D'±†,á°ÿ€ „_·†;VlY²d‘˜U{víZG²\¥)Ò¦DWФqÔ(Â$’Ò”@V–"„i$¥%‘ÄÕÝ$H’qäJQ’·EØ"l#ÐÍfmeµl‹04 [‘’ز•9á­HJlÝB8Ñ–›HÃJÚºMbIÚRoÛlkt’‚¨{“¾Õ[Û¶$aÛlC­¸šl‘ †äܸìH¶ÙjãytÛ‚Ñ–V¶tØ$Ë˳ŽM·°?ý-© AÙ¿ƒn+ñJ@¯¬ØÆ"€ mØÈŽ5Òì+/:m:ÛÍ,7(d­4×RóŽ­æPkn¶ðÚØŽ8ͯ3‚ŒsŽ¢òŽK¢?åêkN±$Þÿ›.,"ª©ÆÁ]+!¶´&¢¼Õ*¨Hãú-,ÕȪå–ç$k»HJø ,$œÔ·IÀÐ [„ë’? ó«ö"šZ~¬2¾9嬓Î;íÌÏ=õì“Ï?ý жºòh«8zˆ#«5©Ñõ(REmzèPG+-‰$J7-)BÅ‘2@•„·²,¡GŠà(ÔÈ*u/ˆŠe«s%„"J "GXÅÕ‘D85‰IˆlTµN!]l …$I¢SeµyÆ®EvJˆ~³OQ(„r«F9*Añ6íKì(!"€42"‚ÓgoA‚[mÚx.t1Ö£eÕÿ[m Žn9È#ãìkVàN ÚÊÁˆþU €‚6zÏ w5‹ ƒ’$‚•£Hì%¡ÔbIˆÄ6Õlkˆeg @dwB"«N»{6ÚIÖ¢l³Ò$ZsµrÁÊ—ŽÜͰc8C3D)ŸXˆ€46Õè²Çnkè³I ˆ„‚8wàjÝí¯¢€éújfokÈ¡ƒH­¢þÀHwŸKëÕ´®…´®[ÒLw|æÉ5•¼r‡-óÍoœsÊ5ï²X§jmBî—;²¼'z$SíÚ›ëi({õÛŽbнð}FJVMú¼Ôï±O€`qœ¾R„Ä&wÖÈnx§ý ©IiBPXh3¨"P,‚ûÊ‹”¦ÏlFŠ[ùÍ=¸¾²A8œÝmF1†‘Œc4cÑxFBy¥,YY”˜•)¨ñ$Ž$‘˜ñXÇš„@ŽHD_ñ*e%EºV’»<¤V·ÒÿKX‚Hø"Ú#DŒ#³s! aˆÓ£qBh]2m ˤ ò¯6<ä73iši'G¹¤lv“„:R*äeòLÍL“&Å2ŽPbÛÍl! •^ttfDð£6˜ä-;9ãˆj8¶šßÀ’kŠ–CBxy„ ùˆ 1†%NÎñ”ÜÌØ€BP>‹!z\–³Ò%ÔŸ’jšÍ>Æ“ï­r$ª´V~ªÙLŽ€ Šû”¼úÊ’8©vzœ#Á.Ù Kh;:/8Õ Ô!ý‘DµQqM:š7é¢NŽO#6!Áuþ˜Çgê¤<õ©EºS U¨Eí)QÿjÔ &•©Ku*Q_—Cq…id ­º•½”eUD¸• ó)Ý9T8ÞV’‰ß}e/bMk’PCéí0ˆ:‡ÄeWÑ¥l2â6ÐGœŠO9åû÷¾"¦ÖoDî« iñ#ð$SJ@È -5˜!)™iã_FóãÍûÀ,rÛÓ[¾óuÇ…·Y »Ü€AbE,òa§>O®F$-ö<Û!Ð_5<¨dE’= üʱÔÔž"±†b‰D>º&δç6XUn„†û¢ÎJï`ß™mY6S‹=mDZEK[~@YÅèTµç%Sr«‚6d£¦jÌêýÿ`XÀNc¡2‹¨’$Ê ¨ ëœ:;îS|tC@à+ÔÊ Iƒ·@%ªÀ àS—iÃe@e™“º X)[$ÝNÉ1Ù pÿ2çÆ•µÕ™F9ek˜³4«¡¤}[,#J¡$Øæ!é ‹pÖLy‘ ÕXg0e›¦` p9Nê0 Kó§ ʼì~Pã‘+J¸r’à²81i.ñà¨eY“Úþ %1Y1%²s$TB l8x`‘ &ï† €Ö&ãj†L'ͤF±C^ %Ž€‰$ÁÑÆÞëçâ²Q `CüÕ®ômÙ¥z À@æÆ9lÌ¥ i“yS¢†ÿpä7E›¢ÅœCá¨l À¿jk—:kpkêÌšMC‘uÆU$€>:²ã³yÛÝn¡M7ap.ÜÜþ¶¶Ï-nt—ÛÛìN·¹£ “²ÈŽÀ[2°Va%ðNTŽM\Òü·H¢‰A«ZDzU„¼õy¤íR‹šƒ±øœ IíÑÞV0$ð]ÖCZ.*éç?)$Bž gó[°àùM_¥qÿ]¼æ¹«z;;¾Ðp‹Ò±ŸÈCˆ?†<1⻡ÞmèùZI07˜@ԲƵqçf vòî{›e,v<3.–q%Aå— aÇô%Zü~±I.xløÿ­lš-Ä›åº&鮟ݡ̽£öŠåAúnÀ»õòn'é‚£¢¡Þ¥žK"Ø€E½ïyÍgžó›÷üŸè7Vå*FiJT‚2±ÓS…õ7äëU–²] UùAöjW–Òp$5,/A¶>ž_Q PŠ”;îÌ/ãZÉ•#L‚+3Ÿ%©‰±Ì“RÉëÚèHp¤³ŽÄùF¥’R:å©”ûտɳ„Mw¥.K‘ºã§t€*‹ýœ£ ;Åùúï&ŽÏôêˆJ$ ¯¨ÜãR¤ïŽ|hضÂûŽ‚Hª¯ ô¦üÐOOÊ:0-\Íø0E¿,(%Kÿ(…#ÁʈÏQW/õhP×Ïc_pqpg°kPƒ…q0Þ@"ÁBó®®óœðó ð ·H†üDJâó(Oj#5FÍŒš0 ÁP äS¨ðO¢Cƒ8/ Óˆ!ú£ Ëè Å0Ãpå°?Á¾BÁ(åuÜ­MÂ×ÜTÆ#JåS0‡\2ee:B">¥ÔqÜP'©¶mŽÚMCÂu hB"­œ¯Ü(±Rdä¤$QÛ ”(D_vŒ” q'.ññè11ŸÊÜ*¨€æ¡f‘R<‘Õe' .íˆ ílÑ m ð}ÑwÑKñ¡±ÿ™Q«q­ñÝ®‘ùPÞÀb ï épí°ÉñÍ1ÑqͶÔñÙ1áqå±ÍGÏ*nq¿¯©n‘&.E^ %4‘ýQ© ²r!ƒJ ò!2Ž’O!j"%’1!5")r##ò!=Ð#;’#Eò"IÉ"‹ŠGò#Yr%]²$I2&[&gR&ƒ µ‚ª>Oé±'íñ'}2(r(…²(‰ò(2)‘r)Keô Á¨Q©Ò£±r«òµÒ*§Ò+³,³r+¯²+¹’,¿ò,ÅÒ,Ë-ÃR-á²-×Ò-Çr.í2.ÓR.ñò-õ²/ÿóÝp2vªJ) “) ³0ó031s1³1!“)ñ1û^‡-Ó§Œ°5ó2op3Ð3;“3sP4}04?“4‡ð4UÓ4Ys4WÓ5[³4as6e³6S36o“6sÓ635{ó5y4uó7q“8‡S8ƒÓ7‘s7™Ó8S ó1¥32©s:­³:±ó:µ3;¹s;ïÐ+ »Ñ/ùò/Ëó<ër/Ó“<×Ó<Û=ÙÒ=ã>ér>ßó>í3?ës?ï’=õ³?å“?Õó?T@ý-»$æ-:»³A½ÓA!ôA%4B)tB-´B9o2³Bm’&_²CA´&EôCGÔCM4DÿI4EO´DQtEU´Ea”EeôEgÔEm4Fi4Go´FqªJOª óB…C‡´H‰ôH4I‘tIÒ)*¥’>TJ tJñÓ@ÔJ ô@µK©”K«4LÁtL³TLË”L¿ôLÕ4MÙôJ»ôM 40TIé”Ií´NñôNõ4OùÔN5´$*8›s939µPU9õP µQµ8•Qõ8'ÕP!µRUR5õR7•R;ÕR=•SE5TITM5SGõTóGa"H÷ôUû4VauVeµViõV¿sªôPKNÑÔMÍ´M·tMõW‡UX½´X‰õX•Y}uY“•Yÿ¥5Z©õY5X›µ=t~ÀÑV½WÁõ[Å5\Éu\ôOßhGu´GÙ•GÝu]ßU]åµ]áµ^ç5^éõ^í5_ù_ýu_ÿU_DŸ3»µ\Ö\va¶aöaÃÐIlg¢4[§ÕZ-¶Z±õb7VcÕc¡c9öcEd¯•d;¶dU6eYeTN¿‘Avf!¶fiöfm6gqV0É"KS5h#5UQµT‹VU‡Öh…h“i™öi?õh¥vi£–j‰Öj•¶i§Vk±Öi«–kÁj¢`å`wVgÑölÕ6mÙvmTbųW[6dçödéÖeï6oívoÿ3veñ–oGVoû¶n÷o Wppmb[y¶m×m7r!wr%÷Ñ•ô6`û`97s;ws=7tAwt5·t?×tEuI÷tY7u?—lu²rgV‡d·v)÷vm7w <óJ 7q±ý6± Ñ#Òx‹EKæxcyMöpwx§—p÷z£{©Wz¹W{­7{Á×Ý`6,̶\£ ™’bÁ‹rÀ`ÁGæwåWwéw~íwO.7P¯6l¿ýzÄXâž¼vT1¢ é!ä ™jª35±,AP€$0’öWl³Ö‚ø‚ûwƒ+˜ƒ5¸ƒAøƒE8ƒIxkÿ1Ø„=¸„»¶ha7Êw\' é (©!·ÄÂtÁj@úÄvXR@³²!»î·ˆë÷ˆ8‰›’wŸòqÆ“X¥Rd±@ 0.‘!âFh¢al¢Š‡­Y²ä–Êe18)Qp„%2FÆpäQ ¨AS@ä"rØrQ^J@Ú ,‘ª ¼Ï{7|¿w{q9‘ù‘9’)y‘-™swNæâ˼"®æÂÈDðG1 .ïÄçÀ"⨇4üc„®ÈF´®9üG„﹊n–…N,’ä',âàhJ T#ˆíV®å8™•x™•9góŽÿ@W]^íhpÍ ¸Po2å•[ù–^CT¤4¦ÙÖ\¨ºø‹ý¦Óxã¸BÃ_ÖüÆÐØ…>>ªÌdDab#Z–Na@ Ù€$ä@ºÉ„¹ rŸŽ¦©\w¡W—¡U÷¡[·¡%¢:¢)z¢-:¢[ø…ÌD¦¤îG¶A½ØbÉêÃeêƒ5ú*mNä¼Ôp-˜(•W¹5Pä9rÄ,Ô™ëÒª~ÎÐ,(d<予8˜Wã4š@š Pþ9ˆi!ð˜9ª›Yª©aá6û¢eËeËéZÙ×VqǺdm–c8ʱÆ>‘"”enÚ Zêb6ê½8›[îfüÿðåY,"ª ¼/ì ÛÀšà  b¼¯Tº‘«’/y’#û±%²-»²1›²5»{Áw|‚£³ê‚<†$D5(´›p;ž¨¥}«JP4fÚâ~« ?ú½žD6@‰>àƒ½Êd‡;C,b!âWº£;˱|Ëóª÷Pn¿±l‡¶Y@[i#RJ!Di$FªŠ£×¤ÅÆRäjîé”zæžäÚg:¢×vNfŒœ­&Eà"Ðn‰˜‡uX‡J%!æslAÑuáѯc²9»’/{³ûÒ-}Ó=]’5Ô9=Ó§1“c6£ó^„'ÓÈÆµ‹8¼« c}„}·¹Éèô„†Ë}]Ëý× ó™+Z`ùEQj&Ù+2‹ÿ‰à€IÀ!C¢]zj I€;£‹£·ý¢½]Û¹=Ü¿½ÛÁ}ÜÅýuY5 VÄ‹t=ÎÑÝÓ1¥…=Øé}Þí};¯šbIYÑN…¯rˆ±ÓôEc þS˜·àÓ3{ÔþÓ>Ô#Þá%¾c={‰ë=ãï}ã5¾ãk—º;\ÃEÃ!|9MòÃCžä¹;åYžÃ]å_¾äc¾Â[æm^æožægž*BÜã}žãþç…Þª™øIÌ^Ôû.ý>—~4à1‡à'~Ó’ê¾ê>ë¹~ß·Þëµ>ì»>oM|Ù]™¯|è5/Û‚¾íÕÞíëØÏ½ÛÏOWûÑœÿ’ÊZŽDE0#…J1DÒÍ¿B+úE]”Ù rúÜ%ßnjeÈ=òç~òͽòËýò%ßò3_{~a££væÊ~Ø$K|\M²A_¼Pìhý,2+ôi'ôE(ˆÊà®.³8/Åõ$î6÷‡¥/ÔPÿí…î‡óò]S*–ßAVðÍ&ŒC,ZF¿»:HÎXlêþ¦§qÊ8W‚š"q–ZGê1Í×úªúÕÀ¶"ÿH¨˜q\´GõŠÅþ4ŤxqÔ%ôÞ¯hAy‚H,8°àA 6LèaÃ…)N|xQ¢BŒ5FdØäÇŠGfi1$I)Mª<ÿ¹eÉ–4gÚdyS&Î:{Æü 3èË¡.‹Öä ”èQŸBæLêiÓ¥P©N}zUªR¬[µš,àd Xƒ%H”-QÀ…ÙµgÙºm ÷­Ü¶IÌ"‰‹w®Þ²uñÞÝË6I‰6Ûþæ-kK^m¶Þ²ÉƆlà¾n“¶k9®År)Ó%!‰óáµ™+ƒM"1^WjÃìp[šµy®|9ïfÏI¶µ)‘Û¬+3oie‹=:9òåÊ›3î<:ôéÒ«S¿n=;öíÚ»sÿî=<øñâË“?ß<íÛ±Á\hðýEùé;´o° ãý¶lág€ó9tKŒEbPh‰ÝÂY}÷‘ ÿƒª™e`c Ù"¡6”؂ڴÑ$ø@ÄB6ö^$ö¥a‹eÔ†-IÈWÂ~· h–$'ž´P *îWhjhV‹ 6FBI¸’H$pZ_¶1Ph J‚ÄZF£@Hð#ƒ –UPÚc õ磘ûñ¥‚¶}¤ˆ+!1‚Ï‹:à–}~ {>øg¡Ê硊&Ê(¡‹:Úh ˆBJ©¤Zé ˜Vªi§~^ê© Ÿf:*§¥nŠj¨“¦zªª ¶ «¨²®ê*©³¾z«­´Æ:©{ ½W™ê™×\7&æ†-Ûè•„6Û´ø¬{iÉl·˜õ£*Ò6ÿí-mlVØYHLÈ׸¶†D³·¤Ë5ù¸µ™´IDra2"!Éo ýf,·eíÆµÖþÖ›Œ?&goIH"XÁ³=+nb¥•U„+F¸5¦±ôž†eh’@§¢ÂŠ… \¼¹9k‹m|LnœvíÆî`ѦM°Â½âX>‘¡Ç3±=ÿìsÐ@-tÑDmtÒH/­tÓÜ©gsµVVLuáȶ ¡_€ !¡m‘„Q‰phAI“Æ Îù"†(Émц •E >P"¤bzN wõ7Qß ÆfÍ~Ú‹l8Cj¤æ…×.BŽrKc 'VÕE%èhÿäÆ`Þä× Â§æ@·|,PŒe;´8AÊbdˆ3 @b>: <Ö¥{e•ñVuTÍ'ï<óÒ/O½òÖG_=ö×CÏ=WÚß=òÞ‡ÿüøæ‹~ùéO¿½ù¾JôÖ°HFÂf2“çò`¬ûîi£MÞ&Ø 5\ÌÇàBjTÆYq2 ‘âb%­`ÿb ƒ¶A›Ý°[oÑ`jPC.Ò¸"o1–hð¬ >:½YaoS£Æ´¥@gÉ_ýàf–Þè«qlI„+Þ‚áIÆiDdš‹ˆÄ#*1‰L\¢›Å'’G~ga À8i1‹YÔþHÐ,=ud6qêO@¤ÅÙÿÁ©.< @EDÂm@ÛœB8úÈ-$ý‘Ï@`œeŽŒÉÒC¢Ÿ|•€n±]Šèœ¶$†,oŒã!t6!Iw×£+ÒQ©Hn@, ÙG°ƒl‰Ž® ýQˆ±ZF¸1² ª°ÓG‘ m•ÄôZ1‡iÌd"s™§Tf3™yÌgJ3šÔtf5¡iÍlbs›ÓÔf7¹yÍoŠ3œäôf9ÁiÎt¢sãTg;ÙyŪån¡"ÑŒuÃûåÅZf, v@Âü†d¬×³@§bè2M-Q³bœ@>öe qéjLÄHÍZæ’ŒY™Ë ²:ºîCËáldd„Èmj$(_‰á dlŠÃPšË…ÕE?*SFÔ}%†a³© bÝz9-ê’2Ê%«×kAxu‚H ‹„$ Éhe´#ê„jò"| !Ið§¾ 2;ø`(_’DBîš46«.ÐQC@°¤2D"ykX³÷Üö­ºçSŸu[]ìNWº×ÿ¥îvÁ—]ïv—»Ú/x¿Ýóš7½ÏõÕ<ábϦÑÏ~ø$Vþ#˜H`PL†1¡Hõ§¡…G…WZKkx@·H"%*KoԖ͈ 6‰yÖM¨Qϵh§q“rÀå,Ø<„4KA„öo3¬…  ®åÌ/?ê_ÌeÅé§úÕÐ]jkÔ³AˆK²†+buÉZm2“Ÿìä(CyÊRÎj|­è«]åÊT=ÑrL,"ŸÆý…$hå  þ"™@‘éAk–ª (½6úm]h›gÖ«Ì·efž#‚K5¨buÙ›LÞóã²¼Gµ¬Ú²¥4ˆ$~tHÿ\Q"ØŒµ¨…¦×Â+\iyÔ¢.µ®LÍeRŸzÕ©Fu£UÝjV¿Úյе­g-ëZãúÖºîu¨sýk^{×ÄöõGÜ  ¨Å—ÊÔQ“ƒSUhA«Nfi•e mf_{ÛÚî6·¿íípƒ‰P*_ß§Þò–ט MúØ ÎÑ&É!rï—¡ iéÛ:Bè9³è¤èV+¼Dá«GÖ=oào-Pr’ºí qòF<Ýg/Á).ñŒc|ãGïÅ;¾Þ‹Üã$yɾt¿¾j·¸_îò˜Ã|æ2¯9ÍonóœãœÊWþU<ß ô ÝC‡gª‚Nô¤oó?H7z§šÿEËÊÐJ‡zÑ­^õ«k=ë\w:Ö½¾u°wýëd{ÙÇnö´£}íÐD6°†ºlË}çs¯;Ýïn÷¼ã}ïzï;zÊM&¯‚uä&/<Ê9Nxæ™Sñø®xI '-<à‰oñò†@^ó•×xK.x‡þ¸'¹|K6ïùÎcÞðŽÏ|ê]¿úÑÃ^ô­gýKÜ>D³Äï¼÷»ï{üß ?øÄ¾ñ§Ør¶`¹j°.ö°Ý|èÓúùLwôÓ¯I}ë[’ê á~ö£ÿýé[ Ü/ˆ÷Ç~ð§_üZ>ô·Ïþø{ýóW¿ýå/lúçÿþõÇ¿óõÿügk¸GO°{LJÿ€Åç¹— xwØ€ ˜€£Qhxˆ€GçV5¯g{±W{U1f­÷gð&.huoQ 3M²G¦W cp1ØP 7‚’6{%Xw6LµÀßUoz"È] q„´‡5åWx€XƒKHz ƒW8‚Yh…Zˆ„]È„^¨z§r x€4„‘mâAC®¡a¾‘ªt-p3LƒÙ€Fâ" •u¸3Eã9ú‚Dî‚ äÞÑie(Ðd(än€P‚lð_{)`†¨‰™ˆU=7X¤vb'Šg·LÃ5ŠñVä6'¸LˆòЧhÿ(L¥f¶` º°5ägÕ` ŸÆv‹D\¡8o N h€Á¨N)m€•ÆvVG\ƒÑ(tŒˆVJGq uÀ#)0JÏ”q`z²hޤˆŽÂ¨ŽÖÈŽç¸ŽîØŽ!A€Ê–|L„ˆâñOƒsÿIo!·ôqqˆÍÁ.kx0qÈérlábo‘ÖCÁ¡g°Ð·’  ˜Øm€IÐö¯ŠóüØpA±À`¸ñBf tP9鑸$l%>ÙPXXP‚‰’(QPQÈB¹㨔gAà”ÊQ(V™ÿ”¥dSi‘Ȉ@Ù”Yé–pÎØ”`Y–q•fÁMÀp §ˆ?y”Š—rANi”P9”œ¸‰…I˜(5>÷U_Hü‘Š%×K§1$R7Œ¡JXF&R`¡.oÂ!ŸSb#­uVžY9øÒ"CKF7°ygj‚[¾Õî¶&6R9F™ ’Kr$™¶ mP Cø –€†ĸ›)1^2$4ˆZÅ%"¯)! šrõ›@²€ÕP ¾˜™ªd— Až%â=†¶“MmŸÜÈy‚4ŸðI&Á òY”ÁÅòÙ( óÙpÄÿmÐðYÓ¨ qPhÁ zÊŸUø“æ¡‘ŸO¡óy”M€ ZfÑ¡øIJŸÛ ñYG*Ûøžô9ó"ŸRxEŠ P£ò¹` ðŒ*Ú¡˜8ª mÀ óYh\C Ê…Œ†QÚƒS‚PJ¥X¸…ÈrF$!1‚CÉ@)„‡á,Õ¢Aú•2hªbR-’ЂX2/Ûà¦}%:ÈR$Þ.wa/C/„AHÉÂ4†Aüä` ä1˜QH”!#2Ã-ùS3…Êâk*0}:3kx%þµ$é•rPSI ®A3*ÓQcB”\n¸þ6úbÿ2ó¢bcó@¥Ú/BFž’¡6Îr«k 1©ãhq€ 9š.pЈeŸ)°–<ùž(°“ ©¬wÁËjpmଠFq`¬ÓêÍŠð k wñI ˆk‰¤ß âZÈšÚºÍÊ5mPrÀÑ*–(ÜúˆúÊuY°qЮžq­n1Žñ ®tI¬ó±Ùº­Ýj|ñ°ã˜ך.c?ûë4Žê¿tÑOfÔSdPÛ_¬jRš:C¡ú@(Ät}C %©‹$Á³,¼¡!Á‹‡(”ÀzÍUØœÁb#ÙØÒÙ"ª:TÂ$€A…ú_) ÚsŒ Œà¾iPÔ&´¥íY ɪq„A%P-Ȫ% ùÐ`B"Ù ¡ ¸j“Ú!wÁƇAÅV¼°ŒŒ±]ŒÈÍÍÖíl ‰pàÈój¬ÀÑˆÒ  z°f½Ð걋ÇWœÇNIÇ$€°ÞMË-Þg~<Ýå{ÌÞmQÑWtÉ—ÌÿˆH`”Ø­ÝÙj—Ryß$z®¡ìà¢,n#K5éè5T+ _—[kE™nåšYã-’’ÍQâ¥H‚ʹ¥abà ‹ÕV‡êEøäE£iV¨:Y£¹Zn€šUKÃn•‹:R-˜)‹£0Áb}ÆE»i¦X\bFq¶$7T‡ ýñ£m²ôZžE«(bF,Š'€ˆW‰d„e-A‚,„´Fa\ïÁǹ7„¸›Då‹­hƒÛ(8ÍyöŸ)Т{”ÈÚ6ÔCm—Cí wÑR×À»‘¥§¢‹º äGèì¢LØ Áˆ–±“ÎX¾(M¾ŠÞ‚&úÒÅú£G ÿ!‘HŸËêp»ÁR¬Ü¸®ž»q@yÂú ÚèÒš »»ÀûÓ :éq0êð-8éKáðíÏ.íï8íñHí꘿Â"×CÃ&ERרÀU Ö_…1¡-&ªESffX…jaí~-Ž=@ì!´Ý& ô_j"I ÔP:v¨…21€‘ÛdµcÿõæIf`ý‹UDP 8BðlÑ/)$@:a ¯Be!¦ AÛÃmø!v!ÄD £ZÂΦÄf 1L`F€h‰nŸü­¡›ßƒáÈòÆRì¤pÑŠü- ôó–8ÿYÿ:Ǫd(ߥt¸®rL¢qLßEÏ¢ßý­k”`õ¾ðɯ;¯0dö ŠPÜøˆ›\ßþà}ïm¤¬˜ƒ×ÖÔƒîögëÜË,÷f²³MQƒ¦u;Ñ‚VÑ‚+qø%Qƒð†5ìVTð‘ ²`ƒº» L ˆk¤’cŒPñø|UùVƒŒ–Ù+=—WúÖDúO¬„b %hiÔMzƒ{+mü¤ï¢­º/Úçá$Ä_úÓß}OⓆ¶ÒÊ_úˆëÒ>GýßüËÿ“Á?þ>©üØXý Wþßÿ“á †ƒ¿ÖjÖf ÿóïÖ"¨¥lQ†u§_|$Jÿ$8Ð`A„&,¨í–Cˆ·l-¤ˆ0I¤$mRDRQ!’$ )¶Ù–Ä£H”'U¦´ÈÒ`G—1W¾L"Eœ&2uÎÜÙ“çOŸAˆ"‰M6q„.%Ú”éS§Q¡N•Z•êU«Y±p‘‰¯_ 8ùJ‚D³`Ó¢5[ölZ·lÕš•[îÚ»tó¾m‹·¯YIÚþòK8®_È–»¸pcÅ‘õ2F y²Ú¯–ßJ²ÅÙ³-7+Ãmc bHÍŽå‚Øk×lm!«–œøòìÑD_F«›5eà„5'q³ N®ë&λõ]æ{Ýâ¾][¹Ýèz³¿ÝN}¹mðס ŒÓÿ9kñÚÃôÞ|÷ûöσǟo]>|ûõ«ï_¯¿?~þÜ£Àÿ40?Äk¬°æBk ¸ÂjB­*¤ðB 3œ° ;ÔðCCqDâDKLqE[dñEcœIÂÏÊL-…SË®õêñ­Ñ rG¼†4RÇ#yDrI%›,’É'ôÊ)¥’Ê+­K'·ÛÒIôˆ¬2J2Ç43Ë2Ñ<óË4Ù\“„0Ã2LçÆ”“;4£KN5ûtÍ;{ó“H=¡,­@IˆŽN<íbÑFùRìt|TREÝóÍM5åRLOµõORG5µÓRQ=õSU[eõUQ]Öÿ6W•+Ç-’F^eôµW`6Xb‡5¶XdU6Yf—u¶Ù w-¨A±œHOÇ:±ÕöZnG˶Ûo½ÝV\pÇ ÷\sÓ-w]ÙE×]uÉ•×ËÜâ­®»çè /|ïµ7ݯ.ß+O·÷¥a~ –÷݇†xb‰+†÷âˆ1¦Xc‹3öxãÇͱÁ· ”ÚgSFye•[fùe—c†yf™k¦ùæci$(jÏr‚SZžuèZe-:èP&Zh¥›fú餡Né©—ŽúêªÆÚV­³–šë¯›j°·Ûl²Ïöm«×v»ì·Õ†{n¹ëN{É‘çRèd›ûÆùoÿ¿|pÁ 'üpÃG|E¾Kè9Ç}ýS0òïK¸@/ŸsÊ5·ðÛ-lÓ>óÉð-0ÜfÄoi³N£0J¶N;9Mc¾Ôã‹X¨$8”ó± 2#û12ôÀüÀd Är ƒH¸ I3™h7ˆ7€A?K‰:Kðˆs=†¨µ?; ÊcÀÐÐAŒã3»ë²`ã;¯Ë¹¹ã;$3@B¿K¹-«»µSˆ=3ˆ%¼¹GÛ¶ƒ>)L07«Â¹Û$p½aKCmÀ°¨ÃA¾Kz¨‡Es¹ƒ ±Û ôBZ0í⺡ÈA¬[¹„ ³Ó»‚6?{lÌ3Š10ÓÑ2»ÆpÅʳ·Œ¾ ¼_lG0;v¤ÇÓGÌ5rTÀƒü614ø }.‹.Œ4®‹ÔÈŒD®ŽÜH\4årŽR2¾• C“ óˆ-lˆ8DÉÇ»¸ƒXF'#ă000ÿÔÂ8üº[`;-¹¿óº(œˆ'J‚àÁMóB&ä9±;D§ :“ ‰Ö;°£\¥Ì9ä½F7©ëÉ‚€:œÄ•ƒÊ±«<‚°I¨¶-;¶«‘‡B³t;D\I|IŽhG»,Ëž4K‚ˆ…l¼NÌO,LhQ¯a)L6¤íS°ô+è3½áÛ¹‚̳QÄÌ( ‰Ë WT¾P6¼`µÈT Ø+ÆÒ# îëº8Åè‹J+ûÛÅe$ðÇ·5Ü+=j´µà ØÜÙ¬Lí³4~D6ð» UDFÀÙ°¸<¾û $0rlî”Eï“Îãš´Ì©»o4 ÿüÎÿzCUÛ3]D¹: O‚(H7£ÎÕ>ì‘l¨i²ÜOìÏ"ãÏÿôOýÐ4*$[A“ôµ»ˆKdŠÛô?Ï›°ü“9¶ûÆùÚE‹¸ü2¤¼GBRlB>ûÉùÞó3 ƒM°4t4Q³?)‹¸‡Û²ŸŒA‹½#·ñ”Pãü;¯·ÍcPž‹»UJI€85kÄå9ï›Á| kˆ…9ƒ½íº3[‰­´µ&Ĉ 3.Û9•¨ǃDí´ÓÁNcK±K)ôIИɌ#@´< {=õ<(k»+g‹B3LA%LBu‘P¼ª{‹ŒóHëÿ`ËýÍ'C¹ßÈ!4 6œÌÏä‹c¿>ËGÌÄR?D 3[;iD‹Yc9ÓØ°LeÔ %¶ãó½Ì; HýÅèÅÞ”älUýÊPß¶Æ,9ó²—»¾—˳X°†R¼Ì´ ȳнK+ <4M1=FZ·è¼#@½(UÌÔ=‰è²¸`S³¨¹Êã¿VÏÊ`C´¬Ì~„F„L HÈÈOËW~ ¸DíW‚ã×ÕW€X+¸ÝWZ:8ç–œ†íµ…xØa¯¨/I‹…Š¥lh„˜à½©(Ñ•;—€4Ž8Tõ‰ýº±;Y™È@-T™Tšeœ®hÿ[<ý”šVñP››)1¿ƒÒ´'!Z" Z¥í"˜Hsq?¹á W稯2züEýš³ËðÙÑ@‚w3A<ÁÚ²=ÛE[²M[˜-@ ,›Y‰R ©ÁÁIÃZøF½Åˆší[¹õÛj®úHŽ1ZÙŽl—ÑPW«-¯¨du«Å-Ú˜Œ°¢Æ-Œÿz\ì\ÂMÜ ]ÏÝÑÝÏ%.…eÁ¿]]Àe]×m]Ø ÄÌ Å$Ð=ªÚ½”e(ÝUÛ±ý]± ÞeÛµ-^à^ã^Û=Þ¡:PïIÐ×ÞØ^é­ÞØ=Ôƒ +åÈÞ‚عꗀEXñÿå^5Øî%Øòõ^õEßð%ßö=ßñ…_÷5ßµJ]è%¼¡^ýµ^þÝßýM<«2Ûk Ú¯Á]'1ZNÞ¬ Z d^VàåUÞv`ß•à F^ &Þ Þ1·%-Ã$‚X3ëYYÀëê_öß^a9ÔÓu˜¹Û¿mœÕ°HN‹ÍÑ’8» ‚|hƒÁ£¨lC!‰Ó‹Q»Œ3]Ò}a%Nb&Fb'.](^â'–â(N\ûÕž'ìÊ’#DΰŠ.Æ:¤/{Í1ùI«ØÉ†hP?´@ea7Va8~㪘Ý-⬎ ˜ MûÅÐ=å›Ö—8±4AÚ»TD3jȵ¦ÿé‘ÍÛ‘ŽhDJ°,s1ŽdÇ3?‚Ì4¾È[ÈO ¶àPÆ`Q†à .å NeT^eRnå8rÞ}ºß Y8‰º¬»Ì/4H²œ9KÌ2﻾¼‹=“SR‚H|8á³+;©0cb.»¸t9/Ë»…Ñ/„;-þEc>ˆZÌ8þf9gq®ì…_sÑŸ ŒÙ׈ÔÄ(äFŒ Ð{=z¼µü+M‰øŠjìÑ|4<„4x16h {½fÅœ‹Q*“¯…°_œÁ›5NŽÑ_#¸”Ö´PÖ£ß÷M_öõh‘^ßøé’þh”é&éùeiù}éô½âÑFœ°Žÿ‰•A’ý0|8Œ&D”¼Î Q¡4Ù Ä0Î0ÁÃ:1 t…9¤^ˆ5ˆ$棎Â0^B4ÌÉ|ØÄqþêpk°~[œ=,¡2° ³CÌÜRÁÝB®ê<=êãÔPmGÜ£ÇY³E7K¢®œ ‰4 26H4!`4¡¼FUÇÐè÷DU[cL^ëJ¹ÈgÖä ‰l`VŽ`W>å̾`ÌîlÍölÎþlÑm¤éà$s’èC›F æcÀüºÔ0c‰sfk–æ_îÑjNʦ4ÎÉd¯Þvê™CB‚n5í6 }CÞÎj‘³êá«k±žnégî-´Öˆ®óÙÏ„L Ó‘Bÿ^ ¹&ǽ Ñì ú$U[£ ŽÊÕ@‚z€…ô ÕÉðÖmIʼn æËÇbƒ õ|ìЀÿO"žÆõ†“jÀO*^ð&®â)npp wp ð /.™Ví®µÕ¾åà¦ÄªŽ s+K)«3ü2H»Ðد¸¤X|¨†q¼Ó4-n-Ž Ú¶ÃL¶m¦ÆÑ¦ŽK“=D’0Y$¨w¦n#¯î#_]:f¯œÊî<“° oÔUÊ‹¼uÄèÈ‹>ãÒ¬µ¼s­¼û3 4pN¾X×ÇμXáÛð™¼é¼r¶`ËüŠÏh5ìÝÄÚ#¿{íÝQí=í>'í?tSôAtUö,XVÝ`ÿ"a¢°þ… œ,‰Šl Ò$GrMÏt¹-g“®Üã)\¼B‚®EpËVâ µ´ÛO‡é”véVõW_iZ?i•¶uXŸu\¯õ–æõîÍðê…ÁMvN'vcçB?tS‰“Ë–›0±ìÍ6ôg_öj§öi/tmgv?ßökO ÓFÐc÷b/wr?wŠ¸î ·pv‡pw_÷w¿pxŸwy¯÷v§÷{·w+Iæ)Itÿwsx€Gò%¯ÝnçvkÏv„Çv>÷v…ÿö…wø†xЇx2JtYxßxïxBõt]ïõ]y‘/yW¿u“—u”?ù\_y•oy˜÷õ——ùÿgy×vÏyŽßyÿÄdɃ·ø‡ú‰ú¢'ú Gú„?z¦Oú¦_z™ ÷çíyž¯zª¿zÔRw}Ç÷xÏw¯ïz°çz±ßz²ÿú±7û²Çp~O"„Ëx«{¬{¸¦‚¯x¥gx§Ï{¨ß{¼ç{‰×û¾ü¿÷{.Âx¹?ü¹G|Å$wùšŸy’·ùȇü”|Ëw|ÌùÉ¿|ͯü̧ùÏß|´ÀùÄ/ýÅ?}Ó× Ÿ×Ù§|»oýÁw}£üدý×§ýÛ'|‹—úXF}ßOýß~PÜG¡³û´?~åO~æG{çGþç_þèoþ}ï™1[XàÏ~áß~íþëÿW)ƒ×ý»·ýÙØÏ}Ùô'õ/ÿômÃï~îŸù¯ÿd"þ~BTÎýΗ|€@b`€$4ˆDÁ 4ñ¡B‰:´˜cDŽ72¼äDGž,éÑäÇ”"U¢l)“%Í•6cÖÄy&Ï—>Iþt t¨Ð¢3w=ªsiO¢J›Í õiR©U‘:µškT®T·2½ìT­]Çž-›°€n–`XÀ‰¸vë⽫7/ß½~ûþ+80áÁ† #>¬81ãÅŽC~,92åÉ–+c¾¬93çÍž;ƒþ,:4éѦK£>­:5ëÕ®[·ž2n²ÿµmQwBÞ!}ßFâðÝÂ#Gn29på½7}:sêÆ«c¿®ýyvîÛ[÷.|wòß‹Go>½óõîÕÃo_zùùáßËÏOÿ¼þûöë÷à~ì ˆ_ÿñw`€ ú· *!„ H!ƒbx¡†fÈárå^_²½V"lwIb‹‰+žØ"‹/º#Œ3ÊX#7Ú˜#Ž;êØ#?ú8"]z½…›Éq„äqI~Ȥ“KB©¤”ËÙ"I”M^ùä”Zb¹e–_zf—crY&˜dži¦˜j¢¹fšoºg›s²Y'œtÞi§œzâ¹gžúhŸƒòY( „j¨ Šÿ~â[³É5d¯´YŠ@b:©¦™rº©§‚ú©¨¡’:ª©¥¢Z—l•2T$CNx«"—ÍÕY决vÈë®Ê ¬¯Á:8¬±Â"[l²öº¬…Ä2û«²ÓF í³ÇR{­³ÍfËmµØ~»­´áv;®¶åZ[£éEâ©€]ÚX–ªønª÷Ú›/¾ûêÛ/¿ÿú0ÀWæ®]®†è•Y-)ùT$V>Õ†-I|•’®c¼°Æ sŒVÆ«åñÆ"ƒ,VÈ'›œ2Y*§ÅòÇ$ÃŒòÊ3·LóË2לóÍ.ŒóÎ6÷ÌsÉ@­sÐDÇLº±€Á9&QW­MͪÚÿD}WAI Ñt^ó’/Ác \6Ùg›6Úk«Ý6Û7®ŠWmà…èmƒmhs‹6¶ä- }¶ð}‹D€ï­•Dxá¶F¢7ß¶†­ÍÕz—pñ¹äb~¹ævsnnçéz:裃»¹è¥Žúéâ’κꭣûºì®Ó{í™§~;Ju³›×Ó+¶±Mâ’Û"¸aHPŽ—ãIðí†ÔW·1u ÁOL½]‘lcx’ !¶Ûß¿ ¾øá“?¾ù壾Œ¿#|$¢nâ]BãIà&àyå=P·DâÄI@„o\«œ- IHnp‡{åÀDApQlà(Á RƒÌ 7èÁ ‚ÿPƒ!ìà?(Â’…&ÓÒà)µApW›Þ6ƒÀ»Ü¢^%0^𖵺OÙË^Öl± é…M‡êK—èÄ&Bñ‰RŒ"m7Ú¸*°šÝ‚â'1$$A´1I\P<ƒìÐ!±E$è­QEI(ÁÔ¨ Þè v¸[íú¸G=š¹óc ¹øGCRwƒ<¤"ùÈHB.2‘t¤$iI͵PH0¬á cˆ/7Tžy—«ý°r¡ÔKãD©Ä*ÂrвŒ%-giËZâÒ_싈‘~–3/ .~ ¢^æX¼9"{Sž•¼‰Í‘x³Å¼º¥kÿ–+š/»y4£qó›Þ '9“†4Ÿ‰3åDç:…fNp¾sœñTç<ÛyNw²³žúÌ'?ñéÏ{®,“Mû‹<ÙÉÆ%pyIBöô–=çåÐ.¦¬ öò6µ«5T‡Fte.;zËz4¤ ©HKZ˜+¶Šnm©ä•tãRòÀr‘)r’‰’$!j¬¢#F,ÉŸR¨‚ *Q‡jTD ©EUêQÙÔI>õ’Iu*S«JÕ«BÕ=¼CH»$eR½’¤býêXËJÖ³š5­Ûå[Ø¢Â71Œ—AÃx¢«·â5…z]!_Kè×¼ö°Ýë`KXÁ"ö°Š5,c ëØÄòI r#ÿ¨I½‡Ö˪5³˜Ý¬f;ËYÁ tnoÑbTõH&™bæyiqX«×Âvµ²míl_[ÛØr«±}ìby«ÛÞî6¸AHˆ;Õ¬bUªKM.K«ÜÒh ™ìªgEY‹ÏV»ÚÍ.w·ë]ð±5" ÛgP„«§9¢—Ž8]ozÛ«^÷Ö ¾ì]o|ç[ßôÞ—¾óEæ~ßkßþæ—¿îp là#øÀ N0ƒìàCøÁŽ0…'lá cøÂÎ0‡7ìáãÔ¼¾±ˆK Üÿ¶¯q‘,m(ëY@i0–qŒ 0c×øÆ:Î1Žw ãÓ8È82‡lä"ûøÈ=æ1‘ÿ™¬ä&CùÉRF²“©e+O¹ÊZ¾ò–³Ìå/{9ÌXs—É f3‹¹Ìj>óšÓÌæ/§ »rþî¿BûRÞAw¹èBBRÐç?ûÙÏ(4¡KP€Aº†FôŸ]èC?šÑ~vt¢)ÝhHWÓ—–´¢5=iOÿ™Ó‚&ô¨]jB‹Ô§Ntª[MjUÃÚÕ¦Žõ«eêZãzÖ¶fu®o­ë^óú×Âö5±ƒ]ìPÙÃ66³•}ìU;»ÙО6­ Gæ:·¹z~®U‘ëmncû;[u7 ã ;Ýê^7»ÛíîwÃ;Þòž7½ëmï{ã;ßúÞ7¿ûíï<à8Á ŽÿoÄ™Îs^8ªÂk$§JI¤P‹[ÜÏ–øÆ.TèŒ_üÏ ¹ÈKîg’ŸÜä!O9ËWîr”¿\åyËans™ã¼æ9§9Ïo®óŸ÷|ç>:Їnt¡#½èI':Ó®ô§7}éN:Ô§nõ’Å$Ö:Ä·ñ®ƒ…+}Ô@½ÚÝsãrøÆ%’0‰oHÂÏ0¶øÜÓmñºÈ=ä춸ºëî÷×Ýtüº`€À_üð„| R0wÅÝ<ßowWžò—G¼æùÍëÝòžçüçGú΋>õ¨_}éUßzÖ“>ö§=íeŸùÚÏÞö ¿½îMÏûÜÿÿ÷Âß=ñ}_|×÷ù‡N8Û¯pNÙY®¤í6¸ýÈç  »øF&]ìB!‡¹Ÿÿ± ’ÏärPAúÇïþö§|æñ/9ÆS þö'àÿx?ýùÿàÿ `à`"à*`2à:`BàJ`RàZ`bàÊ_õq ¶åÙRŸ†`¶ÙÍtùŽÙ‘Uü-|ÃýáºiŸ.8Þ»‘À.XBá­ÛŒqáI^º¡éõ Ú ºÅÁ7´@»YÂ.ÜÞÞ]žÁ9áBaJáRaZáÀÝó=ŸóqáŽ8œÒ¬”=ÁS?Å¥œlCà\lƒ-ôÿÈaßÉyœËqܬùYð\ ¸@Ê5ÁÎ_ 8˹Á?ìaÔÁaȵÀj`2â":b#Bâ#Jb$Râ$Zb%bâ#f@á?u"'Ê~â(†¢'–"(ÒSA°Ø }VºÍ6|ƒ-¨@Ý!ÜÆiƒ~Œ¥À7üÃê 6üC0J‚¢ñb0ö".¢À.ã.äÝ?dO0~ 81~Ã6Ì "4ÞàÆQã7¤€áéB1ÎÝ4ÊÁÝm_ € ã?Üàäå¢å¹c<Âãò£=ö#>úc@ä@î£@$AþãA*dB2¤A6$B:¤@¢€vaEná‹D_ÿpàÙnÛ³\_ÈY‚$4Á%üƒš|Ã-4ÁÕ`$Á?0cÈõ¢-Lã6P\N9c4ÞÅéŸ%´%üÃ$Zlƒ3Ò¤.@\B¤ îÂÅ¥€Q¦@HZHÂ?8Nž\ °áþeÜ7|ÃÅ•À?\‚Ÿ¥%„Ñ7¨á%²e&ºe[Âå[Êe\Òå\ÚåÆG‚`¸íå·‰ _êåm5j]˸if© ÊA;ª@8JÂ6ü‚ [¨‚J(üM¨ûAè…Vh‚Rè†Zh†"è‡6(†r¨†v舂h„šhˆz¨Š¦(Š–è‹’hŒ†Åp]^çz]ކDB´N¡IŠlÐ*: f×ÜÍÁwâXg¢eª[äÙXhê &À4:ÁÝ…¦à¹;¦€Ç%@|€3ú2Æ]¤&ŒcÊÕ]Þ&ÿáéfȦ7þÃ-ÞÆõaÆ)@òÁ^ðßž¡òý©Ÿö)î*¡ªžªñ)* *Ÿ.ª >j¢2j¤"j¥:ê¤ÞDF禖TÞÑ- Ñ^¸Õ‚™FôÖæªRËGZœ%lçWâ!xj¦dyZÂy~CÈdL~e­"Q†%È9ãÎge Òß *kúùç̱`l®%9b_]Zë]bëµjk¶rë¶z+$¦@’`GŽk_Š+¹† O$ÄÕ¨ÑhI„Æ)IáŃ˜ ]¸˜H%æg.&:¦[gJ^ÄAq®[ då7` ‚¦À4ºÁg’éÂX8ê‚ÿÄÐ ¢æ6 ^ þƒÄ{¢Û.²£Ujlö)¬4¡eŸc4«:öbº!/ª¤è‚TÞ“¶ÛÎ6!2aÐíÐò¬Ð-ÑþìÑ*mÒ2­çmÓ†ÞÒ:-ÒN­ÔF-ÔúlÕbmÏríÓjí×^-ØfmØ’íØšm×R-Ù~&EJgÛ‚”-8ϼb óDSåHBãäM$¨RâèÊõŽ•ÌëÃØ”[^´Ï)’b*–—Dd§Å±á žœm†º ÈR#šg çŸuå7 ¥Ÿ…c/þC™¥?¸\WnC5îßyÚçvú ö"Å™&5–îÉe¬@ Øç®®¨‹Ê(ÿ‹Â艊èð oð/ñþnñ"/ó*o‹:ïñ>¯ñ&¯ôZoõboôf"âz¯â¢¢~¯ø‚oârE 5DŠÌI5IÌ-HBDà4ýíÞá¤5Q‘î«f¡] ¤ÀXg’€lÃ6´©î¹£ñM^!>©äÍaÒ ´€P*¦&€$âBF$D’°—ðCšp £ð ° ·0 Ÿð Ëp Ó° ×pÚ±-§ê0,%ÐôDTÍk½ˆÍ%”ŠÄØàóŽDî BÊÜhäJ•k`‹«®œpÆPêîÐÅáò2¢Ò]"„~kwë›q£ñÿ«ñæ%«ž«¹þ¥_N1Ÿ OáCHL€D¼€®Ð«AT‰©Ñ0Ù‚ofá¢U¿^HÂ{jûA-nZíÙ2á^­'GáØ6ç(“r)›ò)£r¾=§Û²òÛòn]hÏ-DÓ›j!«H+Ù…®,1þ¦áÊ•[Ù¨Ž.Gãö_À2¡   Î‘¨öVÒ`4S3ÕYóÕU36_³Ôqs6wó6{s8ƒó8ks9³9o"1ã¨uªs;³s ¤o™DŠŒR„ÄýøP|©ïýà$éYYj¡¾pÛðB"4 '4C;ô 74D?ô KtÿESôEG4FOtF¤¦¶òGÏÒDéE7ñ¨rO ”*^ô2àÀròôr±7M©*£«‡ÀoXq³qOóôOûtPõP uP‡ëÇ1Û´×ñR¿N<{ì þ3r!7S àÀÑý0òs䫪 tf¥Ò›5H£õY«uZÆc$us’WøÎuQDN@4%ǹÐ^_ß `{a 6^Œo]v÷–ob›âb;6ùB6boL×4vd+¶eW¶dc6]_¶fë„VcK¸Ö= ôZ›6[ŸvjFY£vk«Ôk»HFŠ—ß´RïÔ×në—€ùÿoû6pÿvowp·p#÷q+·q3wq;wr77t?÷rOwtS·tc÷uk·uswu{wvw7x÷vwx“·x£÷y«7s3õmÛqS'õ{»w~p„½æÖ}<²»ö~«vó÷û7Ã}¡0¯ó0'^[‚'„‚‡ƒßõq88 D8›Dx…C¸;x†ø†c8‡¿ó Ø«‡kx‡“ø‡‹ø“,„@ö •6€»x€¿xŒÃøŒCmI{ã8n#õŽÃ7Ïw|;µ|ç¸ëxùûøù’+—qÕ¶«ôÅö€ Ly•Sù•[y–cù–ky—sù—{y˜ƒù˜‹y™“ù™›yÿš£ùš«y›³ù›»yœÃùœËyÓùÛyžãùžëyŸóùŸûy ú  z¡ú¡z¢#ú¢+z£3ú¡7Á•÷¼Ú˜Ó ›¥¦kzºmú¥sú§{z¨g:¨º¨wz©£ú©«:©¯º©³ú«»z¬§:¬Ïº¬·z­ãú­ë:­ïº­óú¯ûz°ç:°»°÷z±#û±+;±/»±3û³;{´';´O»´7{µcûµk;µo»µsû·{{¸g;¸»¸w{¹¯”{ͱûËÍ»·ûº»{¼Ãû¼Û»¼ã{½ç;½óû½ëû¿÷û¾û{ÀüÀ¼À#|Á'<Á3üÁ+üÃ7üÂ;|ÿÄCüÄ[¼Äc|Åg<ÅsüÅküÇwüÆ{|ȃüÈ›¼È£|ɧ<ɳüÉ«üË·üÊ»|À¿”«Ø¼\Ý|ÎãüÎë|ÏóüÏû|ÐýÐ }ÑýÑ}Ò#ýÒ+}Ó3ýÓ;}ÔCýÔK}ÕSýÕ[}ÖcýÖk}×sý×{}؃ýØ‹}Ù“ýÙ›}Ú?}pÀ+W) ýŒË}ÜÓýÜLŒù…Úë=ÚóýÞû}ßþß ~àþà~á#þá+~â3þâ;~ãCþãKþÑÏ|åËüåüåg>æÇüæ{~烾æ‡>ç‹~é“þé¾é§>êþê»~ëþêÇ>ëË~íÓþí«|í<ÛÛVÿÛKßî¿î ÿï¿ïï#Í']-?ï+ÿó3?ô;ôSÿô[ðö¿ôcÿöW÷7?øsñ‡?ù¿ö—?úŸ¿÷_¿ù¿û·¿ú¿¿üÇ?û‹ÿüÛ?üßý§þ I 8p A„,è0!ć #Rœè°áÂŒ %n¬ˆ±cH‹/j räI“)Y¢t¹ò%Ç–0iÊŒ9D‰œ;uöäùÓgP C…%zÔhR¤K•6eúÔiT¨S¥V¥zÕjV¬[µvåúÕkX°cÅ–%{ÖlZ´kÕ¶eûÖm\¸såÖ…j¯Ä¼{õöåû×o`Àƒ&|ØpbÄ‹ÿ7füØqdÈ“%W¦|ÙrfÌ›5wæüÙshУE—&}ÚtjÔŒê4èzçëÖ³e׎}vnÚ¸wë¶í›÷ïÞÃ…~xrâÈ—+7îœùóæÓ¥W~zvêØ·k·îû÷îãÅ—|zòè׫7ïžýûöóå×~~úø÷ëð±&m °¤ Á$‰A•TÂgzP›"tpA /œ0C7´°BC¤PÃ;±Ä=4ñCUDqÅ]Œ‘FmœñFkÄ‘Gs<±G } ²Å!É"“¬®&ízÒÉ(¡œRÊ*©¼ÒÊ,±ÜRË.¹üÒË0ÁÿSÌ2³ZMµ4Ñ\SÍ6Ù|ÓÍ8áœSÎ:é¼ÓÎ<ñÜSÏ>ùüÓO‡úÔ>ÿø+”ÐC5”ÑDEÒE4ÒG%­”ÒK5µ”ÓL;ÅÔM=5ÔOEýïG%Ue‘U\ÕÕ%c…uÇW[­UV\iMõV^gí•H`mý•X]…ÍÕWc‹M–Ù`—uVÙh›VZh§Å‰ÌlÍÜVÛn¹ýÖÛpÁWÜrÉ=×ÜtÑ]·*@Ý ôÝxáWÞzé½×Þ|ñÝWß~ùý×ß…H=•`S øàR^Xᆠføa‡Ž˜â‰-†øb‰1ÞXãŽÃCÖÚ©½vW‘AÙä’Q^ùä–UvÿùØ—eŽ™ægYžÙf˜sƹڛkîYg y&ùg¢ biu•Nšé¥nê§¥Žšê©­®¨€ÞZ뮹þÚë°Á[ì²É>Ûl±9®xíŒÙöØí¸Ûžnºß¾[îºõÆÛî¼ùÞÛïÀ ºè” ÷yçÃ6šðÄorÆ%7üñÉœrÌ/·|ñÌ9ÚóÐ7øêÒ±6õÓUOõÕ]oö×e*m´m¯÷ÛuÏ÷Ý}ïøß…·¨ïâ7þïä?žyå‘_Þù桟þùꥷ>úØ:ûí½½{ð¿W\üòÉ?¿rÑÇO?|ô5_ÿ}óÙ‡ÿs÷ëqöücßÿ_ÿþùÿßàh¦àpx DàØ@>Є  °G½ë]0{Ì`9ˆA ~°ƒô`A8B'~öSŸüR8?Þ¯…1„á W¨Âö¹Ð†ô«!y(Ãúð†@ÄV XD"шIDâ•ØD&Ši‚”b©8E+V‹WÔb)(ŸÈæ‹C#oÂ(”1ꦌ?9ãlÒØF2¾pd£×XG1ÞÑŒxT£ÝG?ÎñvÌã ÷HÈ>‘‚,ä"©ÈFò‘Ž ¤$IIGFÒ˜d¤&™ÉIz²’ ¼ä'7IÊN–2”¨e*OÙJN¾Ò”°d¥,WYÿKKÞR”zDU_øCñ—:¦/‰9Lc ™½<¦2“ÉKgö0˜Ì”¦ýžèDkV›×Ôf6¹¹MoV /H(8É9Ns–çTg:Ù¹Nw¶žï”g<é9O{ÖŸ÷Ôg>ù¹Oö ÿh@ :Pƒ¡UhBºP‡6¢•hD):Q‹V£ÕhF9ºQ"xÂùæH»YR’žÔ¤)EéJ—X›‘$1HL2S™Æô¦4åˆN#ÂÓ‡øÔ¦5Å©P:Ôæ©DMêQ•ÚT¦>µ§KªS§ ÕŸJõªTͪUƒÊU£V¬[ kWÇúU±ž•¬h5kZÙºV·ÿ®Xmk\µ:W¹¾õ®tõª^ËÊWµúÕ®uÅ«`;ؽ汄MìaÛXÆ>¶¯‹¬c' Ù¿J¶ I K9«RÏv´ŸmhI Eˆ€Ô¨1ÅÉUWkÓÖâôµªMíÑX;ÛØÒÖµ¶Õ­NeË[ÜÂv·µõím‰ÜÜ׸ÀEîr…ÛÜã:W¹Ðí­t;Ýç^7ºØµnv¹»]ïV¼Åe®vÛÜºè%¯z»[Þñ¶—½ç5¯{Ó;ßøÒw½öÕï{åË_üÂw¿õõï} àüØÀFð‚üSÔ L¤£•pi)²”y}k(ÿº×¹¶¯ƒ½kb[ØÅf2²lf/ÛÙÑnö´¡MíZ[ÚÕÖ6`=L:X;Öàÿw¸É=n“†³À >pƒ×Ýn³ûÝîî/¼ç-ïÿÖ;ÞùÆ÷¾ïÝïtÓÛß æ÷¿íMp}\Ý7øÀŽp€/Üáo8Ä)>q‹'œá¸ÂSkjœ ÚÜåyÈI>r“—¼LΕ·­ë–cÛÚ.¿¶²gþìšgûæ1‡ùËi.sŸï<ç<·ùÏ{t¢ÝèI/úÒ‘Îò!žê(úÔ¥^uª·Ì£õÖµÞuP{Ôaçú×É.v°ÝìeGûÚÏÞvµ»=íqgûÛé.w¸ÏÝîuÇûÞÝîqþñêV|à ?xÃs™ÃéÑqÎx3½ñJG:ä?yËGžòBÇüÿå+¿yÏwôš}ÐIïxÑŸ¾ôuíöÑ ßúÿÞõ±‡ý„Ñ}ñ‡Û^⯸îqÏqÞÿþöÀÏ}ð‰?|ãû¾øÈ?~Æ“ÏüåoÜùÊ—~ô©}ëï¾ù×ï}õ±?S¿Gö៽øÉ?~ó_Måayê3Ï~ΣÞôîÿ<ü%?ù>þù¯?þ÷Oÿöëÿÿúïþüïý®ÍébªüðüPÁ%ëôîî&P+0ï.ï,019P;pCGðKÐOPM0Q,¤äÈcðegÐ"ñbñ °íïù/‡ÐyЉ°‘P—ÿÐ “  ™mõžî¯°³ ·P K ö„oú´ ¹oûÄ0ûº/ Ñ ÇÐ ŸO Û0 Ëð çPë éðíð õÐ ù0Çðû@® ¹Ñ qÕÒ!Ö/¥° §Q‘Ðñ•0+;Q'1£0§êñOÑSS-YP[pcgñkÑoQm1q‘yQ{qƒ‡‘îUW1—Q(bEÑ¥ñ9±Gq±§ñ ·ñ¹1ÁÑ©‘»1ƪ™Q›qÛ‘÷ç ÷0çQë±éÿñíñõq ùû1r Ò !ÿQ!ñÐ’ «ËÏ'ò)Ò"+JQ ñ;²ÃÑ#ÍQ­ñ#ÇQ$Å‘$O2$A²$S’%U²èJ#/’&gÒ&kRJZQ‘'}Ñ'wò'‰1({(‹R(’(R)“’)‡r(#‘nR*qr*«’*Q#¢&·ò%»Ò$½Ò%¿R,Ã’,GÒ,Qò,Wr,Ó²%µ¯Ò*ã.çR.½ð´ò Ò/ùr/õó²/³!ÿr0Ó030ýr1 ó!SãÆL ¡rê’./Ó23ó58²-Ñ4Õÿ²,Có3E“-¹r-I5GÓ4U,Ù¯Ì|M&1“65Ó6k“ˆ"AÚÀ ĉ*t3'O )r8‹s)‰ó8³)•9—39ŸÓ9£³9§Ó¦t´á:¯sñÈ 8cJl¡_P"o“™B'¡“:¹•9¿Õ[ÃU:Áu\ŵ[Ë]ÏU]E0L}«°3fêFg”QUÿËLßÕÚ`LñÔLó4ÌøôXU`–`™¢Eâ:ƒbGßs>£•FB‡´'µ'+Ic4c9UU;¶TQd=vcGUcKV4B'ÖìMKíC‘Êœ– ¨Lt`g¶`k–f§"CoáP Iµ´KK½”I–Kƒ–h¿´h“i—vhÖi•¶i¡¶J®ªÒt7†º”êµZ¶ÔÄ3*oÖfÃlÇ–J25U?VdM–d9mÛvdÏömCÖmÕnéVØ„•lóVl÷Vo­d[Ó•\×Õ\—p×p÷pqWq·pÉ`û–o'Wr+×*ì354W8·œ<ÿל@WœD·H×tÝét7uWWu[·sY÷u]÷sawve7ti÷vmwtqwwu·ty÷w}7uc—xk·xs÷x{7yƒwy‡×xŸy¡Wy¥—y©×y£{§7{«w{¯W{¿—{Á×{×|Ç×|÷|…}×W}Û·yÙ÷}Ý×záw~å·{é÷~íW|ñW|7K•pésI€˜€])–x–ؖ؀ظ€i €‚)x‚%˜18‚ø‚98ƒ=xƒ¸ƒEøƒI8„+Xƒ-¸„Q„Uø„G˜…¿–v¶ˆ†¹¨†o؆s‡wX‡{ØvHˆO¨„Dˆˆ‡Øˆƒ¸ˆ‘ÿøˆ…X‰›˜‰ŸøPš šŠIŠ…hš¦x™žÉе8š¸˜Š¯x‹±¸Š»XŒÁ˜Œ#ÇrÓ˜r×X©Â‡ß˜‡ãŽçXŽë˜ŽïØŽÿΉ“Š—˜ÿØy¹Ù ‘™P˜‘ÏØ‘¿Ø‹³¸Œ#yŒ!y’/¹‘-9“%y“+™“ùAÚ˜GY”K¹'ð•ó8•WY•[™•_Ù•ãä9‘ ™–oÙ–sy–u¹–wÙ—{˜/Å“‡ÙŒ5”‰™’‹ù“™™—Ù™‘“Y™¡¹“§yhL›IY›%–»9–½œ¿YœÃ™œoø—qùœyƒYÛ9ß™áyçÿ9aª9™ï9š›™š¥Ÿí9ŸŸÙšû™ŸÿyŸõ9  Zf²Y¡·™¡i¶œzœ#¢'Z¢+š¢åEžÝ9ž7šž3Ú£9Z£;¤?Z¤×¹ Z  :¥Q¡Wú¤_ú ýY¦z¦Uº¥oZZZ§š§ýô¢-¨Z¨ƒš¨‡Ú¨û‚¤CZ©“š©GÚ©Kz©Ÿ:ª¡º©?†¦¯Ú¦k𥵦]:¦±z«Áº«qZ¬¿:«£i§Óº§×3Ú­‹®ßZ®ãš®}¸ª§¯ïZ¯¥z¯©š¯ÿÚ¯»„Æš«Í:¬Ï±[± »¬½Ú±É:±;² YÔÚ²Ù³kr®7»®;ÿ›³?Û³C[kú:¯»´›´SÛ´UµWÛµ££°;¶!{±)Û¶e»±i[²k·'»·y»Œ/[¸3›¸×´[´“¹—[¹››3Xû´£º§ûµ¥»º©»µ³{‰w›»o[·½{¶Ã;·ÅÛ·¿û·»û¼Á{¼Ó±¸Û{¸ß; ™[¾›¾çÛ¾ë;¹±Ûºµ[¿ûûºÿ›¿|¿œcȸ ½Í[Á\½Ë›ÁÓÂ|½œdàÛÂÝÃoð¾7¿9ÜÃ;ÄáØ¿œÄ \ÀGÜÄKÅWüÄwIÂ)Æ|Âe<ÆüÁ_œÆsÜÆg|ÇaâÂ<Ã|ü>œÈCÜÈ‹ÿÉÜwX\Å[¼ÉŸ<Å£œÉ¥ÜÉ©Übk¼Áu<Ë{\Ë#üÆ¿œÇ·\̽<ÌÓÈÏ\ÈÓÜ꒜͕¼ÍßÜÍãO¦œÎ«¼Î¡üέ\Ïó\µ¹ÜÏÇÇÿœÌ±|л<ÐÌ ýЋÍ]Í}Üà\ÒåœÒ'ÝÒ+½1øÜÎ7Ï9}Ï=]Ó;]Ô—'Ñ ½Ô}ÑSýÔ½ÌU½ÕW½ÐaÚÑgÒkÝË.×1=×w]ו<Ô?}Ô]ØA؃½Ø©ÕaÝÕ]Ù›ýÕŸÙ¡ÝÔ¥=Ù%‡Ö¯ÝÖ³öz×»Û¿ÝÛA{ØÜÝÜÇýÜÝÙÙ£ÝݧýÝ«ÿ=ÞY}ÞcÞá߉Û÷]ÛûýÜÀàÃ=à^à9{ÝÕáËýà>áÓá[[ÞóýÞ#žâ'Þâíã—]â3¾ÝG†ß?ÞßCž‰ žàKžäOÞäëxážåWÞåþå¾å1Wã+žã©ýâk>ç;Þæuþæëý»A^èEžèýå>å‘^é“þkb~æeÞ飿§ê©^Övç~ã}žëyëÞëµ¾çyè˾èÏ~u–^í™~íÛžíeÙ꥾êçþéë^îí>î«#ì»>ëùìû~ïðÿï ÿUÌñÑ^ñ›Æíÿíò?ÓóžîïÞò)ï+ó©ÿ{ì ëßð;?ô¿þó=_ôKG_õŸõÉ%ò__òa_ößþò5ßö3÷k?÷7¿ÅAõÿôƒŸô…_ì‡ßø‹ù%bõ—¿õ›ß´fúc_ú£_àußúyÿö¯?û±÷ÿ†øýøü¿ß÷ÉßôÅ¿ü͘ù×ßùÛ?8©úãþç¿äµ¿ûïßþóŸûõ_óÓ 0° @‚I,HpaB‡FLØPbEŠ -fÄñ¢ÄŽ?jIr¤IŽ'E¢\©²åÔ/YÆt9‘¦Ç™8k漩³'ÏŸ!wõ9hI™DÚ,ÊT©P§IaFEjTjUªM­fÅ õêÒÿ®[¿jKv¬Y®gÅ¢ÅJ¢DÛ·nãÂ+·.Ý»vóâÝ«·/ß¿~,¸0áÆ#^¬¸1ãÇŽ#Cž,¹2åË–3cÞ¬¹3çÏžCƒ-º4éÓ¦SÆÈZcë×®cÞ-»6íÛ¶sãÞ­»7ïß¾ƒ.¼8ñãÆ“#_®¼9óçΣCŸ.½:õëÖ³cß®½;wàÝ ÿv|øóæÓ—_O¾=zöïÝ«—~üûöó×ßO¿?~þÿù§Ÿ€à&Xà‚6ˆ ƒ:¨ „Ná…fXá†vˆ!‡z¨¡ˆ Žâ‰&¦XâŠ$¶ˆ"‹/º€WO¥UãZjåx£ÿŽSñHc; ä?–F–…#’GÙd’6:©¤OV9%“WJ%”KjÙ%—Tf &–[ZY¦˜f~jlªæf›p¾)gœtÎigxÞ©gž|îégŸ€þ)h „6öwˆªh¢Œ.êh£>*i¤”Nji¥˜^ªi¦œnêi§Å(ªŠ2ÂHꨦ¦Zꪨ²zꫪ¶*+¬®ÆJ묶æZ뮸òz믺ö*,°¾;c˜g&«&šÌ*‹ì²Î’ í´ÏV+­µ^b;f¶×vËí·Û†›¦¶ãz+n³Ôš[.¸ëž-»…Æ;è¼òÖKï½öæ‹ï¾úöËï¿þ ðÀˆ}j0ÿ¨'Œð 7ÌðÃG ñÄWLñÅ'4¬±ëñÆ òÈ"—Ü1É'›rÊ,¯ì2Ê/« óÌ2×\¡»é²‹.¹;«Û³ÎïâÌsÐíý³Ð>}´ÑJ73Ò@?Í´ÔKWíôÐT§$ðÖwÍõ×^‡ öØb—MöÙf§6]cìvÛp¿-wÜtÏmwÝxß­wÞuÓܲß1ÿmsà„nøà‡ ®xáˆ7¾xâŒ?îxä”+”õåXgž4æ›kµçP‡>5è£wnúç§‹n5稷®úÕ©—îºìâ®­öí¶çŽûîº÷Îûï¾üðlïm<ßÇ'üòÊ7ÏüóÎGýÿô¡NùõÖg/ùö•kß=÷؃ï}øß—Oþùã§_ß묳OúêïÃ>;ü±Ó?¿üî×?íüÛŸÿýíëßþü'ÀNIx$žÈÀ:°| #X(êYPz¼ 3ÈÁ z°ƒ üà§Ð'¾šO}'4! SȺ…/T! g(à ȀÌ!w?êχì¡8Ä ñˆFLâÿ–XÀ"2‘€œ £HÅ)Z±ŠX¼¢³XÁzQ„_ #Ç(Æ2’ñŒf\X [HC6Úpplcß(Ç:ÒñŽnÌãCöD:±‰Hì#ùGÒ¤IÈDrŒÿŒä#3ÇÅ-Z²’˜¼¤&3ÉÉMzmh eEIÊQ𲔍<¥*ûfG=¶r°|¥,ñKZÎÒ•¶Ì%.w9,HNÒ‘ˆ\ä/…ÌFÓ—Å”d2‡iÌf*™Ð,d2;IÍOZ³šØ¼¦6³ÉÍm– •à\¥8ÃIÎqš³œè<' jÉË[²ó.á9Oy¶³žø¼§¯œÉÌgJ3šÀè1ÿIЀt M(BÊÏe:”‡ÝŒ¨7%JщZ´¢½¨ÒÉQuvô£ )HG*RHÑSŸ'M©=UšO–¢t¥0miL_š26Ô¦þTèMºS攡?í)PûIÔ‡ò4¨HͨÿR5ºÔ¦2õ©Nª&IJÕ’VõªVÍ*V·jJ—zu¦_•©XiJÖ°–¬hk,…ÊV¤§o=j\}:ס•®wµ+\óÚÖ¸Jõ¯P ,`+ØÂÖ^\M¬V«ØÆ2ö±ŽU˜Y'›Ö³ªµ²”½¬f-ËÙÌvöU{ ­\ùêVÒÖµ¯¦M­hñºZ½Ž¶µ¨Åéa KÛÙÚ¶¶¸½­nûYÈú¶·Àý­pƒKÜØxö¸˜Mîf‘»\å~¶¹Ð}îKcûÚê²Öº®½®v³Ë]ên×»Ý--lÅKÉÜšw·è=¯zÓË^k÷½Ã/|ç+ßú¦’¹Òů~»ßèö7¿ü °óÿ3ÞÓ’÷»¯¬Zì‚÷Á †0ƒ Ü`­÷ÂíÍ0†7¬á‡¾ ¶¯ˆCL⛸mÿM±€<à³øÅ*vqŒ§áOØÁ6®°‚u,aç˜Â@Æñ ?™ÃH>²’“ÌdΔøÉ'Ž2”§,å*CgÆX^q–e¬å.sùË0ö2ã‚LdyÇdF³ÍÌæ4÷ØÍ?^3$—Lç&Û¹Îx¾3’©Ìg+û¹Ï€þs”·f0úÐbF´¡Íh.¿YÎ.3œÏühIGZÍ–Î4¦7]élåùÓzµ¨CMêjúÔ‚FµªSÍêp*ºÐ°~µ¬kZÏzÑõœt›/Ýéÿ^ÇYÓ¾¦ô¯9=ì`ïÁ£Nv©—­ìf3ûw«Žv«§-íjS»y·®5®µÍíl{ÛÖàÞ6úŒ­ëróºØè¶ºMìu›Øé6ª³çýlzÛ»Þøî“µ÷}m~û»ß¿Ô·Åîn|à'¸ÂÞ½w·›Ýä>·»%ñx;<âðžxƵrïŽçûã9È ð’ÿûä&O9ʱƒð–üå wyÌaÎpcüá·8Ås®qœïüççyÅo,ò¢ÜèH?ú³W®ò¦3ýéN:Fd^sšSýêVÏúÌ·~V¡{è>:ØoNv‹ýìaO»è’Îv¥·ýín7/Ôç.õºÓ[ýîõÅ:×õ^õ½k½ï€ç{ËÞsÂýð_G»á¯v³7¾ða»äã>ùÊSÞ½vÏ<Þ7¯ùÎWð½ßGøÐ›žôØcüâÇîøÕ+¾õ°‡¼ìÏúÙc% !ù ,0!µÝÿH° ÁƒIȰ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ+KJ´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ·*¼¸ñã¸Ý¼¹óçУKŸNÝ. Õ³kßν»÷ïàE‚ÿÀ¾¼ùóèÓ«_ÿ:û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèá‡vâˆ$–hâ‰Ê‚âŠ,¶åž‘ äH‹4Öq6æ¨#Yn,´ã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨒGꘜªêª5Áj…I¼ÿ*ë¬H™ŠŽ8Ҫ뮼Àë¯eº*rÀ™%‘ç+\ë,eÍ>+mFËÎ•ê´ØRc¶ÜÚÅœ©xp¸Ý–kU+×µè¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,²‰ìVK®o'¬òÊÜ¥ •˽Xº± 3ËÐÝÜS)AÐ.8ª3Sì4ôA4;% J¹šD =ÐÑAïVKÕXgE5C)ˆ&µ@[g-6AÈŽÝfØ}1göÚlcÌsÛpÇ-å×~­@oË­÷Þùªÿk ߀.øà„nøáˆ'®øâŒ7îx¡Mùãu!aUÒcaî“Ì0iÞçF¡­çÉ,zK§;„]¬¦™å±>øß>ÝÒéDÉ.íáh;©±P.¼ƒm€„ûðZm»å6È« zóNµ2˜6ÐOézõ󺂽¾î]'Pe4züö2O~¾Ê¬6pÅŸïþûž]¿Úóð×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁza“û४E?šð„(L¡ WÈÂèÀ¢…¢ gHÓ”°†8Ì!hn¨Ãúð‡@ ¢ÿ‡HÄ"ñˆHL¢—È&ù1ñ‰PŒYJÆÅû81#$àFBXEíÄŠŠÁvŽ×´+vQCº[ ìÎh"Ìq!<‰í~—‘¥‘ñ²Åñ'->D\|ÄS×™'@òˆL$–´§H8¹'Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“ ÌPûBIJ]ݱ”4#*gâLJP0P{ ±VižõI$ŽyQå [9š«Ñò#`|‹.sÊÁ ó—&Zã@öÈ2\¢%˜Ò¦^”ic"óšØÌ¦6!èÌmvênÞœ’-ÃIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M迺©Ð†:ô¡¨D'JÑŠZô¢ͨF7zA:„™ )ܰÃP‘šô¤(M©JWJÃ’²ô¥0©LgJÓš"di6Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «X[:Ö²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺BLšv5 ¨ ‘¡1¯€­’¯NÇÿö°ˆ¥˜KUÂËÄŽ¤Ž ^#KÙÊZö²³&f 3ÈÍzö³bÓ,hÙè„ÑšV5‹Ý 8’7ÉÖ]%\lÓÙµÁ¬ö´ŽùCì€[w¾¶·À ®p‡KÜâ7<2<®r[TÌå:wE¿}®t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯xÇKÞòš÷¼èM¯z×ËÞöº÷½ð¯|çKßúÚ÷¾øÍ¯~÷Ëßþú÷¿°€LàøÀN°‚Ìà;øÁް„'Lá [øÂΰ†7Ìá{øÃ ±ˆGLâ›øÄ(N±ŠWÌâ»øÅ0ޱŒg¬`œÒøÆ—ÃñG`×\$º !ù ,ä ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤ÉŽHØFÛÂHWž|(s&G[6sêÜɳ§ÏŸ@ƒ J´¨Ñ£<Tê‘éÆ$8¦DJ5c‰ªX³jÝʵ«×¯`Ãn ¡óVΨbÓª]˶­Û·pãÊ»ÐiSºiíZ¬‰·¯ß¿€ ,ö*߇“ TÌñ0HÆaº%B¸²å˘3kÞLԩ祛tQoUÉPï¼Ê¹µë×°cË˺`mŠ¢Aо½–7Aß›ÌN¼¸ñãÈ“+_μ¹óçÐçæ>9}ïÇêѳkßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸÏY´}úøóëßÏ«hÓ`&Gà&¨à‚ 6èàƒü‘á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@‰Þ€0‘AIh‘’!Ù“BF)å”TViå•X:Y–\v £+™ÆA‰$KQ’€¥—l¶é¢S®€ù‘#QVКYÙéæž|²IVŸ€*hEØ pfDr$a¡]8è£6èFB‰Fj饘24I‹~„VQN>$™Y™–jêqtþµÍF©$K,§Æÿ*kz6D@IŒæÄW­„ç¬À+ì°Ä+‘týjì²Ì6ëì³ÐòtkMD*û²Ñf«í¶Üvë­vµŠ$a¸ß–kî¹è¦«.§–díºðÆ+ï¼ôwk„äzÑ»õöë↓ÖJ¡ÚT“¾~ñ*ðÂÛV:ž«Äñ»Ø[ Äkm¼9jPÆ ‡Ü¦² dñCØB4©CÔ℟¶kѽ„º©Bi ÔSc„pDÖþ,òÐ:,@#  Òªi3)ÓÅ<Ôm™‘Ña-€ÖÁš’jœY²BŒ­ÕD§ý`¡e ¤lÛK拘AJ¶QÕÌÐJ)ËÿÜPßµý3“= °&Å €·CfÙ­öãRìñÖÝü[F¤¤÷@.cDÂâ© ¤4CJ%µA–C®:}›Içm²¸ù»PþäC¿:G4÷:â~+ÔºÜÂm¶¶¯®|c_Nœ£;„¶Ùmã¸@™;„Sö}E_Úˇ¯ ]ÍÛ9ñ€œPÎ:3týõ a/7A§ç}÷(!䨠T“½‹ˆÐ’<ñ>ì3H«P¸R$sÔ³ÍO¸[¨†!Ž8“å G9ŠL.!¤9 /Ô¼ˆPQ)¡šâבÍ)å0LŸJFpMèH­b87ƒLç3# b—ÿ:'Ä"Œ‡&;’Û”ø2Ÿ¬I)záÛ=RL§SöCˆR6w<”ñ‹ûùàqÄh‘€ñŒP‘@ ‹Q£AxĂȱ"Nb’SàH²ì`icHˆÆBŒ†Lä‚h&HÍÁ"µÈBÝí‘’4\»z§¤FêDB¤Ô¥4“¨aZ$„¹ M€cMtSßtK8§IN£„€1¼ž3I.¤&WQå@°É²„ p%![;ÙhÿÏð¦S² ¿´™Ee ¤€TˆìŠ)7.–ó¡HÖ„0ö"µÉªl—; åp#»ëLAaÅÒ2#I,QÏ… –#“­*sÇ«“IÉ"­J`T1¾ƒ´W#­zÝ%C'WP÷"=ÛB¶±¥öf®½ï}€ÝKÞ‡$”ŽdŠÈ¢—Z!X€bµ«x­³ Q†2÷â k ÁñÕ+ç×®H>2žï €þcà»øÅ0ޱŒgLãÛøÆ8αŽwÌãûøÇ@²‡Lä"ùÈHN²’—Ìä&;ùÉP޲”§Lå*[ùÊXβ–·Ìå.{ùË`³˜ÇLæ2›ùÌhN³š×Ìæ6«èÿöjeDX©šÕõ#Î4ÉeÝÌç>ûÙ'„‰ˆIhÙúψN´¢sÍžì™®vË¡÷EâE+R“GÁ´O4méNÇmµZ±Ý¤5—ß„ÄÁ$ æ <ý-nz¤s˜&¢Ú˜‹™p·´©õHò,€[cDÖñõDtaNDØ!w‘ÍêsñåfoÁš@ìÊdÕ˜MµE˜=cÏLsWÁ‰v)Àh›Õ ÷b·E%áðS»áµGäÝlS•T¹i©F4}¯j DpCTÆÉÖTⒺƬ@>†áÇeIF"^ïGi{”ʱR˜Í¤™š›"¿šbFî¢å0¿ÿ¢·CI³uS:‰Àüiˆ+®®RgDÓÔ.H-Ö‹‘K"Á7•àýH~î!Õ&¸ÂàmŽtÎÝU:Í¥¯Z–…Nšå¿ R ™ØÜwqJK]Žëƒzñrâ^H¹#ý€‹Ø$&ûCØÍ —V2|¬ÈgØ)穟*ÀCav.>uê8<MÿÊ×5âpí]¤Únð·ße¥oeŽ:!ëEùˆ-Á„}z“P×üIHptÒÒ$‹9ÿ›@¾{n+I–À“Üëi "âDò)§¶¹+ÖO~PhSºMª}¯\Üy¡xE.uƒÓ ÀIéGýH~Ø_ãt‘èâøiBÿáoª+ŽÄÄ€}¯ p_×ÄýáÞÇ ÒþjcZýWÑúEd¢ œ´\ýaF*—bé7ßg’']×-Wië7{ä7BbxÂGXݱ^=RubåƒÆYlW1~s0[Ö|H‚4 Q-v/Øw¶ÂOvm¦÷+¦‚ÁƒKtqˆK‰§Ó„EKN4R$&Ee÷HL8s1€ú'ƒQ+,(g¶Z¦dYWnUV³ÆDaèJdXyGg"h„j¸†x„¥q; ˜†gaµJ uJ¿‚~q-˜‚Ät+}Sw±‡1Ȇˆ˜ˆŠ¸ˆŒØˆŽÿøˆ‰’8‰”X‰–x‰˜˜‰š¸‰œØ‰žø‰ Š¢8ФXЦxЍ˜Šª¸Š¬ØŠ®øŠ°‹²8‹´X‹¶x‹¸˜‹º¸C¸‹`Äk†(.[@‡(v&†Cqgex8–y( c$_èH!z^5¨$ÑE]<Êè‹p!%â‚à/äH€[Ñ;Ñ…Aýõó„f £d‘SŠñ\2dƒ¾z >Û‡IHD±¬ø·íÈZ3g¸Ö*“{ÓiÒ?Lò©[0µ×G¾.±8«ªeH£$“£IWñ ‘aõ< ¡—;t`QEOpKøÆ|úlK·Ûbk¹;d¦k–;q;Á³ðÃh‘³zˆJ‘Cvƒ'DàŠ&·áTÂ+§»ÄJLá´ÙrÃÿv:¶^!f„$ø á“£WÇeC«wQ(‹×X+ØTð“¿Í¸eI ©R« ¹Ú® á÷ »Ká+™:°0¶ú{×À­›ï¥|P5Ö»^+b›3Õ§ ÛÀz«r:»»¾4Å««»ÍÊŒ,LeÊR+d±Ž¼RB÷Zz•ýD ‹‹'„hÄ*8›9‹Ž&³($E¯%?fUwª‡¾s+HÒ±‹«(H̬gйÜËY—µg¿ÂK´b$¡—‡«Ä#ˆ¨jv‡Ñ»RJ7/ù¥óò!Ç]Ñ9!ìeú×…Ø{Œl,7Þ{K<¢>1‘=\Eä‰JÓHKHKhˆÊÈÌZK a$‹Ü‡á:J¸sL4z¼‹Ä¸‚Úé7<,*Ê•œ"F¦ìÄaÅ a'…<ʺ,[.ºË¾üËÀÌÂ<ÌÄ\ÌÆ|ÌÈœÌʼÌÌÜÌÎüÌÐÍÒ<ÍÔ\ÍÖ|ÍØœÍÚ¼ÍÜÜÍÞüÍàÎâ<Îä\Îæ|ΗŒ~“ËèÜÎî (\¤Åï!ÑKü9w ½--ŒtìÅÍ:IÁÎÑÕÿ0Á)ýEÓdzQÃÁ[—B7mKݳ¥#ÔHÔÚÁb}S£5±;©f~]ªÔT]ÕÐa$®LCmÕ\ÝÕmÑË‚Ï^=ÖÃl;o|zjÁ‡[]¶Öd}còüÖ"Fv]ãr³Û«7C$“ìL‘-×B¬•?ë¤ÙR3ÌïEiPYq-Øt!Öo˜}Fñ„—wy:(»u‡Ml’ò)³0µ+Ùêá¿i7$¨ÑÙq±–†`¥mÚš!Òú a‹#!øÃz$¹R,&»ûLR§”UzÁ/ã:Äžm:ÝOl»Zª°É´­"PIV Á q:HÂ)Q„¨ÿ ë «pÙ`ÆÑmha7쨨r£JÈÚ|ë¥Vð³ZðÍ»,´Þÿ+s.}²û½r}½çÍÛ°ÚQ÷ƒ½ÖÀfÛ&±Øv)©@ºÑ™k=à]ªÑ¶'¤Zí¢3%EyJÄU5q &¬xЏf3;4†”{á$žÉ·ˆíâÓSáìAVbKq¤IòŠŸ‚6pkà9±W1íãžL¬¢o׉'VÓÇ÷bÔ¹Ò%A~nô­¢ÔÝÒ†q:/̬Ô×LÎØm»àÀ_ÀØ ±±*í5¼ËýW¸Ã0<1±ªKžæ3ჶóÛ?W £yµÿE$‡ð-Ë Ž"bŽBˆ !‡Ž‚JAªÏ'“N‘DPwʲ֔®àÆ|1:b$`+ã€NAÚêj“Ù4H´‡†„«Éì­F^ëÄ*Óz¦bK(VY-ëÆ¾‰”=ß0V¿›NÉ11dAŒÅ}ìÖŽÔÍÙ®êÔÞ&ÉÀž¬>ÃS0h~íè[…¶íŸýã0˜îòc õ3Éî¾¶þßÅñ÷Nð6Èó®¯ÎIçmð»i?6›êÐèí¥nmá®+ÑFMðîϽS”‰iäx·Bo¥Ìyxj€'U4¿a–ïòASé‹`~ëmÿl»aaØÖïBqç\˜™=ÓïK‹sç:l:bßDVP"³DV8ÏfeŽEµqŸZ1ð ѹkÛn/?ã>õ1~bñÍLèø’ñÝ3 ifǢɾÒÑþq?ÏLb±J!öQxMpð·s÷ ‘^n´Ê\—Qϳ­ÿ–!œœq·óºòF:mp3·’ôˆñ¡ÆŒÂù*Õë‹wV ÐÆ áö<±(Ž#ø±Ú'ÓõÆ6§Âáné.ØtÿT¡ EÉ€¯\dFŽHR·üÁ÷FýŽÿú!±å1µ1ïb?ñ—礑=óiP§,h/‚´P%ýþ­˜úžñ„QâDŠ-^$˜#A†=ðRäH’%MžD™RåJ–-]¾Ib ˜#eÖ™Ï%MœA D´òæL? ‚˜84@Í¡lÚ“gÁ¨,— @Aðêí§víVìX²eÍžE›VíZ¶oµ…{0k\ºuíÞÅ›Wï^¾}É‚ [uãTˆOö URˆ}®4,°€É¯¥)ørbC#sZôhÒ¥MŸFZµÂ/[¯†[ölÚµÿ_NÌØöí‚!Ný,q3Ä¡ºuç=~p¸ÇGøV,8QËw_Çž]ûvîݽ^üxòåÍ ²rÃõÖ)‡4¼4~Ãæ.ÝW/Y?áýóýýÿ0@$°@D0Ad°A„0B '¤°B /Ä0C 7ä°C?1DG$±DOD1EWd±E_„1Fg¤±FoÄ1Gwä±G2H!‡$²H#D2I%—d²I'Ÿ„2J)§¤²J+¯Ä2K-·ä²K/¿3L1Ç$³L3ÏD3M5×d³M7ß„3N9礳N;ïÄ3O=÷ä³O?ÿ4PA%´P¼^kÿÑïE‰?C-q(šÖC¨÷C̉4šh²¥4Ýt"ÜÞ#ˆ&FõÈRN Zõ¡ã,-U¸†ZÎÑÁ”à­J¢†THíÑ ÎUHׄˆ=i›„HA6Z·JÂѨŒ%®¡ÖÝ–Uî“ÉY[)Bt¨Ö(uÈY } ]ƒnÒé V'êVV«: ÚËî›·Ô‡HH¢ßޤ%xÅ~³SV¡Vµ ZV`x#D뙋 l9S7$eo‰¢‹ ™EXrøÝ“JÖJ ¶·!uQ.(c—dŽÙ¡– ‚Æ×Ä2­©¾$l7d¡ù¢„WûxY»Žn¨cƒð¡GdEbzÿ¥ª-ºš$§#Âgh¯%lê¦Iu)"I9!§¯º QwéÈÙƒ!ú´ c·ššd•=*:m\ºy¢¤Uòô ·-âO¦Ã¿fœ¼¹‚¿¼?y/X²I)ëÙж»qϤ)òÃ.»X¿Å³…8h½BïÃRZütç¦Ja Ù½Rˆs”4 Úôë(ðχ'0áHXt·bØVÊMJ¸Ö :ž Í|õf)"BX¶cù­p–æ‡ú&h|â×÷Ox‚”O[0$²Ç½¡qI@ùÚƒJ~‹ã÷¢¾ò–¡PSy{ŒjQˆÐ €ßC"˜I¢d4aT§Û±Ïÿƒ×©Þiž×–Œ"X‹úB‚@…}Ð… r_cFÖ®9SAL=²F'!F Žw6è·õàð…Gì ‘¸D&º(*Í1g4ó·—¬§56dNB’ÒÅ1Cô—C¶2FÛ5ÑŒgDc?gı¥‹*¹áAâ(ä¨ÑŽwÄcõx¡7®6`Üc i%Ò‡<˨$’ÀQg¡™""%9IJVÒ’¥$xúxIN²e(’É“t„”q‰WE¹Ê<]O ®L,¹CVÖRWQ¡^B“ðÙÒ—¿f0…i¿íÉntŒ#4@šqÄfœdY „ ÑÿÄf6aÂÀM’‹Ú'ñ>éÌ…ÓœÚìæ9Õ¹Nv¶“MsŒUOviwÖÓž÷Äg'O™O~öÓŸÿ|a::P‚Ô EhBºP†6Ô¡…hD%:QŠVÔ¢ÅhF5ºQŽvÔ£iHE:R’–Ô¤'EiJUºR–¶Ô¥/…iLe:SšÖÔ¦7ÅiNuºSžöÔ§tèO…:T¢µ'ã4jRyÄÆ×)Õ©²E.Ÿ:Õ‰,¤jVoÄ­(Ê„Zk€0Õ¹¸yä«aE+‚Ð'·|a/­oP²Çœ®wP/â4¬âÕ¯çñTäP5OIýÕ°ýA™T»Øó¸'Š+³ÿ ™EøO€ìY$c5«DMs³Ÿ-coR¸7î´§Emj•ÔAD®ª…mle&x–%7ÑM$©BE§ä3ºå2ghLew1¸¥e•[Ûä†1žÆ5re8Ýå÷¹×unt¡›\¦2—ºÎÍ®tkÜî6×¼ß=¯rµ;^ö–½ïU.x“»Þõº7¾é *;½;[þFó`ÿ•×T‘Úßµw Ž‚Sb`Š(XÁeqðÑáOXÂưY(\ gøÁ.OíjGDÄ&@‰rb§Å*v1Œa¼âƒÌØÅi©ArŒ– ¤ÇfùñËd¶y-Föˆ*Aÿ,ïV" Xr”KÓä( Ê0¹²X¨Œ‘,¤Ëù²@Â,€1ùÉ)3šÕl3G$Íl^sAÞ|‘9{9Îv†3—ï æ=‹¹Ï©3Ÿó,ç?K™,(l³C>l F(ô£{+é†@Òx6tlÇœ•_-ËP¾ò.j×f(KÎjÞ2Š’èLöÒ¹töê‚%Ë—þ².riDSz×A!¯réHü£ „ˆ°“JëV_]߀H–SmAW;!.ð3×bcnרÛ™vCº îo«ÚÜ÷¹’îc„Ýë.w»ÕM‘wk{Þ7¾·Dêoy÷ÞÍn‹Š КÿDد)xB,QfÿÃ0Ј’ð‚PüÕÌž8ÆÚ~Éa ÇÆÈ7jr‡\‚Ê'ˆ®qX"ÜñF²7.Û9Èœ ,WÆ—£Â€U»’fµÍ‡BS|柭L¯I©ç˜îò.òåDK=#&ÙwY²N–­¥ëZŽ7Z¾^ÝÛv6² -“­-\ãQ€['îë[ûÖìw/tÅKè}ÕùÆÒñÎ8™€êxd|àusØ (ÿ¤oGH–ÛPp‰7$8 ¼ÁtÍ»™ÃA9¬Ó.zÒ{ôÁxêOßyÓcDõ¥g}ìíúÕϾõ·—ý k/ôÜûÿº÷y=îmß{ÈóS±5 }¤Ÿ¾g«—ÀiÉ÷ûÊ1}‘…Df/¼¡°¯£L΄Pñà„å_Ø×Á®õð}]âÆ ÝÒÖþøç'b”K%óÙg\¥×ÿ@Ë·±O#³Ì6µÃ4ìc¿¼Ã¿&BŒ¾r­€–+ªÇK¹óۼݳ<á£Î[@<‚¾J<µtì@¬6ü»H«ˆ@Û@|4\AlAl<3|AœAÜA´§ík`­ ,‰à³%T?Þ[ &tÂ(ô½&œ(œB)´BàÃ@+̈àÂ-Ä@-„=*üBÚC,Ãgb¨°ÿtCıˆŸyÃ:dÄ`°Ëò!ÅØ/<¼/™èCë’/@t²ˆ‹s)ˆ6<‰C|$E4 FdIJ€ÄD4‹I$G, Kì*‘º!Ýy¤Í(;E”?Q°µ8EµHÅ´XE´hųxʼn˜§p`ªQÄÅ"ÉÃ]ä­ŠàE“) ûÊ/ŒF´(ÆDâ®ô ‹c4 f¼(22­\”Ƽ(€¯˜ÆkÄÆlÔÆm´²ãÆoÇpÇq$Çr4ÇsDÇtTÇudÇvtÇw„Çx”Çy¤Çz´Ç{ÄÇ|ÔÇ}äÇ~ôÇÈ€È$È‚4ȃDÈ„TÈ…dȆtȇ„Ȉ”ȉ¤ÈŠ´Èó‹ÄÈŒÔÈäÈŽôÈÉÉ‘$É’4É“DÉ”TÉ•dÉ–tÉ—„ɘ”É™¤Éš´É›ÄÉœÔɶðÆôÉŸÊ Ê¡$Ê¢4Ê£Dʤ\²žTʦtʧ„ʨ”Ê©¤Êª´Ê«ÄʬÔÊ­äÊ®ôʯ˰˱$˲4˳DË´T˵d˶tË·„˸”Kbʹ\¥Â²Ë‰²«¼\¨ºäË¿ÌòØ§á §ÁŸÀô(ÿCÌvÅÅĨjêÇ ¦ÆDˆh”Ìl’ÃËt(óñKÍôÌÏ,‰Þ±Ž"ÍÒ4ÍF!¦*ÄÓdÍÖtÍ×„ÍØ”ÍÙ$L¤Íl !ù ,Vƒÿ` Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ“àÞÍ»·ïßÀƒ ¯œd¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*XB „j衈FIB¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·úî¸ä–kî¹è¦«îºŠÑÃî»ðÆ+ï¼ôÖkï½AZ‚ï¾üöë￉ ðÀlðÁ'¬ð CµhÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—¼l&§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøG’®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç Wüpè¤Ï]\é´µúꬷîúë°Ç^²×n°À¶ç~ñèº÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþŒ¶¼/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀðKÛ8 ÈÀ®Œ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…+ï`h̆„‘!ÿ"0Ü‘@7;4Œ ƒè–ø]ĆD,Ì“(˜2q0K|¢]€ˆ$J0Q¼â\n('jÑ/Yü"] ò0+Šq/a3¸'”Dï±®rFªÔù˶h“|ë£/¯ÍæI(¯Í-Ê«<;õ® €„-˜ É-¸#!‰ô›  ;Ë‘¤ž„-· D½$¼wÿû6‘$Q¼@I´Ñú@ì»ßýø’Hp<–¥ªIpƒ6p½ò 䀴³]S=ÜÍns³³E˜<ó9ðc¥H#¶1=mlÃu‘8¡Bn1<‚ A…þÀ÷TÇ:–°} Yè’p "A¸¢ÿkgÙeO ýë ¢—º Á‰|™Í· ×5a±3ýV·Å40‚ÙF÷;‘ÉÌgKìa .·@(Oƒmø òÚ`? ‰¿ãßôz€ËiP€˜;_Ç,‘Iìbz–€áú¨'F‚´Á†DdŸ ©7ï‰$|/)24 tð¤öòøÉ‡+!¥sb艶z,Užt™hʈœR ÆbåÙ\™±[ „¨09R:°r˜A¦B”¹’Ò˙ ¦J )jþRš)±¦6±‰’mâ2ša&H¼Y,pDœ!ç3¹YkÚ¥Œ!“™0I@‚гž÷´'=õ‰ÿÏ}æóŸ¿ä§@ÿ¹OÍõó õ§BJP†.4¡(D'ÚPŠ>´¢½¨F%šQŽnÔ¢ )HGÚQ’~´¤(=©JEšR–®Ô¤.)L!ZM£ÀR%¸é'ušSœòô§> êN…ÚÓ¡Þô¨=E*R‡ÊÔ¢:¨M…êS‰*U *5©X­*U·U®Nõª`jWÇ*Ö²j5¬a%«VÕêU«fõ­k5k[çjT¸¾•­x•+[ÑzW½ú5®qÖ<í †v ‡ýgbA€ÏÄúÓ±5¬d;YÅVö±—,e7kYÎbÖ³ší¬h?;ÚÐ’ö´¦M-a3»Zж¶´¯EmlUKÈÿÎö¶µemn]»[ØöV¶¿¥­mƒ‹ÛáW·ÇõlQìºTæ:—¯Ð}®t£KÝéZ·ºØ½®v³ËÝíz·»àý®xÃKÞñš·¼è=¯vKI”™¶Ôžé{çûRúÊ·¾ø½¯~Ý›_þî×¾þ 0€Ü_ÿ·À>0:y’^¥þR½ †°„#Lá [¸Â¾°†3Ìá {8Âì% rGÌÛäúÖÄÀE±pI|b§ØÅ+.1Œ‹;câÚXÅ4–±Ž[¼ã÷8Æ<²…L[£|Xºuí°’¼ä&3ùÉNŽ2”§,å%‡˜'ƺgaºåƒv™Ÿ_ÖrCÃLO2ç–ËcN3š×ìe5·™ÿÍ`vsœá,f:—YÎu~³žç¼ç<óùÏ~ôí|æ>ÚÐ…ô¡hA7zÑŽ6³¤ñ éJ?úÒ“&t¦Ýå¤P÷ÁÝMò“E]^RSùÔUFµªSÍêU»ºÔ  ‡LëYÛ:ÇDÆu­u}ë×Ǿþ1¯‡ì\{×Çî5°—ýëf ;Ù¸6r†ëjjSg·š¯Îv«·­ínsûÛÞ–ð•…b`'ØÜ F·ºËÍîs·;Ýï^·»ç ozË»Þúõ´¸±Zíp§Õß·ÀNðœß±&÷³™½pg›áw8²!>q‰+ÛâĦøÅÎñˆw¼âÏ–ö‘­m^’üäÿO9ÊW®ò”['Y¶ô¦=óHSÓ7¯¹ÌsÎsM÷œÓ?§yÐmîó¢ÝèBG:ÑÎô¤7}éN:Ôó¬o¾š¼å,Ï:Ö·®õ®s]½/÷ÉÆ=Nv—}ìfO;ÚמqŒCûíoûÇÙw·Ç½îœ¹×÷þu¾û½ï€ÿ;¬mjïx¾ðˆÇ÷½xÅ7žñ‰‡¼ã#ÿø–V=ð˜|æ7¯ùÎw;ì8 ¡ÝG?w¹ŸÝôjG=ÝïÎzÒŸï¯o}éaŸú·YmŸûœ/wŸ_šå”6~M„/|šÿœÃG~ñgr|‚,8%Í7'MèÙ¶„‹}õøŒ¯ê·O{ìÏ^ö±w}:íÁ?~ñ{?üß7´+·‘çSD”s‘§äOÿ›Ô_ ÷¯IþóO“ýDþý÷ˆö7€óg€(!O!ù ,D¡†ÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\Éò ‰–0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“_,¡¼¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢@À裑¹餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ f úöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅøRÆwìñÇ ‡,òÈ$—lòÉ(§¬²‹D¬ìòË0Ç,3±TóÌ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒûzKã*J ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧N4ª·ŽrTñë:oMÌþU-¶ç®ûYÌíîûïäöüð¡×¼1ñÈÌzòÌ+||óÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ ëqÌ 7X:áqðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢Y‡HÄ"ñˆœy—ÈÄ&:ñ‰PŒ¢\$'EÀ(±ŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñœ@@!ù ,\ŠƒÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶í‘nëÞÍ»·ïßÀƒ#N"¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öégˆ%ü)è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–knLôœ«îºì¶ëî»ðÆ+/‡–Ìkï½øæ«ï¾üöëï¿,ðÀŒ '¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñœE|,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí·Š’ü-øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜ëŠpæœM\箵ú褗nú騧Žª·>¯@®Çnðæ²×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü ºMÿ  Õö¹ð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢1‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹O “º€!ù ,0¶‚ÿH° @"*,`¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»÷`[¾ƒ N¼¸ñãÈ…·Iμ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+/¹ÔÌkï½øæ«ï¾üöëo®šü+ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗núé¨S„Dꬷîúë°Ç.»u$Ìn»hûí¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢:‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhLc !ù ,00üÿH°`ÁH*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠIr ˆ’(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ'É">ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ /Ö Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8¶'GŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢¼•Àè£F*餔Vj饘fªé¦œvêéu|*ꨤ–*a¨¦¦ªêª¬¶êê«°Æ¥*무Öjë­¸òˆª»æêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿õmðÀlðÁ'¬ð 7ìðÃG,ñÄWlñŦ€ñLL(ŠÐÆ 3Y@È$g@ÉhžLB¢'¡ìòË0ÓFÀg!ù ,æÉÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤I(t3°ÄI„*_Êä˜d¦Í›8sêÜɳ§ÏŸ@ƒ Jô#€¢o$! Ò§ 6,0ªD«°j¸U`׈_¿B [•kY¯gÁ¦û,Ú«kÓŽûVm]¶Ýf5{Wn[º{áö­;wp`»‡ñNŒµpb¿yó}Lø¯áÆ–)v¬÷fL¶ ÚŒÑ¥EÌ¢S«^ͺµë×°cËžM»¶LÓ¶sëÞÍ»·ïßÀq†hX¢@%Á_“¦ètàg‚Ï;”š¼ºõëØ³kߎ“:uèÒFÿ×8>éÀï ËóVþ zì¹ËŸO¿¾ýû»[î7x‹ñáä_xé'‘4ß‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ:¡Fâ‰(¦¨b‡Þ×¢O®(ãŒ4Öhã8æ¨ãŽ<ö(Ñ‹>ºdDiä‘HŠwÐH™˜ä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–éf¦©æšl¶éæ›pÆ)çœtÖiç2…çž|ö©%š½çç „j¨PLªè¢Œj(hN­4*餔–©§G©DÀ@— hA—~º©D.t)EŸô)u©Ntj¥°Æÿ:e«PŸ­¶áÊQs²öê+¬ºJtj# •JQh ±´ÔA£þêì³Ð.iM¹Bq¸KµœµBÊF+î¸äFéGÖ‚ g¨5‹ Æ>$‰¯Ôª Õ[î¾üʸªhŽ€o°LÒ6!+P-QKýF,ñúr+ ¡i0³HP¼;!KNlòÉ"‚̱±¼,Ѝ¦0Ê4×LhŹ\P ='òDRI¢²°AÍkóÑHkç$p²H„°EJa´1½IòmÒXg­åÏ áL/É=ÊëH ;üÐÐZ§­ö…×õÚpÇM!¼ÝzöAŸz]’¾zçÿ}»aË-øàC-Møáˆ'~’¦ Q7dyG¹’ ‰êM‘åŠg®ùæœwî¹HŸÒšÚ/‰ÎT¢ úç¬÷kxë°Ç.»I¨C¥’ߎTûì¼÷îûïÀwÉ*‡˜K´zðÈkýz}O'ïüó ¶Mã«»?D²JÅC¯}ÖLa,€ôê: ×ù à=Bào¯>¿$[+ä lºÑ‘nêÕD篺EM ÄóÈ ùŸ«’½õGÇëÉùâ¾L­$Í+ÈÌ ÆÌ#¯ Èù"a6„° Øê CÞvÀªE D_CŽB·Ù#ìù CàW’ôÁgIØ¢ˆMÈÃF5"$¼œFÿ¶Á0†äP$ÛÒ b1œnŒ~¾:¢ ‰Ð/!2졳ôÀª±$:­*CBª¿¹hg4È 3’E†ì3*yOÚX·-Ú1Gÿ*Šå~X‘ B$‚6ñcNr¸CÄb¼£"å3Ú-€aœÕX²‚ì°Ž\L2ÁLvDz$ CôæÈ‹Ðq‘¨„Ðeâˆ#$‰YN'rÅ›T1'— ‰Þ<‰‘S¦ò—<"ARx±÷D”¦¢£7} ª™f¤ä#—FLÕ7—*1™ˆx?—Ä zbXÍ Ö˜è„C„¿tºó ÙÔg"W섞q‰$ÓSÿÉRÍ Ò£Ü?Ûó*NGÍÂÙ jÍHFžÖò0dÖDô¢]ãÙcNÓœ¦@| O™j™ ½'Þ:ZF“¬£0•ÍFcJÓšfˆoçTéMQúÑ––ón9y©M‡º¡¥¢ÜA*Q—Z)Q­t¤+ŽFszО4+tOEhVBC“NS_h[D¨“M¦š•A=«Z×Jwnõ˜C.(W‚”§œOSG=,âõ]l lšfÉ“»ºf›‚Mlœ•> $¬ûå@fú½~Ú-&¼„êW+ Ò1„4$pêc'Û®nÅ‘¥~ÏUÛ…`u³¶rÉ37RV‚ÿÈV±¸ÅIZsBL]‰)™MHúl˜BŒyOdJÍ­r¯ÔΜy39lÁ†äJ¥Ø/‹‚t(¨Ð6ERU ¤éß²†äBÕ¸ò¯,]®z}ã°Zk8â ]m+D$¾Á¯@ÎÅä„—ó•I-×K࢘®cÃtLHrKR-M‰zàsû±zDªç9¯]]e4ÖOšñFvû¸¡–Þ³a,D¦ß†ò –HŒ!2/Óðw"ŽÅIv‰ò´‹øÇ?ùNÜÕ?¡E¹4å@f̽î S»É*ƲK™†™š9‚,£Jv"H¨Ç,Ó2!Q¯@ø˜ãß 6ÿ AæH‚Kæ:{(ñ—¾é0ã$Ù "¼eè\‘Wɹi lsÇ §úGT­•/ƒh9BkÄr·ô²kJbž8– ìBš7`¼íÔ}ÌȼšVjèÌøÅ˜,Ý“ƒ$\A¤­7ÍëÅE–j Í'oèÓÖϲ~¥Èo‹ya‚Äl³oÏ~}C:nùÃÒÑ“ù‰9'÷úÛà·¸ÇMn”­³ÜèN·º×Íîv»{½~·¼WCÙyÛûÞøÎw™4­ï~ûûßѹNð‚üàO¸ÂÎðrÕ»á¸Ä'N~SüâϸÆEÒé{üã ¹ÈGNò’›|2'ÿO¹ÊWÎò–»\{{ŽæÞª“½W$Ë~yë:®óž+RÌ )e…‡"t¤›³>OºÒ—^Ôï>EP %­f3BfY¼¤6±yj;bs_B°ez¬x![‘ý7É] UÎ.l‹=°@s/2žm‡ä3áÚ¤o¼óö‹Æ[&¹hûAbTÄ ëu¡±H ¿ž„«ÕÉ$®â xSÎK•|ßcG·!•àï,ÝÔ²G{ÅÃÏÒ)^åM£‹Reñ(.‰´*_× È¨z«ºÓ'’‚„`¸§›/”Íy¥ì#’+ ¢‹“Ø7•o¾Ú ý´/Dú#Ñ…Ý ‚ýcí¤÷Áÿ]ÿœz›4kfØg|>»‘£ ÜQÿÏ«VÅgÏÃq…°PÿSsDötá;ÛW¸’y±|a+Ø¢~SWÖ·ÙRKàWŠDKy"Á¸>Ô‘w2'R…ÖbåH¹Ð,´ç»|%ç…€Á×Y Qtö“xcO¿÷å1€€k€ó‹RƒOq| ñb/Q}2±‚¦+H„@‘\­ÅáF¨5"H7ô…"13|'9ïA-µå t¥UMPtÄfaUU„%sJ>Ö豂ìW›2… cË!€]¨&WÇ´·[Z‘¦'XPÿh "½…óˆ!ƒÁK8ˆX L[%Sˆ !kxCYÈ}¡¡0 W{ŸqˆÁ*£xè,M`OšÄe1´‡&›b‰Ã7´GOÁŒˆ„_&œ(|=7± ‰HRJ˜ ˜Œƒ8ÃBrØ>WV–¶˜^•u}E_—Öûdm/˜Sö$Ža]uÈ)§r=¿vWö¤ؤSøHúÆŒúØ@FR‡mtRS/d„S]ÓÆ–RªY¤ñbRìUb5U£79þx'Ƙ‘™6 Åw?ÂOF2tCIq¥]ÔDòŽv3ŽJ¦wÖ‡(…9ô$ˆ2Ù‘{ÿ"Š8¹“<Ù“âÂv>”B9”DY”Fy”á”H¹”LÙ”Nù”P•즔RY•Vy•X™•Z¹•vD•\ù•`–b9–dY–Ïò‹f™–j¹–lÙ–nù–`²‘p9—tY—E¡“wÂ’â•v靕ޛ¤—));Ô)(D°Zö6Za×K-Ø¢s“~µl Yaó$™,…>…sA™asdõdôÓ¨UÓ$9ߨӄ—e‰–D!¢Á…b71®a›}9'zu’æØƒÉtó‹êAaçôV€¹WèÅ‚=U{(DÀ‰û¤$á’Ñ™Sþã@Žn:äD^äF~äHžäï4äJÞäNþäPåRŽ8L>åV~åXžåZ¾å{bá\þå`æb>ædþ'"]æhžæv6ãjÞæAµ¬VÂ%è˜n~(^^çm^âf 9mtÕ7Žçî–×þ‰Œ‚>;ÿÞ£KùßJuÃ!9¡1U‡N(~07AÛPáÙeVéœ ìAè&›³æé=Äæè[¬tf‰¦¾>ŸHug.Üþß’ŠÜ Á½hB Ôpç¯n&UþT="Äéÿõë[$fÚpÔF¥çÑáÔú]À0YÕ Èž9¥"õ‚´¡a¹|í:m¹æ+Þ±:^úèàî+Á^$ê×ížî›ƒê%1ÂÆ œ+®àz›èòÞïþ®J~°Éáë¢ÑW}þï®±îïäöM:©çªñ ¿( ?ñëfë›É†ÊýæOÒs\5WGünñQñ[¤L$o(ägNQ1á­'žâ:ÿ´´ä!t¥Ð;acóSpžòÏòí*DÃ$Ý”Ö@ï!lþ"oÂ)lFº²µúÓôÚWÙɹFöÃôª Pž•ô¯AðÕ±êÁZ½†À^Tœöb?%¡QˆÄ| zØÙš¾BcCCy•vÖ!ê$=òo"LÙCïˆ?Õ÷Ïì®faÊ…Ÿ%ÁûPß8àC·õÉ]2<¦õRû=î†nØbÍ­I[ÓFï•o«Ë Æ^Öáö„ÈÐáÁ‰‘Üña>+v©ñcHº!™R¥G…ŽV¾„SæLš5mÞÄ™SçNž=}þTèP48*€Â¥&lŠéÁ§£–PX5¡VƒQ´A˜ÄiWƒXrˆ6¦Z¶Õ ÑëAWDíÞÅ›Wï^¾}ýþXðÝ‘wÍPñV$š?†YòdÊ•-_ÆœÙçÜ»œcFêVé^Ï¢C§Dú֮稞O|}P`ˆÑÿ[kÆ[÷nÞ½}ã80öoâÅGž\ùræÍ?牴´Áá «kl‹súCÕ>‡_O‹vxèåÍŸGŸþ7xõíÝ¿‡_þ|úõíßgÈZ!ûƒÛkògê'ÏÌ¿¼‚ûL¤®S Aü„8Ç"¤°B /Ä0C 7äиìôÀˆD$ɨ¹ì‹DäT$ˆÅ…\ì0Fg¤±F‘;ìFwäq9ÐfòÅž¢rP€ñ@$ë/a3èÈô‹lÉÍn '˜ ¢Ð„ì±Ë'ô2·Â$Óf'“ÂD3M5×ds?¡¤$ +K°…×lù Î4rêŽ/8Ñû³MA-î"B’ƒÿ¯;£) 8Zô%ÏPHÌŽ,À1L+EÆHå€À X ƃÀ€Òƒ`$àÓNÒ” MeÑ1W35hÖCwå¤@;ºÕº LÈá–j ’DE¨Ï•\Û©HÒ˜d(Ž‚žb"¢@›)4SIâr Æ4Z*ê,èW‚¸ÀZb·Å^çÕLW âB‰¦‰Êl”!T’ä¦1IúW£3q:8%]‚%)`ð„Š2ÌK† rw ‚qU ƒT ä¯B})ß‚ˆE(ã‚À"±b˜6.ÈÜ‚¢Iåˆd¦7ç !– 0gÇíÈe†TSW¨p#òÖ.˜©ôUÜ®ÓϨx[pÿiÛ´DL—jBä— z´Ýu·ë›Eæj©ªì%ÐÙf{.•¡xu¦»=žë `•«E'œí…t ¯;²ù¥o!"`îeš0[……¹Šf(ìƒç p¼7OÚ7zµh J €6¨È» ‚¥£ïÒæu¤üiˆŠ´º J;Ý„·?ææÝMŒ Î]°¬$œN °h#ñèæ9Ç~&Í }¨[Vß |žÚH8!‡¿2òʨ—U#à!Êý ”5ÂÖù ªðÚ½ÔL,6,$cûË^wä6žtÏ&&[È÷Ôr±!½KEŒAÂõŠò¶‘½$ÿ} aDGHÀ¸íD0¡YV:H²áÄ]‡sઠG)œu$…:±\¢wâAD,Ua …8D4O4ÈœôB‚Õ¤CÙ^Ö¢20mï~1©á’ńȡ‡¹au$êDŒDD#e Iõl!¡¹ð²F7Ö&IÆSɱ"-" $‡1LàÈ™°ˆ+Ìc‹üøFym%u qŒ´8x-²‘ÁNhsê¥Ñ“)‘ä'mT>QÚÈr¥Desè(µ 'ˆc™#ÓîDé` i/Ye·šVK×)Ēײ# ‚¤üÒ m;&D‚hc ç%&2È+›VÙY]©ÿÄf6ÏsFmvÓ›ßDŒg$Μ r7¡¼$:Ÿ´AÁèG ñ:¹¸´IÂç%© .kÞrUÔÍCÞy.iDžàD#‚r‰P†6Ô¡…h˜ú´¥âÀé *tfx–ò †šmÞFïXV½ª-âe¹Ð-Ž+,r¥}WЈ¢r¡5ÅiNuºSžîå¦=-P…꜋Õ¨GEjR•ºT¦6Õ©O…jT¥êMrƨªSÅjV-¤P­vÕ«_kXÅ:V²Âä§eEkZÕºV¶¶Õ­:‹â[å:WºÖÕ®wÅk^õºW¾öÕ¯,¡âXÂÖ°‡Elb»XÆ6Ö±…lÿdé5XÉVÖ²—Ålf5»YÎvÖ³Ÿmh•JYÑ–Ö´§õMQ»ZÖê…›½êÉZ;[ó©ŸHBSΚ’%½v F”)Cà¸Aß-D,‡1 {ôC4¢2ì.WnšÜ:Nçƒ )*m›Ýš^÷^á—|š¸“ðj×¼áâJ|KÜŽ¤Ï„²µß>b(ZFÄPÄ´ˆ°¨rÔ OÕ\²^òÀ— éŨF(¸Ûüž×Áç O¼+RÞ$}&p+“¾åŠ™ðcL†á„ÜÂeãÕIû¼b %å'~HÀTë4†DOOù`É•ÔU%½ž&O2˜˜˜h8¸3§#AÿüÓ´AHÐãA>[¿•«h4IyV^#¯d†ú^G"\‡ dÌ¡5rBb¾ŒÅþµpBHXe:¯äÆAé„aLäâò W Éb.¾™½*Ù³@_èàšU!vôÉŒGœvc¡rÛÊàÞZ!åÝɇÿà 80sÖtªåÒaÿdú¶4®uM%çÇÅ nt&2µé°Õ ©H—U¢®áÊ;˜ŒXH­jËrWF×esBÎm’탊é ¬A”e/Ä»‰Æ-Kr枈šÙçŽàqÔåÝ3FOÀ…4LŒè]‡p' ÖÉCÌë¦x:¾è8NÌ-”ÿoÎÔG8¡ÈIÑŒ¾‹ºƒ!$Ÿ³;¼ ÷àtÀ¿>ܰÂ0Dþa Aÿ ˆÂ4„CÈ88Á8Ã8´Cï° àê¼êøÂ;„Á1„ŒÐA‰Ü Í“‰ƒ5”©C?dÄ|륣ˆ”Ë‹7lÄJÄŒûy¹ ÈˆE´ÄN4»W»´u¨Ôë ±èCO4A@ R‚·2$ “hà{ NDÅZ´[2ˆ$µéX¶”“n+©à°@2)´Å'³ £ ñ‰“0¾•) 02ÆcäÁ¦“/”S2ýÒ%’«˜S¤FTE6¡Åp4G`*0޲µ×I ;:!-|Ä Z€²i<Ç{”C{ÄÇ}t©Éýj<¬ôJpůÜÇ‹ó ~)| ©˵dËcܸ®„›ÀkË“ÜÊRÊȹÔ,û#9’ðI¼ôK^¹Ë¿Ä¬6L¼œÃÂɺœ± ‰xqLƉÇÉŒLȤ̎ ÌËÄË„LÌäÌÉ$‰ÌìÌÍÍÒl¡ÆüÌÓ¬LÓÔ̈MÓôLÖM×LÍüyˆ×TÍØTÍÖ„Ü´M¹©ÍÿÐ NÔ”MØ$ÍÝœÍÞÎÕDNã¤ÍâÌÍãÄMÝœNéLMê¼Në„NìÜNílÎÜ9Ä,Ì+ò ó4ÏŽ@Ï—XÏ•hO•xÏ”ˆO’˜Ï¨ÏóöÌO÷ÜOøìOùüOú PûPü<ˆôÔˆûTÏ]ÐÕOåOõO P P %P 5Ð&yPPP­Pe?®Œ¦™¤GtõÓ?Ô@ÔA%ÔB5ÔCEÔDUÔEeÔFuÔG…ÔH•ÔI¥ÔJµÔKÅÔLÕÔMåÔNõÔOÕPÕQ%ÕR5ÕSEÕTUÕUeUÖÓWEÓ8•Õ0…SZUXeÓZÅÕ5åU7½ÕXµÕ`ÝU_V`V]5ÖdÍÕ_]ÖbmÖceÖ^EÖgUViVb…VgµVmÅÖVõÖo×p×q%×r5×sE×tU×åÈuu×w…×xM”×zµ×{Å×|Õ×}…:zåר€Ø%Ø‚5؃EØ„UXÆò×…u؇…؈•؉¥ØÿŠµØ‹ÅØŒeWåØŽõXImØÙ‘%Ù’5Ù“EÙZKÙ•eÙ–½ÉuÙ˜•Ù™¥Ùšõ˜µÙýÃÙœU,‚ÔKžÚ Ú¡%ZAá[¨É¦¸›-Úsó.|kZ€+(¦TÙ¨e@¦µÚ¿BÚž Ú¬õÚ¯…Çe[·Æ±íº“(C±Æ‰3Û¶uÛ~Å·EÀv•ÛºµÛ»å;¬Å[„+[…èž¾Mˆ¿} Á] ÂU ÃM Ä­¶°\Æ-\Ç=\ÈM\É]܃\ʈ˵\Ì Å Ïí\Î ÑÕÐÝÍ}\Ô\Õ\Ö­Ü\l\×ý\ÒÓ-]Ú•IÙ 7ÝÝÞý£ÿ^) Þ²^þ)ÞÓ;Þ’#^áeÞåu^ãm^è}^ä^ê^å•Þìµ^íÅÞíõÞîß[¬Þðý”òM^ñ½^ôå^õý^ö%ßó5ßñußùßô­ßõ½ßöÍß÷•ßý¥_øàþ `û`ü-`ý=`þ%`fàv`n`~`Ž` žà½Åà ÖàêÓÛ öàáá&á6áFáVáfává†á–á¦á¶áÆáÖáæáöáâ â!&â"6â#Fâ$Vâ%fâ&vâ'†â(–â)¦â*¶â+Æâ,Öâ-æâ.öâ/ã0ã1&ã26ã3Fãÿ4Vã5fã6vã7†ã8–ã9¦ã:¶ã;Æã<Öã=æã>öã?ä@äA&äB6äCFäDVäEfäFväG†äH–äI¦äJ¶äKÆäLÖäMæäNöäOåPåQ&åR6åSFåTVåUfåVvåW†åX–åY¦åZ¶å[Æå\Öå]æå^öå_æ`æa&æb6æcFædVæefæfvæg†æh–æi¦æj¶ækÆælÖæmæænöæoçpçq&çr6çsFçtVçufçvvçw†çx–çy¦çz¶ç{Æç|Öç}æç~öçè€è&è‚6èƒFè„þIÿõß½‘_‡N_ˆ^_N‰n_Š_‹ž_ŒžÃ†Æµ‡îèˆþè‰éŠé‹.éŒ>é>_žÅ•Né–öèˆàh™višŽi0ªiœ¾éAËižÞé ûé…˜ié‚!ù ,8‘äÿHP €‚I \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒÎT(´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK©«²“ ]˶­Û·pãr$ ·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ<Ñþ(à€hà&¨à‚ òvDö!Dÿ5há…f¨á†>À† †(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Ƹ]…Ÿu(ã8æ¨ãŽ<öèã@)äDiä‘+Ùˆä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ"öa©¨¦ªêª¬¶êê«°Æÿ*무Öj뭋҈뮼öŸ6¾+ì°žz’-Ä&«ì²‡)Éì³ÐF‹ÒVkíµ‘éšµØvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðì9;›ÄWlñÅgœ.]Öi«±µ»|,òÈ$—< %PQl²yÙøUÀÊ*ª¬Ù%0¯LsÍ8ç¬óÎ%rÌóÏ@ìäРɼ’ÏA'½§Ñ¶1­ôÓPG-€ÓRWmõÕXgýóAÆREµÖ`‡-öØd—}Ñ×f§­öÚl·­4ÚnÇ-÷Üt×­(Ü,á=‘Þv÷ÿí·„;ñý÷à„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûíÒ Ž»ŸºìsA· åûðÄoüñÈ'¯üòÌ7ïüóÐ?¥{ôÔWoýõØg¯ýö¤Ëý÷à‡/þøä—oþù觯þúì·ï>­Ó¿/ÿÈñÏoÿýøç¿nýú÷ïÿÿÌ˜ÇØ·þ‰“B Gò²’ˆ[Œ 'HÁ Zð‚¹Š M¢@ ®¯ƒŠ 68zð„Q HLˆÂºð…0Œ¡ £ÄÂÀÔp†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ǘ£’ñŒhLãĄ̂Æ6ºñpt ãHÇ:ÚñŽxÌ#¤T¨Ç>*ªk~ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZZÊ ¶l sÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉgÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡ÊœZ!ù , sgÿH°`A*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨cs’ìèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«2‘ÿëz 묉"„뮼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üö ©$¶ÔiKpÊ*+ÀÝz&P Á ` #m¢‘M²ÊR‹ÔTcëš°ä#P£OlâË@QM5D¤ BÕ0‚@ ðrÌi¶‘,oLD$øðŒf-Õ 1PÄ 4RsšCÍrÀ4’Òf l‘Œ}&#Õ qpÀ°d,c÷˜ ” Ä=RCÍÍlµ,•€µši½t’lj09Ï)ÉÆ˜¬f@!ù , uiÿH°`A*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(/Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*ëm Të¬;"„뮼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëªq,pT2°‘¸f$% PÀ@ àð@%D‚¦Â ÕbÆeÉú °’@ äñÅ I’Çe,>PP`ñ™,¤+B9‹é1 mP#@ "'t2ÎeC%•€6õ,æÍE,ÐÍP]&ÆØ ¡ÒHf$!3t´™ aPÓIG½pÈ+É<ÒHØŒrÒL$äuØ [ù|f ³,€Ì`ú›PÇM €«Ã6©´@L¤³˜g ÄuÜimfÛ &ÙH¿̳o£I ÙÍe@!ù ,´aûÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É‚Nª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËüO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–ê#¡jª‡ !ù ,²cûÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦K6sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËûO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ†A$!ù ,²aûÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËúO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ê¨E‚@ês!`ªS!ù ,8‘äÿHP ‰‚A \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒÎ$ ´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK6©£²Û ]˶­Û·pãr<(·®Ý»xóêÝË·¯ß¿€ lñ,áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿èü'à€hà&¨à‚ 6è ptE!_>àƒf¨á†v(P]èáˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4ÖØS…6æ¨ãŽ<öèã@)äDiä‘H&9ˆJ6éä“PF)å”TViå•B‰ˆå–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–j*§ZÆ©¬¶z)“®Æÿ*무Öjë­¸æªë®¼Æšj¯À+ì}¶ kì±È*¸*J–$ëì³Ð6k´ÔVk-P¿^«í¶ÜFFd8v+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄG¡ˆß -OáÚ¦PÅ ‡,n¶‹lòÉuüS¶‹XÉ(ï¨Ëe›¨¦IÌ8ç¬óÎÁ<ÙÇ<ǧ_%\6GЕM»ÔÌ1½TÍHÛéth·D}"Ëdœ±Õ\w³Ê^‡-6Òá–½Ø-¡=öÚy* œÛlÇ-÷Ü©›Ïtç­÷Þ|÷ÿ]çAE[e·ß„nøáˆ'ŽÒàŠ7îøãG.%ÐÞ1.ùå˜g®ùæ›Zþ’çÎùè¤#7M§—®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwï=í¢/þø.)írL“¯þúì·ï¾Xx¿/ÿüÅOÿýøç¯íáïïÿÿ  HÀòæ|L ÈÀ:ðƒàˆ Á Zð‚Ì “ö Ômðƒ|ëGHš°`"<¡ WÈÂÊr$¬š åÁSÕp†8IO”B˜´`‡@ ¢ÿ‡HÄ"qL:lÊÖJrÃ#±‡“=C'Z±zM¼¢·ÈÅ.zñ‹|šâbÄÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘W#IÉJZRo“¼¤&7ÉÉNæ…Œž ¥(GIÊRšRö;¥*•ÊUºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™Ð$e„@MÄÄA׌D5)S€†$1‰Û gŒˆÒMº à  K7ÅÉNåCDø]’€„v~†‚ötL€Ðÿ@bù ¨Œ²•1j ”/È™r   $’ˆ.&@A²–5Z”,j1I5Ø p~ô+­œåÞYjPà'-KÓ˜Že‰)¨MwÊÓžF.¤> ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚÚö¶¸Í­nwËÛÞúö·À ®pc‹€!ù ,8‘äÿHP €‚I \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒÎT(´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK©«²“ ]˶­Û·pãr$ ·®Ý»xóêÝË·¯ß¿€ |ñ,áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿èDý'à€hà&¨à‚ 6è oIa_Bàƒf¨á†vXáCt(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Võa8æ¨ãŽ<öèã@)äDiä‘Hftc’L6éä“PF)å”TViåR^©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–j*RYÂ⩬¶ji ®Æÿ*무Öjë­¸æªë®¼Îšj¯À+¬}Ú kì±ÈúhK²Ì6ëlcK>+í´ÔòBµØf«íe¿*ví¶à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,±eß Pq€mmOìñÇÒ®ZÈ —lòDt!•ñ@[“X·'ó¸¬e»¨¶IÌ8ç¬óέ\”%PuÌszÙøUÀew ]™ÐB‹ÓK]¢ô3‹&õÔ&úl±2õ×`GœrØd—]ö’h/äµJc›ív kß÷Ût×m7Cs·óÝ|÷ÿí÷߀ߙ7RƒnøáËŽøâŒ×™vãGŽ“â’Wn¹¿”_®ùæœwîù¦™§:D£nú郕.’꨷îúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡Ï=ëâ—o¾èÝ2Ôùì·ïþûð»ErüôןÒÞöç¯ÿþüO~ÿ  HÀð€½ÈÀ:ð $ŠÁµ­‚@Â7ÈÁzðƒ ŒÌÿà3šph%<¡ WÈÂbÎ…0Œ¡ gh: zp4,T #µÃŽäh>T‘Öÿ€Ò„ ñˆHL¢—ÈÄ5ÙP(C I›Â)"*[³‰©ÈEÞm±‹` £ÇHÆ2®é‹2£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'II U­’Ü91ÉÉNzÒd›ü¤(GIÊR~%ЦL¥*WÉÊVºÒUO|¥,!5¿YÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6mCXmS4$ˆå7'ÓÍq†&â4'dÊ©ÎÉ Á!ál§gØ)ÏÍ ³žœ¡'>1ñÏ}fFŸþ¬Ì=Ê-o´2ý<èVÜ@€*Ô*é$É@*‡R´1 ½èc,ªQÅL´£5(H“Ñ‘šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´·©E@!ù ,´_ûÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËûO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ‘$2Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*jš$Œê\”j*›!ù ,´aûÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É‚Nª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËüO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–ê#¡jª‡ !ù ,²cûÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦K6sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËûO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ†A$!ù ,²aûÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËúO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ê¨E‚@ês!`ªS!ù ,²agÿ ° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ê¨%‘@jt`ê©mÄê«°Æ‹*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð"d‹$aJbK˜¶Ü ¦½aÖBï¾ú~9o½{é/ÁøÜ%¿` 0¾ÿ~Éð—K¬0—ù"ÜpÄ^Nìe@!ù ,´aûÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É‚Nª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËüO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–ê#¡jª‡ !ù ,èÔÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É$ QB@%H¬Œ9Sfʇ1 ÎÈÒfˇ2 ö|)peш9=Y0(Í”>ÞdJµªÕ«X³jÝʵ«×¯`Ê¥ !Q$Ê Ht-¶+Õ6|+ðíRS!¦•*·*]¸{é.,Û—äO˜+xâb‘2ž 91eÄ•%FŽìø2gœž/wÎŒ¹ôèÒŸn štꆫIŸŽ-Ù5kÕ¡e·F}vnÓ»iÏþ=ܶæßƒWn\âÍäÇUCMÚºÔ–1© ¥¨=a^ª,aöÿ\»ÖzSƒæ¦˾½û÷ðãËŸO¿¾ýŽ…½¿ÝÏv¿^þ ùÆVD{-” U&aß”ŸGgÝgá…f¨á†vè¡ImIUÓˆH…x‰Ù„ÐS4•8âP0båÓŒ;)XR…á(‘Ž.]Ä#ýèãA@>$¤EGV”$EKNÔäŽDiP‘=‘•AF‰¤–Jrɤ—N‚ å”RDeCX)æ•k2ôRYg24¡ä™xæU=…ç@ÚèYiV©¥ ý¡HfMØSvF 餒VJ饖fŠé¦švÊé§ž† ꨢ–Jꩦ¦Šêªª¶Êê«®Æÿ 묲ÖJë­¶æŠë®ºöÊ믩êf’yáy”]o§½·OÀ[H¬D‚MÓJkÔ^›­µÜN»- Øv®·ÝVKî¹ãš›î·æ¶«­¸ìÆ ï¼çº[î»èÊ[ï·ë®Ôï¾÷ú˯¾öæKoÁã«.ÁúþûoÂ+ÌpÄ °ÁC|±Ão<°Ås rÃ_rÉ,²É$S̲Ëw¼rÊ(KüRJ7÷ˆ3y/ s>ç,4ÏDï4ÑGï¬ôÏC' 4ÓECm4ÔN½tÓTK­5Ö\G=rÅS‹„AÅ~höÙh§­öÚl·QÙ´ÅÜÜÍÉ]7ݼݭwÞ|ÛÿÝ7Þ?ExQÙ%áöáˆ'®øâŒ7Δ\;o‡cäQÎSŸ•c~ùäš-ùyœ‡ú蟗ž¹è¦oNúé«_ÎQ†gF¸ã´×nûí¸ç¾ásº'´¬…‚[4ûƒc÷nüñÈ'¯üò]Nµ´êÎÿ =ëÑç<ýõQcÿ|öÜoï½ô݃ÿ½õá“?>yŒRDBñBýÎüûðÇ/ÿü øý{û­?þçÏÿþþÓ[ð*2<ÄŽ~L È@¯Îržc]ê"¨º Bð‚à ê$ÈÁ v "ÿ‡(Ä"ñˆF´!G Ⱦ:ñ‰PŒ¢§x¡õ‘m…TÌ¢·ÈÅ.zQ!ÃÀ¿HÆ2šñŒh”ßw`wÅ4ºñpŒ£ÝÆÄ9ÚñŽxÌ£ØDfíñ€ ¤  è°‘ˆL¤"IFȹdŒ~d¤$'IÉJ¶°Ž–̤&7ÉÉÚݬåé¤(GIÊRr(Œ4¥*WÉÊVžd© £+gIËZÚÒ9ÐÖ-wÉË^úÒŠÕñ¥0‡ILRï‹ôY1—ÉL[:™•Ãb3§IÍjz“Ö̦6·™ÅO¶‘›à §8YˆÊqšóœèDÎRÉtºóðL6ãIÏzÚSCÀlß=÷ÉÿÏ~¾ç˜©ô§@JP“ S…M¨BºÄ\‚’¡¨DÉJYNô¢%h93ÊÑŽös”±¨GGJÒqγ¤(M)7óM•ºô¥Õ(LgJSa´5Í©NYyÒúô§šd)NJÔ¢.r£FMªRñËo.õ©PcO£JÕª^³¢Ò´ªV·Ú@™rõ«`mà3c™Õ°šõ¬½›*Z×ÊVÝy3˜m«\s‡Ô¹Úõ®kk*\ñÊ×¾¦M­~ ¬`í#ÔPö°ˆ¥WËØÆre¬Nu¬d'+#‡Rö²˜½ÑZ°šÙÎz-Ö ègGKZ©<2¤e-­j= ØÕºVµ…ékgËZCÿŠ–¶¸ÍìM ›ÛÞÖÖ ºô­p1ÛÔ÷¸q­+r—XÊθÌîW[+Ýꮵ¸ÖÍ®]«Ýî¢u·²õ®x£JÝñšW©Ø=¯z«ªÜõºw§zÕç{çkÔòÒ÷¾*M/~÷[Sîò÷¿…ì^Là’Ú·ÀNè[å›àc´½ް?ãÛR [x¡¾°†ß©ß {xŸþý°ˆÍ)`øÄîÌ0ŠWÌÌW˜Å0'„cLcf:3á­±Ž{©âûØ•þ±ylÛ!¹—à…î‘—LÉ3ùÉMæ,”§lÊSùÊ“¼1B±Ìå Z¶Ë`ŽrdÃLfD†¸Ìhþc’ÓÌæ@:¹ÿÍp¾ê˜ãLç7Z¹ÎxÎ"…‡šç>ñÍ~ô%¥,èBkñ̆N´XOGVE;Š€~´¤çb>OúÒ¼3¦7V35šÓ Vã—CMêå¹Ô¨Ö¢SÍjÄ•øÅ­Ž5í"-ëZg¨Ò¼µµ®§é]ûzw§}­6ZûØì95²— ¼"3ûÙZ3´§]cSûÚLQ6¶·ý•^sûÛà 6Ž• îrwÄÚæN÷à­îvgÛÙîŽ÷Ø™kyÛ%£¾·¾—Èî}û{p¡ý·Àäé9üà A7Âí­í…;|ÀE¹íÃþjKOüâ ¿x¹qc ÜÛ—÷žëò‡g¼äÜÿn8Ê?ï•ÿ»â$wùÀO.ógsœÜ5ß6Èsžn-[œç÷¦9Б­ò¡»{ÕFw·´“¾o¡3Ý×Ez¹w.ujû<æUïy¾³Þî¨sÛHÿú¶—.v­÷¡eOy¿Óþmª³]×#ïøÛ‰¾õ¹ƒ}ív·zËó¾l˜ËïP¯;à—}óÁƒ=à†'zÁ!žøe;½ñö:äköɧÚï8·<¦¯ù@¾óÇv;è9}õ¿>Ôœ?}ž%¯zÔï½õ²&;ìeúÙÙõ¶¿´èsŸèÒgž÷}®=ðËŒûá+ºòÆ—´ì“já3ŸËÅ~ w/ý6Çý÷ÕO³ó³åès¿ÎÈÿ~ÿœ1/þÍ ¾ü‚þ<ú#øõOñ&v¿¡·/{¿þd?þÁLþýšþþÇbê€Á×~~â¶e¸zç·€lvØ}¯l¶|¨} xahdÔ×Bæ{ h}8‚WÆ&¸cú—‚Gf,x‚%ø‚L†‚2cXƒ#v}8Øe¸ƒFƒ>˜ƒ„;ÖD(gw„O6€Jxd7Ø„¦ƒP¸d=8…ï„V…C˜…'f„\h1ø…"Æ„bHcOX†&‚h¨cU¸†Ý……nÈ_+‡æ‚tøamx‡Ò‡z8_g؇~˜€?ˆ–‡„x\|xˆç5‡ŠÈ_vÿ؈ fˆ˜[‰8‰oh€–øƒðk™è`’oÊtw׉i¸…&¡˜!ŽÔwŒ6Ф`Ÿèn©mdøŠ?ˆ‰¶x_R˜‹‹¼ÈZx÷‹øÅˆÂ(]^XŒûå‹È(Yµ¸ŒWˆ‹Î¸^jº†Ôø†ÁxæEŒÚ¸\Ø—˜„àè^•8ްæ˜]Ó˜Žã¥ŒìØWåøŽ¿µ‰ò¨]ßXÈåŽø8Wñ¸”õ‡þøôˆu‰ˆÖX´ÕÉXܸ—uŒ9\ú‘_ÕŒ‰[y‘ƒµ‹é[Ù‘Z¥ ÉW 9’‡‘&éZ™’Ke‘,9Zù’$)ˆ)“óh'hÿg“ÀèŠ:™Y%Ù“u@)Y+9”?%’FV1™”×E“¦Ç”ÍuP)XH9•!iŠV‰XB™•Q)Ž\9YUù•Pµ”bI^ù”e™\R™–r–lY_Xù–l…’r kY—få’xÉ踗M©Ÿæ—~U”‚ù`ÙX˜mõ“ˆiTt¹˜lE˜Ž¹Pz™JÙ—” Vëx™y—š9–‡Ù™\¥˜  T[9šäÅ™¦Y_Ÿ™šTE–¬™_N‰}¯9S9›÷ä–¶ù`qÙEB¹‰@¥iGhù›ŽS›Œ'9²½Iœiµšy4œÌ¹8®ÉEwªv–²ùgÙih€'”@Ó¦ÿæœLµâù!¢iFÕyžµSÐ4ˆ{ìÉ6ÆÉ<á9ŸÆƒ›O$ŸøùW–¹GëÙŸÒ‰GežŠ!U¸œôsŸz;úéDüÙ õ³›x ê6î˜ff Zm¨ig Ú¡ôIžw¡"š!Ó¹Ez¢m“™ƒd¢,Úl^YR£r£À…£Ï¢£v£€â£u‘ ú @J¤9z¤;Ф=ª¤?ʤAê¤Fš¤Rº¤SÚ¤Uú¤W¥Tº¥VÊ¥Xê¥ZÚ¥bú¥c¦dz¦fš¦6 ¥kš¥m ¦oZ¦qЦsª¦EZ§xz§zʦ{ê¦} §*§J§ƒj§|z¨~Ѝ€ª¨›ÿÅ“1JRéù¨œ’:QõY©Âô ˜jRÿ¹©–›žš_ª¥©¤ºMŠImà’б¢ñ§ZI”jI` ­šm` ¶0«)6ª· Im  ©UmЪ¡«mБાjL$z‘PnP a ·  · áت­¸ú¬£4È ¼š% ¶Ð¡®6"®‰Ä‘’Pô n଱­Á«íÚ«¼j Ü ¯YÆ™·ª ëŠk W8Úp@îJ¸:°d Úà­áj°Œä}­* ‘p Q ûmp ì²q ˲n «¯«H ‰¯Þÿ‘“1¬« ±±€±0« ’ :³Q”¡Žºk«ì:¯·Ð´?»´Ò*²á­Ùú²F¯£º«É¬H!´!°R+;’À³Hðb›µñ­á­nr«®‹ꚯ,[µ%Ë«n@¯áz«õª±l»¡Éª>Œ êÚªY%g›­M +° ¶U;¹¶€³ƒkg ˜ûP˜›¹å9£ «Qn;º¿:%ukºè„´Œ§ºüt©®kI¦»´t†u: EŠ»Pª»YÊ»`ê»e ¼h*¼iJ¼²ª·ûÉëË;¹«¼Ï˼Ñë¼» ½Õ+½×K½½k½Û‹½Ý«½¿ÿ˽áËLÍ»#då+èÛ,黾êÛ¾ìû¾î¿ð;¿ò[¿ô{¿ö›¿ø»¿úÛ¿üû¿þÀì)9(œ(œÀ¼À ÜÀ üÀÁ<Á\Á|ÁœÁ¼ÁÜÁüÁ <Â"\Â$|Â&œÂ(¼Â*ÜÂ,üÂ.Ã0<Ã2\Ã4|Ã6œÃ'Ü%ò%=&?<&fR&:AÄɹ%AÌ&Iœ%K¬&Ml(OŒ&mâÄCŒÄUÌÃWìÃY Ä[,ÄElÅ_ŒÅa¬ÅcÌÅeìÅG,ÆiLÆklÆmŒÆ~¢ÆqÌÆsìÆu Ç#¾Q¾ƒ1½râÇ}œ½,Èü½ƒlÈ…<¾àÿ¼z<¼\¼|¼ ÁÇÈ È•LÈ—ŒÈ™¬È‡ÌɉÌÈÞëÉ› Ê‹ìÈ¡LÊÅDÉ¥L»U´¬üʰ˲<Ë´\˶,E’|˺ÌO%€®ië˽\¿,ÌÁ<ÌÆ\ÌÈ ÌÊLÌË|ÌÍœÌÌÍÎ,ÍÐ<ÍÖ\ÍØüÌÚLÍÛ|Í݌̻\Ÿ;JiÎ#áÊ{„Îá<΢ÄÎæ\êœGñ¬ËîüGeUÏï „œÊ’Ï!ÏËÃÏ!Q(aëÏ 1Ïa³ÆR²A¯–ûЋ±©;;¹Xëíh'ÌÂr꺰,+ á‘ÀÑ0Q<(<‹-²Â|«+TÎÿÍæq²mpI`Ò&ͬ=}Òæ*·¸Š},] µѬ !°W¡«ø*´øª®ø:­êQÓv&M·b„¯«ÊÕ<åªÕ!Ò‘üºùÚc{IpÔ<ÝÕÞZ¯ ÐV­7ý²,ÔÁÐb„«t]% µn±Iý²½ÉÔMÝ«ÑRÎ-Q®v]×ÕØ—K¯¡Ž !«×؈¸MùjŠÑÒV‘$²&ý³]·¡ Ù€«Ê>Û¸“+M|=»j ÐØdsÔ¡Ôs½ÖRŶګĊ¯·*™½"°=Ö±Ú}- }46ÝÜfKÜAÖ9û´ÿ×µ¸á«ã­®üLÕ =FèíÇ*ªÍ®<[ ®ýÜq×0Øœm¹=ø-Fù­Ä}«¼-ÿ͈몮« ŽàÚm»Z°î³»JÒ±ÜÉÝ·½ŠÝèAßÕ¼Z ?!·®Š .·`ÝaÖ@mµŽžýÀ ¦i­3n×zâŒÑâ9›ÚH°Ú¼½ßAÓn9 Òž¸«ä¸}@$ãΫ<^ËMÛÔ}(;­ž]nÔq›áSŽÐ¶üÚQ®€K±máîÌÝ÷m ݯQãJ‹íýÞd+ò½ÔEÏUQ²ƒ I)!ÝŽÑ«¨=àÿQÙ¡Ð\Þà$ñåøÊÔÛ}>쬈‹«™²Ô  ë³çÛM°O›£Í³³ £mãXÚ”16B°•nä !â ¾à¸ä;ʬš!´u«! ¹­Û ûÓÆÞ¬ˆ{¹ ØpŽì?-×U=ëaæFœÐ¢î†ó#"­t½ªÞž¯àþíZ¡«áîãLíôÃ/¬«5ŒÚI Ãð®î"íÓN(oŒ9öÇùŽïi¼ïþÞï¯ïÏï_ððÿnð ðî°}Ò£{¦ÿ£ñ;ŠñŸñ¿ñoñò¤/ò&Oò!ßÑôž¯H-_×-!¢"óDJó?ó oóQŠó(¯ó>Ÿó@ßóA_ó;OôBôDÿóHÏóIôd^ËÑ2ð ?õR_õ oõ õZŸõ\Oõ[ïõ}òòVó)oô'oö(?òh¿öŸögßölOñr_òn_÷qO÷w+Ïå¶$ö5ÍÜøÞ,ø€?ø†_øˆÿÍŠOø‹øÍ½÷ÔØ-ù³á–¿LOŸùƒ!ù ,´ªÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ’¤(´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë\ûìÀÊ‚²Ó®ûÖDíîûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(La†pÄ…*LL H0ÃÒð†6,A C‚` ?ô!Aÿz·ÃÂèÐ!G,"a@@‚ND N@‰¨DÁ$QPÈ«˜P‘Q@>@P‘‹Ù¢ÑhE Õ€ÅYF˜‘VȲG5âQ/!8cAE)žñzñ#B‰È» w¸í ÒÃFúE‡:„ÅBiIºô(%(£@zWÆCv².œ@=@yʽ4q ’E¢x»;¶2/ILe*oé–Oĉn¢)y —\n’˜Žœ£e¹L:Ž™vÙå@¤ ͳ˜Ñ‡Ÿ¼f³9ÌjzÓ=Ýü¦8ÇIÎršóœèL'DJ„$D" mÐ! ENuþ¤mˆàÿ†wÚó-5LÂÛéÏl“ùüçQ [ìÓ îLÂGj˜Ð‡*(Ipƒ-6šD¢ ¡ ‘Ða=RÉÚ"/¼èNHÐOI ’øt)5K‚̰¡IÐÆCY*€[ØB¢*½ Û°O5"“#%iNÝ€„“ $Ÿ’@©6fԓ̰¨é'S=rD$·åV«"¶AI b ‰6#.Œ„-ò)Q” @¢M(Yo ‹d£våˆO[ª I$Ô ë^iˆ tš/§3C[hò¶€-(òR„jC¯‹¥ Jó‰7´A !É!? Ã[¸¬o ­MPúΗ`‚ä“ìt*k3+ÀÊö+‡LêoY2Ï‘Ôq¸ÈM®r—ËÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯xÇKÞòš÷¼;-z×ËÞöº÷½ð¯|çKßúÚ÷¾l @@!ù ,ÛøÿHP€À‚*<ˆ¡Â‡ BœXÐ!A‹%&Ę1âÆŽ9r9P$ɇ&O~\©²¢Æ–_Â4(fÊ™4Yμ¹³fKž6}ªúSèI¢C’DzT)H¦Kv„úTjFªS­âÜʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·.\ ñnÕ‹ïL¿·,€ðI†I"æºxo^Æ'L ²1NË#_Öœy2dÏ’û~º 厘a¦ÌYukÖ 7ÇîLZvmÚ¦Gç.Xwo»Àƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_a€þ(à€hà&¨à‚ 6èàƒF(á„VhaPf¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öh㎄ãŽ<öèã@)äDiä‘H&©ä’L6éä“î”TViå•Xf©å–\fH@—`†)æ˜d–i&’:ž©æšl¶©#¶áæœtÖÙÖiÎ}™¦|ö¹e+~*è ÂI衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvê)‰_~*ꨤ–jê©ßñ…'ª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔÒ¹gµØf«í¶Üvëí·à†+î¸^Kî¹è¦«îºì¶ëî»ðÆK‘¹®:½óáK¯¼üöëï¿üþWÀlðÁ'¬ð 7ìðÃG,ñÄãí›!¾g¬ñÆwìñÇ ‡,òÈ$—lòÉo ŒòÊ,·ìòËWÁ,óÌ4¿lqÍ8ç¬óÎ<÷ìóÏ@-ôÐD­àÍF'­ôÒL7íôÓPG-õÔTWmõÕXg­õÓHoíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿ=]×~.øào‡@øáˆ'~VŠ7îøãG.ùä”Wn9t¶\^+àr®ùç ‡îb梗núéŠZ‚úꬷÊ®Ç.»´ž³Xûì¸ç®;r¡FˆñîÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè§?°úì·ïþûðÇïwï·³õû‹SʯÿþÓõÎrýü‹\èéÜï8|!]‚x%°M› Þ¢‰–ÏÌàÝ0ˆ(f9 q<¨AiC@%ÐÐJH#ØmGY1NÕCBÚð† TH —Þù" ôÖÿqHÄ"Š¥†öáßp2D#:ñ‰L[Ma^#¾Ä…PÌ"Õ°H$.jñ‹` ™¤DäŒ1ŒhL£×ÈF¼•q9ol£爥8ÒñŽ;c›vx&)âñ€DìÈB²Tz !ÉÈF:ò‘LK"ùµÈ²T’Š‘Ì¤&MäEºtr“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À æó&)Ìbó˜ÈL¦2—ÉÌf:ó™#æw¤YhZóšØÌ¦6wtÉmzó›Áq¡ÁIÎršóœè$5ÓÉÎvFÅðŒ§<ç‰ÎnÒóžøÌ§>÷ÉÿÏ~úSPãü§@C¶Îô e#ò‘Ðx´¡ÅBD'JÑŠ¾è¡ͨFýƒªOnô£´'HGJÒ’š”~<©JWÊÒ–æ2ˆ.íÊ-è&'vzti7ixø¨Ó-aT%"IPÏÒ‚žVÈ FU[66ôÓ‡ ©ëj"T}ÔT¶HuªX ÝizÇÓê • 9ͪXcH—¯šì?f% ßxÕ¢Œõ­ˆ«êÌVˆÔõ!w…«^÷Ê×¾úõ¯s«jZ4XÀö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hG{¼ZV®¤M­jWËÚ‘¶µd:!lgK[\ÿ¢¶¶¨Œn¹“×᥷» .²¬(Ü⊠¸ÆM®r—ËÜ6½¶¹Ð®t§KÝê>ð¶ÖÍnÕ°«Ýîz÷»à ¯xÛÆÝñš÷¼èM¯z×ËÞöº×=å}¯|çKßúÚ÷¾øÍ¯~÷Ëßþú÷¿°€LàøÀNðZøB<5  ‘n»RÓÿÈ!ø˜bAð‘†çZøBDøpÌR$¤AŒ0œˆ›#‰ôÌÔ+!ÎðЉ#ÑòüÎ…0ñŽðâ‡ÔXÇω¯[ dU£ÈuéjF”\žüáƒFrz*l4$$=–rU…¼¾Œ¨J!IøÍ@–*€KYFE“Ϭ"¾ø/ÿËl޳œçLç:ÛùÎxγž1å=ûùÏ€.a $J‚P9Ð JB$‰$ ¡ ‘h1¢C”[ØBNH´œ E#!}ž4r ½èZ„!œöJ$n¡$ZÔò!à†E×ô ~©^,¹6 Ô°6N˜×ücœômH IÍë6”àÕÁFÏ$ñéœ/ ІK ÒÚpƒ¥Ûj`G;.§Ö! $‘î¯@Ù®@«I=lsŸCï­S„ØâÙ]Ñ‹¬€l ÁÚ`ô³í}ïà,:n¨ä³á]h$H·°…«×ÜðîŒt|é6RË‘ ›ÿ@¦ðmK—»ãé9u Vm 7û+—7µÝðB3æhaˆ¢ ‰68ÛèÎK·Û`pIhá’õÏÞ$8.7§zy¸Hähýënâ2ØÇNö²›ýìhO»Ú×Îö¶»ýíp»ÜçN÷ºÛýîxÏ»Þ÷Î÷suÝì\ï;8¾&^ð`™:â¹áÅ;þñ;ä3ò÷É?$Û–çæ3Ïù÷T¾óÞ9HÖAœÃ“þôD2=êÍóù­¾=ª½ìgO{5µ¾ö¸Ï½îwÏûÞûþ÷À¾ð‡OüâÿøÈO¾ò—Ïüæ;ÿùоô§Oýê[ÿúØÏ¾ö·Ïýî{ÿûà¿øÇOþò›ÿüèO¿ú×ÿÅÆ«$ !ù ,ÉäÿH° Áƒ H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ JÔ!Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«W•¾ŠK¶¬Ù³hÓ’t¥¶­Û·pãÊK·iX¨ÔÝË·¯ß¿€™² L¸°áÈ+Þ9x±ãÇ#Kž¬r!å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ7âÞÍ»·ïßÀƒ Ä@ãÄ“+_Î<©åæÐ£KŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„éFá…f¨á†vèᇠ†(âˆ$êôD'ú•"C–èâ‹0Æ(ãŒB­˜^4æ¨ãŽ<öèã@rgcDiä‘H&©ä’Lr×âiC6)å”TViå•Xf©å–\véå—£E æ˜dJ%f™h¦©æšlVùd›pÆ)çœü½Içxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªªag®êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À®Öj°Ä&‰c±È&«¬—ÃÎxì²ÐF+­PÏNkíµØf«í¶Üvëí·àwK¸ä²dçGç–«îºìÒ¨M»ðÆ+ïŸÕ’d˼øæ«/zÍîëï¿C†\Àl0|é*6ðÁ 7ìðÃ÷ ñÄWlñÅg¬ñÆwìñÇ ‡,²glòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐ.é¶ðO%Ï–4ÑL7­Y›Öë´Ó)L}Ö]O lÍEPÕõz_[-á.€©àÒ&b§Ý’Ôj·=5Ûg=”%P-M‘Ý;Éí¶Ux÷ÿ”M`xvÇÞÔõýÓ»Á=šâ„7üNË'ïüó;6ýôÔc%û¢¬Wß_$ÚÃYf½w/þøäƒ$}ù觯þúì·ÑùÁ/üî×oyô¿ÿþü÷iþþ  HÀð€L ÈÀj€Œ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WÈÂºð…¯ GdÃÚð†8Ìá’ ¨Ã÷ð°‡'KÑãÿbR ñˆHL¢Dº%:ñ‰…¡!kóÃ)ZñŠXì^³ÈÅ.zñ‹` £Ǹ/Ä‘ñŒhL£×ÈÆ6ºñ¯’"çHÇ:ÚñŽxÄáóÈÇî±ù# IÈBb0{†L¤"ÉÈFÚDŽ\$D¶á/7¤Q’šÂ¤#‰²¹MÎ’+¡_X‚÷“&xR5’8¥Áòñ™&¶¤ˆªì ,mÓÉXrÇ•NѤ-wù±Y"D7 /‡¹]Fë9¤”H0Lb:óe¸|Šè$2ÍÖmÄpÆ|¦6·ÉÍnzó›~dM6ÁIÎršóœèTá8ÓÉÎvºóðŒ§<çIÏzâgö̧>÷ÉÿÏ~úóŸ ¨@JЂžç^M¨BÊІ:ô¡)¡$D'JÑŠZô¢éÄ'`4ŠÑŽòh`Íô(K8*Òè•ô¤(M©JWÊÒ–º”=$}©LgJÓeÒô¦‹&NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PjÐb*ÕªZõªXͪV·ÊÕ® Ó«` «XÇJÖ²š5¬z©ÅYÅã˵f§ Dp«\çJW¦Rµ®xÍkꊠ×Ý´U™}e%+›ö°ˆM¬b×z×Å:ö±¬d'KÙʺ¯±–Íl‘$hö6 A"á†$@Š˜ý¬SJ@‚$A¶ ÜÐÕÿƆHplk›ôV$%hƒ$"ñWÛú¥·mp÷²ÜÜË·°Åo á– ÅõˆeR™„$Á¥®_ŠhZ„”6#fÈpY[è¶Ö³àm®xáÒÛ$,äIm˜®þâÓ"¼¬µ…6ÜÞTÎW.ú5HmC`é¶6¶­Íïã" û$´ˆD‚;BIh£ $­€%!‰ìN8-ž%H„ ضµ³À-|â¶X†{F ®R,7 ¸¿¸e-nÁ[ã·$¡-b*%ÑÖj$Á¾Erk+ÚØ&À,.r["!áØ €µ:exߥ ³Ö’–®–ãâZØnØÆ$áñšm,£$¡ MÞãR;ç>3ˆÏ~´ïMèBúЈNtR¤fE;úÑŽ´¤'MéJ[úҘδ¦7ÍéN{úÓ’B$¨GMêRsìͦNu– «êV£eÁ®Žµ¬g=>VÓ:&¨¾µ®w}²Fóš+¾þµ°‡MìbûØÈN¶²—Íìf;ûÙÐŽ¶´§Míj[ûÚØÎ¶¶·Íín{ûÛà·¸ÇMîr›ûÜèN·º×Íîv»ûÝðŽ·¼çMïzÛûÞøÎ·¾Ý§Ö!ù ,ÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ÉÒd’–0cÊœI³¦Í›8sêÜɳgG>ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©§|ìé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±Èî B²Ì6ëì³ÐF “$ÒVkíu—\›i¶Úvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆkPòÖk/bÝ«ï—ËFï¾1¶0li lðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmt¬ù­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâ¯ö+€ãŒGþdÒ’Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌË yóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ï?o”ûŸHÀð€L ÈÀ:ðŒ 'HÁ Zð‚dQŸ2ÈÁ…% AæAlP¡$ °„¡Àl! $”†˜"ÁÂ$ᆠ¡—ÿ"H‚&’ ¡”mdˆ ¡-@zåë% i¡À&¢ 2Š©¡GÀ(€ºZ·˜"ÿe3zä_XœµÊ(5>Œ‘„6n!/ª xüŸ˜( r#2´…-œ¸Â:Ú‹ÜâA’àHv$„%hÃ-9Ç’ _‘ðâFhøI$Am œEù?@¶!„Fd$,¹jIâ%¶àã mц—ðÑ€/$ #aD ‘ $´ä!  [ó‡$AÂA^xÀ$ð Ÿd£H´ Á$H‡ˆl 5ÁIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷É Ï~úóŸŸjC@!ù ,ù…ÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ êÑ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ïµ dÔ¾,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§ÍV $$„¼ÿ F¹!@¿ ÅM­‘æ`Kùºa‹$m Ým´8³o×"P µ¸‘D H”w m8ûo$‹ @¹mgî `‹-Db8³Ô:GlKò·6v T»¯ ‹wHz{NûÛ¢g.‰@ÚXîìðN‚åµGr‹@F½Ml½¯ÞÞ‘ØR8à}ã>èÄržÒ-¶ð-‰6ÈãÞýóÆZþ9ôá­-óÏï·@o“`7øÃ"‘Dæ•ëˆñ¶  vµ`_ßr÷«åNÿ# ÝJÀ=ÕÀ <dg7•¤wÍÂá ¨‘Ým« l#Õ–(Â+ !ù ,è®ÿH° Áƒ*\Ȱ¡Ã‡#Jæmöóëï-~ ‘ƒEì'à€hà&8T 6èàƒF(!nLhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ… ƒ,Æ(ãŒ4Öhã8æ¨ãŽ<ÚXQ…gÅ"ÀOÙã‘H¦%_’L6‰‘4Áèä”TViå•H0#›‰å—`*–D˜d‚'%C%”©æšC¹Ø–+lÆ)£”^Öä†WE çžJÒwᇟ„*@@ ”†6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ë.®z¾;l$Œµa‹¼øÆÖU–¼tï’ù,ðÀHÚr/Á7U@Tc&ª¢nÅQÄÅ[ÓÂg¼ÀçÈñ[rÇ$—lòÉ(§¬òÊYÌòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ù䔯ŒhHc4råœwîùç ‡¾±iŠnúé´áë娷îzH›7”ùë߉ 9ùÙÞÁ´'¦úFÑí{ïÄÖðÆ'¯¼¥¬/ïüó|j ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€jšÈ@Çü®Œ § F«yÌ 7ÈÁzðƒ ¡G(,ä‘ð„(¬JE¤G‘ª¸,…0ŒaV>†;Úð, K€nÈÃúpSø!§ÿx7‘bFB,Í fc»$:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ#úr(Ç:šÎEt´£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“’A¢Gš'JPš²q¥Ô OÉÊVºÒ(º{%rL(K5¬–¸”[ 1Ò°]æ2F òå/‡Y7Zª&•A&1—9£UÊÆ™&3§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨DûVº‰' ͨF7ÊÑŽzô£ ©HGJÒ’²Ï˜&M©JWÊÒ–ºô¥0©LgJÓšÚôg%@éM'C‚ U"±SæN×R$$¡ I@B "qË¡Z†Iˆ„$î% 7Hµ©Áª@’pTÕiÕ©n©H$Ú¨FâDäˆlq‹ –`…‹Ÿ‚€6¬Õ H&AòŠ©’ŽÐi\"T†ˆG¯&yà^ǓӋØ®oµEN'+$øÉ‘øé`/RT¤• Ÿ5 ëÚ ÙŒ<Ö`¶Hyîe¯· v³¡C˜ZÈÿdIMLIi òÕ‹J5|ìVU [ˆä"µ`HoS’?AL¶Yîj%Q‘Џ•ª’Ømq +Þ…V"Ç5Ha-rTíZ6x™, –z ò¬U áÝ®B[ôš–%>“êzZÙ6Ð÷"Fr ì'”UH0Økå›è„A·ìbÇëXá6–JøïCz;U¼ÞÉOIxlt»`§ÆW"¶Z_R‘<–©I(ÁrBK[hÃÆÔHn\Yc¤”âùî@RlËÚ5¹º›±Fì;&ûø+%PR¹J\ êÉPµû¢ÛvY&%Ʋ_ee1›ùD—Cì™W¢æ57çÿca†sF䬹ÖÙ q¶óEè¼g=[„ÏöóD=hAK„Ї6tD½hEÕÑaô£ñµª_kXÓšÔµÎõ­ÿ±ë\³zÖ¾Žõ®{l^»ØÇv5²“ýëe;ûÙÐŽ¶´§Míj[ûÚØÎ¶¶·Íín{ûÛà·¸Çíí]#Ä¢FwªÕmjv»;Ýð^·ªßjzÿƒÝ£Æw¼ï½o{ç{Þý¸¼Îïz ¼Ý7¸Â ÎðÜÞþÞ·Ãñ„#|á'øÄ3Nñƒsüã9ÆEÞñ‘›¼ä(ÿùÉUžr’³üå.ùÊeÞò™Û¼æ8‡ùÍužsšóüç>úÎ…Þó¡½èHúÂ'Žr;ýéPºÔ§Nõª[ýêXϺַÎõ®{ýë`uÓÃNö²›ýìhO»Ú×Îö¶»ýípûØãN÷ºÛýîxÏ»Þ÷Î÷¾ûÜç¶øÄ/ñÂ/Ýð G¼¾ÏøÄ7~ñŽ<ä'/xÅWþñ——|æ)¯qËwóŸ×|è9ñÒô¦÷|êQzѯÞõ­'}ì7OûÑ×þõ²WýìmÏ{Üß~÷¾ï=ð‡¯ûâ³Þø°G~îÏüä7ùÿ˜ûß§Oýê[ÿúØÏ¾ö·ßwésÿûà¿ÿøÇOþò›ŸúÞ?¿ú×Ïþö»ÿýðª¥ýúÿ^ù÷~þÏû ÿÿ§ØûçÁw€Ä'€¨z/‡jþà€Xoxoø€xˆ˜¸X ¨!ØHtJ—t&˜‚Gq ˜€8€è‚1€ Ø‚4(ƒ—~ò·ƒ<¥öƒÆ„B„D8„FX„Hx„J˜„L¸„NØ„P„¸ÖƒTX…⦃V˜…}÷€\¸ ]ø…^†`8†bX†dx†f˜†h¸†j؆l8† ‡Zhe0sˆZth‡rˆ‡w¨‡uh‡}˜‡|¨‡l%ˆ¸‡xXˆƒˆŠxˆ¶ooÿè†øˆ’‰”8‰–¨†¦&Uš( ›Ø‰œø‰žŠ 8Š¢XФxЦ˜Š¨¸ŠªØŠ¬øŠ®‹°8‹²X‹Ÿ˜kX¨…ºˆwOØ‹Qø‹¾ŒÀ8ŒÂ8„¸f0S…Œ¨•ŒxÈŒvèŒË(ˆÐ¨Œz8§UҘظÍÔh‡Æ†kÅHŒä8ŽæXŽè(…Æ& »h…Xkƒ8òX5ø‚÷8ƒ6¸øˆƒö8qÚ† †Y†Ù…† ù€ ¹ ù‘)‘I‘© é¶ ‰¸‘uØ‘€È‘鑆(’ 9’!y’&™’%¹’$é…ɉ1©3 “y“ÿ‰“2©“4É“6陨78”ü¨BY”ô˜ôÈŽˆ—‹íø”o'„(•F8•Ah•?ˆ•¼¦•aX„\ù•U–^)–T9–^)ˆh™–j¹–lÙ–nù–pé–fY–ty•di—s‰—u™•wÉ—yé—{¹•G8jL •;X˜°æ”†¹˜hw‰ŽY‰ù˜’™Iø‘~Hˆš¹ˆ™É™˜ù™†Ø™Œè™¡ ši0.‰n“¹š”Éš®ÙšAɘñ‡˜«¦˜²y›_wŽº™Ž¼¹›¾Y„7vÂÉŒÄéÃiœÅùÉyœÊ‰œÎÙœÐɜҙœ\Ù›Öù›ØyLH˜¸ù~ïkô—”2ÿ˜š/Yp.j©€Hjë¹n´vžwkF9ŸâI”GyŸô9z=™“ü¹“ý¹Ÿþ : ?) J i‘¢,‰’ ª’$¡*¡:¡Z¡¨èY“ ê“úŸ¢j #Š é¡ o‘ ”ÿhŸùÉ¢0ê1ꢗ' ¤g›â–Z&cx ¤¥TöòwÒ¢Ö]Ϧ \%cLéH¥¤©†¤1Ö\¡&Yúf Ñg—\ª]Ê¥Á—b:¦dZ¦fª–é¥jú¥kʛܩ¥ìG›ª†£á–Z¶Ð•Û`Twª SõmHp b'§¾v µà~"¨xÕVxÿEkª úh© ÊU§e÷ššÚšœº©d “›9š¤*š¦jšˆ˜ª£zª¥Ùª§‰ª{šš:«žJ«¶ú†±‰©çG¨¦F§àf§„Yé‰kdå_¥f¤ùæ_þÕUß©j.öG…žÏ:jHÅk’ÚZÃê§Uu©º vl®m*®NœËy®Ï9銮ÑÉ®êÚ®ë¯6F®ãZ¯ôjŒ¢Æ«ßú}ÍZ›ñ¢8èV\åþàIðjèF/À ´¹ ž\' HPjê~b£éæ£Ib„9±õ& mà°%€”-J²3j²2š²ûv¢ Z¢"ʲ9‡µÀŒ9¯/ÿË¡0k¢û©¡ ú >[‡œØ‘ š ’œX´H{¡?«´ *7‹¢8‹Z3ËV©³?™³OÛ²,»­ÿ°¢K£%‹Ÿõ‰²`{²¢‡˜ç«ß–ZnpcY­©f°›Ñׯ²6…ªvYõ6&; ¯&Y·SŠ­SÚŠê­ûÚu‰§zÙ¸€é¸‚Ék™5JE:|Ú]þZ‹ –¹›k„az¦“&?"k5¦þe01&º¬;¦<ë¹Ë¸;»žc”›&Âꄜ+„Húº² »´û»Âkjúzo“j¨)©v;m™›¸TW¼bwW¬¢F©Ôz©·` kjÜQ!Þkºyÿ«bë–½h+µjÙ+¨¡v­¨ ð¾ï+¾Î«uµª©wÒV ª’ôR¿¶ ªÈ ®ªªz8&nP ˜%hIÀ¬…ŒC[ª°ºˆ$ɪ¯Zšj™·Úš\•¿º£©÷r þ‹«£¶¢°¦;Û:(H/Ùv/Ä6¿ß½Ñ'½VG½¼&Y~»•‚JV¡æ_ÈÊj¹ »&± k­Â*ŽIà5L¸5œ»¼ªwÒÂ. u÷Ú›™å»Mìd5¯öšŽXi®ò*ªc/É `/²Rœxº¶p'!& p|ÆkœŒpÙAXòƆΒ[åÀ¬‘IÅ£IU÷Ã7¾zÕÓ7_zýå÷ß~¸à€¦aûÆÏ"­ÂÍ·Ú€Ómb‹+Æ86i˘ã½r‹Ð¬Ë%5“G>¹P•KF¹å•SÖs5F7ޏ7›)¦YâŽkÆÙcŸå²”`†÷M¸è…Æi¢f:馗VªT NMõÿ]«¯Æ:ëeÝH½¶ðë Å~ìÍ>+C´×»mµÝûí {…±n»ïÆ;oµ-î±ýî[î¸ÿ[ð ñ³§P\­‡<òÆÕhʪ%ÇD²{¶{l™õü勵|òÏýl³gÿz÷Û‡Ðñ®£§¿þ’âuRJ§÷/H¹¡VŸ&@þj4`…À°Sñ‡„²3åìf³`Ïx†ÁŸùÿ;!SÈË\Æ2–„'„Y Gx2™m‚|¡+ØAfƒ´Èðh0òÐ>,à(Äþˆý9Ê“€ª$5Ï~O„¢Ö¸¦ø½ÏŠUäÝô¶E.vÑ‹&’¯8F1†Ë"È‹bÕxƖ诉k„cY¥ 'Šxwô]ñXF‰Ìu±$ín7HAòPÄÝ!yÝéÑ‘{|ä#ƒ&GJBQ’êXÉhC8¤Þd89JZMO]dDeS97ó¥Ï•ã{e+a9KYÖ’||[¥*u9FqùJ“ù%0éKa“˜Ç &2‡™Lf.Ó™Æl&4Ÿ©LiV“š×ÿŒ&6§™MnnÓ›Öì&8¿©Mc¶$Oâ¡$Ú/ é°=žâãYDš„ ÀpæID~îÓŸFügƒò0zþ ¨ÑfÒ?R‘‰üã"êЈBTv‹¹ÅéÎPƒ&´£ "GCŠPÊ“¤#õ(JKZ%&L4‰-Ö)¤Mn²’Áõ†DJžf§§ìê‰è¦Å/Õ¨_ª-p¹®Ÿ6Õ©O- ÜX’H) ê܈M))œ^„9;V²–Õ¬gEk]ú˜’Ä ±Å¦šw‹6œË©8íÚUÓÅ)î5ALõk`;ØÁZnˆUí\-̼‹ø/¥&},ÿí ”¯®´Ÿ'…¬eEšÙŸ¸a³Uih9;ZÐ’ö²‘=­f1[ZÖ¦V´­ý¬k—ÅÖ¶«Mm&ÝšH´A;]íß]ÓEE$\’°™ëëq•»\æb*—6¢ÕÙf¸øñÔ°#qXrjQºfÕ©·@pY“ÏæŽåEozÕ{¦HŽŽz¼ãOu+¡ê°ÿЪñJE½®WrÉõo€,Ø]~(ºÖQOç…Û™À“Áî¡=ŸRÙÛ¢¶ÂªµðÁöZÙÂÂ1‡/,â“8Ã'±i‡bÃÞÐ-ïmqŒY<£˜ÃóeP~ã¸_ZítÀR4å…3²o¢|;Ö딡Ki“o¸Ñ&îó6SÒÜç°˜ÁÙCnGÿ|æ½…À’ŠØ"pé-jÒ¨»”©@R:`§‚¸¡êøgm!¥Hdª?ºqa»yö˜´ANà!^ôÊ=©­ÓîµuŽÆ|g•Ú rÃߟ*ðžê‚OoÂÕ•tcÄëJ’?„²lç $,gL£mØAÆÃ¯˜F’ˆÁ”Á¸„˹LËHAm¤Ë·tÁ½Ô˾4BñÁµlËÍã.õûA±$Lî;Kü˘G†à(ÌBÊóG)ÜÓà ’+;‰ê؆„¬L1”’ #9º£C™@9° 0âk9‹¤DüÃ×Ä×›£Í;\l0‹”¼ž FÓÎÿ/¡¸¾Ù”ÍÛüMKl‡€{êÃð3Ž‚ ?Œ˜NŒS¿Šp‰™P¸: ;µøã†0‹s©p»´ScŽ»‹NIˆ±+;²(ÈªÔ ãÄÍ™5•$` [¨¾3ÆCF¿{fœ@ž’¼dKuÜÊæRÉQKìëAÃôD†Ð¼{aþŒ"¤:‚È„(ŽuGþôºx”Gê¸\óš|üL„hQÆ‹²²=êÒ†-t_Iźé0'”„éðÐ'ë=! )¸ª¿ÙÓ¶»ªBá«þKêtÍUI¾ÀZ>NJ(½,¸{ú¢“P‹ØÉ‚;¨#Ë‚xŽÃ³ˆÿêLºÃ%Û¼sîFÏÙ°Pó< $ØÃüKÏH‰+=%JÌs þ ðÊ'G¹JÈÊx«‹¸Q;kÐÇYûºˆ®Œ¯$ÇŒÒåá»K²2K¾ª·Rm<¡ãO S¸®b*‚SX-f㻑K –°´ MNC©ªŸ)ÆŠˆØ¨Ó$ÆÚQ®=ßÀ’áÿ)Vã5žâ#` Fθ ^ìÈ:¨ ¯¨c—_¤ØÛÕZÞôøÛd£°M¦àA†`6äEVäFFd8fäGá©ÙÜ7zÚ5=á!ü:×Ì”<ãOnîº+–£4fãSFeèC¼£Q*ˆßíÂ9FŽªKÇþ¡åNýcélâz@^öÒŽÈe&>W†£çMåcFfU®dMªŸåÞ‚¥Lÿt)ˆ°‰$8<àØ=îˆÅn Q¿3ê(åôMæs^.,u®Uù%Ò—«ßI(óÜÔüµH•åWtRÆ’V®0V¬/$ŠÈ\ ÆÖyöMÅ•MVhGnhI>䇖èÿD†hÙºà‹¦ÅöˆÜŽWÚ¨è «â!eWå,æÝzSádeáðfÖHiã+ãÔ=X^#SFçœ&°n6fg°¢Uîáè¡çW¶H¹ý|Þk[C°Lâh•ÎÆ`nÞ’(j8zbÖjæêàH±Þ®~“ìµdè™Ê—•Nh>X½ÓÔþáTxéNŠi®iój}3gçÁé­ÖkQåév~_vÞ]Ò„d‘¢çŠã ®Û_®‰ÿm¬¾æz‰j!¡Ÿøc¿uM *ì>¨BvhŠžèÁÖìÏ–gÑŽè…ÜŽFÏzs1Œ^í¸miéV)i¨ÍäÐÕ»•vjm«²ÿ·~ëŽç‡%›V£¼Þëãn*ÙUnÛõ‰ÛuîÙÅÝÝ›Ý-‰Î©Â©|RüªŸ«þáXbƒ ^¯2^§{ˆ¦mS»-’\ã.õöˆ\Ö9@o¹êgœmä®-J³4¥ªkû°æSÕ¾Þ2KÛ£MÕG„Miƒ®ïUqæ{é^©}ðÕÔƒèbjîAkã¿ôí¸¦Î¹ÎÔ¯kÌö¾kã1nþþŠUma1ñ$lŸîëž&¥_å—`mVÄrW:êlù¸jüíº{¦Ûþowòªû:NjZ&L€.®…"h{ à¨$Ohû˜ïHN4n%m+÷ì-GWœ0Œ 2·×í,ç(9]hÿWkm£žŽF“NÂ`‹ mã׉TŠü%u9ð]ÎœÚÆä3Béܦ"ϺRáâªÓª q‚ÕI@òI%î³q8R eÓT}Ð6s¾WEˆó‡£ O•±8eÁ¸SÈ¿Oú%S÷XwYªjˆj Ö•ÛîYén¤Vê‡tRm¬cøå2ãì^ï&Ù;øc樺v¨ò4ÊêŸÂp­Kô«¿¨tìÛ¹ªóÒ6…:‚Ó¯"ã_&r ,¢|’²;J÷êS:a»—p»7;«ð~m€íBñZpQ)k¶îsïMëÔ‰p©qÙFïv÷Côoöp]LxÉæÿâŽô4¢º†hÓ8{Ѓßï!£:ú3÷Kkþ ô¼±‹YKL‚Œr‰ï˼$ß$ÏŒÒïR×8×ÛSÒÚ»½Í l„‘ˆDM޲SŠÒó¦ÉìÞ[;á*EdlugË66âdïb‹Êfâ©g˜Ì&óÍ܇,Õ°qŸ F7°/íRˆ€Q*.óIÞD4=?w¼”T•é4R ý k>Žç‹¬N“»¢¤ úÓïû3@Š™ÜÞ`Žxo‹Ni>™—ʈhºÀ·wàØ.=w—á{ˆ¶Ä/¨µÈâ¸jYo¦‘þ,HPƒ ÛPXЖm·!‘TðVE‡‘$)˜$¡Æ JB²M#E‹!´ é’`¤ˆ/gÒ¬i󟿎7wòìéóŸ¶þm Ó ¿ wÞ²åô©­¦PJZêÕ§Y©NåÚukÔ®a¿ŠkÖ–Ê‘¼Z-ë–,ܶq±¾•k—îÜ¡?kmø‰_‚møêÆ €ÿÀ´,ˆðŸ6¡ýh¼×ß6Ìš3sÆ ±›HnÚØÂ,@’¿[Fµ!ììz3f…¯gcf¨íõÇmMjssÚŸoÚ´÷/nhâ䉿<Êü¹Ã7:OrÔzÁH% ÊIrRw [ß î+¸-IZ…ØC~ ))‰^má Ê×Ýr›í!Û˜$h«„D²É7FIX¶“ýA· y2ø qè÷OD'ÀI<=%Ɇ:Åᇢ%"ˆ#†x¢‰)–¸"‰-¢Èâ‹.Úw‡0ª(£9â¸cŒ=Þ裎3—!QIÈôO Kýã'±d‘mS”üc éàœOßõ¥—ÿ'I"!IJwÒ™ÿ”T‚C… &œ½9'…ý…™ŸšH–Y ml£œtz !¡Ç)§RæÐ¢ 5êÑ£“):)£”:j)Qz.ú$Aþô‰…I,š`vþóÍ%(ÜòÍx ÈÞR‘2)Aµ˜úF¨MtZ§ q´h{½4+AcføhJ´âôi¢•S€—:+-µÍV+)RJ(»-¦Ø^+ì· Nk­cGEb¡¸Þ.¹“±U¼ZÉûî¼cÙ/½ùÞ[/¾ûêÛozÜ>Û/ÁüüïÁþ*\0 Û+n¸CŒ„d‚ Ðè`9gT£þ<¹iB‘HÙ@· Û6·¡üŸ-ÿ®ÝvšÊFº²Ê.9QÍ›å¼m¸™Q˘ýf;ÝY·ìzÛ®ÒMCÌôÓK{{hr…RhõsÒyäG[„g±ýÉÁPrXÒªyHÈÁ—P¶öºÍGP}!1+Ò„¹q”$·:ZBz¾¾MÓÞ7c½χ+N“Q1Id…ß$å•[~9æ™k¾ùæ’NS‰œ‹>:饓þ Ïmô¸G~%i••‰XGSZ†¥ä< gI…é©ç¸–é] Ån|ñ½ƒ™šžj¶›’€<‹[?ÕË:øõ4QtØArJa`n @Ð7Ð~Ó‚¨à‚ ¬²z*kªÇýHÿA`®içþ×u”´À”äx)qÉøÔr±îùDÜc ÕÆw®Qe ‚¼ -¢Å!]°ƒŒ°4))A0$*(.&Åí\ÓÑžHNX”ÑP7mšÍo(Ò&–e²©!ÍZ³†´ "‘àŒfF´"̓ÝËžbô@'DkÔ1vl(!mØ0[`´ ìsš ‚&Ô=lsI°òžøÌMn$HŸN£Ü‘?úÍcÅM1$ :¥ä D>¨qa“Ú$‰Ir&ˆd$&!sG—p1“ž$TLN3ɨÄH“L†Šž1m'uBÈ$[C7ÿ>Æd‘=Ù—Æä;8I;-ó%.¿$'êI>AK£Ç2M2™·Ñ‡ˆ9¨O Š&“šÓ€µkf3iQëÔ÷s Oýæd“9@€¤3)Pû\àøµÀMøÆ«hÇDå\¶’óÒrÀKuM5éDBÜzE¬<}Nh3ȧ¸ *haó›•(Fq¾nŽ«¢í(G¥åÈœë éLçCAzQo~4b,}©J•e?J®¥Û„©KcŠÓ›ê”Q%8©9GH11Î"ç  cT˜¤Q11§Cš¨£ÑŒ3,K™kNó? -"³ÙÙ9c4¬z&A‰V?Ã&´ ÿíL:ûªGwמæ4\P´Z!©8Èõ\‘!A Š9ÿ*Æv¶ÀóT€<] ‚oPÄo|¬J·:ÖM#Ÿ:×`¢7¾ù )€sI×zR8j*’´¦=­i3hÕ¢¶µBä6 '[eáê9sŠÍïnÌïàvyrê-ou{›å©4ëâ Q†‹ÜÜ ÓµÌ¹ëöPÎð!¦%ƒ*vÓé>¤~Þµ'>5[ ¨~-Š9Ò@…÷¿®1é¤-/I$›Œ¬Ä–4‰ m1™çò·¿ÝcíKšâ߸&@dâ<›°*XÁ@C0‚ ¼è*¯NdhKÙ‘1ýUaì°` #~ÿ%f¬Ñæ5X¹>“µOeïs¥Ÿ¥Ž_S 5ò*öØw&‡”n%,¥›\RÈŸ”ÄpCâ”"¹É§Ý­4£¼»aByw%q“”‘çä›Px¥t…”\¥:×j}oS–ñTKü1&1:aÄbL@ûÔiö¹¯óüîš â)T2޲Z CþI\-ª(*‰Ô¯HZã¡üyQÆbW²u71SôËcæéµ€cÓKsZÌžör]1-êNƒzÔŸné¢n‰[hP7H†Ø¦OæR“:Ö´–µ¥qjœØ¬ª¾î5°ß* ¯û×c}ë¯m­ìY·´ËRlí^¹v$|C*H@Ôè6©À dÿ@ æ)n 6ëtÂçøêu¤$q‹qŒ¬ó´R#{#Ig'óÙdAÄ{r·,p§¬F£ÜäÀþÉ*g™ál8ă›e…¿ÄÙ ²p§ ñY&J·Ð3¼;âzÒù}ßõnà‚>ãϼþ9Rÿ&B_‡dxŸŒ¯‰ð¿û¿¨u Ń.ô¡Ý“ †ðÑkÈ`¤3=é¯)ºB,¾ ŒwÃÕéÈx¬Sm¤ N€_€X®»±ã†Ÿ P'ì‚æÜ³9I\lGúØ¢øÉÛBpœï‰ rÝTwœ|I›8¨^È/<â åðˆG™ÊŒ_<”oMfSÊ9ËÎõEÿ5žÀˆ† WM0@Èá—г}ﻳéY•KÄ …;¨ú 1AÔ•ªùRÐbFÁÑ ÒÆ«J’q^!ª¦Ï¡­F WJèJu_ëIÇÔ·¾þåw­këgŸû”Ç|÷§þïkûä÷þøÇOÕ`‹µØì_l¤„ì÷“•þ5ëòÏ/þòKTêÐù»E›ìLÛÖa[ÌSØ•Xa…[bÛˆ€ ´Ýݰ›Û¸‡dÍÝ‹ÙÍÝÝ‘Ü[±ÜJÚ¾}ƒ à~LÈ=Ò¿)DVÑLÁzOÀ% Ö  žn pÅ.×òÜÖoåànõ  aâùßsÄ`÷hÿÇDA•Qè¹Àȹu×É©žÊýÂ7 €œÊ?¤yYŒ’¡×ÌÅœÛyÄRÈ^?ÐËéEz%P­ÎRTš¢)Ký8á{5‡ËÍÞ þ! :—Ó "Ó-!b„I^öÇŸ”€ÜA ´H†qX¬ËGT› `› ` –, Ù‘[b¥]|¸“è…¤@A¨X´˜›„øÈ¢em  ‹Þˆ-¸cIG«LbbT¢C€Í’¬` Ÿ¡É ²Ø‚ ^ >#4FcAÞãi™lT#5“"R úAƆ‘z„ßö-M™QוSG  ÊçEá–\bÁê­ºÿÀ:µÀ%¼¢Ò,”Bf™Sh„@"š¨”RêGa,ÎØPTa=éYØÓœÔ¿Ê–€S‰«Ô‘¦t ?vc§ÌŒþ#Iš_úñßHš$Jž$Hî_K–¤8ªäKʤKòÚüÝdû%[NÚŒ°ÔNÂßNþ¤OeJÆdö!!‘¡G$õáõ H–@”@ Ü‚%db¶! ØÑ¸›€l¢ €› l ¾Ýà¸P¤Sr –ɘ`L¬ÎQX€àSIÈ6ÀOW*–Ú©QHe ã1Ž–C´ -#!1ˆ3J£c>&dF¦dBRÚp´Á#_LHWó˜c…œÿ”¹E$†È™šÞÊSÊy×=æ#—þÈP äI¡A¦ ìÂ7H!=ž=Ñc•ÙÜ%´Ý\Â Õ¡Ž‰×_ä!í!qÝd^'vf§vfgeÖ„-´„-lT†8¥õXsV¶æØi¢VŽ]aÑa¢Ú9b¹“ lBç¡z„áQHfaæÂ%Þ|N”‡©I€ÈAŒ˜'º@ÙùåÚI¡`e©€% ¨ v`à]„%¦MÀ^q4æv–¨‰žh&Þ5‹®¨‹úáäaÞ.^‰Ÿ‹å%³1avV=­“j‚žÈ '<~×<ªœ'>~ÿ!y%¤b4Š 9€whƒ˜SJ î} BF%Q[<ùfwU¡*ŸŽqÿ¤HÒÄGÖ¤?h ¢ž-£¦­¢–nêž®êFêêBª£¶.Mê$PÖîPÚn’þ¹ŸPî®±É.ꆶîÄZM¦Ð?ÌÁXzªb bêÊŽ[(Ž[_þ*Ì.¦F¨eÍÆ›ÝiéÄ%8ÚÝ™óîêƒVï|~júšj®"·IÁ†ê³Víý0f´r-þæ¯íØ:ÿ~-“)ÜðþDñ*žÂaK¼mºÎm=]!É«,ߺ"—Æ&ÿÌ\z) Ð?삌˜LŒe¸.®¾šXp¿z™:0ä&® 0§B§ÎD”,ˆuê¯ï0Y¬#Æþ°gÇr£Çžÿȶªòªgóz]{²¬šÑÊÖ§Ñ‚ÝÚ©fÎk±ðÜÁ[ÝUц/i&ÿlТ,íÚ©¯ÒzÓŠ¥Ú)ü"ë%ÿLí eñŠ®mÝ/ÿ1 {Ðÿz­ÿ°!—­r,ê².ø1‰”nƒ$„Qè«ë7|«DdÜŽ+…ÒÞz©Æã‘ŠæÞ®k EAA8|G…$QíÉ\M¥SYbBlÂX’Þ ØÙÈ9@°t׈u—ž™“û´ðh)ÞÊ­w¡@D¾óˆ‘EÜБEÔéF’t“ž­žº.8Ç.#ÃnðŠ39/:³éž³:K îònPÆÿ3P.ïÒ_=÷îë®óL°OðƒøÆ_ UPk¬“®óæê{¥b­ô&–¯þ¥ìÂ.”Ilå'IµC–x1q˜%Á-à‰o%'" z¦€ƒŠjpŠÑ;ý%‹å¸)4K#Ö.v‡€àüî1ò¶j3úq C]Á¡ÅR:EPJs-õê`ê`Ró`Tû R±Ù15¡cv¥2G03“k ìâ^¡W¿p)C?eœ†À«ä|f:ÅJ_·–@À’0¹Íæ ÀI-š"ów ,XÿìI!AÝBa(ltvk¹´ƒì×Q¢ª±Úd udÜ[¬!jÿ,g'˜U# VÒ‡eVf%Á¯m›lC1©2àÒm‰­ïi¯MJ_ˆQbxôº‘öèYèÉšXMefÛÐJ%œvL¿6VÂñV¦i‡Ç­HmZ$1F‹(Öõe+’]Ò’ew“ r52xS#"WM>—R9·Ô?:™SÒö¨5 ß-(O®'Ã-¹ýkEäÙhCB±!\3¡íJò§{ v.O.û)m&À^£#°¾ðj¦ž<*¸3«[®…¼ª}t$Pš•Wønz§³KtLe;_;‡ó‰YðQŠnœ·‹£¸>{”€µ UÒ•Ô”þÑîPÛB-€Èmÿ ínOÖsÎ4‡ÈsýÕŒ’Û8ƒ?÷„?3湬F Å…®¯$tùB¯©öj3t_*÷|®BŠ7ŠÑé¶l`VŸ¤]¨†ÝCÏÓˆ%°š[¹9÷™æ°J¨L¢>ñ·…4xhÃx &ÕòtÍùsÖÚàO]y4ØLXºw»Š`1ìRÉÒ ™éà¾V”­ ™$ jÀjx‡m”%H’@×àÐ1\yÄPz3pK0p.pi†u`õÉE0~gÈ­+Ú¤ DXû T¼Ä—uè9@&›k¾þfûòoRî ö×·7î…—$f³ø\‡ÃþDß –v—èŸìÿ„®dºC$«UÈç$F)…cÜÅð8saÕm<bwöl!ottÊ$|‚-Qƒ}¶yWX$:aGÜ # É61s?h|Ra©¾v„v¼ ËÁ6ì‚7ðfFÇÁØ‹l Àz:1KO±èùöJÏS„"· —˜(.÷?/¯.  ¨— R|ÞæOo’ÙÂRú‡´Œ؇n ‰whóÖvÒKÜ ÖË;I¨Pˆkº}äÐ슭C™.Oé–¥}ã©úîtQí| øN‘o7*ÓÄ^Œ²ó"³3ÿéè·ö·S’ýö%ÈZ¨˜ŠDRA'Dø_GŒ‡ÿmkƒ˜qcÇnû×ÀÑɶ±üÏ€§ ¶5štiÓ§Q§V½šukׯUK’ŒXlÛ·qçÖú±ã$˜ RžÐM¤–N`° ðÞ%GOìOºä¤I"wck›¿²›¶Ù†ähuê‰Ñwwؽúté¿Ù§ORŸ$%´m‹D‚»ñôçÍ“î¹ ì!† ¤(´4h<7ZÌš)+( « à³Z¸PD @…/ÌŬ*ÔpÄ)¾qɦÀ‚vÿá« [øúÆ Ut¡…“.ÀE¡6,ñD³ H E+t’E QÒØ@¼…BlAÉ&¾ÑF€BB‚X 4ŽœcПŒó¢m8SÈìl©ß êLƒP±[P#ô4CMC´4EIct4GmTÒB)=´ÒD©j,’G/]´ÓF?åÔÒQ1%ÕSSA-MΈh3þDh¨3Ö† r€áâ¤ÎWö~¥Î–pƒ:$¡.ZÍ/X`¡•õÙi·ùmZø†„½býqCh©õuÕq$Wrá$wÀ¿ÊôÈ ·œ€©`ra¥ D‚)¬z[P‹D`²i_àÿ؉»Ú€P’$ž Ó)¨œú&Ž@¡Þ{¿Ê)'³ð*é,}w‚ Þµâ8+ŒMBëߺ„´É…nI¢/‚Øýg0ƒ #( $äTLÝŸB– [˜YÌ?5ë€äÐL·"Òj-jª ®Zj«©¾Z묹žÚk¬¿Þ:ì®Á.{k^+²Žl±Í^Ûí±án;n¶é~Ûj ÙÄІ%!±æ˜k3Îö/Jèê¶Ñ(:Í´MÏñöÖ{\ò6 ܰ¤ž’¬#ýÊ“¼p¼A?ÌÜ6r¨t„N÷‡Ç1 *=‰Ó ‚½õ‡d'¨öƒL§½õj⟠‡”Ò [p€Ã+_ÈI™HÁ…„ÿª€L¬’Ê’²2þËo,Áoè¿ùf$ñqù ­¤Ph>Ä ™_’VÈË}’.)l2û ™T«¨€V÷Sž’²2?hCÓK‚d@ï¨iXôûLìt—»Ø+ƒ¨ë 5èÁ‚P„t2šg†¶´7af ~2s;Š*R©ª! •Cê‡;ôaxC!òpˆ6”D¬p'B‚l£ˆA$âØD)BщQ¤¢“HB-În„ÿxÕéÈc;¨´®KÑîø$Æ.ªQ‰¶ƒ–³ e §¼qVÉÚ†˜îGêè‘=ùQãÁÈ=2QÜù•˜´5,8¦[ßÿä³ôøA.¶q’[d£%³XIM²qtRÌRÐV˜Ð­k#ÔIA¼1…Ÿ¼ÅFŠ‹WL“ÑÄ_>9I­2°‘‰E%,qÁ/ä@¾mìBŽ’ØETЄ$AAñÉ}¸ÂÌ‹~²ôI/› ZÑŠKp^¶¹¿U:sCúÛ&5 Ë|/Ú¤_e(žœµ‹3HÀ%.èIA’\…$HgNˆ4çè*ŸäçAêmäÓ"Ú`ZB!Ñ‹4ÐNiZâ?Xeý  K€Ó T¸ö$¥/æùNw:’”ňÔq‘citæãG”úÓ>%Mœ¶ö ϵT¢í䀴Á0[¤ŽP‚ë)Dÿô 9´èBL=™.¤)™Åï‘—ª7¢ùÕ SÒ•þ'¤}¨Î#Qó’”U ¹ÈKNº WÅ)"¬&Sp]Ÿ¤gW§šE^‚ë_Ź¥.}©®€ž˜öiÐWÁ•L êQdB¦ fK+ÊG©R+$þ#PõìªôC›Û}–´£üMmhƒÎjL·x•sì¹)Zm¶W|Ö° -d52YÞ²c¸âã àë ÙT$N+,…Ôfg·¨²ø®Òâí§Ï±_"1³ÄP…gÓ5È>þ¡¥î²`Y)YVê’Yþ«ed¼ñíÜÎÛÝ÷†$²Å ðnœÚÕíb˜¸O©9¼‘¯HÚ¸ükâ£%Or’‚ÐJš¼”8/åb/Y¶7'µ¤¸V4f—mú÷šd9QØW—¹È¹gI°š ØH¿¡ŸëÒ˼мVNYVÿ4O›MÙú›ãˆÎp©O=¡Gì1g¸Cu­oÝ1„Óit¾îžÇ…=>æYÙÑîuûdNì;–¹þƒ÷Æÿ>þDŒ=»ç½îuE}GW$$ù¬ríY„ÕJ—¨Ò#¼ˆ`¤¾OšIS𔄷Wô)+ÊsÁ–Òº¤³XžK›ø^ ‚ë•@oŠûëa'×މªMìqŸûáÚ–÷»§–´zü_íÛ÷½Ï=cæ> Pâݳâ•CÊ‚RÞ”[üäûu¯É¶^é³7äøÝ ö¾_ýšXl½"™~çaù±’e?eJÀèu²àKeòù…¹¢€õpK/È7æigz&ꎯë Pêî¨6$aiìð0x,ǘ Í´ŒÑÌ¥,ð¥d*wê+ÂàØM‰\'ÇíÛ:ˆ:ÌD©ÿöêÔ–'Ð\0¬(íy,­ýìÒPò$MIÞ‡ñ^0&O(~ä ðFO¬mý'+ˆ‡B/+@Ó(Òü§x¬LOõ¼Ãw2CHP“º¥ Ÿ «MàLàJð É Ã0àÖÐ Óð Û° åP Ç0éP ñ 3 ÞøÞüÍûhÝ–HÞßúðQóÐ íp’’/N˜²œÏ-"Ž•&.å|",NÄäž ãLf—Z®ãR`äZÀ›..,žIç21–Vñ•èË,¬©•x‚I¦$ ‰Ê¢.\BeTÀÀ<&½ÉúOé:¬0"‘1HÌ•q™±c¬¡‘áÉÿ¤±£qñôÌågŽQ¢ôîzøÎïÄ‘òÖjEŒ‡ó®j¬°¤¬ÐëÐoð”Ћēpxó²GóØ =/¥Ðòðê µ°iò&N+r!²!k«ø Rø¢E¸$2"-\òÎ!ºQ¢&ñã¶úD²œ®¯äXîä(±¾º¯þBæBø ûÈ/åN¢âЯ,Ô/¿ê$ßÏ$âϾðE–ì¯Àf.$`ÿT ÿŠ C‡ò)¡2*¡ò­Ñ1*±Ò*rtQ„æLÁ2ÇRÏÀêÔ MÐÀ--¯RàG OEÔÒ,¸©ñðæÀyr-­DÒëBÿ¨ðÒíòPmDìÑyÞÑ0ñ0DCŒ§ ?/³'KØò`¦C$*Ã8£V’àOš€tÀ2Øà°I³+ï0,çp4MS5Qó4±4[“5_s5±6a³Ýø-Q7±ßЦ7sÓ7…38‰³öbÓ6i3Ï4’A:2¢>’-ÀïDÎo:Åæ8Îq®$ÿe«`­Hì,b±™6†œÒBçP1–ÎÓabÓË_hQ½¤³&ÀçB'ÖÉ:§G㪲³Ãé;¶*‚*0¾ê¤ò@4A›ÑëôíÔíÌøô?B)tBr9¤9êPÀ ”ªÑÄqDû°Ê‘Ðÿì’«ï¯Ê* QüOHFPô\T0YòâqCü‘œþÊ&n”KRÔ°Š&ÄõtI™´I·î"¡4ø€/J©Ôø2tÕ…CÊ,¡Úà¤ú¨s$ϯÁb'?1ÑV.'ÌHXrLa’úfRü8Ðn²%Ûïüæåbæ¯>ƒ²•&ÌDÐÂ(ÑiÃ$¬˜²A’ÑIµQU*¯îQóuŽ“4!ât|0³ÏhðSÓ~ °º3{àÒ@Ó² «XM”'.Aõ±'Ó/ ÓG­ŽäÑR-&ÒçGáD†‡T‹ ë'UëêC· n¡9VÓ” 9ÿ¥õR§u6©õZ­5[S9±u[oÓ[«\»Õ5ÅU[1)SÇU6ËU‰…},fñãhr^Å",Rà82¤,:‘&L!@_a1Ø‚=Åâ ¶•TÑdæ4å°i=1^Ù"=V=ÑÓ>Uæ,b`6+jî̼%‚úBé"Ë)%µdMödQÖd5´@´”A–%ÙævTWI´f‡P­F+¤ðü²Cl”.G{¢äIúNòVdÒ 7Uûnó®$i}”I«z V yôH˜Êõ€ªeSökÁ6lÅ÷V–@¼¶@ÜÀÊ"fú"+ØïãÈTüί½Ð ûNR!ní+ÿßôä®i'+FNQ‚N}Ñ^MóTüöTþ~dX¦_xbôöOd€"+(1d“¼•dǶs=÷sAWƸ[¿Ò\îe')*dc‚ï`õu…ðx{5.Eô,ÏÊF»DGk•{Õ/±G0áÑñŠ'.GK ³x¢Ð¬Š•u;µ,-Dk› ȃD“[M—{×5{Õ|½W|¿•|ÃÕ|Óu|Ãw}ÕØŠÓ³eJßw7‡S~߈}ËW¥­läl Ä ŽÌ!®«mÃï=é5n51ü&î%ÿÖ &ä–^kåü¶b'›~±=!`Ë“>1¸b{±c˜„?ÿ8oÇ s0tY¸…´B/ÔBÁ†Áîìh¸íb8‡gC·KÑ%¢PW¡üIójmöˆÉ1g{f«Ä1•öEEdhgEŒ¶Jˆ7E¤$G_ÐiÉʪ€­®xfEtJ4Dk‘ÔMØ…Õxµ®JݸÞЭ"åØ3Ò‡Ç%Ÿ#muŒmeÖ,^Q¬ÖK™$Ï/ûv'7&äú NIf=_Q&·¾NîN“)'Sü 'Q¦.DÆKÐ/^õMÉ (B¶»6—Q9•=0+YYr®²*[ùsz¸]ù—#ÏW“‚!TW®ú.Ti·CuvÏòTQÔEÒ’òÍ/yW‹¹•š÷hÿÉÊ0‰¯ª•ø§ ó ­m4ñ,szý²z¿á3ÃÇt¡õ–ÛwÓÕ¹ÙùÓ×ãž»w í·~ã7ß‘7ûù~ež:„üw¢böî"J€u¬€ûØ`%ö¡v9Q'Lñ`A1‚;Ž‚=ŽÀ"š×kâ&%``Öò‚,þ”a/Ìaâ¢ß^úGT@3 T•mú¦_/–a9ͨQ§}=®”–•¯ :“#˜ BL´m‰‰F§xDvv™³©¥xD«xDŸ8Š]TDÞªVZôi=ïf»™h©™[` $!qº­ÝÚÇÞøé7®çضêX¨nÿ7ɸ+¡Õ!lÌd·£YnÙ r ùnÝ/bMfo oG"nç4n?†½þÅ-ÊOÃʪO+¶¾û'ŠR”u’±÷Ô Nù­™4©‚ µð§[ù•a{§ƒú@ÄÐÜ@¶£uF4ë¹Íry ¾aÚ€->—q·V…‚Wc7i÷òl÷Ï‚Y­`·w+ó­ŠV“{Д6-]7¶ê.ÑQ›§»¬ 2§ÚˆCÄHÒš"Âm{åù·ú{kY¾í» gïOJ‡‰nžé{ç}Ùžºሟýù7ÿù}Ýc8©…ëû¿ã! š"(ç8à{C¡bœÙ“œ0ñ£E<Äÿ/Î`x±A[±^7:ÅÏSYÜ'Bú=8`7LƒC8ít?uÂ=Qx—æÅìà´]û@­nƲ®Èï†ËŽÓnìlxBwX†qxÊs¸¶d@B·[[Ã#— ÂG¶º©É<ôšöH`y…¤ª‘¸«ý.«ÅqÌ™öïÀZ~Ujðr4Hö®ÏTF§@ ´7”TÍx$RCJÙÔØÆ,‚P”ü0HÑuðgŠo¡LÃê"¥JçZ"k¡6äXÞ¤ Ë"²"ifÃËC©ÑÃwÖûÄÑô#»±CNYÖ'[Ö¿X¾ØËBÊT¦wÝúòor³b´K†eÿ²© œ`¨}l6–¥µD#Ç!€LÕ•Ñ/ÂÛ="c›¾å!¨Ü·‹Ü­]Q-Ð>ªì8ª¬/‡¶³Ì½åÝ-J;§Iý\&œ#ü› ‚ûÄüùà›TϪҦ9¢˜i—}9hyTxþ‹^(΢`0+ €ÓíT§éB0þ—õü>DÒ»1-  x£àºð |’FkŒ.ÝÌ32YÄ>Â|]Ë×êc ~Àï;è1©`h˜~"R' Þi6î¤räHpž8åH[ò£ë™È¹ ÿÁ)·ïÈ[Ìž½%ìù­æ‘^+ü1¸18Ü <üLÿ ;Æõ~Å7ñ$¯)Å+8vÅWq— šB¿±õ^D$V!h¢n]€<5ž„uT\gW0Šô{¦ÝuÄKläQcÿ¸ öˆY¤öOC_µÁÿàc @Zf"Ira†!a¸¡†¶pø¡‡ Ž(b‰ž"Š$ªhbŠ.ŽeŸZ®è"6¶x#‹:Öˆc;r¨_fŒatV$?I"ÀXhuTAõU”1Jù’IDâ–výSB$Ûhãß-I$ÑÖ”fJù•gƘƒT&QÂEH°&T vE§šzÆødŸ~~e˜}4¨G…vt(GƒV˜¨Dþóh¤R!6¨$(Üò°¥àD à gq¡ò&ê§¡zjêy£æF@ ©¾€*¨ªž×\©²*@€ ©ÚJj ¡6Q§±~Êë©«Î*k±Èöêôz,qIJê*±°® ì³´>ëÿ뮨¾ðé ’ )VŠþ4®¡è®K.XW9*‘-Ü2 Lt‘ÿܲfò9¡“Ž€¼íÆ›SÂ*-¼ÔS ;ܰÂ?,1ÄWŒ±J’¤‹è?‘P òÄ"_2É#g|rÉ «{pÇ-Ÿ»/ÿó.ÌaU³D{q 3Ëê¶¥Ø]A¯FY ¶M^^!9§WA/6XGB[æÕÎq)¦D’tyÙZþ¸‘¤`O_ݳË>›vÙj|öÚþ(AzTáÜS©$ޱæZ % [r¶ ÞÝàÊ®«q†^¸ ñŸtÔ5Nxo„o~8å'@ œ3_ t ÿ¹æŽ77ù㪧îg÷Ù_ %ÁU€%a G ˜ûADþk_$Tà„u«SóÎ?}ôÒOO=õzobõÚoÏ}÷ÜÓþÓêë’ƒ.ÉQ Ë÷©g™RJ‚WTúSÂõ÷‘àå™îOÙh\úK 6ÿEiLþ€F¾2¦:ñ¯}hŸE·ÐÐn}4HC€HÀ^ @¬Šp„$a p¥«i•ðS-¨•[`ˆpT&4€ Ãêp‡<޳vµÃæj‡ÙúT{8Îøƒ‚¬ÊdÞ%¯¯hBø€¾´2<™ýC B:¢ÎàdŒLI T̈ƈÿ¥ñ)kLXIÒÍ…j¬#ïèF;ædtÊóØD«˜ë@3ãÈÍ$‚ Òls3ŒeèbÁähIÂØY&©aò.ˆ‰äÕà%þÄ…€Üd`‰ÊªDÐLt ,@°…$a5­¹œB29ópg—êA/¿èHî—ÂiO,Ò-]‚‡˜ÌÜÍx” _.s7íÉ|ÜÍOíc3³KåTÆ¢ €MwJ ¤•àUæ"ZD_Òât–Vzsž §fìIÏ|vF¨4ÚXä f, ^]À·'5!I~SSþÚ„¤$ÔLiZ“žš&¥6aÄñ³ý¼„'‹ŠTÿŸô\¥ÛxÆ6މ]mKéI9"¯rŠN°ÄCn¨Âd‘j§ÑâiqU­F«…ÚZ•SèÓë†@jOŸ D¨ê”†ÎêÖT£z›!ê4„ÀÊ!q\Hæͥ_CéÛ^æÒ´žõ¬rƒ6‘(êL! g¾$Â/[ø« „ß­²³ –¥c]ka‹Vþô`äc‹¢6¦Xµ"¶¥‘­ìdKØÅRÖ¬òJÂ-Ú@0HÓb‘cꉿj³ˆšš`Vc— ye’`³…6j 5±eP_¢Zan!€.Ù"{±­c‚¡½ôe¡Nóí[2+YèZVº—í™I'HÏm\ ÁÿšŽ pLçÀîsä%r†£¸×©qîINt¦3^ó~7¼ÏQ¯yïkßü¦.¸©ÃoéN7^öŠwuÖ,¯êdW0’Òí–fiÝ ·6x¦=(;7м1ÁS"R°‡hÛµ„øÃ$.±Çb)D*Ò|0µÝ‚è…P‘¾¯£ó«G#âõM´R“±G¿b‹6Í? µÒœfi0!+;擉x]»É|·HˆäpÔÚpÚB¢—CxÂÌ…U‡D5¡ºìeÓq¹_nsøå0³g…eÞV›Áå¼ *Ú˜²>ê‘ÏÂØXfõäD÷iÄS!‰¢Osд3åÿe.miG&Ó®½ ${ËiÃ@švQž›Ÿçö1ȦKO €ú63›ÜŽ Þ3M`G>Ôt\x~mkÖÑ:׿žµ1‡=ç[ךš¼N!¯³¹81Á£¦b´•Òð³ÚÜÖLO¶”‹l©Ûäö¸|nûOMn·›\QwO”£|·Ë¤V7º bíf©{â¶d5…°¡U¡å­¡*<á OÖÁÕp„;üT0øÂ'qˆc|â?Ô¸Ä?îñ/KäÅŠî×üòժܴñ,¿ÿØ}O7æ§¹Íaβ[|Ì"¼ ÑÌqžò—ýçC—¹Ñkô•¿ hÎítnÿ~µ¨eåéT:\>Íô¬ChJ?úÍ‹·¸±RŸnHÂW¾ `V‹Yuþe»~ÝÞß·/Nîžcœëæ÷¼Ã}ïxwAèFGwÀë½ï„çÍ´ñøÄ{óK3Ò`Hùȯ…ÿ«üü(?¿4í/J›ÿ±E½²@ˇ~Ý’W¥ØÁwj»!Æ>YV;Ý ûØË~…ÀzýìoïÃ.÷¼aU–Xúà øÄ/~}Béä[zÓÊo>òMi|µ”úO©Ÿj¾Âê´Ã†6È.6± þïO3˜Þï~øióÌò«ÿüëÏáOúèG?þò¯·åmoüó8+ùï¿þ×d@e“…h:ãu”õÿˆá Û0pÃQpWI%R5X¨q-ôzhx¦RUø#è%è/ãJp€`÷u]‡t,˜tBç‚-(ƒ5Ht3ƒ7hƒ+ˆƒ0èƒ=¨rº%„[jDzgU„U§uJ˜„Vçt/„;…l3}¢±nÕ÷'e‡}ÒqB¬FßQx‚Çwux6xÂá:ʆf8†¶9g(†kØvrhxTÑMˆ‡y¨‡{8Oÿç‡÷Fþ'ˆȇvz¦ÑgeAiý6O»° ² ›Q*ð€½‡‰™HBµ§‰±gŠÒF}Vˆ¥hЧˆŠ‡æ|«ø|ÛÆŠ¯ØŠÏUÿŠUÈM¡A…õ#·f4*ÐU±”Û÷líg~âWŒÅH~ì§Œà‘~ËxŒÄ(ï—ŠÓHÕ¨‡ˆˆÙÈÚȇú6…lE>oµz+‡!qŽ" äó!ÿð ž'äd§,÷øp#§øxq ·ùh+È÷ýh,€ãøhB&d·a{°q ºr‚ÓurQ¨ƒɃRHƒŽé‘ ’#ù‘%)’&™ƒ$I.Kè„LxIMÈ’ÌÇ’3 “5ù’/Y(*™’(IE$A&i_b ¹Ø ³d@!d§Á ¶a9´1tµ}e8‡d‡lH‡gxwTÙ†VÙÿ·"•ë–U‰v“Óì!MÒhi©–kÉ–mÙm´ÈMmPH:ÓèÃaÔ¦3†F) è( -pSt‰¡H˜·Ç‰… {»‡˜,CŸÄTIDÀç–•i™—‰™™Ù'p™÷ÁPtÓHP0׆”¦…ÿ€~_Èj) Îò±1ŒÎ²¹ŒÉhŒ³y›´™›Äö^d™9 ÐBé–šIœÅiœ²CRôwœùvˆ!yês%¸ˆXvI? 6(J@¾'ßPÙ€®G‚"h‚(žå‰,9žáIžë©ží)ÓC^õ˜YV‘i“‚:ùƒ¹“'ÉŸûéŸù霊Ÿ9 ú)ÿ <Ù39‰ J áèXýy ýÉ™úA”¤É¢Yš¾³”ÕD–8´ñj`¨•W¹•S‡d˜†ÞG¢+:¢-z¢×1Lí¡šÄ!Âi‡x¹œ9ª£;Ê£Ä7¡ùA”v¹E8Ú&ÿð w,v0Ãá—©Uƒ¹˜QŠD‡)¥U*{ñ阀*($™wC”= ¦aʇ±‹É'“eJ¦Ð7‹Íij¡9š8š”›ÐU·–šìa:Ý"ŒÏ¨›zº›ºa›| ¨¸¨¾ñ^¸Ö”»a´1œbÊ¨ŠŠÝØñ6ˆ“ênk(*É(Ð%¤þ±Vƒ’± }©-ž’ZºOj©ª 9—«JÿÒB+«°êª$g«¯Êª¹êXꀦJŸ&ÇH  ¡ÆúŸÈ¡ÉÊ ÍZ¬ÎJ¬ÑZ’4y“Mç’R×:„Új„Êê­Îú£õQ¡F‰—û”—à‡ ¸†vÝB§_Y•&Ê•/Ê•¶¯%z¯,J¯òú]ÎQ§ç‘^©öM8ê¨k°õ‡y£§°œ—°œ§y ëy—'z +z– c'G©wr;”F Ѭ9ÙZe¥'‹²) Šj( ² ‘~Ãe*ð{_z°7‹³Õ–¦hjgº³?+¦®ûD—š †mÁ-vK­K`ªCé5¨}*¨W»§XkÿµYË~`KN«€yKƱ¨9k¶g‹oJ©NÖcj«¶û˪R‚e;7˜!iÂT7äUÉ4Dàbžî¸éI¸ƒk¸ìY¸ˆ{¸¹·ëA( ú¬“+­Ç ­’K¬fS¹ÌJ¹˜ë¹–[¬ÛÚ’£K­¾e06i­¤‹ºÛú¹œ{€C[X˜H·DWMPGÛAMËe²æ8¦Ã»ú:¯Á+¯Ã›¯.*¼Å»¯_ÉjÇô”ÌKWe‹¶ÖÈx" @½xè¶k+©Ù›pK›aáAI6ã #’ ¶8˜°NŠT* ¿ñ+¿=„+)³‘¾\Æg6{½õ§s·PsGý+ÿ@ ´>˳ìB˦ÔÇH" a’ö ¶ðj‘MKIwʵ[ ÂU+ÂZ;Âá7w\£Mðb‰ÜÕÐKÀ¦h\?dãÃÃǽ“º½k›½ÞK˜tÔɩ߰ ¿àˆsÐUŸÒ¤²J,\z«Y«»*ÅQLÅOܪºZÅXlżê«Ëë)Áj‘ÃÚºr „oeÃßÚ¹ ­Œ–VަÆcŒÆ›‹6ŽÑáÓ[Nƒ„ù“Æ?³ºÓ{"^[©“š¤º²åÒt†,º\w¹o º°+ãꎈ„rз旣êª:º2`ɯÈ{¼¡LÊøZÊÀK¼§ÌcÉ”3zÿ–7JÚ5†³l<¶|Ã@$á±ÇÔA*uKf7 ?MbÌ“T?«Ìüó°û2de± & ;Í>¬HmÊBº$vf–“¥ó+ÎãLÎ=ÔÅó™¢8”™Š e$§•³Bqh•ËR¡–\p(_B$±nWàÃi[sǽõ1;‹À˜6nõ% mJ¥ä| ì“sCP¡ùÂ*µSPLÒa¨ðÁ%Â$LÒ!]Ò#M¨›ü›è¡¨°\zoCa’àV0%iÇ%¤‹Ø¨ø´>]Ï¡ c¹óüÂdÐ;Ïvÿcf!òÈßvB¶%•Zˆ¸ +•Xg±ß Q,N@,ž’ÄLª{ŠKׂ[׉k×y×{½¸éé+ç ¬N ¹rL påAå+úFZ¦#²Àg “Í6HÙΩ •t™Íhã{LÆœƒêŸçchCZY 10F‚w%ÚŽB„°55J³By4×zºÕz‰!4As’H’ÁȬëÈ®‹’Ü’¬Ö*à,¸†8’ó¯ lÊÕÊ¢œÊÖm¼Ù}Ý¥<–ÿª-P£¶Ãåö_a;•Hwé;öBÁÅÞ#ßóMßô}=ÞVßù­ßûͨÔa*Ì]ÿJñ’mAZÃloðs%m %9¦7`"sÒ;Ü>µ½@pÁå‘@wR7Qج½õ~Ö[™B¥TÚáýU^å—$[Î1.ãòÛBòiªß¹¿Á0–Z>1Eÿ°ØLýHù–¿ø‘Ÿø)ðøŒùOùžŸùœ/ø›ú¤_ù¡¯ù¢ÿ÷¨ßúoúžO÷†|¿øÁrm Þöi¿ö*yòâã¥ê[´a¶ÓÞ'o°gü{RÔP]àÞXd!AâÔÎ ? ÅyÉÜ ¸ƒ¡Ëì°Ì'zbB'U\.?Û€? D±Ë,âõ%û’bA¡ |ÐÍ5[·  lÿøÛ´ÿ ¼¥­`A .TØáÃmm$A¤èÐbEŒm%ÉØñâGÚ8‚$²¤BI‘NšdùÉÉ1eΤYÓæMœ9uÚ”`[ÌHüÅt fnl5ú/(€”)î¤ZÕêU¬YµÖ¼eëjÁ­aÅŽ%[ë6lIJ;´ mGpdiR³7ýmÛÛ—ïß½¶Ôþ+@’?7†«õÛ˜0MÂŽßB" ’­HIolx#’[þØNŒ\zh^Ô©k¦eÍš¬¤6ÿ–êœJ³„ÍÚ3sëܧÕM\ÕZ#ßš„xVÎ’R÷ŽùM§óæÿŒßÜ}ÜúLÁÀ{N47f hŽÿ üyË×Õ¯mu›¤êìåÏWÝ@ ào½ÚÂ[“­€ºþ‰Ï¬Ÿ ð@GCPÀmJ¸Lã¶ið¥ 4°& +\Ж6J@¢‰”d<JHB9JÀ 3>[km¦Óhª‘F™üáÈHlº1G™ÐéǘˆüÇH$mŠä±’ÌJsÒÆéplÒG,e’Ä+#¯šÒJ›ª,2KÉóL kú2Í2ÕIJË6ãDsL7딓Í94O>é¼ÓO0mñJO;ma’Ð?ÍsM@ûTÔQFmtRI+t¨v2¸D/µ‘° ÔÒFõËÔ¿2%4!QKMõUÁlih¯ÿQQ¥°=)õÔÎEsµT&]#k#•´RÆ›l“>½‰SggR5Z쨵öZl³ÍIд9V[pòËuÑ\tã;wÝrÙòŠ]x÷º`Óš÷^|óÕw_~ûõW,Cáäö_‚ ÖJ2ÓFxáÒ cøaÂbUxâ¾ «^洞îŸwê˜7­6Y¦«9:”Ã*™ã±Ô%ùå”WFíd–S¶øfœsþÇÛiùZkPƒ¾9^¢ÓEC£‰Î´hv…¶ ã];ÍÒ$~ÓJÐtõ•ÑmÆú³o!Ý:Ëm2ë±F[ðû•W±i¢Ì®™FäHj¶µ°$Î>Òñ⊺×ÿšðîQ¦ˆàœnÄW¼íÄ_ÜîÆ!|íÈõ§«¨.SõoÇ;—ÜsÊ'çüsÒC=É[[UÔÕO}L7×[UöÔYõô±ë6½t#1†q›$Ê>1Ac›¯ e«|7’°ÕãPGh“ÈZ>»D’é–à÷šo)ÔþGªèÃ,J%ùML§ÓW}öÛ×­Bí-ŒÁù ¬_ÀûùÂ0þ]ì~ÿ]È}6ñøŒs‹6(ÿÈØzD2”ËÐ(%òM"A¾-Í=Ö‹È $* nÉ)QZŠ·Œ7Ÿ ÆJq¡Ð]øBÆ\£!Å&æ0ÖP‡ “!°ê£ j£ ´šNÿðäáŸ(;m8Ôz„÷½bx@sÞ•(¼!O>O„ML w"fÍÆ‹L”´zxF4¦QÂIZ™&/r½QŽn„£ È»Üéi6T _nS9O­Ð)‡ãðòø¸ Š1Jˆ„ƒr3º_qpIGqbô¦;ΉÆ+Š$ƒ=@求zBL\˜ITw˜T%YùÊPÂRt­Ü]-S)ËUÆR—³Ä¥+sd»Øsv¼XEÌcS™ÃT&-o¹KÆÝq‹Ác)÷E2j0"ÍSgbc8ÌUmšÑ àü-zR:ƒ2'9a$F1OGk¤g=íiÏ9æóhq¤£>‹ÿvFiʇov!Øè#‰$ä­+áØS¸ë(f¼ŽÜ–Ä¥„ZM>LBD‚·$Ô‚>mH‹R”ƒ½¼ÝS¥+eiûvøÒî&¦0¥©þúCdÕF§9%Ü‚~çÓhíÔ‹<à‹¬“¡¡¶T©Ke*ÁüÙÏr!í©SÕÐMƒõL^BÓ—Yåj.»ºU¯†¬cµ¥3ÍÚ˲¢«bM«VÛúÕ·²u­dk\ézV·ÖU¯x…k]ÚTÀV°ƒ%la KØ¿V±‹elcûXÈR+±‘¥le-{YÌfv°ÒÜ«Zù*×ÏÞÕ³£ÍkhízÚΖ–´}5mjY»ZÐÂV´ª¥íkk[ÿÄ-«,®Å­m7YÍW¸Ã%®p©JU©B5€d.R{ÜâFWºÓ¥.Skz݆Án¦Û¥)¡[]ð†W¼ã]ßq•[Çžš×¼V•ogëÛÞÆ÷½òEmkí+Ûúâ×½ù½í|ýË_øþw¿¾o™j·Ì3SÁ Æa‚œÌCøÁœ"°~}õ]òfXÃæp¸–+¿Ó/ÄöÛ߈ñgâ¿4WÄè…!†;übÇXÆyÁnS¬]çØ¦ÏÅéŒ}üc y'ê=or‰üTöΈ¾î/€—\à;YÀPÆmRke*OÙÂúÅó.#«-7™ÉQŽšnõòYÚIXͶZóTNÓæÕÕÿÊUi®U–¥ÜV YÏ{¾Ïv*(*òÙÃç]/?\dKЋfôÍ µ-e5Z[;d³Ì]LÓл=–t§©ÜCjº˜à†Ó†&Œ‰‰€<ä0¶0q¤îÿïÙ>&ù'C+—%±™D‘—“¹7º;{ÉBR ¦X¿€©Œ™ ª’8¡þèt£ ¤PC¨“@ËCÀ]$=^ÔE`lÀ^ô¼_Æ`œÀa̼_´Cœø²d|Æc,FdŒF_¬Fb´FeÄÆ^”” ´ B€ÚpE¢hН³¡°#ŒÍБu<;›˜$ŒŒ„bBYÙ‹„ZŒ™Ú4E+E~DޏÁ:­;0ü––*Iîø < ®Ë Ý‹HÚ›ÈÜ£HÜ»H‰¬HÛ³¼Õ£‰‰ÀHÑ3=ÐËHÔÉÌÉÒ«=“Ü=öD™(ŠøPÇk ç;Žä3 ‰>ªÿ1‘P¼Äsù¸ 'ª±¾Ž*›ÛèI;ªncA*dJôc?§T¿*¬%m˜t¿˜¿ØðP:%‰X” ¼Å@sÔ¥LË,늭‰º©T˦ô€pû??éqôH®›:ûZ·À(±SGÒÐŒZx¹#¤7/²·…hÂ[8&T‰½X|¤3¨\Ê+ìGRÜBA±—x>Á<¥;!Í!©Ë<Ï„ I¨Ÿ.f„ ‡ë°î8ÍŠC‹éñ¤où¾vëÈ­ð8$?û)sL£³’ƒŸS±©šµp¾zlDæq¾©ÄÿñÍô¹LÌÌžˆ6HÅÁ‘ ÿïXº˜ ¿ôìD³ /d i“¶×„¬G£ŠúŒ1〜¿‹ø”¶©Ð¸ðà8Ô»Áp ÏÍ¿¨ŒJCÌ;¾I %¨G&$)©GÊ€7»?¼ëN͉ø0: AϪ ñ :œÐṵ̀Jì©¥(Õ8´9š>¥É¡l i#Ql ¸|Ê·¬6©ŒÊÊRúR¶ <\tgóQ!ýQ^áŒÐÀAÁ²¸$R'u+/¡²yÛRd*B9̈t”3¿Ü± e2îüÐ çÓ¢FˆZ*@SS›ä5äòI¨r—ü¡£¥S?ýÓËY /‹Ó?M Ã.´Ë45ë®>-TGÿÅLí|T±Q>ÅSJµÄ¤¼*+mRNíÑ3ÝTOÒ*U& Õ+ýTREÕR›2UÌ~[¦KÓ.}U"U&MSIÍU]}T“ëUæÄŸå¤¹™ÖäÖbÕGÙUe]Vf¥EÕ±D=ÔLCÖñkVk½V?½TµT;µµâ,P ×TµUU-Wr=×SE×N×U×t}W'ãRW7c’ÕyÕÖaWóÃUlíWÝ3mÅÔô:1BËÎðËÔdýW…]X†Ý3~mXˆX‰­,¨ÑWu5Õuu׌mWŽ5WxÅXµØÙõØ’½X;{؉]Y–mYÀRY—Y™ÙF¥Y›½Yœÿ­'pÕØåY’íÙŽEYŸÚ Y¢5Y EÚŸ]Ú£E6˜ÍY¨Z©½—§Z«½Z¬ªÍZ®íZ¯½¥dÚ¢=Y£Û¤Z³[¥mÚ²]Û´e[²Û³-­ýZ»½[¼] ŒÙ[¾í[¿ý[À \Á\Â-\Ã=\ÄM\Å]\Æm\Ç}\È\É\Ê­\˽\ÌÍ\ÍÝ\Îí\Ïý\Ð ]Ñ]Ò-]Ó=]ÔM]Õ]]Öm]×}]Ø]Ù]Ú­]Û½]ÜÍ]ÝÝ]Þí]ßý]à ^á^â-^ã=^äM^å]^æm^ç}^è^é^ê­^ë½^ìÍ^íÝ^îí^ïýÞÑ €zm_Ä%_1_ÃE_ÖP_Âe_p_Áu_ø \ùMÜú-ßñµßüÅß`™_À½ßÃàôÝß&àî_ýE`þ=ßfàn ÿý[.Ü n_¦à ¶`.à >`æàö`nà~àõ%áþÛ€!ù ,ÙÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cË!»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñã\k5Œ„¼¹ó碓ܽºõëØ³kßΪ­îàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)dUD iä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jê©d–€êª’Qä—%¬Æÿ*무Öj+CMܪ뮼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç ›t2×lóÍ8ç¬óÎ&Àó®4Gõ]_HËϵôÒL‹HBÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒo•FãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîzFŒ¼¾¤Ï²×:í¶ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯½zOoï}½Ðý÷äƒîjù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:Úñ'㻣÷ÈGáw}Ô Jð4¨*u)š$À$ È#"á¢4éI¬Ò mÚ)ÙòH@:Ò’À¥,7²ÈY:¥J3Hja RúÒ,¶_¾Ó†ñ² ¦<&Z"q \³•„”fZІH¸9¡î’„Mj³,mpà óøÍhž³,´“„’€`¦òi1d$$Áÿœt–Ÿk '9I M€BÅœM¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0µ BcjÄ^Òô¦8uÏ=sÊÓžúô§ ûP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªTÅèƒT#W-HV-²Õtuª` «XÇJÖ²šõ¬hM«Z×ÊÖZi£­p«\çJ׺Úõ®xÍ«^÷*R¡òõ¯€µ uKØÂö°ˆM¬b+À¯2ö±¬dÏbLú v²˜Í¬f7ËÙÎzö³  ­h Û”v´¨Mí]  Úµ* µ°­lgKÛÚÿ†Ô¦¶Í­@r¥ÛÞúö·À ®p‡{ÅðwŒ§¥‹ 6«‚ãJÔ–Î .t{šÜèf´ºÖÍ®v;ë€íz÷»à ¯xÇKÞ­½¶¼èM¯zñÙÝõº—¦Rpb{ßKßúNt¾öͯ~/uY0á7"Ë I€ÓçØFw¿VßA2à¯ÅÁ§„pXœà [øÂΰ– ¬á{øÃ ±ˆGLâ›øY¼=±ŠWÌâ»ø„¸}±Œg, +ÖÆŒã0wÌã Ow1¬í±‘è×!¹‡ßH’lÂþ2ù¢¬|²”§Lå*[ùÊXβ–·Ìå.{ùË`ÃLæ2ÏèfÞïL‰Xäθ¡B!?ÆÛNÝäØ6ëM:N–ˆç4wÍysžæ7ÚõÙÏsÌsž=7AïÉÑˆŽ´ÿ-éJ[úÒ˜¶×ž°i¬!ù ,‚TÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í› àÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©¥Z%lÙ"^†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ%ƒ0Ï<½EBmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûFôân IãIäF$ˆ·QÑ Q|$8n Ñ¥AÁC}ßmHbË𑀄ÐÿÎ÷ñÞƒOõm¸a~Þ` 0~$ÁoOQ ’HIÅÿM‚$IXölq‹ýùOzm@Bü =ã)o|€K‚-”ð>ç½/‚¶hƒ¨Á6\0‚íÓ`$Ô÷·¤ $_ïºöÁºð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢Þ‡HÄ"‘Qþ8¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘ I"$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.‹¦‚]úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›ÙlÁœ!ù ,VÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*-Jb©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8çL!5¥óÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×n;®>ŽDàI´‰$¸!Pîz7Õ†»ûD‘@¼ßIØr‹-I$TÞI$|$”„ðx—°{$àDB ‘TwS¶”@Âó½·ÑFÏ˽{òiOþùw_/P÷)-l! I$gwžAHàòáoé#Höø×·æ5/xê\o5rðjü GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†÷òÇáþÃúð‡@ ¢ɇHÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ $íx(ÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™Ð„WÞ!ù ,žÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×l3d ܬ3R!óÎ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褯øO‡ÿsºáÿ ±úàüÛ >¸ìð:౻붎»ïÀó><ñµ ïûò¹ïÎ÷ñ¾ P|߸#1»êØ÷Ý;¶X‰äîwëÿD"IîþðwìÿôO ¸‰ðIÉì·¬þþ­÷>x‘Pø'¾Òð€ŒPW‚ïE¢mŸ$‚Ç7$¸Áù+4ø7@ð‚ \ H`?I ¡ '¤àÝ(ò@$p m0áÞ"èAÃÍoÉ]’ C½-"ABllñ¼µ! @H #D@}xkà rAŽPo$° ÚpÂÚÂ*ä›$j!½$DpŠv+ Av(€$ˆEL çx1(ÒñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈFbF!ù ,ûƒÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖË- ö΀øæëoVý+ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg=_ ýþKB]çË5×þ‚M „MïØ]ïÙ`ów½c“P7½f}¶ÞkÛÿíw m«í®ÞpãËw¼u'nw¼y§ 7¿ó*Î/àò>.÷ÞýÓ¹”ÎvCÿh.î¾ø’N8èIˆ^n♀Ä?IÀÀ}ûBô¤¾¹½·ãþúîôö>»îõúƒûñ¯Ç¾Þìu B€Â €;ñçÝ-PÊ (üñ®«^ÞàŸÝ†(¸ï¹‡¾Mèâýmøä,X‚D·#q‹ô‘H"@íÝ,½Þþ£ˆX ¸ÿüãu’pJð‚0ï;Öìз ˆ}h $ ñP¤I8ÛåN@ÛžÜ ×Ù‚7KЇ}l½+‡yQÐõM«Â¤6[iªBSDïÈ57°Í\_D«™YгVÁªÓ®]§Ýr}b TB#EÒöŸ™úñ€ ¤ 9ŸòˆL¤"CÇE:’Œ†|¤$'IÉJR¤‘\‰$R4ùZò“8!(GÙÕÝ¥¤LeL8‰9Ä<{‰(" Wz•@%,UùA„e­ †bKŒ¥‹a:Ä€‘RPµX²X³üþRB1^òð È®¼³”˜r J&jr’]¶ä›Ö´^΂¢Ìm æ|šäðL.„ž%hƒ—PÆÿ’óÄ…ÀDEèYþ +´gDš J „œAIš`Ë•`³ ñÌ.BP„jQu¨z:K9ƒ84$¨¢'ÌtQœ'ut$ rQ¬TÒ“­ŒKj¤-Ú?út*â,KP+R©G £?µYMrÑŸ04vÛhH˜Ð‘¦ÒK¡ñÒH!b¨'eA,ôÈW™Ôi);ªèAÔ:’£Êd«+9*CMb‰Q5Õ-Øß2 "ղꋧI»IÀRÌ…|ÕFcu‰—”gSD“%b«QFÄ–QV D˜Ïˆ9ë×Îzö³;™c3‘Ñ"„O3Š˜Ý^´°’5“)© (Až…ÕÓÿ.$tòÛHOIÂYö·À ®fº“[’iUþë²>:Î&$°G‹®Œ:RÜ×’µ¶ÂÍ®v·›Ô.¯$(tnE^MÓ®p!æ}®r©æ4õT¼Ü¯|çKßú¢»öͯ~÷Ëßþú÷¿°€LàÛÐÀN°‚m†ß;øÁް„'Lá [øÂÎpš,«á{øÃ ±ˆGLâ›øÄ(N±ŠWÌâ»´=ëTtªûâÛX]ðÍ#‡oÌc•$ Ç—i0-ÿÃTÉìø;GrÆ6!¸DJ޲]’,å*[Y(T>J–éBã¸8¯ËWÆŠcòNÀÀµ2sóÒ;”Â>dÿËa²šçLg[éÌi'Yæ!æ¸Î€ôxàŒ–1ëktV­èF Ñ…«u1f“i²9†v´¦9riàtzÓ õ•!L»„Ô•µªWÍêA¢zu„ž3kãܵÕ~P}ò1oQH?­ÅCÒç¡Î_|‘ÖLâ§DSz•D~б0ÒbÓð„Y*FbÄífªj¤ÝVn‡Ðôéóþ³„H˜¦ ÿåÀ–uvy!‚'O¢íù`ö#Ô¨FLê “ZäÞ¸Þ“kmk‘58Ëg­È­u›B½.Ü"wâ7HÊÀŒ”)W Àå©»¾:%ØxŸ¢9\I<0¸ÿüÛKb½’n:%áª< ŸÂ“jÞ—|I7e:_  Ì9FœfêéâÉD"…I_Gâó‡¨NåÒ^îz•FKÍêEÏH–Ç\ô6š’~$H­² ¨æ.DL2þ´sÄí6É8ÛŸRf™˜!ˆR´RMNX†f¨0x†çQ„j؆nø†p‡r8‡tX‡vøAix‡z¸‡¤Ä†|ø‡€ˆ‚8ˆ„Xˆ†xˆˆØy˜ˆŒØˆŽÿøˆ‰’8‰”X‰–x‰˜˜‰š¸‰œØ‰žø‰ ŠÆh‹(ЦxŠ=TЍ¸Š¬˜Êã‡$1+yam­Ø°X‹j¨Š%ñú‡‹idƒLq‹¾ÈKÂ8Œ”d ÆxEÌ¢Šö¢‹ÉˆÎøŒ¦ÒøÅXªfp`ˆñu‚Ü(Iݳ[ñj§òæxŽÃñM«‚aˆŽðBh!z¯ñ57莤±NøƒÑÍÁ@sp%Ž<ÂŽSr©L+¸nB(]¿·-ˆÂ±~Ázfpa‘é:!wp¥v\å? á@~â'b¢|y£¸‘·¡AßD’!Lç795ÿ)‹c’KQªà’–q,Ô‚ G7©—¼aOËF˜¤„íè>oöW™$ñMÓ²#Ú¦,â“[´ˆ˜²˜EX™âçxá—žéWÅp!&A| 9St©~aø…‰ã–‰gÕ'ú–šðÑ’3‘)l%—¾iDõÑeèSÊ–ƒÑ™HƒêµxKèZbS•ÅyßÈ„uÙ…¥Åš(Ö ¢ÿÕ>Ã…Øyžè9ðh—,•)᜚ÑÇiaé)&á‰/3RŸöÙŸBŸÃA9e¸±Ÿo韣$“ê5‚›u—Aym{`ë©¥™)±¡¡ Jžð¹m1W²¡r¡  ¡•#q¡b1š¡iÐ,Ú*š9¹$jŽô¢ °5ãù.I  ¡Š>šå6¶1‚GºIc0£nàÕWšŸ-@!ú¤:Q‚#DQà¥Z¡¡‡¹¨9ùY|²¥V¡vä¤dJV M'”kú.R7:§~ÊCpZ^x_³€‚a¤š¨÷ѧ ÿ%‹‘§Š©’Úš¹FM¨“š©_‘“ÖDª©  Z˜º¡Zª­Æ¨|º¨Š«ÚYv0¦«²ê¯:«¶z«¡Øª¸º«¼Ú«¾ú«À¬Âº"Ÿ:¬Æz¬ƒ¬Êº¬ÌÚ¬Îú¬Ð­ÀQ¬m¤«Å9ƒè ÏIZ ñx*§U¦”jâJÍqWÁÆt=§®*q¦ÒŠ5:0 ñZxšïŠé7"x6"y…Ü ‘&…V²55©<±&ò3¡­á°ùêóúv"ªS¯õ*ù@62œGQR䇯ëØä®Ç$Má±I ~ Åo³'  H2 qÊÿB–œW?ÈŠ³8Á³5[±Ùt¦A;·à'Û054ã³Q$9Ê*'²"!²;²Ø´5-5®Y…;ÔTI€*^ò"XÓ@îzW c©*A/ÿ3ª"ù®U‹3½9²„º\Ëé*z§A†Cg1Ç´A´ÐF³Q}SG·I"µQ¯·À Š{K¢: ÷¸'¸Ga² ¸ƒçh@·7IIr®q+ªS³TÝ“iµ ·ž›˜«1ô¬®Â©BÁ©w®á˜HÉœ9Û»ÍÄóIƒÔª»+m¯Ø©ѹ­»¼U$¶¤Å·Z6ˆŠBÖºµŒZ1l˼ÜëADÙ½–ÿ¾Š´½^A¾â{¾pHtÈ=èÛ¾éù¶R8›îëÔ:¿_”¤ö['Õ›¿üÛ¿þû¿³·<ÀŒX¿|ÀœÀ ¼À ÜÀüÀÁ¼Š9ÁìÀæ{Á¼ÁÜÁüÁ Â5¶¿"\Â&|Â(œÂ*¼Â÷bÀ,üÂMHÂ0<Ã4\Ã6|Ã8œÃÈáÂ:¼.Ûg!Ñ¥=ì–{6O›¬EL]…Áq ¹Ä#N$€Œ2,ÅÌ»ŒZ ™ñx` ډݱprw\ü°sO’)*©íGÆ´AmùYù‚JÙ`gËÃrìpìÊÛÇ­>јK9ަR]ÿ,Ȇ!À+1¯[•¦Œ¬#"(·‹6’“ôç¢qÆj¼¿tÅ“ŒI¿!QQIŒÕ Ê£l¾tÉ ,@ò,`| …l1¦„t‘²àw­Ì.øûËŠHª„‹^Xª )¡” Êl1žÒxD,ÌÒ<Í ÊÊÔ|ÍØœÍÚ¬h¯»ÍÞL|üÍ㩇ÎËjÍâ¬b?œÎCòrlÎì<;ÏØÂYD»Îôlð|þ0øÜÁ?R¸a ‡;èìŽÔ‘œ…;2ršÏÁ‘qG,ûìîÜÉt»š àZHP¬0óÏdðw.Z¬šÒA £D³lZ+Œ¦ŒÒ‡¸ëìÈ‚ÿÚ+=©A Ótb dyQÈwfÇÉ:é±#6°]òMB=Ô3ÑLMé¶‘ÓO i\ÕR”Ò‰Õ\}a…×Õ`Öb=Öd]Öf}ÖhÖj½ÖlÝÖn] øZÑ!×A×a×× ×|}}m=×~=Øo]ØÇAÓ†õ¶ØÁØáØÙÖØ’ýؓٱԌ¡×‰=”{ý¼Ù Ú¢=Ú¤]Ú¦}Ú¨=ŸÚÙ¬ýÚi£Ù° J=Û¶}Û¸ÛdíÚUÁÛß̺ÜÂ=Ü!æÛĈí/}ÜÌÝÜÎýÜÐÍ5ÝÔ]ÝÖ}ÝØÝÚ½ÝÜÝÝÞÿýÝàÞâ=Þä]Þæ/é}ë}µ}Þðßòí’ï=ß’qÕó›Ü×=ÝÖͬ&Û'Vßo˜ÊæßÌ»ÜÐý àšaÜö]a«Mþà°Áàà«ß•sÒs(×Ná¦ÑÞ¨aás!â½1áž&^Ò'î¾$¾â.þâ0ã2îCG6~7n>ã<~e-Þ㌑â@>ä6#äD.?~äJ¾äLÞäªÄßNåuåR®;^å6œäXaäXÞå^þå`nŸøM'Zæf~æÁåh¾æl®¨ÐæsqToçw¡t®šn:çGqÓö}TN&beþ.jþ1ßp熾sÿ.W)èjØÐ'{èvþ»ébÁLnŠ?6ryméž~ŒþéLñç œ¢Nо¡~ê3áè´Éêi±ê°z>ë¶îA™~ëQëñRº¼þëP!§¤NN ìáêȾìÌÞìÎ~b“.Á.ƒþìp¤ìÖnÀ]湎Ø~â ðážíIQìáÝþÓNîaî>1îUžîî>Ì4ó¬Äé¹¾îäï3!rÊã›ÎîÁï(Qïî@1ïÒQ;AÎMâ4!ñ,Æð%QìŸðoÁnñáîß.¿ñ$oéžïÁð'#_?-ðò%ÿþ>o>ð¼.óQó ¯ó /ßòO„QâDŠ-^ĘQãFŽ=~RäH’%MžD™RåJ–-QºpQð…Kš5mÞÄ™SçNž=}zÔöSèP¢EEšTéR¦M>…UêTªU­^ÅšUëV®]½~VìX²eÍžE›6b̃lÕ¾…Wî\œþÚ¥›W¬½}ýþXð`Â… FœXñbÆ?†Y2S$ILÆœYófÎm¦ðZôhÒ¥MŸFZõjÖTÝZölÚµÿmãt{[÷nÞ½}3ä;0Áo”Á‰GžÜ*‹¹W]útêÕ­_Gj ûöÌ$p^üx­¯ÉŸGŸ^ýzöíÝ¿çiþ|úõé;pÙþ~þÿõ0@$p°Ø(‚®@d°AŒk'¤°B /̈€¹†3ˆÃŽ<Ä0DG$±DOD1EWD/°\d1Fg¤±FoÄ1GÛûÏ 3úQBþ„ܱH#D2ÉÝ~T²I'Ÿ„2J)×kcJ+¯Ä²(I²ä²K/¿3L1Ç$³L3ÏD3M5×d³M7ß„3N9礳N;ïÄ3O=÷ä³O?ÿ4PA%´PCE4ÿQEe´QG…4RIG jRK/Å4SM7mHN?EÆ»@ÝÊÅJ[:UTRW=4V©sc¤[2ÓŽ=æ  ²¡jý)ÖWSóÔ"ýx ¹ÿ.+V€[wb2'^]MUжÈSiWkö·l Úv®S¡Õ­J„Jˆ( prµ&]Z—$s ÚöÚso[¶µYÁüvÞ»µZŠž…È_‚žˆ` Ža„kJV_9”× ˆ¾ká´¤˜bϾ©Øt!å· w Yc“»—0_Oîl["@\ƒˆ$2ÈƬä’W“P»³˜eÆ~–x ŒFºhm":¡m›Fèi«Ž‚ê“2^)_‡°Z1»ÚMÎj9¹@ì®ÏF;í¤p®ö!¶53û¸¸Õ¦»n»ïÆ;o½÷æ»o¿ÿ:Ä6…Ä $IÉJ’¬r^Uš$ERÙÊZöK”f¡œHÈ÷J[ú²5U¢e’„ùËbV¨— 1¦2ç„LÄ4S#ÏœJ4ÿBL‚`nšËÌæÇp¹njó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ¦›¨Ã š“jJô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–º´}}©LÓ™Úô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©P½Ó¢ê‹RõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«ZÙH«®u/$([ß:—´u®t…K\÷š×ÍØ$°k[ûÚ™½ÊU®„ÝŒ`r×ÄfưuìeÚjWÅ-Ö–xdËWÉNf± ¬g%³Ù¸ À”ÚÜä‰Úez A­ˆL‹ØÎÿŽV2yi`)«LLÚˆ³®…Ñ}+ÚÛbF¶Æ½Œ7ò6Ô4¹cùÇ?²ÝÊL·¹Õ¥Ì?€ìf÷1yÙ.’ÐÜå~w.âåîtÏ«˜†¤w¼Þe/bÞ«^êÊ×0ô…o“î[˜üÖ—¿„Ù®_éJÀƒÙ.nAàHøv ªE°\¶®>jC`¡-´± û¥Ã¨…K[øÄùs=ü–møC¶Øð6lÁ]³x/vñŒ¬ßxÂè°õ¦ãƒøøÇiyñ‰cÌá#¹/B>ñ“§Lå*[ù¢Ü»2]l¡å.{ùË`³˜ÇLæ2›¹M\Nò™×Ìf%9¹ÿÍp޳œç<¥4§ÅÎãÉ,Ë©â=û¹?xþsV²¬’@ úЈN´¢­ØçE;úÑŽ´¤'MéJ[úҘδ¦7ÍéN{Go&H¨/2j”º"§>uxTýéV»úհ޵¬gMëZÛúָε®w½OVóú×À¶°‡MìbûØV>2²—í”F3»$Î~¶´§Míj[ûÚØ~Q´³­Csоþ¶¸ÇMîr[KÙæN÷ã­îv»›Ï}·¼çMïzÛûÞøÎ·¾÷]Eòû߸ÀNð‚<,.¨ôƒÎð“T²á¸Ä'Nñ n»â'”y3^Ö&á×ZuAn’Ó¶ÿ19¾ãMl‘sœ&,’²Ñ=“™¿ÌãQùËó—[ç=qÐõퟛ¤èF+É—.žÏéú¿`îèÜêqº¼¡ŽªÓZê:û¼½îi±«›ë7{UÔžtö²½1ho»VßnºËý$RèØÅKw²ûîkê;àg-ø¬ÛÝ"…ÿßßÍDöŒ~ð?ß?¦š$'Ìäñˆ—çâÃÓxÓt~Ó˜|GöqÔÄ·„äP7ýHBÿÕõó)A}VúîrŠÀ¾¬þöè-ôÖ ÖÆ÷ï²¹¬Z€và_ûöcAþ7/úæo„ù§q=W¤ïaÓ+_Â…û÷ÃâÄø^„¾®Œ®ÏýòSšú‹¼øÞ?d}ó»ÿÑè'‹ÖßOÿúÛ¬ä_)øïſtóÿÿX'ñçnèCâ€I²8=ë·€&s?‘{¹Çè€xf xxPßpè!(#ØØDs(k”·‚.ø‚0ƒ28ƒ4Xƒ6xƒ8˜ƒ:¸ƒ<ˆV؃@X&'„DX„Fx„H˜„J¸„LØ„Nh©ö|ñƒ…d!ù ,tñTÿH° Áƒ*LHb¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sªd¥Ë—0cÊœI³¦Í›8sêÜi‘ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ9 rÖiçÕщçž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯ûì°Äk챫J‚ì²ÌÆvI³‚> í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0ÙPÌ4×lóÍ8ç¬óÎ<÷ìóÏ7ê ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×]¢°ám÷Þ"ÎÿÌ÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×ž“Þ¶ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L È@ý€` Jà·€¨à'ÈAÒé| Ð ÈA RЀt !1¨A–ð…áWø@šð…'à@ÃŽ€8œ AÿZˆ¿üCG4¢‘¸DQþHb›( ÄŠù[¢·øÄr1‰Iô"ÇØD%¤‹ûã©X@0¢±pŒ£çm ätÌ£÷ÈÇøm£€ ¤ AƒÅâqˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNz’‡ü¤(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2c÷G43Í,ä·aÅ–à™ü# Àmذ&6èm‚“›Ò 7·Npг€æl'7áÏv¶¤œNjƒ©$ñãvú ¡ÌŸ- ,vn3œFÜÿÇÏmn zjƒ"1РtwÊú@ €üà %g3m¡¬ÀåLçþþHMØÂÚ¸…- OmPs…è5á¹So:Ÿ,çKmªRÿ=“¥@e`Q—ÉÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­pk–T ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬biÇÅ:ö±¬d'KÙÊZö²˜Í¬f7ËY­4i!ù ,²çžÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§Ïž$~ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð:AAÅkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷ÝxcíOÞ|÷ í÷߀.8GÚ!ù ,²úÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öj¶æ‚¸æêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-¶~ÛüéÏŸe”vžÚ€„gëy‹ QöÚv¶ Åç}gÙ{×­özþ¶ßtÎøÞv €wœ…/Þ÷ÿTyL€/Îøà=^~9L…#!xAˆçøOåžÃ¤¸Ý¢Ûr‹-¶hó¸éœ.SÛok# %üs‹ì¥ãhûé©·”¶-’P’ø3»é¨_»Km».»-uoÓ¶Äw_¼JÚoã<î8dôÝ»ä÷è§oûJwûó{ìÏçûþ®ó/SòÉëQòl!IìÏ€°C`âö÷: €r"àþè?Æi~ÃóÞk¿ôÕéþêì4B ÎïNÞ;¡œ>‡¾?}Î&!ù ,´æTÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«nY$¬+i´ëî¼B Dï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀N—?‚nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.úè¤CúÏ-ånó¹ÛP‚­ƒ»6ðzìÞúÓ:¶ÃNx·³×Îûí°/üðÅs<ïÌ¿­îÇ7ï»¶Ë3/}ë¸[»»í½{»| Û”€$ÚHb êÙBÿú-¶€„ÚŸ­üæ €¶`Ÿüµ­Û¢Í-åë]öø'ÿõÏuôž§ÀÙÅ.~¿ÓÔê~‚»Ùù}œšàP¿NiPƒÕêF(®þƒ„ß"Ü Qè-žp Ô– _ÃlÍp…¨¡µLè²Ð†9ô!œs(à ‘ :œÖ …˜Di©Ðˆÿèá¯5Aú[Kœ"¶˜D"në…0ta ¡¨EoÙB,Ž"¨Æ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•‰l›!ù ,´æTÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\É’#–0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ë.P ï»ß Dï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷°í÷߀èOºÿnøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ¿\xðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  H@†5ÁM!ù ,²çßÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§Ïž$~ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð:AAÅkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀ӭMà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ºÎþŒ®ã?·\d‹-ÐnóÏE’°îì6” í½®{³ƒ`;îý£ûîÊúC;¾ß^úC üðÉnÓ;ò¿ßîPóÏïþú±Ç#Ÿ<ð ÿ¼óÈJ/€÷Ô[¾øão_¬ñç£ÿýò aŸ½ýÅš/úà#dÿýÚ#V÷J¼ˆˆÏîã^ïJ° JB±KÝBþÀ ~¶»…-€hÃ|Ô^ûš'ÀÁ v@lA»Öo{$ŸE;[hãüÞõœ@òåO6¬aí1æ¿ òP„<Ã7uOú$3(îyâ'þ rȽèàÝÑ9ßtÞ·ë«Ëp¥q¿ ÃâŸç.º´_Rùï–WnIæŽ^"Gâ­ƒîyè«3®‰¤—L!Cë~Ã^9ìR\"éÇëî=îNl2Ðã‰ÚB-–8|åßL|öæCʽòÈ{wç£3¾‰$ñC ¼ë@  ‡ÊÙbpt昇;Û Ä߀À:êÒ Þ AJáÿ¨`õ ;0/t2à ÿ1̉0¨[”2@®p¤`C˜C^‚y¶ûº†8Äæp‡;ìa£â&‡Æ9AˆD,"ê˜D"ªnqûÅ7v± iEQŠÛ b%…Ã"vp ƒ ã?üÃImC,?JIhƒT£#åð¶`>m¼P‡mlÔÂ? æûyˆÄ#>ªä-´H#"²’‰T¤?6¹ ˜Ži¤¤W))L @8|e?‰F+ºQo´…. BEM½±”¸Az™)Æ’— !ù ,´æTÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«nY$¬+i´ëî¼B Dï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀N—?‚nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç SýBè8Ž>Ðá>ðÏ$¼ C¸2|óÏ ¯§þO ÿH"® ÿPÀ쵃 ¸³.îð¸O!Å.Ý>@òÿÜB8·.ý6`/<ñÙ‹|÷Þ– îÿPþ>ÓgKü6âK¢û¶t‹û-¶Ð®6ÛhÓmî¶ü“¶ØÆ?°W>mÙBï#á ˜­âoý+þ‘>mùƒ‚Øà?ô·­ Ѓ´…-na>nyp „Ãß¿U>jp\úñ€ ¤ IÈBòˆL$UZÀ¦€!ù , ­—ÿH° ÁƒI b¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J`¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵkB¯`ÊK¶¬Ù³¡Øf­Û·pãÊK¥B¨EÔÝË·¯ß¿€k¶ L¸°áÈ+F©ö°¤Å#KžL¹2Ôm–3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛd‹âÞÍ»·ïßÀƒ ÷®ã ulH¼¹óçУKŸN½zhåÖ³kßν»÷ïàÃÿÔk»øóèÓ«_Ͼ½û÷ðãËŸ/´„ûôóëß ÿÿh˜+hàpá‡à‚ 6(S,F(á„>áG …f¨!JnèᇠžDDˆ$–( „ÉbâŠ,êg^A#¶(ãŒ4ÖhãܽˆãŽ<öèã@–†\Väiä‘H&©ä’eÉä“PF)å”d1×™•Tf©å–\vùÙ^†)æ˜d–É"˜f¦©æšl¶Ù^#nÆ)çœtÖ¹ švæ©'R˜íé§žü)è <)H衈j§£RN&ꨗ*>*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·e6 î¸ä–knDâ‚•.R!œëî¢îÆ+ï¼ôÖkï½øæ«ï¾ÉÁï¿âÙðÀ&­+ž#Lð 7\šÀOÙ(V;lñÅg¬ñÆ£Z1SXv,òÈ$—lòÉ([‹pÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`o¥œÂ9­ü[Èa§­¶bðKöÚW'÷Tfsô˜JÆA¼ØÛûñÿ=÷†›æ‚KšümxI~®8щ{Õxeh_TÀBuõ¸A‘/n˜6„ÚÙšÿöñTº ÛSàc]ú꬗®ç)¤\Û YJ{ë¸ç•êˆU.ïÜ®ûðÄߌæñùž’qz^üó;?ôÐWo½²À»§¼QÙ_ïý÷à‡/þø+mŸ”ù䧯¾è¯ïþû8Ÿ+òúµÿýøç¯ÿþ'Û?P[ü#YŸØð€œ’ÿ2´À:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ "Ðÿº‡" ñˆHT“ÈÄ&:ñ‰PŒ¢§HÅ*Z‘gK¼¢·Ø”,rñ‹` £Ç“’ñŒhLãÍà5*snŒ£c‰9ÚñŽ,#÷ÈG‘è±€ ¤ScÀ@òˆL¤"ÉÈF:ò‘Œ¤$'IÉJ&kêñ¢[4iÉNzò“€¹(…«üq”<`©w´•Ô*$,]÷´!á•GÑ &[Ò‚YZ¦¾ÔTÜ’`~—Æ´ '“ÉLø™M9²äÞJXÙÌjöd—&³R‘iÍnZ › Y&PFg¶ÊQ3"çò*ÆNoºS;àÌÓ)gÂÍwÚÓHé¼§>3ÿÏÅô3vˆRÝ?÷IPð‰³ M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚ”^ù¼©N³6PŸt§@%WOƒJÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXÍêz†ªÕ®-§^ «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷*5Uò•8þù«`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³ ¥ehGKÚ– ³´™A29ÔºJz{íf¸*ÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p‡KÜâ÷¸ÈM®r—ËÜæ:÷¹ÐÕŠ?$Ûè®E”I u·ËÝîz7Dÿø®xÇKÞòò»e ¯y×Ë^*q®½ð¯|çû$ô–žï‰&}U:ÝýúW@øýïSª«’[øÀN°‚£¨Ý;øÁ-10„Ÿ¢[hc~ï„bámücµD$D, müà ÞpM.ü7$0ޱŒK KX V±KnûøÇHm›â§ùÈÑF ~Œ„$´¡ ‘HBJ@'¡È:I‰Ä8HÄ– âËXÌQo–;² 3ÃøÿÊÙFd|Ú5Ÿd=†1°ì%Ǹc¶sHðãHìã!|ž3Œõ+è‹„×Í(H #b‹×¹Ñù†¾‰ù"’ˆ101ÍmÄØ¯›þÆ'îp…¸ú wØÅ/â†ó™ÔYr¨é]XâRöfð‚)8Á˜Q³¦ ¢ëKãÚ"·°µ²/!…ÈÀÚ™®-…=|cÙIö2ª«fÃLº å–ô@Ò-›?ÑÌΦö ˆ­í‚ ؈¢ý샘Æ9¾Åµe€ D wXÈ6lÝïŠÔifv‰y à yÁ@ N`'û fŽDÃ)’gì¶šàÙÿ>Ç0KüâܵxóÈ'ã|{ØÃ6È2l'Ìú ‡ñ­g.qç—¸¶E¾]»»áC6ð›Õ{ 9ä|!;7È ¬` ¤Í0ÀÓ‰>m„mè“%ª­íz/ÄíÛ†;A´ñð“!Ûè4ÚÍ.€;X]î™w× ’w»aìw7;ŒÓ.µ+}!ýõ×@”N`ºÃØîw7È-Ξ„÷úÝÕY9Df€q +Zì™?ÈÙ»éK€žåÝ ä€:ø©÷·Ñmþ œG¤µ2p²Á=*;÷aø@¬`ízÞ ’ñ âŸ;÷ºŽí&¤0lÑ åÑÍÿ.phèËü5C¿ªÞO«^¿@éÞÈ–KŽ| Ã¼¾8÷guì|ú1}ÊWaf¨&·Pm§mƒs[VnÇz8w1va± w0l®æR°lœƒ%nÛ`|ŸF€y–çVa–0‘LÓi‘gü–z¶`|¸i8€Xzˆ7pvoу"„ áfèU~Á„Qio–~¨kà×ç„h=¸ƒðÁn-q}ÆD…%ðƒ a y{†„òçfh×'ç¦f–gi­ã…ãÆ$ d ¦iš& /v‡GØ)RèD„æc%ÀF-ØI@âfidÿ¨8ƒh1~d”(djÈfQF‰zvx—8hf' n0b¶pcXЦxаA‡¨¸ŠH‰¬x¸3H¦³˜µøŠq¡Š¸¸‹¼Ø‹¾¸!¸ºø‹Ä>ÃXŒÈ˜Œ9VÊØŒÎøŒÐÒ8ÔXÖØrsÚ¸ÜØÞøàŽ´ÑK &yâxŽ7áŸäŠèØŽîøŽâ¸e±¨n*v´%Ê#0`dÇŽAŠ–ÒZd´ÉÃèÑ€„á卑¥qAŽ5aÉP‰Oí˜ õ*^xŒ/Ñ‘\ƒ ûT‘É"y’Õ8‘?Ñ$yŽ ©’/‘’2‰Y/I’4ÿ©Œ9YU ié=)/éŽC).P”±“Г9”¤æ”<•×(•F•5IViYy•ÂÅ’›¡”;d’\©[‰ey[LÙV 4þ," –*ô“=ƒ‘Ç—c™zviGyyY•¡Žw˜6Ô–]Ò—%á|éQóg y3„y2†)˜!—f5™+˜›)Bb é*0iÙšˆµ‘uÑ™M´ Ÿ©!¨é±¹³)2AÙ-¬ùŒµ»‰½‰B–I™Â Á¹¹Ilj–ñ›¤ålÞ˜ÃÉÉ©ŒÌÖ©cÓ¹‹¥iÕyÞ9_Ù™MœðäYžæé\Ýyžêé%¸žîùž»²žHHŸWTœð™Ÿó™ú©$ª©ÙX ÚŸº`¯ z  T·¹jÆŸÓ!¡ ÚBøY¡Ïvƒº¡Ú¡ú¡ ¢":¢$Z¢&z¢(š¢¹˜*Ú¢¬B¡.£2:£4Z£Õž6š£:º££ïø ¤!¤÷ÉÿÏ~úóŸ ¨@JÐKE³ uØAqRÈ„:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’²p¡&M©ÂPªÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢µ@§<êo”¦Tà4´©PªT§JÕªZõªú«&V·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­—z*\çJWem²®“á ’T¼úD˜üëeX*ØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³ -KöBË[6S{;­jWËÚÖºöµ°kjjÚ´ÿø#¶¸Í­‹n«ÛÞúö·ÀEQmÓ2ÜñÈ5¸äür— Ÿâ2w*£U‰sŸKÝêZ÷º%T.v·ËÝîz÷»à ¯xÇKÞòvsæŠ, ¢Ý…´—·MïGÚ+ߪXA¿øF}_rWìà 3ˆök“;È` >ˆÝÂ[å4ø2v¡Ý /d e#0K¾q $À>°†S¢_ÈÂHð< ‹¸Ä#¦É‡`Çø#¾±Žû2cŒèbÇqÂC^@¹&DÈt|ú2Y%F^H’’á'_ÄÉÑã ¤p‰[ÊpÁ/‚å/›*/pAA@7Ÿ¹ÿ"žA‚£ü2¿Ù óš‚AˆlçôùΑ…½’È€¾éú3¡ÝK BÈzMýVÒ+ñ2¦;âä¦ ÀÍ›&ÉCMj£”YÓ¥æˆrêÕY¬gíTÓúָε®wÝE£—×YòÃÊüj‡{#ÇvYl­ìf;ûÙЖկ£MmÀ1»ÚØÎ6û«ín{ûÛà·¸_b½q›ûÜè(ÓÍîv»ûÝðŽ·¼ç5o7¾ôÎ÷G*©ï~ûû߸ÀN`­¼«-(Œ½Ù}5Á.¼ ŸÉ^qosûÎ ?8L.ΤiÄã7¹@Dn²„¤âÿï­ÉS®k”óÄ.·X.’™Ó<¬Ÿrº`çØn½}~ó‹}ÄD¯·¹^ô¦g6éUºÓñ*õÆØ|êQ­ºU´^Ø«KgÀ+v¥V.¯ðÚKfÍŽõý²"B?ÉÛÉËtŒp½íxžØké˜Üý"s'ÚÅS÷Ò>b{ßWàó>‘Qûtñ1¼[$ÏÓãdá”§JÆ)bù°®û0d§á-f» ¿;ÅôA½»HNòTežñé¼FdûÚ·pð  ý@^¯Þg–ö=œ¹ùmû¥ø¾øÈOþ[u/ãcøÊ¾»™/ýê[ÿú:…>ö·¯|sÿûà’yïjòã÷áO¿d¯~qÜ'ëþüFäßþúS–ýOÁ¿ý÷NPú#0æÙ¡ü'?­W€äÅT¸€ Ø€ø€8Xx˜Ò„~ØLB€‚"8‚$X‚&x‚(˜‚*¸‚[áeh.¸1è%!ù ,tñTÿH° Áƒ*LHb¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sªd¥Ë—0cÊœI³¦Í›8sêÜi‘ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ9 rÖiçÕщçž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯ûì°Äk챫J‚ì²ÌÆvI³‚> í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0ÙPÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m·…>Ý­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë° $lì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(ôGÿºð…0Œ¡ gHÃÚð†8Ì¡wÈÃúpt¶0 6ÿ‚@eQÛPá#1[ÜâÛ"þX‰Ìì Ipƒ?[$AOA‚-X¸=2>ÄŒÙÆ R‚6€‰n$À(€hêû‡æ8$Ôbxd¡?l:Fè[£@ÚȇøC‘,Ù†úüQ=Ù‘ ÙF!‚„Fž¯’‹ü&²6è) ’,ß#õ$‰QžQ’€@’àJî¹av­Üˆ$XYËìmCOn0ã7¾ñ‹;\a2Àî°‹oˆR!¦ÈÅ·ÆüãÙ…%\ Ì`xÁœ`‡]<“ fT#¬>[èéŽ*üÆ%dð̓$Sw¥?ȨÿB@‘c¼L/%2P’‘¹ƒ^΄¼@ ­tåiù½_¦‘…ò”ÁÀyO…ä›ÑÆ; ½HЉ¢Ø…ÐP„L` 5ç(£Lň’…¶D=)[ØB’çL£4•%ÊT"QD ªÉ@Y 2³¥yiAìàLLºSH é^n*€ÌIا(kñU°ê3…œcnú[ÈqއTêȶ13@“¡ ‘jAœð ¹DO~ ÌMEJ‚1î’–ÿDÂ÷HKžš2ˆ&#¿¨ uÞ1°i1z‰zND ù¥‘¨Õ»°u—·€(÷HÔªöV|- EêFQÿ"A–ÿˆ¬jéÚ®Ž ©tb¤-.±ÒèÕ!/ç|ÚÄücNä¢`Xøh¾V·"(oe KQ”»”¤uE™„†øVdÛ0©Ü0DKLž ᫞ Ž:ñ ¥¤“$¤x˜ V¬_tƒjM™EØ‘»&ÕÆkÝÄ$”@¬Õli)¦=¾q¶P(KâbÚ᱄tÓMI`1ÿðH°_S€‰Õ•£“Ú× À”@m+”ÅÙ²ÖÆsU/{oa )À7!Mø þ!ú6qÄH,±6jlQj£’+Þ¥²v©Å\Ù¼ÏLð‚½Ë’È6šç poŒaâ²ôÿ¸q‡€„_|œËå"W Ë[@Y°ÏŒâ?Ü©`E‚—Å)™WKIþ˜¼`ž0ÅÈÊ’~ΪIf’é´ä&ƒ6ÍÙ¤-úÙ_/>‘¼tz.€êÖŠU"íí? ¼OwÂø—½ÝgÉ®ºd sà ™3'íì‚_8S Èh§‰âdÙ‹©4ujJkn7·/¶šQ IÂ'Ó“®•‰L„¼`ÓÊþ‡%ªŠ_ 'ÆÊX&A0oj ,ƒuŸÚ^ëâĵ¨i-d1û±5æR›ÂF ’Ü9Ï«ÃÜB®ÊÎÆDÑŸI"ÆÍhÆË5Ç’¾˜…³êÏ[Ù èÿ&H¯1¹ÆC:†Ôè\&C2 Dר<&°õ*ì‚<ÙiÔO¹·ÉšäR(7AÐ-c2 ÑD©÷®JZd#ü3¸‚@äü :Ò»~Þ)ADJ§€‚oYÅã7ˆ,9LÁ×Dô.­YãqבN$Ùߨöü"¥8Um%%óEêé‰ãS/ßrÇû¦wÅ@È.rpñ}C‘–¨ee•øBBñ™’˜b˧I=ÅÁ•žÌqä-¼Yô©s–Ö%?ý ë(‚r³4¯^éÂ^’Z·ÒèKöãÁ؆ˆâÚfîµ§ H „Ip£‘€e‚trùÜC>D.i¿ o!%ˆÄ·ÐågTIúÙ LT³Èþö»ÿýðÇ•ãOÿúÛÿþøÏÿܨÿþ¯ ûþ€8€X€x€˜€ ¸€ Ø€ø€8Xx˜¸Øø ‚"8‚$X‚&x‚(˜‚*¸‚,Ø‚¤.ƒ28ƒ4Xƒ6xƒ8˜ƒ:¸ƒ<؃>øƒ@„B8„DX„Fx„L¡`H¸„LØ„Nø„P…R8…TX…Vx…X˜…ªÑJ!ù ,x#ÿH° Áƒ*H`¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*¥Ib©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ì³M ý,ôÐDCÙTÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùŒiƒþúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷?“6·ÐÆ6¨>‚ØB9 -( [ð-€ÛøÇ6j!‰HTPÚø‡?¶!€.ðt`Ah¾M€ÿpCÀº°‘À?@èAm„ð†&H×v $¸ð‡@@ÿlñ"ñˆH\ ¢ IhC"‘„$”àhIB‘ÈE# d‰j‹DZ$HÂ2ˆ?Š8Á$À…gT£ ‘¸Æ¤Q v,Û6VØB-"„‹hƒ Ýx.æñlÛð! ‘Æ‚tq Mla ÐXH@š-‘-ŒÄ>ÂÆ"D,,Á bÄ-’ÍŽ|ÀIyÄ„H¢¡ä@ŠXDzE¢…«È7æèE…¼’…nPHŦ¶á ߨŦ0ƒÈ` {ØÄ7¾aȶ°‘¬ì%Øœ€$lò‹ø†7æ …Há3x ^ 9P³‹ûø7 ùÇV‚í×60žTå6ìÚ”ºÚІ‚Ì`àXA:V Wtà ‰¨*ÿþµ w©nÙz›v‘›ªå$J óbÆP†·Ì '‚‚èÔ yt¢_ùZt󳟺ůÛXšR©èT*:âK0Ѓ{$l «ÃŠð¡ÿ !ÿ‘„ÒF°± Õ!T»W¢QËmC°ë)mü² T«Zaú€LB 2ˆ[ …KØ‚†ÖP‰± Ã$4LmA‚´!¶xô¢b@ÉWÞ·ƒ¸}I°\ ¸SÛ¸%Ú`àˆ·²•5kZ'h¼ 4oŽiCð†ðµ+ @²ÁÈ-—[L"6÷þ½ñ¦ ÌBälÝmƒKð9Dÿ¾¡†YØá„àP1`¤}¨\;–q¹ø}±]e\ßCÚ8U·ø¥}<…ðzT£Á?P€Y !] ,Ð J¬ÚÙ½LŒ Ó8C@׎n¨²6»œÇWqËy´¢˜9õËæd™lEª3°]6»YœëùX‹ÏÚó0ÿ¸¥•íÕ5Ê÷Ø:]ñaçh×8³ ³3 ±(ÉZöÑ’na¥‰¼ ¹r‘,$¢T h«Òù€Ýbr½¸cT›Ú+|­®ØÀ+¾8U;=kš¼ÝP¶Y S0$Yˆ×z¶Ù‰Ü.# ûçR>[ J•õÁR™¶«âæ§yÔ¤nÔÿga¥§ð œѬŠõäT½ VÒ¹àX˜mOéX¨±Ä¼ë”|t=¢­9^ÈZvͶ Àæ/.ñm`lÞ,´— QŸrÇ4ˆ%œÀV^‡ë9E"P`ëY²»çOSé~¿©Ë_ø3á.A$±* ]ȸˆñܺUiÉ—kŠLÂD² ]LBNg_Ù¢PƒÿP$›1Rš{ÄeFf8ÿñ‹rÿ£l­fy©ãý&Qªž÷Ú/Y« š6€¯œd#[U¯{=l©doÎg(ÀÑî[ãL ,í(óYÆ>lÜ4õâ²5n…\bëmÍõ<þžlÑ×»Êp%hà wP‘y^b5O6¤rÇc5âõ9¸á ¾ý‘iÛeª[(߯ŽòånäBÇÕS†ô6˜ôC%€n nÐõ¥q‘”tò÷}lIWwuB¤nëÇ~HE¸HÔÏG7W% 8BÿGU%è?.ø‚0ƒ28ƒ4Xƒ6xƒ8˜ƒ:¸ƒ<؃>øƒ@„B8„DX„Fx„H˜„J¸„LØ„Nø„P…R8…TX…Vx…X˜…Z¸…\Ø…^-(÷…b8†ÈÑaX9 @9!ù ,îEÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd?FQÙh7‚ ¤íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúçŸÍþûÿü•ÐFmä_BAî—ŸD$nhC˜ì/}%ˆD àÏ$HÿXð $¨ +è<¸Á1 ë'ÂxgCÂÿÜÁd‘ˆ @ Nð‚ñÚ‰[ØÂ 4¡ÿ! ä„1"ÿL¨DÜ‘ I„$lq@T0d`C68ò†\Ì¡ 9¸;ÞïˆLÀ%¡@‡Œab á8‘*æŽm„5((þ0 ᣿è³ÑP¼û_›(BäuT G;ê.ŠP4"þ,É0fðlò›H(­XÃP~²wŒÄýðçV¤’gK#,÷7KÞQ$*Œ„yÈGvñ“g›a0?©Ã#s‚¿ÓbFÉ? ™ô‹¦4§?jZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèÄÝ?⃬SÛÀ;Ç׆[D™ŒD<·AÿÅ$$0žÞóþÒøÃ~ÛÀg µñOÆÐ{·@ÿAEÜ·øÇ6Ú°?[HT£þü>婉Üâ ‘øC)ÂД–šØ{éKB*0 :ÜF$˜Ø†Qrï@݆?@H¡º"@õÇ6þÄyn/¨)è<ÿq‹ÊSžö¢÷ÖùPØb’ “PR°Ñ *l§H Ë’DŠþXgBÝ E§¦Ó{½«^÷Ê×¾úõ¯€ ¬`KØÂö°â´…6z‹’jƒ¨±Åm!YÈJ/¬–…'PµÁÆÎÂS©%¥¬-|(ÚšŠv!™%ˆ=}§Œê´ˆ­lg‹7ÿl#¡¢}liwkÙÔ"‚³ ®p™Q ÷¸È^Uƒ{Sf±˜)Áb‘K]ã:OÁM‚-„ZÍJ§³íê@Wë*¼±mC^ RÝ!Î6 ë/u“wPÙJ!íÈ6 [$ÄW¾É5lc«U죻ÈÙÚ_…$Ø v½zÃ:µTžÇMH$œ”7¾sƒl)Œß »S ¶­x!lbàmC¶6È7¾±‹;La3Áö°‰S· ²Õˆò`Þí¼œÈŒ§ …Há8žÁ ¤ ‡ow©ÿ@ò×ÙâÞ¥8¶n½°@f¼‡GYg~ `‰_ ÷ÿű-n‰Ëû clÀ=È7lñ‚)@Ê/ò þ,'lâDZM‚yY TßÁÿÀ7ÊŒæJ›¹ÒióqµäE³·Ë¹Û0z©dIcʆò=ƒU?@ˆÜ|\ðºÁÓŸnôe O‹†y!ëT,B$!d~׷ߘšq¼l3㸠±¾Â?¬ìaì Æ+£‡ ™/w=Èz7|ÄÕFՔ܎ף#½‰'³:Õ¬†2B°l\Ù‚šÈ÷Ž nËÐ^„óätkA€¦X½O÷»8 €$ €Ò—Žøš 2ƒèâž!¤óoȘ÷Å·.§Å Hƒà¡&ÿ|gAM/Î&:ž²(ˆ“¡Œã?³zÕy5A>HYYd9¶¢¢A&[ÓËèÈ.à>‚„Ìó‰ë@SLâzé”À,³#.…oØÁ µ@Ä.‡KŒv»@±IkѲÝ2Æù;Õ r" $m˜g °ÍiË ÏöÒ†ˆO_K Ðð†² ¾ñ ;èü NЄhõ1ø–v ¦½<ܪt§fùªy1ààOŠÀ×Õ¥žuXÚÒMø þ!‡' ¤ì¢Ýhl‰}Z¬v·æžŒq/zk] `äõË{tù~ò 7ÿ^.ÿû6¬YÔ¼Õ¬^<PÐxƒÄÚ –È}ÿ@ v~ ]!ºW7ÿsÍÊ•ôþ&Héõ‹GxÖÅjÏ—-0jvŽW›0Í&/{±…´çQqpqòWà% —TFu1d^UuD«µaD•rQu|ùrQ^tífsj¦}‰Ö}±Tö&da÷@eBôöN7 •CHV×Pg –Rùâ²egJ¦lg€²5{rà!ÒæaP[¸`ÆWhb)&^"ö{ä_ ¡”zúñ ¦¦jÙ÷ Á…,ø¿`eö/èNYwñWT†Õ/ÖFjþ'– •öN‡ÌE{NÿðU3(Pa„[Xa{øJØ/–¿p ®6*‡¿° Ke‡z3¨‡•˜;ü%u qˆhæ„Âô‚V8ƒ@ì…`«˜;_FÁWj¿ð 8¶ˆÛçQjg È8].Èpà–`\Vƒ[ÊDö»` ÿ@’Õp¾†aÚ^ØÖN]·ÃŒ+¶†ÖT’EIù·t@5x•ažGŽ·#jχ_B6Zº° µ@CÜEdÖ¦vó¥… —;iwzóO­¥Q%Å_ñŠöŒ†oôxG²5z!T—PúåVð¸?æ¥kE&<ûÕ_¿øiK•[ 5`ÜH‘38ÇÓŠX§‡qZ·p£ÿVÕu‰ÁPö˜høŒüHOcɓŃOÂõD$@þ]L'TÕõaHy<À%\X©CÒµ“ù5=‚'“Xù?´È•»H=>tVR´Xº“ˆÕ–nù–p—r9—tY—vÙ7( 'y—À³—ïÆv˜ãÃLCpI>ES{¨Ú£ESõ —€—àcÖu˜×c ÞÐK¶ 8Õ*{‰=“äSà¿° §i‡ÚC‘¡Nð™JðNF™>КÔ•¤*°=ÞðV–p@žÙ{-U–ÑSŠeM ¬¹*ð ûU|Ú3cN€Û° ¡€ˆYR(Màßÿ© ·) p=óĆ-ÜÉ—°ãšQlMEIÑCˆ± 0¨^–<£¤h·Ðžáç9=”ß  ½9?—àOÙœ!!ŸÍ%€r ïÉW.¡‘‰ð‰;-p ÿŠœå£w° þ¤–ýé=ªMrð¡2ê52h?-š1j; Úð *ôs  œ‘À#†—— +!—¤—Pl¡*!žA¥Á“ž H:/`<:¤&¡€M]ú3*8Œ)XgŠúi ?ÔŤ•˜D±NŽyOq !RÀdx§FÑu;e¢n$9ó¤VEô€‘bz/*µPahJ:œ7§7Qž±ˆ˜µY^õ q@ï©©™c\%Ðÿ`:Ñ¥-° ¡Zvš0¤!¡¥Jº d ãé XžÙž¤& oŠ=eª<Éj¦i::7j/º¡%±¬ÈC­"A­åi«Às¬ a­Íj7qú­¹³^mª>K•@ß  ú>v0$ RÀ­â:¯³®ôz¯øš¯úº¯üÚ¯2mºP–€§ñ¥è#”9ê¯ [6Ïj>½Ú°³#¯ã3Ù¤­ë9ºJ;?I0 (p û>ÂZmà›±Ÿ3d‘Š:!ù ,ìcÿH° Áƒ*\Ȱ¡Ã‡#ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎÞÂóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd·€$”­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯¾Š¬ï>B 1P¥~ ö $‰n ŸD’°ÚJ€„³%!m_ùÐ[Ü¢ 9 ýÈGÐO ¬ŸkQòá A Šhƒ X – ø+_lÑÁ¦ 5$Ÿ’?”@n€aÿÃ×Áþ„„¶X!ú"¡AÚâ‰<_-ÜA$$áŠmH‚ Å×¾ò/‰ï £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ#éþQlczH0¢-&(ˆ´Ág`¢@ ‰¼mhC Üßÿøhq ü‡#ðHãQRŸÜ$(ÿÁÇm ²“ ÙÆç'RòmF<Þ+WXº’mØÆ+ò[\ÑŠôµ˜T&O¶€á#]Ù?[” a¢-JØ?RšÒ $ØßÂü±W¶¡’HÛ3gþC›'ótéÈÿ d…ÎdçB¶‘MPJ"‡ÙFðiÿ¼öð6ÄmpS -ˆ@åA&jÈû`òü! IÞ‚`L¤$>yWžó‹””('õø;Žvd—$M©JWÊÒ–ºô¥0©LgJÓšÚô{¶ÐÆ-tÊS‘$€O  ¦9½ZDÿð£$‰ r2©|â-žHUHRÕ§ "‹§mxc‡«XÅJ‚¶rª9½ªZ« ÉæÙ c«\0CWÚõ®·lž#K W ªûìâü.Š×ªy‘ˆë êQMRcå@ì*̼O•cmƒ7‚׎u‚1¬'‰ V$˜t²ˆ6øÖ$´ …%fêHÎÿÚõ nkwÙØÛ ®@,òÚtVV(•„XA{ã¢Ôw‰ +VaëÛ„(7¬’ mu{§ ±2r ßøÆ/îp…˜÷ wøÅ7¨KÊ܆U—–Em|s·°v‚ëÈzwa Há2xÀ ^0'Øa¨/^ï»ÝÞ>wþ°…XO;^ÌÀÂæµ°†/|>âµ»Òu¥0a{\å7]Iëw×{)øÅ3€±€ l‰|¯mhí]µ{XÜÆÀ7.±a OÀÈEî0^·1áÔ¦s»·sïw° 9x1ž–¯œe, `»(l@€H8ùÉ=5Ÿ˜WRNòÿ™&å#: "çu×§|,/†/l^>g˜Ï±Ã7œû  xq+E<ÙÑXr 0ç?Œ:¿ÃjR~*žì-ÒFÛt‰µ ßðÆ ²,cR›Z NøÅ’ÃJøBy¾¢É­üq ¸ZI¸¨¬éüÛb‰ÝŸ&IdÌY\·`5¨‰Ìç"7»Ù_ˆ’ïÊZ¤ÆÍþ “%{È¥¶:Øâ?º›ÉÀµ•‰5ê°™‹lÈâú²È%ä°å>ÏØÔ\È ®Tªê3¬’ÐF¿Ñ9pÓHX§lÎ6“yÎr¦S¹­l÷IÉCs \ŵ„þüg CF6UÑúPÚšRªOÿÊS>åº7¸>66]+€ƒþ#±,t9-IóVBÖ\׸®8z+›zÔ¾±y_,€à…-¤>Éè}­*W+ir IB6¡¶@û"ñÉg~û¬]ÿG @ûÜžÖ[;½n. b )8[ÃPû?@>‘£Õ%/óÉGžu”“fפLöœ †ã<nejHÊ›kr÷G¼¥Mï.gÀß@þ±ôìÛT à¿».ðÔKtà,„øÌ2óÚ’‚måìMŸऌ¡¹ Íî\‚ãÍ~Á?Z+¾?] › 4îwNY.ZÑ£Ùve•+@lÂןlÿwé'̲êÞöšÄõ¹@ÌÏð–zÆ2p·è¿<à§«¯Äa_ kФ¸ ×>ŽÔ>”cI°nèVf¶àk‹ös%'&.fVðlx'‡¶wa 7vWÜV„–NØvån%`L¬EÕ¤ @?•'vP[—Y%0]ãÂZ1'›àbZöy2zc5zfx¥MxfPV]åsáH¼[CÕQФ.ÑÅnq {`2 |r…h%fïÄG•Åc»ž‘m a†ñÂdïjp<¨[š”hĵc¼•„¶“b‡· Íæt­uhtæjíÕ>[Ä„ò…†°S_*ÿ'VǶ^›pðz'ÈW@ÖP‡‰'V’¶Ïä`ŒX;ÀÅOGu –àj'·X(0T›4†À•#6_zˆ;Ɇ] qcÛ_BW¿M]@vK¶ˆ£h;×Õu Q‡;w‡¦TAŒf¶cÈ(<|XOñGº´Sº$@|Eg†önvŒØ–Œ¹ÃZ`DÙæG¤´„œDI\­Öf6w‹¾£Ž'ˆ¨IÈôD´Æ‡¸|‹fXè¸;à—YoWŽôG/?fi6<‰kÁ(‚­tc’ШHe'Z˳ À5VkGETÄC¹GWÖæ×Ö<«%W0Vt%i9‘ëC1ÿVT5y!)p@ ´U·wf7u”H™”J¹”iA”aä“å•L9•T©6RY•Xi8W)>eØ*j˜•ÒKH`NOIC’ö>‘ðVû—T6)=C”5Xƒ-i>HPk4‰a…Â㈠0[äf ’=Å%R‘Pk°au)}[©< †Z%DXƒymèô˜ÃÓ^HàJÊ”xciX«UÏ×··OÌ”ðEC›XXª$ m©<ŒÕ^$À™'èfŸ)b®šIÜ´O”ãMˆFJ%”šrÉšôšÌã‚m·™¤Ô™…v›öBÏ´Ez™<ÀéJ’€šŽUœ¤Ô­©IƤÿ99•…M´‰TÑ.àJ¨›Âtœ˜‰Ùö–‰sÂiZÿ )@·° Ïxi®|m€œ8±y‹óVEÀL›9dûd— Mð ºIJðIWC±‚s‚Wt»°O N ûI2à°žß)  ÏUh'˜_‚ÃQδ¡í…ÿð q6ÑÁ£-ð «%X¡PxE R àRPŸ–t„½†h»à ¡¡RÀCµ¤Kµ´¢9¡¤ˆC¡Áù N€ß° ááHU¡Ÿµ£KZô ºàûÙ.@¥f]úLGhOÚKÉ<:jzT榊Çœhÿ§©CqI@§ a¢a¥Á§ ©^º;bÚK!S ) ›ð)¥AA©1ŠZWD§‡J…ª*Pª4ʵ¥±:ƒŠ8”) ¨¡£ñª Q-p –ĨZs>4s;„˜‡­ª Q«ê¨­ãL]º —€%  sÉjªPº¬›zÄj93z€s §`ú* ’°Ÿ¨§©Úê¦9¦å]j=j¬1«'ª.p¨êIwƒ¶¡Šö•¯cNVôã –ª*ø*Ñz9®ô¯*ሮéêá…Jð wЫ¿©I:±†j»º®¹ Šxÿ Ràí¢‘“]ù¯.°« þu – ª—  8b>[˜AÄ:®±ïªJšM ìé: Ù± °+á9!Û` ùTNɱ¼¤©¡úM€±ÝÙ–ù95^ßPj.6jª²1´¦^z{Nø‰RŠËGùC¸›#M§P1K&úª º¹ Cyå”Iµ 4$ ;:SvŽûªJ&:{‡Ä© ¤´ ( dz¥ž3µxzšR€A` 5–ñ´Z¶ð M*µ**¶†ºº1a¬Nð –Pºð R ¦L*°ãJ-þ•$ÿ0¯¡½›¶ÿÀ¼B1¢§£»Û»Bá¾ :•å±Q'ªªäkùk°û›9Üë®9¿ !°ñš»ËÛ¿/ÀJ¡»ë¾`ùÀ‡“ˆîó\ >—æ÷”j ü>ÜÁ¼Á ¼>~H#¬>ÁÇÁ‹>,P'œ>É[°c$ÀbTÁÜ:ã6T|ôªjŠÃØc›®)°ÎË•ã&—¡ªEì=åèKCìÁGìLüVO¼Ääccº˜Äë“$0ªV¼=+gÄä“9,;²ð—¬dFÚt·Õ@/F’@Quù ŒÂ4¤´‚ËÂÿ0 (p 0ê>óV–À»p¹å¥ãƒLFŽëÀbÜ\h”Ç~ÌDÒ(Šü=y¸Bº„h<>l CJ•’çÓ^¨9Æâ³…i|;ô©F™ Ê7çZ•m§îµ6% ^Ø‘º s M€?<»ÊÄ\ÌÆ|ÌÈl)Îu ¾ÌÄÔucß`ƒç3‰vpv·ÜÓÈtuº9›§” Ëj¡3ì>G¹çӋлð zj¿¡¾ä£“»¤ ñÉ¿!ù ,íaÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêLI`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh×ÕSÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè§Ïqê·Ï”II”@B H?úIØbKüIÂùp¿6HÂ,@h¾û!Á ‘DþÒ†óå/%hƒ÷'€$DÂ| LÂDâó%Aà A ’O~.,ˆÝPÁñÀ…*ÈýhÁ‚$! ¡øÿö‡B!ž0‚m ÉWA$ØO¶@áÇ·DH‚~mð_&˜>$¸0 4Tû ¢@÷™ñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ä©üÁÆ’5<¤"©:C2ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉÌiÃÚØ†6n1ÊOä€þCeŸ' (Zq ­È6üñmH"‚À,·!€[øŠþ³…/ƒ™ÿÝyÖ¸Å?¶A8ó™Ðà6DÌjZó®t¡ÉMh Êü‡8ÇINqBïIàæý€ &‹ú+6ÊIOsÂÄ‘›“7ûÇÿËÓ(„f)qÒ’œËKç3ÛÐOÖS mˆfC JOäù£Ï,‚6 òP‚l ÏDÂD)ZNáíc J(“¶´¤p)A"Ò†â¦+Áçãt*……ÁéMBSg“ 8žž TŽ"”!¶x&A ’ÔÞmã™,%È7¾ñ‹;\a2˜îð‹o´œuæFƒúÔÜÉt -cAva Há3Èë ¤à;ìBâüÆ8û¸–­öì]TÕêO|ãaÍkX'›W°ö%çUy Z$³<•Mh?2Ôo¥´†1ëä€×ÌÀµ°}í ^ €Iÿ ­ÎL‚!CÛVÝm},e‡ Öâäõ¬å3ç‰ØÄæ®¨1È&X+Û¼ÆÖµyÈ^·‘Üt®Ô¹ïlDIJQŽ´©iz .…bs _•lq#;߂ذÿÔ'0N§zö64„8Uôä&ˆ>R‚÷ŽvZ¿mèV_ ƒëÊöºqÂ/êégö—ª½¥ @Iâ €¡¬ YÝ µÙb¦3ÝcKL¾ˆž¾aÈ` ^à0Û¼´Jb”i³ÿT<›Ü/!ãiA¿Y|V$Ȫ>-BbKK@$ºZ »–Â.àj£ "Uʰvf$®ñË÷^³6†¬âMÿQA[ðø,!/eM=oKÐ ô@,!…· ß Á?äà„Lo:˜•væ¥Ý Ìs³6ÿ°ÅHÝLÓH€·~¦>, ¢»ï,ëÅé²kÃüe׿)øÅ® €2Ã9•Ú°4± üðw»†»Ü-Pÿ¡ÏYƒWÚ<,´ÿ¼-C.Ö…Žÿ„lee0ɾÀ ßp& Æí„G Yœ™¬BÕŒäƒúæ˜ÿ i Áû¿)ßV~¥±u g.qÂ`–-^ž[… ÄeÝmS:O$X7Jìÿˆx@+f»§V”àau©ÄÿݯÆÔê°3] ßùÚÜÐ7¹-AXÀŽó·_¯xeÝÄZ7„"µu)êÁ=…q¶\ºó‚ìA Ö­¬ÁcM(|ø%çbKíõÁ÷ÆôGˆä½¥ßÂÿ㔕ìË9Ÿ÷ZîÜä ¬ÁKÈ$îT=×o bÖ+L¡µ³•Õ÷)ÎŒÿ²\;R}o;žÝ ·Â¡¿Íù"¡œžgÿZ™ bÔ×n±$°©c°‰;Ì` ›ß¯-@úk`s÷ö†„üð/}¡î.¥\Dwÿ°U·` ráEú¤@Çtdz?ùx~g~¶sc†‚µU¥€ñƒe¼dO±Fá$}H¶ST‹çTµoå¥Oéçj†¤_ðÓ[Uå;inöVË„i¢ÔAƒÏ$@àUƒ¿SdÎh‚çY=¨KkkPÿõ_ÿ|¾e}ûÅiÓ×|ñfÚROX‚ÉE…¼c…Ù¶zôDH¡tƒGwV¥<(˜[¦Yn÷L©ÖXÉ5jÉÓ…Ý´om@CnP?±_G†s=ÛÔMÝ„R]†&ˆ<°úF†Ý¤@ƒÈˆÚãK·ä’piu‡Ô‰žø‰ Š¢8ФXЦxЍ˜Šª¸ŠÅŠ®øŠ°‹…$‹¼cg´H:bx‹º¸‹¼Ø‹¾ø‹"¢-PáÀxŒÈ˜ŒÊ¸ŒÌØŒÎØMðŒÒ8÷ekÔf˳ jdŒ~´zÙãhä¡i¤v¤jÔ¸ŽìØŽîøŽðò8ôXöxø˜ú¸üØþø9Yy™ é(U´w“‹‘ùBŒY‘y‘™‘¹‘Ù‘ù‘åÃEHˆæ’&y’(™’*9-¹’.ù’0™ @<!ù ,íeÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§Pq’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—=ëDf§­öÚ,OÅöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯¾¢¬ï>Eí¿P$I¼?U$ä߆-IÀû% "q‹H” î#AèþM%p[úÚ„H¸A H ú @ID° HhƒúÚpÁ„ˆð|n8¡AJÐÊO}$@‚%(ÿÑ}7$Á=h¾ÿ À)ÿJ°À!ª~” Ý—„$´¡‘°… è¶–O€¶ð`_˜AIÔχ/Ã(€ø‘ñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽvô÷ÈÇÓé1#ÛÈ?)€@N„¢ÔÏ ˆüGÿxˆÈF"ÁÑC¤-$ “¼Aé74уü‡6Ü€„4²yƒ$¤-Ú Ä$ÄR!‰Ü_$I%š“ÐÛ-KiKG¶2·€?øgHT.³´Ø+u³ /"’‚·ÔF-_ùÉ]þC”¼Ü P)€$Óy¥@ÀÎ$póÛ!AlQvÚS@´';E9ÿ=mÜB„þä6à©S Ûh¤6wÉÈ„šˆÒ‹ä?.8HIX‚"Lf$§)€HÖB}žDÀCm Ä-H$·Ò òœ}´LcJÓšÚô¦8Í©NwÊÓžúô§@ *m¡@Šˆ¶Hj»ÇCÈb U¥E-úÃmÔŸJED©g[ÀÓ€ú4H·‘Ьva]¼Ééíã ·HBXuèÄ‹v2­®Œj2©'‰°&ÁûðÇHéŰ"“”Ö“«=Û ×½D˜ú4ç`¡çz²¤“]H<íI„ÆFϲpC$ßJHƒ– ‘°ç%3‹¼?*’,bK[?ÿ$µìôäl™ç†{²Ö!ß8©=‹HæmÞ¢m«¾±‹;La3Â6±‰o|ã·m°§6~K¼m(¶#ý†6æ …è>`/˜¤ ‡oìc²¤ý.w‡g íFÒº{˜  «Þ‚¨×¿iq iO¶X8¶åAÛÑ…$˜[–mƒD¿a‰ôž÷Âyœp‰ë*·ÁÙ€-?\¼ã^ö¾ùÝï~Ò_´X –ððAjÏŽ’xx¸ñ?¾±ÈÀÂ3˜@B4ìÃW±Éqpæ»UÚ2¸ &å–bQ‰ÈoÌa¿Ð•C® QÁ¤¯Ðí? œH~ñ–u¤A:F¸Pÿœ@4•i-·/’›Â…gp^ƒhØ M¦=çÛ›D²“± äZIZNƒdˆl*Úç]„”ZÚ`'x#yýzZˉq—Bvzv8ðT`v¿ ~Jò†<á?&-¦Yœ´–6ÛÉR|š7È/ÈÒb"["©ø<©$Ù©T6ù7ƒ€0ÍHØ"t‘·t6«Ù`²ØÚnÝ€U[d™¿–Â7ìàCWr¸„-n‘T¨†Xå~¶oê‹ÌŒ$» ÔaHS;M¤–¼ÿŽß“•õTöVÎ,M*û\|ãvس@œ` Y(¢«dg$®ññáqõÿ»åç²h‚d“àb®ÐÛ™BKÜì$·Rݽâ‚4ሖÃÜo¥ò³÷ÖFÉø›¾þ;Åí«[Ð| @ld„˜plíŒÍ¢¹epÞ [ 0~^èJAÞbˆ6îMr|ê{7ÿ(5û'b &ê½´ô<™.²æŽ´â´ê+b‰îa Xö ŠÌNüCíž-<ìå+–—c^¸nšØI¾ËS®Å¨´³ÙèŽêð¤ˆf g^­[Z¢yÞó°…-ƒ´³3lŸÁ.vDpt '>¯èFGç>ràR æ>ÿ°I ‚ê¸=iPe‹ÜƒHt|·€“ø‘ã“H’õ ôt’&>$’Ûx‘kÕeÊ…L ÿyÙ8‰´Zy’OŽŠ?‘“k%f¤‹Ù”¿E{Ë“[h@½$Y†H[ø‘6·\G9²ÅJ‘´”ù‹‘„Š9‰Bäh'9‘ôD½ä“N—;y<ˆ–2É”rÙ”T\Pé;öDÖµ ”ƒIm¹i%YNÙŒ@I,D”,q q@NjùA‘“rI–3Y–ˆT’‹)X{9—ÀS˜oy•šä‘NÙ˜¤¹;ˆÄI‘d—ÿ –N šq9šåÔfɃHMdš*9PY¹Qª)cÅš’4bÊÛIð•JÙ™¤ô™ãôœÏ™A²µ†$Öš aF £œ¾ù’—Ù’qÿiœÜ¸MµÇ›Í¹]ñ —€&c‘4šMi|)—О3PM´…nY—’e*0ƒ¶$ŸÿÀBW¹|…dÅB»` ŸÃuéIîÙ`—°w  —° — šÊø‹½Ùy±tž‘“ V™ž#¡ô^»ÐB¤N  2*£Å Š2æa½¹W³Ù;¯i˜`™‡± ߀¢e ¼)fA¤ô‘R@:,™ÿ𢡢jéR bN  NÙ£©ù¤2vv˜ƒX&X=ú NP€D F1 Ð*g$` _Š„¡§dvNu:J9ó©c½ÙHFi£Q£ ÑWÿÙ£(é;vˆß0‘à¡p9Œ г)Z:€¡Ô¥ ×ÕIN‰AP&%©‚»€’À¦£óRŽZeº°a ‘M £ W«E• Ç’’ Ðw¥¡¨œ³©M)J/ª¡–¢–z*[ŠUY÷™2$«ñg3¨ù ·zʪrÀ¢i@þp]ßÉVµyR`©§Ã˜MЬ#!¯1¢&Q¬„­%à¥Ì«cj:ffKÛ`d»` ÐøºMÐ^UÀêõ*Ðå4  +¥cÖ˜vP™+ K#+òÚ/° 3Ú¡›`‚é:à:N°±ÿQ®%Ѱ‡*£Á³³³ŠHk²Q²áú™©² O½901£ Q§R«´{ œŠµÿ`èS°áúwP6’B«£Ä·n]ûš¶”°’` Çf´Ü#[Cû>^;òì\K·jû4›>%*·–·Év{³çKxûB•4P}‹>¿x‡Ö%¸‡{_‘p£ú©>F©1¶â“¹j ´æ“¹à­˜{_rº“+X“º–î³£š;¸Uöºë#º~[Pµ°µs`¹[ºüÃKj©–rj>SQI©¢L;¹õvœ‹Bh”w!µË»>Ǻ.¤¸%@›;»éMpë=’¸Äz·ôdª—kÚÛ®;»ãû —˺i«H·À­ïÃ’®ô Rk‘Íhíû>}‰ºå§åS½gÄ™~(?×կ؉=¡g@Þ° Óë·‡Yƒ­kwP?ì>c4 [D>±¤à‹¸[)>9¡ì>Qä~%t>é+AŠ'>þà©;·€Úy·–à6²«>Û° *@»³æ#À¡´Á{¸›ŸñÀàs ’ vÀ^ï#añ¬³û HP¯ÈJV‹>˜9½ûûB‡<!ù ,ïfÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØdJQÙh?‚ ¤íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì§uöDíÇ/¿F$” @HÌ/PH‰úKB( [È I„þg I´!ñ«ÄDJP 7$¡H°úΉ$ ‚œˆò¾òu! Ì_ú$‘„„œ}-Ô_AˆD‚}14H,¸¾H؃! ÿؾüµAÌß ÇG€4q"$°EGx?êCB‰Ø†ø5±GlC ê',¶­}mˆa çG ÊPO\ãøÆ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IH‡üã þ(¤"ùºh‘9¤émDò‡´¤ón!Æü=ò TˆKÃH@… ü‡*‰Åæm£ mÐÆ6d)€[ ”‘Dµá$XR—Û¨¤$é†6à‘̳… Ý þÇøÇ/ òÊ6¬2 ”nhÀ0S›š\ž.“pC$P€ÿðÇ?˜ÈØP•ÛH @ÂX‚PÚ¢ Û°E+—÷ÿLØbëÄgUyH|D…éÄ&<° h¾RÿÐg8“JÜB•7²ÃH’žù#¨*mAG€H©p™RÚ¬©òJÅ‹¾2‡“܆E¥¹Ã.f´˜”é$ ªÏv2/ŸÌ¼…@¤)ÔIºA“· b‹oî4šmèDyÕH’­p«\‹ÄÒ¹Úõ®xÍ«^÷Ê×¾ú\·¥`×z>YJ¨bDŠLñiÕ¨>L©d'Ë?:2|‚-Ád’R…jUªÛÛ$ëΦ3 k€N±÷V¸¥X$6*R‘ÿ² Ûä^T*|Öö ««|™=Íb±;U¥!¯¡Âá^ÏÆÕ(A%²N‚ì£zI!úV¤µdH¦÷9¨”»‘ˆUÓ+õ$£ÐÛ°hMðRW ðm¬óF+€(w ßøÆ/îp…È@V¸Ã/¾ñ_„¨0 öm©JÏ*o`–x^0…HÁ vØEk-¼U†ž­«Ç“än{›N‚ÜáÀ ‘ÁþAb÷jT HˆðqlÈ€r…-ä•ÛÕïp@éO}~ò¿·5éoIj3‘Æüï«­,^Ò—Ý–pB`üU¾› –â£Ý€ÅH°ûÎÑ2„õùY‘޶µàÿ”$ÉýÚk OVCé« YxYÍ1þR5Ìa)Zb œ¹Fo]œu@þÞê*ØZSþÒÔ)Ðócõá´„Rñ}J| ¶È3¨9¾ÀçYì¹1é ù­m‚¶åÙVù°[îM˜_ëÆ¹5î ‡ ,ZÙ«–Á?ö9\Aã÷6æJ‰¾ïßo´;T®>ÅÜ`¨æýT¸±pS#›Í é:A¤à)l¢Á13…«.›gîZ³`T.$MÐvŠ\’öS%¹ ikf«•’Du¼ ¢áÁïZ .xu4ïMdÖ§=é«Üætà{Ž»!§þÄý-•I‚C_K…–x«ÿâoÑÄŽ>ÿqŸvpnõíð”­$9~Rp D+Ž"ûEöO[x[‡.`|qFËçV»Öqo•~ÁághEM÷FK1Kû‡,¥&Ÿ$· ñ¦eh“&eÍׯch,1ä{`aWÐe‘„EùaÛ&gó”Rþu‚·Óy U· Ã÷ƒgQøu ±`kiÓ†ƒ¸£AÄed›p«¶a‚çK ›gXoef2øVJ(;ØEíj—ðsqà‡¤Xÿ`?’PIê´UôÇP]ˆ;ð…bQ¶†w§¤m˧MXDyÒÓ\ aIÛ ùôD°|—§n¨÷<¢õ^Þÿ%gÒ4û MídL뇻3QMhUíT{2eká¦R%ІדC 0^uxoþÀI¤%ƒÚ_e”@<†S»Å[Ü…‰½#I.…['%@Ì”¨5YêF[Þ¦=þ` €XFÂÈ[÷Cm‹È=ªÔK aC´…‹•Nx' Š¥XɵméS["õWâ8ŽäXŽæxŽè˜Žê¸ŽìØŽîøŽðò8ôXöxø˜ú¸üØþøùA6y.c9= ¸\‚ ØVT.?`øF– (ð ›?à§ÓAá)PZ'q’Ÿ³F qˆ9Aé6àQµôŒ6Ñÿ1‘¨3“.Emˆ=ภ¶` Ój ÁJ>àhq­±ªŒú]µå–ت^¿Ùªªdú§aºêZÞ ;£*R¨J¸:õš‹£ê©ÚúŽ*­D­í >“ö›ûZ‘/¨üJ£s?*Rûʰµ5¯ë°È×>à(±üꟅù°Kc–àh*[>Ê›#[>Õ¸›‹Fª¦íƒy4æ²Û¬2»> ÿ©²JÊ>Nú â?å©™œ™>V¤Jº • ±ÈQ'{>«$•.>4X‡w™@ÿ°´æÓ´>iµäPI[µóÓ¦¨»?ïcEMÀ­ä£]ëÃiUYt”>ê¤x¬è^¯4ïv¤&„Hÿ°¡$p }jG|›±qZjû=1Ä`½ä}1¬ßÃ’sYÞ°–âs‘Í¢¹í³ žû¹úS›¹™©:?‰›>÷º>“¤ã›ÿà(𷱺æÓ™úJþu ¥[>"…aGz ‡ >« ‡ÍZSM µÐSŒæÌ¡9yµ½%NP¸qºÕã ª{"I«ª“×3¶`w (ºàn뺩;=Ãë<!ù ,…cÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍé 8÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.;D ,ÀìXSDy <ÿ­»@m¸!IIè,x¶H"@mØ"@ {ßNò;“@B$4ýß‘$AÂöß“àF$~ߎ=½£/ò:K7’$±=AðGâñz#¯-mT‚-´Eô6<åÝ!µ`ßÈG÷„H0ßl1¿éµw~kž@¬§3äy¯w~³…’@BIð{y¡ûJ *wÖ \øx‡A }ÜÙ@@ø72N‚¸³ÿ¢³!ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅÄý£ŠXÌ"®®èmÄÙFàÅ\QgˆÓx¶H” ;€óÔxA8~OÐ І @€ìcÚþ1F7± „ô"ó®¸G=öÏ‘ÛÐF ú‡¶\qIp-yEJ‚‘IøÇ6ð‡I4b’’g³äÿ§J3^‘xþ¸â-Hˆ„$àQ’¨e-Õ¦Jæm£•hT% UéÆä!Áè^òÄÇ00fÅ’Û Á'ÙLIðÌ’þãú‚ÝÁƒ,ã/ú6Ús€Aª6~7}Bu è»ê+xC|V•|9j”×Q5*p‡Èl[)Ãê†[.D”¨ÀUÕ¶ 8v5¦ÑçöÊ˺†•ù2ùZÉ4„•©y¨@@P¯S±+Ô™¨i›>à Ö6¬xÛ?»vdž]åÚ> bO ´Ùì ÝúµÿÀ³™Alû'×°µßp¨GDÖ²ní³¥ÉhoØÙ㢑´3È.>² ç¶k¿ufCdâuµØ= úò‚†”W çUj@[­µ¶·‘AzóJZÄb­§Ê@Œ›|c 2˜@C$1ÊJ¶V›(ù0{K)0Ä ßø‡¢à¶•k65$êø·ÿÐí¢Û‚8/ÃÌåoÕ*Ìà7áH•0C&ÊÛžr ¿7ÜïçK^û÷† .qB>Y_[MŸ ìc òâ°–à¾DBþÁ3ùje€Š 2â‡ÄS@pÁëÊ°Š¶±Úˆ ÂÝÌ ÿÉX-q¢ØäÖvÁsUˆ‡ƒkæë²–´™åÚœµ¬]…@Ø 1.«lÙë[èé·!{¾a ü|H3ò6ÏØ#£òf—@“Ư-¦kÆ,_Ù½¤åªA0Ë€@,¿áÅ5¦šlc´ðAü()Ä!¤²6iûɶW´ƒ¥,Bv‘F…òu£­en*¡:Ù){#y¼Å< Ûb‡ÓšE­@hð÷€ÿЇC%ëÕJúc¯%86"±=G¿vuËᦶ~·¬Q=¦/ ø&›b±Š<ãZR¡¦•6Üpšg  ý»Ÿ÷ "U†¾í©)­}ç¶ x"¤´n¸Üîé“wP8rð„NàOX…}³ ÁÕ»€ŒãVÑÀ7H95!ù ,µ”ÿH° Áƒ’H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ ʑѣH“*]Ê´©Ó§P£JJµªÕ«X³jÝʵk×…^ÊK¶¬Ù³h1:J;± Û·pãÊK·.L°O°Ë·¯ß¿€÷l%¸°áÈ+^ s-ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íˆFoëÞÍ»·ïßÀƒ O‹ïðãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾}ƒæ‡Yâ¾ÿÿ(à€Îd\&¨à‚ 6è WD<(á„ÖÝBá…f¨á†vèᇠ¶¶_ˆ$–hâ‰(¦8ß^*¶èâ‹0Æ(ãR,Îhã8æ¨#TýuàŽ@)äDzöc‘H&©ä’LÊwd_56)å”TVi%Q\©å–Ù¹Âå—`ô¤N²„iæ™ÛUæ™l8"bY¶)'ýÍiç(F‰çž&zÉ矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì®§g³ÐF+í´ =–µH…@í¶¹mëí·à†+î¸ä–kî¹èN$GºìbgK»ðš„í\cŠ4o¼øæ«¯hï>Õß›U¼ïÀlðÁ'ì¨ÀIõ¨ðÃG,ñÄWl½g¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7-U·÷æ„ñn;mõÕ“ukkÔX@×WM½‘$+áÕ/c\§—6Ø n"˜ .iÂöÜ%­M÷Ý5Ûí•Þ”Uÿ=’ØBñmßx?¦Maur6GáÀ1 •. ¾’ÛdIÎøå˜cgmâ-Ô­Ö >'è™—núV–#xT©“~úë°«|äì­Ž^{9ûîðꎜï¼/<­©ƒgûPÅ?uüðÌ7ïüóÐG»ôÔW¯ãòÖg¯=O–нwßo/þøä—o~Æá äÖù§É~sœ¿/ÿü×w˜>ýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ W8·äaÄ…,Œ¡ WÃÚð†8Ì¡wÈÃúð‡@Ì[ÿ‡Hĸ԰ˆHL¢—ÈDܯ‰PŒ¢Sæ†)ÎIt IHüžhÅ.zQˆ\DÎöÅ2š1"X|Hâ¸xÆ@YÈ}m¼âDØGAY¨ŽTºß?<úñ€ äÿö(ÈBN‘†L¤"ÉÈF:ò‘E£#ZyJN’˜—%3,²qP(°J?ù²õQw}‹ëH¹¬T²Ò;Q#VÙ”½Hr%-xegª¨ËE%á-ÙøÌ&{*Zs8Ã<¦2߇±n¹ò'Æ< ð–IͦÜ2a»f5·Y´d:QzЦD¦ùrºÎ(#ª‘7¹ÉÎÛh“H[§FÞÙÎzšˆœöÌg¤è™ÿ~fÄŸR¨>JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©L3ʙڔZøì‰K•§…厰·ÿÌHá0œ³f‚´™z‡CWš3e9ÏùÏÂѲEêle@Ú{6K¢ÃóæC+õÎŽŽ´¤‡uÇIϤ˖δ¦7DAsúÓ ÆÈvmQémhÃÔ•¦W}VÄÕ¡~ˆ'm][hÃÖÛøÇ-Þ%\I-צŽ5QFmëhÿ€²P‚HlÕöd-B6L {%ïÚî?l1f„,›Ù§ÎóOÄé˜ÛØÖý6 rûa7$¡NßF‚§¯M“sÿƒÃßNB¢Ï½ nƒSÙä-4½ebïm$áÛn7–§ü˜{mÈ·P -Š/¹àÿRÍ{nÙ8Iìý$,ûÌÿ±·@nq‘ŸÄÞW¶--š `Íö–IJ»ír´ÜÞ‘XvU[.,×9çËžnÏ_~nm,;û8È72õŽŸ{å Ç—>{\ã7?÷7v±‡+Ì`R˜Â6ñªÄÞ%Pö‰¹ž›ÛÛ·FØ÷áKÈa2˜À ^pv)ÈÁ}kŽzØÍqrÓ#F?·Éà{ob ™AÎ.ƒlâ¹²y¢ÔÞËÞ‡¹¿a‹)HÁ Àf0{'\B n¯ù¹3>ïÇ×ýêr?÷å#øh"÷ñº²ýìûŽ(’x¸ ^/€Äú±?»@/·“ïÌþNÿšp¾íw1ž ãׯ¢M½èƒ6ÜÜË^ýâ®oÁó9·?¶±lïè\ÚPeÌWyG· ¦ôÛÀ|îwn·pæ¶ Ô‡±'±7{/ [×}çwàx×Áàt I†wIk}ñg Ûtžd€{ap!¨Pw7zæ¶ a}Ñyg È·x%§líGët(FÈ…sN·>ExsAg~ Hzú4j’ ~ÊÖýx!xø €7{³'º` a Û¥ [s’ e°†sxu¨j.w´&(ôUs$°Uö:÷.¹ö.ˆ×„µ]»ÿƒÊ–p[çƒö'/àm·.Ðyrp{·§j¤ƒ1—pÙá€Û‚I¶rWV‚ɧ„5§‡ÿðnƒqÕ/ÄvlË×o/(.ð ð®W{› †kb lhkXçlÙA`‡3'x]ܦlâ–ˆˆ,˜`ÿÀŠ8jHy·Æ@8Mð Ìö rÀ‰ž8»¶]g„yfmÍÁ'¨ŠªÊ&àXs°xs²ønÉg‹áHk\)h Ö׋¡yqv³ŒÊ6Œ€'» †ƆÑ÷uÙaƒëwͶfÏ6-¨‡5ÇŠÚXsÐZ‚dnçtÌfnw€qv€ÿw‰ê¨l%ÀŽBHh0ù¨ˆÙánè•u•g^¹–d`—|Ng]IÖ©Èa ¨8¸{Ë–k›P›÷‹¹l —Ðv•ýèÒ˜dN‡ÜŇp…Tˆ€¶ð‚5wp‘`^`zöô|3÷“€瘎~Š—|ç~s—x·„P ü˜uæ§ §Xsnàg èUÌft:ø N‘@x„ŒñmýGK©€_§tá‘d·Ðf@©ko§€eo¼gn—`“Éy:9¨ù–Eg–7z)e õ|m`n¿° >8^¹“"ys…&zVÙ| ‘ƒØxnšÀ•9u%` qÿ·…Ñõl·lˆqt÷u¿Äœ¿`“9ÁXå§qÆöF hn_rêIeü–tº§€Ú` v`x†÷ „xsƒ‡cÅùŸ¡rËF6IÆxÿÐvm· Û¦ ·À…©© (¡"ñ|З»gj¨öq€çtrG¢]÷Ê’IVu¶‰jqjæ£×{2ªú—q%ð ÈysWeò¸'oA:rçöu]èiZ’Ú@`;¤Oº97˜Iƒ-¨æ5˜ø@ZŠ*öv é–ÞõaIp€ '‚[ ¥ææooœi¦µRpß•lËæa„…°âq \w ¦t¦·¢¨sÿÚ¨Žú¨©’úŒ:©-!§–úI6—©œÚ©I“˜žÊQ®ÙeꛪJq„ŒT©Wuª¨úª@´…ýá’°Z«¶Jyz«q–T–H¬ª«•ò«À:¬?!¬eQ˜A†e š|Ä®šϪd¹Ú¬á>̧ªO­o'‚:c.¤­HÑ=ÔjغdÝZNgZjwa–@6fÇI_3p£JÞ@PfHp®ã*¤ᤃ–õŠ) pSfد;Q°¹„ó:-p°ýM@*0ù* 0¬Ë:+d8'pQ®";š( Ó°p¦°¡÷Ú´¬¡$+é*ÿ+3[±=Dz‘±AKâäcþYIþFh3ëh[ªÔÙqò¢F9­q´9ƯA«wñ:+³Û i½g¬±&±±!áf«chûyƪ^•dY+³`á³,a·Î²^f$ë¯)á®q³e«¯®1k³ á*;,V‹·¡‘pf¸(´‡Æ–1Á¨skRËC c–›£Û‚#A}Š»i›ChY†Ë³asGbs z°‹³Ѹt7ºJ÷¹ ±ºŸ†©4¶ F¥qMš’+[°ž««Ss~ñ±Ë{¾khÂj¹×«5ûK¹ÿѺÖ¶ñ¶ñfº+ÕËizKºQgJ·¾I‘¾œõ¬6GqÏ »K›ÓVs·°¬·[- ¿2‹±kx ¸AÀ“vGžth{ ˜»cËJ¾q±а»½(áÁ ¡Ày»­,y–+¼œ¦—kòÚROR½‚kßkcàz¯û+¾b$)Ã!ÄáÂ?¡7,[”SG 91°<\DÜc@šµQ’¯Û½QÁ6ÁűY…EqÔ›²pãhÌÃDÂaÃQÅ/ÆÁÆ.[ÄR,N0ÅOæ³RËÂáÇ3¡Ç!µî Dz%!ÈÓÿS|´,ÇL&±Û;³ù¼A¿€,x¹8+µŠl°‘É”¥ÁìFŒ¯-LVëZ~|´^µw<t|¡ Xž†¬ ŸüÅ3f¹À;É&áÁ ¸>Ûȱ˒챪µËáÌ©œÈ#!¿ÎË’K¿¨Í>¡ÍÁÍ Í’šÄÉ8a3C¼M¢—ùê» \ÉÒ¬ìÎïSºaB½qÊáÍDQÍA&ʨüüÜTKJìŠ$†KÏ$±,. Ï k¦¿ÜÄ›¥\LÎ2áÐçÏõiÛH}!m)è|%¿üÏ Ñ΃¬Ò ¡Ñ¤$¼ÏÏÿAÓ!aÓhÓQQË”rÒJ² ±Äm¬#mEMGíW’€='ûšMQÒÛÎ6‘K×ËÇ€‘ÔL‘j–Ù3: Ê&Ó±¼_¢\ÖQuœ>Î,Õ?Õ&ôlÑžKÖ?a×Ö,2ý%P-p­Ã|!Ö:QÖxÝSï‚ÈbáÖ; }MAmµÛ]“}S½…­aý Ö‹}Ƶ]ñSÙ=AÚ:&Ø[Ú8¶Ö‘Ù4¡Ø¡i¦Dq‘ÍÙVaÚ1vÙZáÚ±ÝÛ‚ÁÛesâJ†ÜRõ GIvfu6·¤,|ÀmQ2ÍrÀÚ¾]–q6Á|ÝÑ·ÜÿÝ>«ÎÝ´AÞE¾æ-¡Ýz‚xÚ CsJPÃÍÝÝKÏ Û‹½ –ÐÜcM¬mýÝgÂßL¤ÛTb¸FœÞ$j›à+‡¡ ·@¶ÜÚVäÓ_NÅ-Þ>V‰M©Ët<ËѵÁâ6{â<FlÓ›¶Iã1ã¡Ú‘Ä+¸<ŽQäÔθŒ{Q˜ž¦á£±äcEqP>QÎSÎgQåvvåZ.X~¤)Ñå(lºùçå]­PÖ]ähŽ…év­û¬G~­{æ‹ÂíÛ¾ÎÁäiHžç|(×ç€Î¥´^è†~èˆ7žèоèŒÞèŽþèé’>é”^鱂疞难éœÞéžþé ê¢>ê¤^{§^¸>'!ù ,µ”ÿH° ÁƒH(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ ÊÑ!Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ+W^ÊK¶¬Ù³h3ºJ˶­Û·pãÊ ,T‡èêÝË·¯ß¿=×L¸°áÈ¿¬¸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM¢ÑÚ¸sëÞÍ»·ïßÀÑ‚8<¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿>Å…0oÛßÏ¿¿ÿÿ(à€hà&¨Y 6èàƒF(á„Vhá…f¨á†vèᇠ†(b~#–hâ‰(¦¨"Oy­èâ‹0Æ(ãPøÍhã8æ¨ãƒvíèã@)dz=iä‘H&©dom,éä“PF)¥t5Niå•:Ý‚å–BVÉå—`¢T@˜d–I¡~f¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸‚Öb®¼öêk­hŠlR»þZë˜Æ&«ì²Ì6ëì³ÐF+m­qLkítZ^«mHÂÔmR^šôí¶ä–k.fÚÜ%@¸ç¶ëî»ðÆ+ï¼¹²‹Ô¸ôæ«ï¾üöëï¿‘Ú ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lsÆ·”À»ñ|óÏ@†¯¥Å-s F[UäH‘¬¤³5 =–ÔçQô€»¦‚K›\íõHE-6Éa§¥óQ–@å3GkuöEm X6ƒ!«Ùr÷wRéBÿTöhç­o¶‚»¸´@Hƒ4\m[í¤Ý…G.yWOvxV•?äøäœwŽ0» ´7J=‚稷;:o«§îúë•n>^ëA½-í°ç®ûî¼÷î»I¸ÿ.üðOüñÈç$;ŸÆk×|òÐG/ýôÔóÛ|Õž}s™oïý÷'>ÏŸøà—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚ ÚòŠ’Ázð8Ýû GHšðB%8¡ WȺ°>!|¡ gè• Òð†8Ì¡wòñð‡@ ¢ÿ‡XñˆH, ,’ÈÄ&¶Ä‡NŒ¢#bÄ)Z‘ˆPÔÕ·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£Y•ÅëTQ.o\£çHGÅÈ¡Ž`B‚UâˆG€¹á†ãcSÚØÇKA®ÛÁW¸P@Hš€ÅvAi"-#‰I¾IlÉGgbhICv29œü¤(Õ—B†ÜF\iä(WÉUªŽ8A%+gÙ°P>årÁeAšÇKZú²;®ü¥0¥ÌaóIÅ$L2-²Ì5ó˜ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ h‰ž)ЂNŒ 6‘¥AÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’Š ¡&M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP-TÊ¡§iF5ŽB“ÊÔ¦:õ©PªT§@[RõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬0µ*Z×ê"‡”@$(A“Ø™o%¡ ’ˆD0YIìÑõ2I°…-š„„·6éL\ñZ ¿d®‰… €7ಠ‰¬c¼„=Ç •Ôlbj”I ¡h$pREk˜Ðij) $[Öÿ†²–=HJ` ÙÚÖ1nÀä@ð 7Äõ·ˆi‘-2+6ØâKEnZJ‰[÷^ú¬îv»ûݺ#7¼ç o- öÞÃlA´ôã~kƒØô¶‰³ïMè V‚õG‘³UÜb™É§I¾ño„ÛBÏF6ÎñŽ—ùáawÄM²\Š›üÍÿökÇW¾òB|ä+‘´ÌgbmÔ–Ì”¦ônYŽ„NÃü$4Ïô@"±r¼JÚçÛxñÊ+ýs’HÚ2?ˆÆ9îËêׯ3ÇkÛtýÚIØ:£iŽm”€ãáíº×£Ž©³ý9BÜ€v`«=#r;ǧìsLK:!CÞ8×ï^¹ ˜è_­Ýý.ôs\䄟Ùó« Ž¯ö!y?ˆÖîÈcþïq—tØ€‚o\aR¸Â6ñoÜô9;e=_x¶XÒßh6Çwa‹ÌàR¾¾qi×8÷÷óÞi?¨ æSwÃ'¦ Ì@ן%~‘_ØïWZüÿrôKnyw“íA÷Çý1)Ä÷¾Á œp ãÿ×öjæxß™ßýLÓÒ‚×wØ7€ÚgŒÇ£wyü÷zYvt!¦p£‡p1à{0¾ç¿Ðiøg iw?vdás$mò¦oûM ç|¸wê·q¿@}Õ7Ö—}3p`|™wmÇ£‡Žå|)$~! øÁ[ׄ~3· vð$° îWð÷{VfûpÉG“•gË!Wwqi&zwhñf (…FæGKL(swp˜›@ƒA€Øg ØËAnw!v 0dIІà'}jgLÿ§og ²` S° Høvw Ög6ˆVè®Wr‚e úF¡å£Gk;y8¬X Áo ¸f)T‡ècÖf‹ñvÕ$XÖ¥o÷ö‹Rpˆç{ Ö‡}3Љ¹'¾xo± ZmÀáh ‚u`x–.d¶…l€È…!xL&§†÷›@w ™X…¾÷~V˜ßPö5p¤˜nÔ¸q’°‚½Qy5¥”.‘b†ŽÐ8¼øZlHM¿('XÃXŒ]ƒ‡Ë(xøMð ˜bÁ8eĶ…m¿‘tcHw¹Æ†$vˆòæžEf½xpú6‰29wp‰mÿ° Rp¾·‰3À“ŸÈ‘ BÇÿŠç!Vd’jÿpfxFf$É…ñVúµÔô†’¶ sPy ø NŒ7(˜}yÈ‘g²–m]è½j·à|t÷6§eä•h&MÒ7•ÔŠÃdxM(Û°{ržˆ˜iÓql‰‹ ±q̳iZÆxÿp±f$°\q…ˆ³Ä•ÿð sà )°q–p i‘R0éÒqÀ–‹'—ˆ]Èav[G~'~es ·Q•Ðu4×z— —Ûà“@é“.ð Z⚯‰‹Å×\ÇtËQ• ¾)Mÿà‚Fsº° úwzÊÿˆƒÙg ßК)iŽÿ¥ˆ— x{ 8s¹'{9)ˆ{àzY³–¯É_`f៟{4÷  ¨‰–¨·ŒÏØš%`v²© 'kQ˜—”ª…þGs£g7xƒSð ®g_Zb‚5{z¦p± º¡Šuýå| n° r r¸ °—.ÿ µðW úXge0Z ×fÿÀŽ ¡Ùz$fE†š†† €™¤–™A( XGbú…q#øš Ñbˆ7{\ =Øž²÷vó`g_¨fj‰¶up¹¦Œç|áoÊ ÷tO7‚æpnGdz*_gAÿÈ‹A§_Û°{æqyš¨¡7yq‰bÇ”þE¡n—x–Z{b¹ç¢šwWmÐc À˜ðªñ€é×”*Çr¶š ?ž)£:s‰ö¦·ê± «ñ¨A¡È†l_6¬ò³«šâ¬û­Ä:­ÔZ­Öz­RBn•Š­ÑyÜ FÌú­â:®äZ®¯³­æš®Û®êÚ®îú®ð¯ò:¯ôZ¯öz¯øš¯úº¯üÚ¯þú¯êQŽ;°ë‡T°á»° Û‰Ó°±;± +­{±‘+°±[-®èÚuì:%û±(›²í²#Ë,[3!«²2+²Wq°eÿu²1³3;6»³>+ZúÕzBû M€,¥7´ˆ5%6 NÐ k­*ÐU[µ“WëæY‚1k€4 SK¬®÷ .¶jËiKà«· š° Úà ‘«¡š…I' –@Šdë.@¶¡A¶aK¶.à*àn`„ëb©‹g_¿¶€[¶ °!ر³¸¡K–Ú±š+„+* °A¸¥»¯–»¯®Çißp v+­k¯·¶Rk¹/À±Q»äú·.0º«ëÃ+m£;œk’Ä­þu¼ ;´±kÁ+¾[ÕÛÎûUr`µŠ»¼Q¼bÿ¾v½*‘½zj‡rñ°K1…c±ˆB¾!¿Ô[>:K1»UÐk€ ›…Û{µM ¾+¿Ra¾ÓÀ?«¯w ÀWä¾±¢À–T¿ºÁi`‡Œü0 ¼#ß j›¶áÀ‰QÁ`¸ÓÛYhR ü)ì"ÌR-Œ/\[³m+ìÉ+C$˜(5Ì; //{+=ì¯1¬œE|ÀHüIÜáCœÄPÅeÄýúÄR|ÅXœVœÅ\ÜÅÃD›ñqÃ^¬O[:Æf|Æ›qÄ º »½Bx3eŒÆr<ÇtìÅK\ÇxÜuÌ%Žûb¼¹õj³=;p…l÷[‡u,ƒ,Qº°±{|F±“¼P‘œÇ˜Ìö§¿2±ÉáÉjvmA~í¹´˜qÉ™Ü@-›Êת€¬üʰ˲<Ë´\˶|˸œËº¼Ë¼Ü˾üËÀ¼2¨ÌÄ\ÌÆ|ÌÈœÌʼÌÌÜÌÎÌ,‹wÇÍAÍ_!ù ,HTÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲeË$.cÊœI³¦Í›8sêÜɳ§ÏŸ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jh]ªè¢Œ¾˜h£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØÖB¶Üvëí·à†‹™$â–kn„—œûkºê¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓïNõÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wn¹Û ”ùåœ3*uç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡G(½G‘ð„(Ô ’€„ê$$HB$Ü|Î…2) JIØB$pCÿpH Á >"L°D"¾DmpC$ 2E'¾D%@B ¬H“- à†"S“$˜° mhâO¢Fƒ q'‘„ CD¢pTÉÛ ‰æÑ$S”Z †èÇ?²±,Ü"¹$Ñò$‘H£~(à‘(á¡ñˆÉ‘H- mhd'GIÊRšò”¨L¥*W  Ä•¬Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡)*Ó!°<¦2odLŠ4Ó ËŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §±lAÎräÚØF:×y‹´Ó–?$§@äirI‘\·øÇ6üaÿ V¶³Ÿ“$ç-ÊINîsS€BÊP$Hbõ4¥< JÐuzq ͨBa’ÌTþ㣠©>‘°ÐðPˆB¬¡F“  ФqCFa²—„‘­â6JR|” fThÚ°Sô¦цLÊÉ?¾´£•\h Zj›ž3¨HBQ1)Ò‚ø£ uC3bÕ´a¡…tjW:"(”äbÈZ b ¦ºp¬d)^"‰…Jb¯ ™ëMZE8 V ·@M|£!‡µãB©ºÆ§†”¤HA¾±‹=LA3Âî°‰o}j ÚW~ã3-hgÝ Hw¥Eí?|j,5­Á,[¿öÚoès¡5dhyû€´wîÁ dà„K<6²þX¨xOøZFb£ÿøÆ¢Kàë^—º µÄ}‘ZÌ6¶µÚ}ªy? VØâÛm{©ûÞø¶·½¼uÂ/Œ:áƒô5«®-9¡Ðô `«±6ÈÅâ¦ý´¿ÿ@ï7æ #˜º>.pt§`Ôä$¿ MqPÜÿ&ùÁÙ†ÔPX¨áø£ÚPh þ± )<@ö°˜ÃŒÛ]•Á!Bß¹™Šõÿsœ$O3ÆÕ!$}±)û´+ÿãÄIøÇb`!ƒV BVpj Ôâ¦fgÜQ™H‚:Ò!SèNYû3G¤Ÿ-h9ea‹Ø2ס˜Üá Ïàw³4áÃ~ÞY ’VèCWÓOª:: [v­šÇ[Cñ†5¤š-*Ðr2[rPhŠ:¾~ÁGíðÙÈáÎö´R c‡&™Àƒ™,™¦Él^°ÇzVeSôÞ·8±`æ~ËWÿ@Â/ìðún‚¢Åv²ø|š!€\¶P³1ûéP[4Z!læa`ß3fîV mèä¸Òrÿ˜Â·—mN‚Œ›Ê'›Ý)Û¢Âêæ¸C€Mz/íÖ hâÿ€fMÿ‘eb'dâvÄ5©æç+”˹]µ¿A,4ô±ƒ?ÛuÎ3‘\RË2È Ö˜Wµfœ"I÷«´ÆcV;.´ì¿œÑJûT¼²å4i¼kRÊF"Iö´A.ŠëB ߯~^j¾ñ ö*¾”gzF‘Û$¨§o±wºO‚Ä| [u±ÿÓ’9Ö£¾4˳år·LwÇ3ô‹Û5Èæ¿?B×ö7¨MøÇ/.1ùøÎ×ñ$E} µ@€f¥e•Õ_Ã¥PE¥ R {ÑUw$ eT6PN.G\†S!e^¶D¿ð Sdöoÿ!·e¶€U(¶z%RÚ|T6^±e[8¸l®´b[$ Ö·q ¨VøS5G\Î`úgZõX˦ ×ÐOZõuƒ¥PPƒhÆD„ÕU7¦NÛ ±õÃÖ}E¸QtXÛ€YTf°D„ÿ°]§ ®´ EµT@|†ôRåw†h5xxRÚ0Pè¤NXU¬g… ¶ XmwO%_ÿ[geW§ôZádhåˆVµ ˆ”Q@7JjhYÚPa‰’(1E‘Ô4ÈPIo.…\/u à¥Q3u|ª„c¼'‹RUn»D‰/öC‘ ¿Èw¾ÔqÄ(NÆxŒÈ˜ŒÊ˜)¬¸ŒÎøŒÐÒ86óFÔx##vØ¸ÜØÞøàŽâ8ŽäXŽæxŽè˜Žê¸ŽìØŽîøŽðò8ôXöxø˜úô·þø§ÓqÚLâ5y™ ¹Ô"ÒT ‘y9šµL§5‘äÁÔ‰JÀ‘¤d¹A9’&y’(™’ÜÂc*Ù’.ù’#S’09“4Y“6y“['"“8y;¸“>ù“@”B9”DY”Fy”H™”J¹”LÙ”aÒH!ù ,ë-ÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§Pa’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙâ0ÐTh·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯~«l¯ïþû‘P I´?ò I$ïÓo¿-’@B Ög?7Db%HÂÏG&’°Ÿ@$X¾©ØB$’õ¹!!„ß@ø'B||ôsCÚ§¶P|ökA’à†ºl‹ÄɇÎÏ=Œ„ ÿÍ×Á0t_$lD¾/ ¶hpØÂõ% ð“a ·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ4i£ŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"‰g‹FÚâÙ†6¶A>GJBÛø‡$MxÀGjÒÔÞmQ YØbþ؆ €V ’˜¤6F9KFÏ‘¶åâJtðØû‡05‰Eô²=lƒ (^&áŽÕæ?>èÌSDš4¦+I(½øC˜IpeÚ@IÓ ÒÔ†œÙÍaj%€&C¤ IW&¡œÌ“¦?JàÿÊBDšmpe1ó9Ì"´‚ÙGBç9L[Ø3yç”æ;%áTT çÀE"Ìo:´•Ü<=û©iF•ò4ž4‘ÐÊHóßøÄ®0ÌÀ wøÅ7²ÒV‘xÒ܇5P*Ìoüc–€f0ƒÌàRp(‰O‚Œ´•¡ÌMU²Õz}s˜á@†ù‹; „©™Sm*ƒ;üc§×¦?úÊÓdÔ#Í0%êÊL óRÈ ¢V§:õSH*GÝéʼϤ>-ê%"ƒ°µ¦f]¬0Y ú.£Òä'laÔ]ÈA 3È`Q+§2õ3 $\‚MŸÿ¢æÚÀ­n ²XZµ Ûx$mr kv•]•f_…y……¤V5®¾‘\sÊÕ•§‘D+ÒÊrTYµh8R‚¼ò“ƒŽ…W:[Y‚·~cµ 1lSgà„_hö$h%$MƒÛ\†÷’œßVµë†H‚~ç 'E×)‰»ªw˜Ú}å['›Ê D /¸¬2WpbÕ4î€6 `–€‚'M)ÛkBPµ³ç ƒÑ•ÕK^ДÛE+ÛàKœ6!‡@Yåû+¤‘’8%]c^ÐHó,§0Nªr·Äæ±-þáPmœS»3n×#©7b–pÂsŸ‹ÚèÊàÿS~‚ &`Ó#7—ë$ñq;óUaB²ÁõÇþ À{S˜yv±ÿòj‹Õ½îu§0ÝÆ6vŠÛ #ª&éò.RtvTĒ܆5ð«¶ÚGØ—ÍcpaEbèTz™¤Pí‡Iû~®´Kó×Q”$P¨xåN³'Kè€%LÛ0€b•^§IÁEWY×NÂÄ?0GQV5LÛP ÔK¶D=Ãô Ú°@½D?àÐm`ƒö”x2øUÖÆÕÔ=Ò¤5ÄJ  7—=r\p@„qÛ“v~·HX˜…Z¸…\Ø…^ø…`†b8†dX†fx†h˜†j¸†l؆nø†p‡r8‡tX‡vx‡x˜‡z¸‡|؇~ø‡€ˆ‚8ˆ„Xˆ†xˆˆ˜ˆŠ¸ˆŒØˆŽøˆ‰’8‰”è1X‰˜˜‰š¸‰œˆ³õ8!ù ,îeÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—mvd œ­6r!öÚpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûð4œAÄ/@ Ù/P$ô_þncþH‘8$¡}$àŸÿú×9  }¼EX` $”À|(ÿ2( Á,ðßúHpÁ Àm( H¾ `",”C2€þ¥ ’ ¡@ ‡H¼P øKÿâ04¡„aýÔW‰àˆYáúPÐDK¤KL  Ó§BT‌  ÂÖPñ[aÝ—Äêˆ,|ßüÞHG„̱ŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆLäõ¶q½ D qdAü!F @’’Äž$˜IdR ÿpCJÐIHb~8å? KRï$„$„[$‡¶Ð†ÀÈ ÀÛÀ¤.ÛpÇéEâ’ÿØF)²6´áŽL‚-þqÊH¸ÁŒ„¦fYÌèQò™þøGÜ@É” Ð@'ýa‹6H¢ %%;Û° [’ÖK4IÿOfâšþæ@’‰ 6S–öt%õ(e$ ètd* b‹ð¥õòg‹ ~² À´E´¡P‚T§¬(õ>IFÚÒ¡mP¥3RÑ}þÞåÌž%)™Í[Hâš%54·qLE/¨É$RÊÔ¦:õ©PªT§JÕªZõªXÍjFTúHöÙ”ü‡-e¹MI@2™øŸ- I]"!!€è%—š=[Ü⦠mJ€Í´ro•yí ò*ÊÊ—Þ#*AàNf:¶žÀ6±‡É· £nðkB€ÓÖz½lèŠU–p¯ü‡e›ÔÉî5§ÒÛÇ1ªR–ÿ>„š‰ëJ‹ €¢^r 9µíA¨ÙAYFo•ôí@öaqv«ÎûÇl-‹ÌoìâS˜dp…=lâß`È?.èÁçAS¥­s¿á9D ‘Á ¤ ð$¼ Ä' ‹ÒþÖ!ÂÝ—j/;Ù|cÑî@f0Küb!ÎÕíj`[‘÷ëå@9¿a‹àqAfà„K@Ø’ée^(E‹L'! Æoig«ÜäI÷²²4°‡2‚€Ø ¿È¤ŒAYQÔ’†´É€-‚Tþò+ÃúÀ7ÜÛo÷ Nòe|㆓¡Â5¬>»:Oò릗%47!…Èÿ"˜’s«YÒÄô¬Ž¬!ÒIÊ’˜Æ•`.èd{¡9®Ðt1C¬¼Ý'äÆtiüQËb8HpÞ?¹ Éšó·²4®6$œ¯\Ê’±õ|Òãüb oƒ` ƒÈB`­$–¼º¦t I A37MQ¤Už8f&Û°ÄR+V²Ú(4Az<ƒ&|ƒ¸/ЮL|lÆ4ÒuÞÌ'ÿ1ØrÞb8+f©,wZÑ»ÃÙ¦…ã•Ëmö¶žŒ†± ¾Q€Ì ÖNØD¡½cÿnæ˜øÜ ¡ILN+»«µ AíìcB[Úyµ÷ú 9àràvA¾ÚL‡Û3þÿÀô@"qÏx»Ì ¥©’Õ©æÈ[_¦¾,=m1ƒ)¼xÁ*/úýï#dš³µkh\©éš¦9 P'A\% I®>üáå™YéÑMø\Ö0¶vK@ÍZ „—̭Á3CîÀB I°`\¡Ûi†Rºæ5kùµ “ÍÙqˆg°oùõ{ênž» „Ħ Ïó3°ÍmÚœ±”àÚáõ\¶¢S&H¬ Rí!ï5™h¿ä©©+š”³~  ÿ­ÂÇLùáÀ ™d¥@0^¯gо !ü/kÐá~{²­qä¼cÞÒ‚ó²éý‡%œ0úËZìÂ!ûðWY¿–Ûfù¯ÿÎù n ~Á…ß«‘KûíÏ*͗ŧô@zhü{ÕF À-‰Šż¶<ái%e¿o²¶od÷UÄ\áPë](†|se “ jr0’pm²P ªµðKá\'÷~®%i $ൠhfjxI襂æÅP‘VZŸ¤ wµÈuI¼õzÐM§ÕY ÁHFxI$ÕP¼5ZÖƒa§•'xvÛPu·L«%l”ucÔO¥ÅLÚWqµyÍC\ò#MHµJ´´X5–…¡%?‘WÁ–}QØH"õq€áCP%ð6Wä¤>ФYØ”zæ~Zuˆˆ˜ˆŠ¸ˆŒØˆŽÿøˆ‰’8‰”X‰–x‰˜˜‰š¸‰œØ‰žø‰ Š¢8ФXЦxЍ˜Šª¸Š¬ØŠ®øŠ°‹²8‹´X‹¶x‹¸˜‹º¸‹¼¸HG„¸UEÀ'=IDô>Ö ×`sžœëŸÿø>Ž4NP—ì“I95ŸïCeñÃöó–©‘îy>gœðÓqT9ÓÙ‹Ú2q4 Ú>ê Ý(>ÇèãM %:èó  j"š>l y´¡Z£6Š,»Pk ©?(àD)Ð/Š>÷X‘õ¤êC£àÃRž§H[ ™€X» $p 8Y™i¤ÜÃŽP¢M*>ß PZú=æÙ˜™É—7ê8øµ¤íã»§»ð ?Ð.p¢kº§2ó¥| 7 \ñCq¦ïƒxjZ>¤iÃ+§‰Š>9Uœ)æhšoªj昩~Zžß@¢Dê˜nŠ>žw ÷B(Z<!ù ,îdÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ³àÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØ,’@öÙÎéf6ÚlŸIQÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúìBûðkôöBÄo¿Aó“І’´‘„@õÈÚÒ—[ô/ m°…-@‚œ/€)àÿ’À P}‘˜ AHà†H ï‚ @‚þ­ ’РK€ÂH¸Áç#Aµa‹6„„%P UH>Fâ+l @ÿja –@ýHxA$´Ï´ A¿ ’àŠ‘`û([¸! `”DÛ·D” bìïÇÆ ¶ñpŒcFt#Ç:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBR{ÿÀž?²H„øc€¤@$IG>R‰|ž6À(7dÒ A( E$Дpb$#Ù†ü/‰šÜ†?lQÂ. ˆÙ†6$iCp²’’ˆ$è¼óÚÈá6h¹Ëjƒ ÇŒ¤ÙJh#“˜üÇ68¨E[y¦=¯7úÉä /BAhƒ¤•X’àfÚ4F!tk׃LNDÐPÖæK%0?ôEsmh 2H?d>ÚtQQ[E¸>$T‘PXi•ˆŠ¸ˆŒØˆŽÿøˆ‰’8‰”X‰–x‰˜H|–‰œØ‰žø‰ Š¢8ФXЦxЍ˜Šª¸Š¬ØŠ¡x®˜5°x?›Xm¬è§hº8‹B± r S ¢ÓàȨn¸Q?q MPà. ‘™ƒÑÒ¸. MÀ‹Þ‹ŽJ–° à阎*à* Ž>¡¤³ .ŒÚÈÛè*Ðw  —` —P‹,)@—Ðp “¼¸ ÏX Ðê(‘.Ðï(*à.à4‘(M ¥ƒ¿à(Pù˜ŽÜè)°,iY«çÔH:°¸ Nÿ™Ž;9î˜ë8‘O6è¡S·ôŒÑ¨Žø¨ÒØüè”ÒH*w*hfó ¦výµ9Œ§ .à験É“OùŽh‰–›ÀnÐÕ‘])uy9pv .`Ky -À’é’0ù”@•-`•b{ø:ß  * –MP–ГAÙŽj9˜ùŽ*° ò=·Ð|¹M)•Q)•Té3 ŒÂh ŸYµ‹âØ¢‹–cY–y–i‘@É›ùŽ)L°x„ñ qàRàrp—6)h)@a¢¹”/Pš‚É“ßX˜.ðŒ±Òè–ÿ aŒ ‡ß ‘܈:rÐ$¤M™"‘f¹–>)œI™\Ø“¨J¯iÿ)A™:v–ð” ¤iù¨PIí(˜.pAð’Ò(—  my u‡×0»  sÀA›¥£Js N0œé“ö9œ¾iŸv °¢*ªPMÐTÈ™=ú mйŒA\ŸS N˜Ü©¤áÙà9‘~9`˜O™£.`²)q8D‘žNj¡v¹:s@–š”öy™?”™) Dó™ŸÓ˜£Ùœêf ;×rœ¿Ù:H*•~ª§é”©Ù¤ÛøN9‚†ºh§ºÿð Óø¤²“¢/Z¦À™–¿Ù“zŠ©‰£`£h©) ’ðiAàˆ™)‘¯ƒM}ªÙɃ) ¥S9¥­Z‘V*«ð íx*Y‘üØ\i”ª3pª¦ÅÊ›azªÇš™f*rÚ¬òÙkZ™Ó8ì8ôx:š0rЖs „ú§Ð Â*$9¥R©”ÜÈ’ÕIš  Ѧ®3¦œ*­”ª©é¸]i”Ù*ø§:ª©¸9™.`–Ôhg&Z:Úïê”éøÛX~Á’!)m©IPJ$¯K;)Š‘ÇÚ¬ áA*ÉŽ&jµ³ªâJ’4¡²¨c›1¦ÿú¯ ÿQ“‘°¶ƒ¤ºžv©³á²ag¿C¬ÍÚ“.a”å:;Øh,ë”'´´#³”$`5+µ"Ñ¯æ ³ß¹:™$ßО·J¨LªŽ-±´·¶õÚ¬lÛZ;;ȶ « RiXk=?úœPy¯ì¶Išq· ˜»¶Æj¦þšoÛ;~+®}+ pŠ©è£P~ûJ*劶æ¶–‰­ê® ?MÊ¢HË>ÜØ ¦ëCœÇº¸èÓ²¢{¯f[>[Z¬*„»>ï#öÙFt±l”›ÙF°®Öš>ßÐ~›º}ë$€®ë)¸ãØ)ð‹–ã3“é Œ š»ñýó ÖK­Jk?ÝÛ°Ô«=¯)¾ÀX£®‹>—€Žê½ý¥¹çª‰•‘×»“íóz J¿È[Я›+?DkGÛ>Gõĵé£Nl*T «ì³ »`CºP¢Q ?ð ð9PÙ¿Ò˜’Bk®íCŸÔŠïë=0IÚ˜'KÀj1­ÅŽd*|>vjÁ€ºéK>ª½r4ıˆ9 ¼G7L^ËPÎ) ?ß` Ñš¯Lx—À°?¸âÓZ”Ôkr rðœ…f¿mHc;vrO)Þ‰>´¶I@•#™¸³äÓ‚n¬ÁðsTM0Ç:š‘ñƒ¬=F=!ù ,ÛaÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sê´H`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wí5ƒ ö×dÿGQÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/>ngo¾@åŸ?~ù%$‘D$I´QB÷%´!‘àŸDõT 훟Ü?ì!A¶pÃAö·¿ê%Á ¶ˆ  ‚„6Db~éƒ ð' $€mèà£BŽP H˜ßÿ¨÷?nð õB˜„ –‘hC«—?„D0ÖÀÿá—„ –Àƒò€¯Dº¡ J‰¨¾*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñŽ’„láÂñŽßòÇùþÇ>Î…Ž~ ¤ IÈBòˆL¤"ÉÈF:ò‘ “£ønm„’Õ‹ %ÿq [ÈÑ ’Ä&·aÉèÙBÿÐF €DbþÀ$Ajq¼þÃv\H+µAJæ¥2— ÁcxB aÉãã?š($A’Ù.Ë·Aäýc;€J¹kÚ¯™ äãð¶!CcÊÒ!©`+‰÷”ó›ù‡•X=þnøGÿHˆ"ÿ¤3çe6“™ h3çÙ»TT"ß@ˆ<ÑwNÝéS‰2Ìç?¾±‹=LA S¸Â6ñˆvs~Æl( I Ëolcrx ^ LA r@fAL:‡*‘›©ù§N fOw*qží¼ƒdPӃ̀¤Ý´ß@OcOT5aÿÀ§÷ÑoØbRPÈfà„K0D§êí&šÒvî¡ 3pjM-ÁÓƒ\µÝ]åèR° d‰ë_KÖ_øÓ®t\'id©VÊqÿ˜8 ÇoÌ!‚Afã*ƒ+,­£Q¨AiÔôó_œT" Ú¹‰°6äyÁ †ZWÿ¢¨¥Ù#Wd®0`·TbÜ:¦"ĸÅ]bT@³4ÚÀ«¢ OUâö^Ð¥Ðiι¬A^ðïÂv¬rÐDvb YhCª’h¬hjˆL[à×ý—-¶Dmjƒ’4UÈ œðÈ r0ëAöÛßmšfÎoá9°S*°·_mˆ ¾Q€|W eõ¡*•‰Š†Æ~âL²â}’ÁGÕÆi2ƒ&|£•H‚}¸ øæ×3Ñef¸k0í ×»,\kºa%vø»RÐB$q×wæŸÿª$"l0‡®ów˜xÇKàf–ÀÀ¶(°D)’ÖÒÜBÿ›Ám^ÿ…Vȶv!3hr3;¼ ÔÖŸölñ|ó™çÙÄøúG”HGËâÙÆÁ1,‹ÑÒØwÎÿ ð@†üczáÓ ík` ’çÚ*v C½+CIY»öT²u.è&>:ÁŠÄ^§N‹ZJtZvÿ@iøø‹KÜš °mr+¿,Q©ær­€ôµ?-á§Úx—%p®6hÕž¢Ñ®kµ?÷Çì_üb S€­xÉú3G(à#%‘IZrŸ0w×\(A®éILAs°¡mñðsºûn¢´}7Q%>ן]À.þ¹m]÷4ÚsÞÝEÎÜ8ß"Øð©A+¼vªsÕ¯ÿÖê@(ù}øSáÇ^:ͼÉW––¤£?ÈÙ̘³sãà®|bÒk£†àzÉŸëÌýÚuÛ%ñò8 ÌöÝO‡Ü¥ónùlV"Áʾäï½YŒ7(ýyí,¥xvìµ’p»ÜçN÷ºÛýîxÏ»Þ÷Î÷¾÷MÜ~¼àOøÂþðˆO¼âÏøÆ;þñgÛUÏçÈ+NÓ–_ÜŸ¿çÚÌÿÌž½èGOúÒ›þô‚lêWÏúÖ ð®Ü䢨©~$o½îw/«ðþ÷Õª½A„|¹^‹Ç/¾ò—Ïü¿ùÐXò£Oýê[ÿúØoÉô¿·}îu?ûàÿB-þò›ÿüù‰"ú±6ûõ»ÿýð¿üçOÿúÛÿþøÏ÷š ÿþû¿ùÄç ðX€8·w€ x*–A²!ù ,ëeÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§Pa’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙâ0ÐTh·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúìó@ûð#TPB±]~mHIHÀŸ$Ö—[ØH˜þðW>ûõ¯I0ÇG Á ‘Ä¢?¨M|,BèW¾÷I jû`ý¦ óEP~HÄ ÇwÁ $ %°E :˜¾þE <Ÿ-ÿ886ØÂ õÀûÔW‚HÜâˆ$Ÿþø' ¶á~m¸bχÂo‰cüÆHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌcàü± øÃ },ˆ?þñ‚²$ô"1¿ú`ˆÙëWm€‘lÃ-b‹Ú°yÿࣨH„R ü+ä-,© *¶–ü¤òYÈ$¸‘é¤$ yÈmPQ’H¡wH—¦üþþ(€t²‹–ôÇ 8Ã…YR8‡Äß6™Ì&"Ó'à6þWE ˜ÿ؆9 yI`›Ü<§6DHHwF¯ž%€'.y™ÿ„$² Z¼E ÉÈæ1pÿ '; òmÀÿ¼ä@Z8ÊL6Qzã„§Aþ±É"’¢¦”¦$Ü`‹Rêx܈IOÊÒ–ºô¥0©LgJÓšÚô¦8 $Y¹ÊU àšæÛÆ «˜Á &’ÚØ¤A”z½[´ˆªT§jËml¨Õ³Ä@´*€Nªð Sµà-ü±É'NOa*AJÀ¿¶! l›j%¯z½œó†%¥%-¥Á©‚4zß0e Ò“*’–WÅŸT ;½PŠP ƒÈ>7ÚKFõ÷L¨@LˆÐ2REÂJgùBÜ•"‡mT£˜˜¸-M)ç™g[hcˆ¶@!A&œ„U’³]@aiÛ=Ë ÃQ½å?üaƒ”º»ß°ƒb\ã$'¸±­pyELüU½¤m$ ¹CDW¸ö2 6ÜU'zX )õ|‡<|ãvH6‰¹JIÐĶõy-cáþ6S¯píc ˆHuúsÖˆ¼E¬óeÀq†úÑ3Af@ã&| ÿƒh,…K¤Ý°¶2ijëo÷r”aìô@æGpˆDÓž~—°s¬émØ"Ðñˆ­ahÙĹ,iÀ·í™ôbÜßÿŽ$Äog>2ÎþÔW»i«á¤2¤Þ߸l! /µ¤)þéh8ªbƒÿÔÖ H.†Ox×~DºÌ­n Z\SPÈ šó¨¢ÚR9AdaÀ„FÞ¢aq"ה߰å&ÂWžéÓâ‹þˆjôñMd]òwg`ïé€Îtu3yüUи¤xW·$Jb+´ßa ͯCZv—F¡¹¾Yÿ"w¥„" ëxÍ3”ÅŸ¥n!?@« „Ò¶-Ô;ÿÚ>ÛUÙ ráKxðVÉ)þëgˆnw¡ïš–/¤Õ&Z\Fb‰1×—kÓ)Õë~øËÈÿÖgoTrf¡ bXdâÒÎÿBq¨ i‰}‹9Ù8'" "úzÅþ·3÷Çg0©wYNõ š€q‚·q9W@(d@ÂvX–tv­…hômš€lsˆ§zpeÌDH"t³DpÅö Öõ ¦l[ç(( »UÍ÷ZD$G<©U[!µ º0 p_su»` <öNvNëV‚,Öb¼ô`€d}´ éDeêµvÍ„„ÿWÿ`Yšvxg|¡DWSØL°Åeè´ \Xi½•LQöhÚpUµzÒCK\ÈYú`|5H”Tm°D6€Ï“Z†i0yÌÅKÒçA×YÔsH­ÿ4ˆ‡Ç?nÐn€C'ZÙÃ_©W\aÅd‘…uJ uB ‘¶>zÅQàôC0ø†¨=©˜tìóŠ9U‹¶x‹¸˜‹º¸‹¼Ø‹¾ø‹ÀŒÂ8ŒÄXŒÆxŒÈ˜ŒÊ¸ŒÌØŒÎøŒÐÒ8ÔXEA‹éãÖø9û YÑé3YÛx:ÞUŽS ^ê£.°ŽêèMPM€DŠ7‡kó„.°Ž 1ô(»à@긻° Û`ŠÄÞ³Ž éÀÆzÆ“dq@ êè.PD 9\±jy)ºð ( I<ß  NúXNN€VÏóX-ÿ? (`b]*ñe(È\‘U`!à#’` KIrùÕ|¼Ó“Ñ.@mq •­ÃZQ‘‰ ¹à;vàP-’‘‘“NˆPI;sà‰‘'ñ }Txù؈:jél)éM P•' ;;).𕉔ñ—àÕ&¹ %)’‰>îIàN ä“®¦±ów<1Ù:ÉU˜F‘™¢óDî”C®©³I:eY˜ù’µ9É:_6«æRIšR9Ž_š iœ§Cš»y>Í©œ—XÃw>È$CgÙ/ Ú¹ÜÙÞùàžâ~9žäYžæyžè™žê¹žYís™ÉÉžò9ŸôYŸöyŸø™Ÿú¹ŸüÙŸþùŸÓÃL¬) ”˜ÚÃ\j>A$>àcĈ:8 š>–¨éžåˆú7ºp vp–`šê#N@˜*ðœæó•ëã•‚‰>†99 ãƒ¢¾!ù ,í=ÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßœN¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—}%f§\ ­öÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþû AH$Äü@B‘¸‘ €üÒW” ’°…Hà†6¸HpC˜Tp}lƒ"QbP%@B æ7Âÿ!¤é«àH6\0…™ˆÓ'‰ 0‰„ Ñw?‚° ’èaúÿ8À8Pˆ¬…ýF( H¢ Dß  ÀM,`ÞwÀîP}SLBfˆ¿2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£w· 4þãùÇ@¶áƒR‚ß?lQAhmÀý„Ex|·À" ¶‘È$TМ€?$¡+šò{}€6ðH@±­üc"8¾ml‘’ˆÄK` Èr‘[Ÿ6Ylʲ/¾TÄ d "Èf®RÎ$H·a‹iú’™ÝûÇ-úG‚6D"›é¥2ï×?u~O4gÑ)môƒ‘pç÷ÉÿÏ~úóŸ ¨@JЂô É-°ÉP÷qÒX”ÄIÉÉm”’|¥„'ÀÑŽz”„¤g÷9Eƒx#´(öÜ™@•dÔ`F(ÀŽ"Á¥Õs'6›ØBI”?­(#kÊQ7€Ózÿ@¢Zy_ÓMB!§ÇÌm¼ð‹qª6JÐQšRïòüÑ ]­Þ?.}FD–’ˆ*U=€KZ®åéòö1}\´®ùF_£ù´rT¤ÅKdY+(ÉŽ˜u­½ßQ‘·HŽ‚à¾<ˆ` 2Y‚üQu+e“*@hö»ØÃf0ƒ)\á›øÆf"ËHÿ«Æ+kM§úÇohcr˜X;Ü)HA³¥­19ºÉÔ ¶blâmEÙÛ;,D3ˆ­g‹ùÇ$pÔ®™*m3Ö]Ž6±·¶xò‚8á ù£-8êUÊ’£ýÇ‚]K$—»Ûè¨òä+@ô¶ëmH{ð …ìã\ÀE9s ÎÖÓ‰àdg¹Yaƒdò¹ù’/G“ÐÛ)D¸I°@f ƒ+X8šÞ€^5WC“…$¸E59C”ŠÂ™.À¢ËÑ6üq*FÈ ^ð‹)È@ /˜ÂsË ØÎtØ‚k[¹ €æäq5r\/YIø­3æ×#QÔ?îWÿ!ØmÂ7þ!¼ ¿ÿýò?l›æÎ€–šˆhÿaÀB0™£è/[Èž ¨+7g … œX˜ ¾QAÊ ÓrÐ…, ‚Ex~·¢}Ìsÿ‡jR¬™õe•ÿZ[Tö¢•1½>Ìf,õÊ—þ´¾R:Ëàr€¯‡mqLóN¸36³*aíK6#1Ú¥¯G gÞ¢­¶…6â*ÖI?¹ –H¦7ÍÑN³ø½I -üc›3‘¬¦wó)]¯VÖÿë?ØLZó«Â½\(}ý‘ê‚Ä™Øô¥s”]ˆú° ùsU7*?#Ûõô5˜»ÈùÞ;_Xÿd6 « 'dÝ‚íh§å`‰Q „§¯ig3S@‘긴ž¥6­Ûúï@ü_²Œ±­ï0—äØÃ2}3,^=K‰¹(EÉ¿ÚJس$&½I®è@2éû 7‰‘Ì^lz ií#_õcÓzÆ»;À¾mÁfîÑWœn$gxè6´á!^îa¿1ƒ ˜Å33Aâ^ÌRrôÙ›™/5 ²û˜Ç_óDnûcÒ2`²Œpd«dLkz³#,A"ù*÷o2·¢$â‰ùAö^×ñ2teÀÊlÂÄÄ]±„Mìè‚«¤léûÈÑ“cF¼UÈãë°¤Gü—pùÿ sÙK"®HH$(a,Àú.ïnó?,á„§G^¶*ˆÃÅkÁY¨~}¯„eX2ö¿ÐdMG~îõ N` âÖ~ÅÔKß=Þg^ß´ –ÐxS s` ¥J·à\¥JFdXç<©×Qc•H²µ ‚eLØäKÛ wt•À7Z ØQE€yÉ$Kõa ÔC]Vƒ£EeEæLÌ„HÆ”J/t[B8`ÑET·ÅlÛH54yà…Tt ŒåQåÄ?cô?%U½w=¿4TPèQa}ÚóKötv‘n}ФU¹T‡ÌfVëãT¿”P|؇~ø‡€ˆ‚8ˆ„Xˆ†xˆˆ˜ˆŠ¸ˆŒØˆŽÿøˆ‰’8‰”X‰–x‰˜˜‰š¸‰œØ‰žèrˆFv÷‰ Ó„çÃz‚µYا>4׊–À>›¥ ßà´X‹RryÆ=´ qP@Iáá- ) äƒqŒàÑ¿Š»h=ÕÈN M õ÷eèãŒásSAaŠË³ r  ë•q‹r° Ö£ *ÐÄh´(*€=M@ÐHŠÑsArØgâÓpàt…ºó ô ðeï3 rP$àI†skÄãû8É<õW’e’ á¿cbˆèS`h]u&hëã*@‹È„uF.Ð@;¹àØ:g&Ù³³ ›  »‘0Ñ(™A‰:sàJ@1¡k’\9ŒᎱ3”;ñ1•™–j¹–lÙ–nù–p—r9—tY—vù¨(ë•é#ràéÙ>ç¦Fƒ‰?|Ù>_y—ž“˜ !ù ,~bÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S7 ºµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4gGBÍ8+ÅÚÍ9÷\ÞD>-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´ÓÍÚá$”@Bm@îH‰@<û½{’Ø" %λnD"| I4ß7 Ñ'A‚$½ ÔýÞ7Û" ¬Yàn$´üáÃïm}BéóíF T¼ßëÝûý%áFz»AHÀ³H¼/oH˜Ÿî²—ÀH°oL ò"‘=ÁE¬Þà’`‹6 €©ŸóÎ÷7Öî„(L¡ WȺð…0Œ¡ gHÃÚð†8Ìá¶1®íцÿ€XmøC >â?ˆ8%ò0‰e³…ÈDïÕ¯H„@þ± ! €‡ÿðGü²x6[ÜÌF¬"ô`DqˆÚp’àÅÿÙ^Œ"(h (± %à£ÿ¿$<‘w|T£Øn¼6ðÎÂã^ ´è[²t€6ÐÀ@¢í‰¶(A{ÈEjc$Ÿ$ )3º¡”TاâD$ˆÏ K´na‹à—¿¼…6éDøQlÛàb(G9Èm˜2ˆvï€hÀ³q/}IˆÅØH.ñ›µÐ¤W‰¿XŽMZtC‹xKIœR‰¹¼e.µøNºL‘ Á§=÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡œcâ,!JQdÉ€ 3 ÜE0Šžl£ˆë¨G[–Ñ|c¤#ÓÄ-QÊÒc­”pZ¬H[JÓšÚT@"=ˆnJ±’òô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªÂl¢VͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬ÑçAÔŠÖn¹à­pýÆ/äú“*ÄœkS€ °×·6AMx`åöK4¡v¸\]оµ ß`"[Ѷ‹&”€*p_7ÛW¾ªÀ®uÛ… RP€¸À ¦Mí¤°Ú)`Õm‡%€^rÚ‚ÿ˜Öz}«Û7¶*ÖÕ øÆ.€Ú:` Ç\;J´}CJHAÚðV‡pv¶m»E @€ê*¤¶Iìî41\±1 ßÐ… €&ðU HflblÕ®à]‚€!ÉÝ+|[p‰¾)  Éåï}‡(¶$A -`H‚ k’;ìâÛȰÖf¹‹—ÀshÂGúúÓZâ¤)HÈN¡&‡Ã’ÀÀý_õÊ×sÍ. @ú{Á^mµÅ®I’ÈÄ}dÍ"ÖH„¢Ú:v»;>±Ö€Öd’8¶pBL¹¶äŒ@€ ±ƒ@@¿»xÂp‚%$±f]<íÿµAóEðÛ2v AÁ˜›v‡ÿʹ$Ç ´ œ@Ú6”¹h8>ìŽÿg˜tù­¤M£ù[³98AXvÂuòV,+ ÆAÃq„ýg ¹Ôþ}ȤeæL§Õ(µÒºœYd¿´%\вj“9B!ñmlAzý6ж^çHŸÝ·ÂÊ¡ ƒ˜-[[˜.@6í·ó}£ÅXæ±ÞŒ-ÄW³~{ã– rÚè Îáößâ8kHNÜ„“÷ÝNjìÀY–ÐŦ-€»n‹¶àÞzÝ…ÄÚxÓ÷±'Nqè@¼oßÛÅå†×ÀmpDXœž GBÆÑ¹âèkê7á&‚áf\njlñt¥j¿yc-Pf_Ž·&ÓWȃóÞ&+‰ÇÍÆ(§ÑñvÌ…¶´<—[™ß[€Ü&ýêUjúth* æOpmØ5:ηëhO»Ú×Þ°¨³[ä{;ºÜÞ³€!ù ,µ”ÿH° Áƒ’H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ ʑѣH“*]Ê´©Ó§P£JJµªÕ«X³jÝʵk×…^ÊK¶¬Ù³h1:J;± Û·pãÊK·.L°O°Ë·¯ß¿€÷l%¸°áÈ+^ s-ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íˆFoëÞÍ»·ïßÀƒ O‹ïðãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾}ƒ{q–¸Ï¿¿ÿÿ(àLù hà&¨à‚ zEDƒFhÝ6Vhá…f¨á†vèak~(âˆ$–hâ‰ò…ˆâŠ,¶èâ‹0"¥bŒ4Öhã86åÐ_3æèã@)dgÆ iä‘H&©$}EþÕä’PF)å”TÕH•Xf™,ZvéeAOî$É—d–IáOc–©¦€,æØšp¸_œtÖibvæùá›zöé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«lzx.ëì³ÐF‹ßYÍ‚´Øæ†í¶Üvëí·à†+î¸ä–;‘榋-ê¶kRµq…9¼îÖkï½ ±ûÔ~mbÕ/¾,ðÀlð£ÿ2µãÁ 7ìðÃG,ñ¯òNlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôTÚÒ{Sż-¼ôÔTO¦-­NWýsZ_5Gi¦„—¾Œe}žÙ]¸‰`.¸¤IÚp—„vÜtÃ<7WwK&õH_ÿ•7A{×ý˜6…ÍÉÙ‚—ðTºDôwJk“õxâ”Wn]†{´¶W'xœ[.úè[MnXßR=:鬷~ò“°„ºØíµ¸ë¸Û{ûr»çîûﵚîÝìD ßñÀ'¯üòÌ7ï<íÏG/ýÈOoýõ==8jõßqý÷à‡/þø{?[ä;|fúÌeÎþûðãh>€óÇoÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L!ÜŒgªð…0L cHÃÚð†8Ì¡wÈÃúÐn? ¢ÿã2Ã!ñˆHL¢qR¿%:ñ‰P,¢H§Ï!¤Y½£¢·¸HD$‹¹ÇHFŠXñ!x)bó´¾5Vq"jt£žÚ(Ç%Õ¯‰Œq_÷ÈÇ>ú±xü£ ·ÆAòˆL¤"ÉȺ’8Ô¢LIÉ[²’Ý &õ„«œq“,CŸ³¨Ç±¬”É*%*½¯À!á”MÙË#YÒ‚UvÆ ¶TTÞ’ÏL2— ‚%0‡óËaó}PÓ–*ërÉc:“)³<ØÂê'ÌgZSRÍœL1w²ÅA­oÙLH3c÷¯r^óœà‰¦‘ªùÉ´!ÕD§<ƒÎyÚ³QêdL>9²ÿÏ)õóž ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0)øê)Óš*íŸ=Ù¦MwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕª²Ž¦VͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\Ý…Ó¹–F”vUÎóÊ×¾úõ¯€ ¬`›Hö°ˆM¬bËØÆ:ö±¬d'KÙʾoaï´¬f‘Ô£Ýau³Š)A]A ˜à´Ÿ%-""ÚÖ.$»T-g@Óÿ¢ö´mD'e誅 @´`%°LÞ*fo¶``´Æ K“H9ØÁ-Ô…nt»Ò&£ìç´‰CôÞí>†l`‚¨+È!ˆhÍKÄA`iB%òÜÔÒ·/•Hô ¦ùþw2)°%R€‚üÔ¶¼†LR‰]ºÖ·VLèN‹Ó‚àÁiÌðd²k`3†sù°iõ‚_S¦Ä.~Œ¶0ã£huñ´±Ž-”ãûøÇ@?2dƒ¹ G&H’²d4YOŽ2‘§ld*#ÙÊAβ–·Ìå.{ùË`³˜é‚Þ1늎fž áÒÌfþãÿ!oHœÛ•5Cù!Ož³’ålg:3%¶~¦KŸ#[=$MƒtPЬè³I™MMëÙlZ—ÞH®kÍë÷•){ÛyŠÛk ¶Z&³I¬‹•d3[LÏ6‹³G2íhÃä×ÂVIµ­Íín{;}»þö±-î¬Û"b,·º=³íucÕ¸–Hº1ÒnwÛÛ0·¾÷OŽ­œ[ûû ùÉ¿? ð…jWßçÊœ.‘…$Ô § Ãpëcó;â"ÙÆ·r‡HaãDÑó™^ðqƒœiÿ/H§/3ñ¦ÆyÓ3HÌ ò‹=Wy6GvxY_0ž ä Jǃ>•™ Àç™@APn–]$ˆëÈŃ£gxßùæ6Õ¸@”žoD¹5.…ójŒª`OˆÑ»#òžêKE20:×%¢ .$Ùç.H²ëí’½o$ïqú˜øž3ÉéA|m¦>«§üê?]ûÏ3BxÖ8®èÀ¼Ÿ. dîÔ1tå™*yë >!ŒOé?– Ï?$ÜÒ9ûRÓ.êñ¬œ¢m}DÖwkØ£&ܼßÈécÚ„ˆHÙÖO=RçîúƒX‚!¾ç|Kt?²)_úÙtà® ¥7 ›ÇþÿIŽ_á‹?)ë[sôÏOb$ü6ûC²~¯¤ìóÿÈõ)âßüÓ[þ‘þ7€a~øCëw€ 8 ˆ- >û·€8Xh)x&¸HØ ‚"8‚Âzïñ$˜‚øƒ‚*Ø‚.ø‚0ƒ28ƒ4Xƒ6xƒ8˜ƒ:¸ƒ<؃>øƒ Âx()„aF(~™W в—p m#-…¨÷‘SµÄƒ,˜„÷qa…R˜N@MÈm]¸.P„Ïöf* Mð†QQ| _ÑF‡M€Á†¿µnEX†1…>!ˆÅ6gH˜bx£7„8ÿÈmg¨Ï'÷Øhćq‰* ±[°…á Ø†,ÁQ†°[r(‰Øk†Æ†S бmÓ6bxy¡‡WFx($`‡ÜÖcñŠÆç… Á‹a ‘¡hoÄX‘v„]iKˆ†´˜ÝhM Œ|8¿8s¦=Û8´hŒñŠæ¦eìˆóxMØŠÙX‡XõHìGY3‰± á‰u4Ñn§w† èoXJý˜+—É-ihî(…‰xˆÿP a….À‰íhjsà‘8!ŒüW‰‘÷æ’Aˆ™\Ó3ù.ÿppÇ5®H„“4ÑŠ5|@y“±…œØSX…a”Aˆ"Ig(i@)÷QÈ“V‰ˆ1•=9ѨYåȌؕ•ê6t=árkèøH·˜Igšÿ ú¤"ñ¨'õfI¡K(W A‹ C&’qê.ÀŽàÙ¥Zõ©ÈȆ,j©3Hnfs¨Z‘¨ªJ•±:«ÞF3iª*ª9ê}ÚSr8–´¬Âjs'€hÀúR`H^—t‰ƒÛæ‘ÃÚt17 ºƒ§‡«^(†­¸§Ò!©UŠº¬q­<³ˆsdä÷—»ÊƒÇºɪƒv £0ÈtWñ®@¸!yÿéD›ê%{ê­;èŽÚŠŒà B™Š%@Ÿ&q°Y± ¬ñ Ž]å° ‘¥±k†ö¸p!+#›%‹ÿ*ÂX²)²ÿy²"…^»æ£@ÈhЍså÷‚‚*g±³9K­á³Bûx(á³4±®LF´Óº´+|”ÛbÉîúí¸ç®ûî¼£d{ïÀŸáïÂoüN°ëI!|¡ gèÒð†8Ì¡wè“ññð‡@ bÃÿH !jɆ 1¢—ØX0ñ‰P„‰£HÅ*V‰VÌ¢§šjñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºÑU\Äá2Ç7ÚñŽxtŒò&$X¥Ž|ô—n¸3@.%ŽÄÔãÉq­ ˆ¬ Xh”&0ò2E¼¤›üÈ–|tÆ‹š´Ô"CP’ò”êK!CncH•´•°¬ÝĨDÉXÚi¦tŠå<IÑEò–ÀäY0‡iË_ó˜U2æa”™fr ™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨¤œ)ЂbŒ :y¥AÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’ö ¡&M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªPs¤Ê¡‡iF=ŽB“ÊÔ¦:õ©PªT§zÀ\RõªXͪV·ÊÕ®zõ«` «XÇJÖ²" ¥fM+‰ÐªÖ¶6ˆ–nuÌR㪘QitÍ«ŠgU½Â…mð«gð*XÇdò £,¬bë,d‚ }e¬dÄ-Óír²˜°X™ÙÎ^è6Tš«gGÑ’ö´ô1-jWËÚÖºöµ°­lgKÛÚÿÚö¶¸ Òàr;[ðö·À ®p‡KÜâ÷¸Èí‘oÓâä:÷¹>j.t§KÝêZWHËMKvÇ£ÚëŠó<9¬wùR‹ñæd»æ½ÊnO²Þôº÷½ð¯Á«R[ØâöE¯|‡²Üü $¿öï~ƒ`ûâ·À¶ï€{" ßÚ¢Áö…ðƒó+á"*xÁ8I0€5œ_K˜ ưK Lb  ÄúqKþÁâÓ".v±Šac[¤Æ3^É‹ý!cH—"1^Í 2äÙÇ+9²”üÝk$È9N ”92å(“¤ÊTv²•E¢åƒ0y /s‹·<,$Ì@î2™³lã‚ÔÿÇQóš3Rå7ÿã-Ƴ@Ðl3Ïù"2þ1‹¿ñ‹;L ›øÅÛü9ÿ¹"Nvñä0)äx,1fwúÑ™2‹qh†Láxæ³›? êwÚÅS 2ƒÌZ rxuBÝêFÿƒÇ{¾ó%"2ë+0z׿Vu¯}Ýfï‚°Ù£¿q^/!=fñ*b‰T3ÄÚ×.…¬`K ÓIá¡`‰ ¤Âî–ˆx2o‹¤8Å©·ôMWû7Þ‰Â%î›<Ü °,NŒït @ín8€OŒpˆlØÁíÈ)n W<"w­)’ƒ Þÿ3ÁËâK”Z±$¤Yü唟yÌ,Þ„¹?n› ÀÎæõFüì󂤚åx®õ­'¢j¢]Ì8¿³v޾U{Ï+?öÓ«u<_a #?~¿Ýó­C¹Å۰Ĥà)LA,n°8 f¨k}ëØþÇ>lìbTÿ‚ÐߨÅ?$¡†ÿ¼ìx?|‹¥cûcɺ²Ïuœÿ\ñ,?ä1ÏjÊ“ÝéȽçÑüæºïZÚ¢÷<‘ƒ½xVÿ8ë’W}¨íL{8Ë~öµ·óí;’ûÔïÞ"’ï¼÷&ÿûâ/…øÊB~÷”oüæ;ÿùÐ>}¿yéÛÛú`¬9ö·Ïýî{aÕÿ¾ÿøs§ýñ›ÿüèO¿ú×Ïþö»ÿýð¿üçOÿúÛÿþøÏ¿þ÷¯zðÿÿâ's8€X€x€˜€3F6×] øV÷€ãU~á6˜(*á7h(!Ø2-àa‚xÇ$Ø‚.‘XeE¡‚?á4˜-à‚ƒ:؃8U~&H€AXC胿W„¡3a‚7Xq9h„”ׄP8…T˜JX…XXHˆwW˜…z%…s8LAuÃ|e²…aEÕO˜@28(h8 `[qè…»‡‚uh‡z¸‡›c†h’‡†цæô†èÑ…§ˆã‡ˆ|ÿ(û X‚XŽèW“¨ZcŠ8VÇR‰|Aˆ2t 8!—X¥(§˜/!8‚J’ŠPቷ‰-!‹ í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0ÙPÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m·…>Ý­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHš þ8à?NȺð…0Œ¡¥J ÃÚð†8Ì¡wÈÃúð‡@ ¢Ò‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PDß/¢HÅ*ZÑ[¶˜ ®ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒãøn!Ç:ÚñŽxÌãÛ Ç>‚h…~ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”l*WÉÊVºÒw x¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌb.KÆL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZShMPZ@!ù ,²ëöÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸIJ´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð")P¼ôÖK®Pöæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.8ÂÚ nøáˆ'®8¸,îøãG.ùä”Wnùå˜g®ùæœwîùç ‡Îò ¢ûHº3L‘î3°þBÿ„+à ´‹{ºA´NûíH”ïéî³Ó.Åæ²®ü NlbîìÐÏ Å%æÒî:óÔ“K|î3Øò±gû:Bº/¿Í?±§/û ³>úà‡-ïåÎúßÈ?þÜî.ÅèóÇûÈ¿Œ|9à#¢@:Ñu3¸Ã7ò¿÷-[s°Å6â¿÷ë{ôàµÂô©O\êó ÏUÂt‰Ð…¥‹¡ gHC²ù£]Ü º '€mÜ],A›ÓU8Q‡æÚ Œ8Dsq‰%ø‡-Ìu ,ŠMׯxDrïŠ\Ì"¸lñ0†‰ßrƒÈÄ‚ ‘[·ˆ„K ÀÚ„8*nkŠB´…-h#‡áâ¡€„;úP\’Ø ñ( &¾Ñ[‡ÌdíhHƒð‘[9<ä@üqIqmC‚|d{HJ†”ÒZŸüJ@!ù ,²ëVÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ën•½ûi€ ï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗NÝ-¦¿8ÃAÿ¤îzÛ­äB³_T»A·W”;A»¿îûïÀ/üðÄoüñÆžnëÊ›û?Í˼ы;;ôÔ;O=öÕËü?þÜb‹$ä2¯$Úl“½õØr‹?ÐOî?îÇÿúßjs‹ýöãß-ùü3H÷®µ [lÏ~ð»A ˜-õ}{òëÖóˆ½oÙ‚‚÷`¶ø=ÿy[HËÀò!”V ‘ÇB°¨¯…0´Ú cHÃÚð†8Ì¡wÈÃúð‡b`¹Ù^Ä"ñˆHL¢—¨ îÍ!D,H™HÅ|qŠæê]¸®x.m Ð"¸P0 ‹ùÊÆ6ŠK}kdãÇåÅ8²QŒÛ"£ͨ>4b«Žv¼£»Ç@ÊÑ×$äÈ»o‘ ÛHÜg [¤/`<J €[\ò[/ŸJò!òíód ®m\Ò•_ÀOi­ú–ÿ€%µµðUò“åJ_úvI@„вŠÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·7p+ !ù ,´æTÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì2€$´+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí·Jþü-øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûxïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwï}iÿ|o_øåþ³ ùân£ úmã­?ç—»>¹æ³®úö þßÎ?îþ@@@$p þÁ@jk@Â6€ZÀ·Ð†û²¥ $áÚ„JpÁml[õû‡-lñÀü]¶Î§ [`6LBÿÔG š¯[4ßù6ÈwÂlÉP·À ·e¿ šð†â:¢ø¦HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2"¬l !ù ,´æTÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\É’#–0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆôR¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿ ˜?éþã÷à„n¸×%®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷î{Ò‚ÿ.üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯½ê¶ˆ<¹Û.À6ã‹ëù‰‡/î6Ú@Búå{¾¾øÞ²Oýð“Ÿÿþüþ¶¥¿ú°Ý"Ÿ(@np$Ÿÿ°%>þÙÏ Ü–ý´QHB’°Å-¾U܈6Ø—Amý#„Hl!ÁoÙB·Ð KØÂlýƒ…:üGz¿Ç­øÃˆ,Ü »õ6ñ‡:¡·š(€'žo…€#¢«øÄ‚‹ŠF좵h-0rŒT,â@ÐØÅ" NŒO¬"Å(€#rqŠrLãñ¸F:zïŒr·GÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZRxMpS@!ù ,²çVÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§Ïž$~ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ë+ï¼ÚEï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀[¦Mà„nøáˆ#@âŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔCæOõ^_®öÛÐý¸Ý—à½öán38âwÿý·þtúã—¯Í6ïï>¸’üS?úÿ„+‰úÛ_ ú‡¿ €ß2à¿% ¼¯üû‡?þñ[pË|ú+Á6 ( mH·èVûþ!¾[ØHÀüwAmPðƒÿH,è=‡¬¯YÛ¨ 6náAûy«{!ÜÆ6ŒlÑ?H\×kßü(88v«ÿ0Ÿ-vÀ*>€JÄ ˜- n1Šô"·%Æ0r‘‹×*£ÍøÄ1²‘‚ä–·øÅ1^ql¼ã ˆÆ.Öq aL AÖhÅpÒ[}ì#öÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(G 8h+ !ù ,²®+ÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ -‘!´Øf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nº˜ÿœî[ꪲž:ë ÂNÐëü#;©¶×Nûí¡ænûë¼ÇþûïµOê-¶$|ò J"€óÙ"@òÔSÿ)ïÊWo}¦°çn$ÔƒŸ<ø›J"‰?%Ⱦ¼-ë·Ÿ©-Ú@ l3ðï©6ö0ýÅÃþ4µøùïµ³ŸïˆìEëº`ßýê7Â’p–@üœe‰)PƒŒ¡åp‰hÝAÌ¡wè„MØB?l–%ÿœÀÁ }R¸DuÃÖ}N4á z(‰%2Ërx¡¸>H‚†¶£³¾± (îP‡õûÆ?.A¾PïÌ*" €Ðo  ±öA+pú‹â dðØqx„£õ,Âðˆé{?`H òþÈ£²°7ƒ) 3($%™H,2Y—‚ ¨JKìB”å?¶‘I7šò”Ãâ#ù6QÆýÍà wøÅ6¶ËXÖq–¥„#µˆKd–à2µQLJÓ”—´eµüÁLC:ó–nÌ&µÈ· jÒ%p¦6ªx‹;^‹˜%H-€„Ø‚–ʬV9RfÅ ÷ä¦&·IÌ[hà¶8ç3q9-ƒÒò‡éL$C§ÅÍhƒ˜ ¦¨­r†ÑŠÞâæE9Ú-bšTz(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªHZÀ¦€!ù ,µ”ÿH° Áƒ’H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ ʑѣH“*]Ê´©Ó§P£JJµªÕ«X³jÝʵk×…^ÊK¶¬Ù³h1:J;± Û·pãÊK·.L°O°Ë·¯ß¿€÷l%¸°áÈ+^ s-ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íˆFoëÞÍ»·ïßÀƒ O‹ïðãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾} %îëßÏ¿¿ÿÿ(à€hà~FD‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†Ó^"–hâ‰(¦¨âN$®èâ‹0Æ(£PÍhã8æ¨ãƒÆíèã@)$z=iä‘H&©do,éä“PF)åtENiå•7mƒå–BÀå—`²”_˜d–)a‹f¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸Ž†f®¼öê묻ŠlR!üŠknÆ&«ì²Ì6ëì³ÐF+-­rLk-u¶\«­HÃÒU%IÝn+î¸än–íSùy‰•ºå¶ëî»ðÆ+ï¼i²ËTôæ«ï¾üöëï¿™~ ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lsÆÈ†«“À½á{óÏ@C†¬§:ÍrF[ÅsG’¬„×¹Œ­žÔI¸‰`.¸¤IÕ\Du×`süuXcWæóHKUöAg‡Í˜6…ÉÙnÿfïTºD´6KW“ÿµwÝ€nݰr{´²C'Ôö–‰ îøãXýXÚSI.@ãg®ùÃUv~å*áµ×Ý›—~-éË¡núê¬sj9x õúS±·nûí¸ç®ûîhóîûï+ÖüðÄï´`£ÂÃ^üòÌ7ïüóœoäôôjI=s…_¯ýöÁW˜<÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'ȰÙaĂ̠QƒÁ zðƒ ¡GHšð„(ŒXSÈÂ:e….Œ¡ gHÃÎä{6Ì¡w1$¸‡XZGÿpÄ"Q 8¢—Ø!2ñ‰P$‰£HÅ* „ˆ©Éž·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£-…ÅïÀð-o\£çHÇÀ4­Ž\BU¦ˆGˆM…ª€Ç‚¹>¶j†ÄNÑÚ†„B6e/m„I y™R²MIxK6>ÇKÊ‘žìM'CIÊá- Yˆü (KÉJ»DR_øze+gi²QöD– ¤FtY^Òò—ÑÁ%0‡¹E_ó˜n&d”i¸91™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~ú“}¶ü§@3eLŸt uÖ3-⥅$  (ªR)ÑŠV q¨E7ÊÑŽzô3‘ø¨H!ÖБš”a=©JWÊÒ–ºô¥0©L›“Ò™ÚTc½©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§z©šRU4¼*r0ªÕ®zõ«` «XÇJV#B´¬hM«Z×ÊÖ¶ºõ­p«\çJ׺ÚÕq«¼«^“tÖ½úUD-âã_ÿb¹& 64Ìëa!CÑÅ.s9ˤc)»Lv2-²ìeÍE$ÜQ›ý ^eÕКV@•8­j_dÍ’ÀK}]­lgKÛÚÿÚÖ¨¼­nwËÛÞúö·À ®p‡KÜâ÷¸ÈM. ¡¦\¾|¶¹Ð®t§KÝêZ÷ºØÍk–h÷»à=ÜÂKÞòš÷¼QânR$Ëõ†§±èå§?xÂ\‘d5¾øÅŒ{ók•úªäü…ŠLàX}Ö;°‚ÌàÇ'[&„Lá [8€ó5H†/ÌáxÃñ®‡GLbñ|ã!".ñSRbÖ°ø! ª ò‚‚œXÅ8VÌ 2‚Ô8Ç9™1C„ ä™< ÈH¶ãA¸Ûc’ xÀyòF¤¬*ÊoÝñvlIbY"ûMòH"œ‘/‹Ù>ìÕé‹û"''ÿÌg޳ySüâ#äÇrfIŒâæ<ûùϧy±En èBúЈN´¢ÍèF%ÁŽŽtU -i”ì¹Ò˜Î´¦7ÍéQºÓ /¨«(èQ›úÔ¨NµB:ŸR«úÕ­s5¬gMëZÛúÖ¸v¬sÍë^û(Ÿþµ°‡MìbûØÈN¶²—ÍlxN²ÙОµ¢Míj[ûÚØÎ¶¶ÌUh5¹jŠ­˜›á¬=k8ëÿ˜DŒçÈàÿƒ%T¶ëŒ<»&¥¥Ô‘Kð2[ÿ¿ƒMl\Û¸ô­µ\ƒçGK¿H©'¾ŠÓÌYˆ(roJ1¼á¸óâ .‡#|ÙÿÿGÂc˜Ó;™â!«7F:þ“lúh¿¦ã3Ï!qþ6E]דÆúc~¤¯|ô>®4g ô÷ç'ø ©à,ã'öãš›ôÛÅý\ù…ÖoúÄþû²ø” ¿ø#ÿ%€4!€A€Ýw€\ô}4~Wa{9çR8HJå‡ü§ÈkX8UÃÇ€Vေx‚Ê׿fXŦ‚(ø‚0˜].ƒ4xfVƒ8˜ƒ:Øk ¸ƒ>h^Ú÷ƒª{A„ a„B˜„ vVÁ„Jø„¥‘bA(U…ÔƒX˜c÷µ…^ø…`†b8†dX†fx†h˜†j¸†l؆nø†r…p8‡tX‡vx‡x˜‡z¸‡|؇)"…wZHy‚&!ù , ­”ÿH° Áƒ Hb¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ Úp¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵëA^ÊK¶¬Ù³h#ºJ˶­Û·pãÊ‹,Ô†èêÝË·¯ß¿5×L¸°áÈŸ¬¸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËž ¹(íÛ¸sëÞÍ»·ïßbA ¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¤íúøóëßÏ¿¿ÿÿ(à€h bE¨à‚ 6èàƒF(á„Vhá…f¨á†vèá‡Ýâˆ$–hâ‰(¾”WŠ,¶èâ‹0æ¤PŒ4Öhã8 hWŽ<öèã@~·cDiä‘HÆÖF’L6éä“P"7c”TViÓ-Vf™ã”Zvé%I|)æ˜ ŠHæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Ö:ꊶæªë®¬š–¯HáÊ««akì±È&«ì²Ì6ëì³¢Æí´ÏaIíµû‘¶Hqy·Ø†+î¸is—Þ’«îºì¶ëî»ð¦šnRàÆkï½øæ«ï¾üþ9o¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ’ÚF\Pÿò–3Í<÷¬W½” ëóÊ) Õ#E²ÒÍÖ„ÐçAmô~»¦‚K›L­õGBoíõÅ]§uóQ–@µsGg5öEi½W6ƒ«ÙnßÖ¶RæBöh{×ÿý®µ~—ˆ´@Eƒ$Ü”mKݤÜ7îøT}O6xV‘?¤øã˜g¾ï¼œtwJ; ‚æ¤?ûyo§—®úê‹^>^êB­-ì¬×nûí¸ç®{E´ïîûïöüðÄÃäúžÂo—|ñÌ7ïüóÐ_»|Ñÿ]ýq•_¯ýö.¿Ÿ÷܇/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁA#¬ 7È7zðƒ ¡T‚šð„(L¡ Ó½ºð…UÉ gHÃÚð†+wÈÃî‹’ð!”ÿd¸ ñˆ4„—ÈÄ”±‰PŒâBˆ(Å*Þð‰ i¡·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£…ÅëPñikŒ£çÈ9Ð1KH°Êï¸/7¤0g{lJù()ÆÒI I°È.(M8¤d‚(É4å‘-ùèŒ+YHNg“ž %÷JèÛ’%§¥*±ÂÈvMé‘«ŒeÌ@ù”ÉydŸk¥,wé]òò—Kô%0‡I$aƘA¦”IÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~ú“6Ìü§@P›¤r M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£,(HGj0‘’ô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@5)ƒê¥õ7=ªR—ÊÔ¦:õ©P*ûh)ÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM+¡’ªÖ¶ºuX—|«d¸„ U®xõ%ój“òõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f…¸Í²Åž ­hGKÚÒšö´¨M­jÙÚ´øcµ°íˆ^+ÛÚÿÚö¶¸½PkÓ²Ûñ°5·ØüOö Ü⢦·Æ…JgW‚Üä:÷¹Ðn…+ÝêZ÷ºØÍ®v·[ªmÄ»Ü ¯xÇKÞòš÷¼è½m ²Þôº÷½ð¯|çKßúÚ÷kͽ¯~Ç2ƒýú÷¿–™€LàøÀN°‚Ìà;øÁh¡.„'l SX#¾°†7Ìá{X46x?Lü’ø†í=±ŠWÌâjÄ.ŽqÏR,ãÛøÆ8αŽwÌãûøÇ@²‡Lä"ùÈHN²’'è‚%;9¾‘|²”§Lå*[ùÊX¦)š%à‚Há2ûm¼º\_Ðm &Ž^Þšõ£îvÿ¹'ó6’ð ] ¤i£qGšl“ºÊŠÌBlc$A¸0.ô ylhB»¯Ÿ%2iO ÚÑÅ[¹-€D×øÒ+4¤ŸòxèÓÓ3G*ý°z!-ðÔk‘° $ÀÛ¨…-ÖŒBQãÉ»ƒÖFKð]{ZÅÅ–Ä?JpëתºÃûЇl±ë[€ö’§ÆØ³éicþ؆-þaë—u» ç–Ø6¨» m˜úØÈ€©_k 8,ÝQÀL"ýêaýÜð¦Y¬'fêl»ÅÙY¿³Ìð†D߸‹ñ]_ˆKܬ ŸKá˜"¡ÚK§ŸïÊ‘#ðà~ÿ ù\Y•_Ü¿“vùËgNóÀ}üK2HÆ7brs¢|<?MÐ Þ°œ×"ûPëÎ cô´.]+W³ÈлZ¬¦ó¥ç0¼¯ôôªt]$_Ï×±þ£°CÅêèzKÔζoÄíG» ®³7ëÜλYÐ.÷¾ûý†Þ°ˆÝÂwÃýïˆ÷¨Ì¿¼ äÜ…O¼äe|x;^Å•Ÿ¼æ7ÖÌsþóº!.èGOúÒW—î¦O½bo®úIùÚ×}ëgÏXÖSÅö´Ï}7¿qÞ{Ä÷~wp¯ûù‘½øØ5*ò—Ïüæ;ÿùоô§Oýê[ÿúØÏ¾ö·¯dâsÿûà¿øÇOþò›ÿüèO?UôŒz„°#ï÷R@!ù ,tñTÿH° Áƒ*LHb¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sªd¥Ë—0cÊœI³¦Í›8sêÜi‘ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ9 rÖiçÕщçž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯ûì°Äk챫J‚ì²ÌÆvI³‚> í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0ÙPÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m·…>Ý­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë° $lì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(ôGÿºð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHìŠ “ÈD±РOà?þ¡ IDŠ’ÐÆ6üEýÙâ‹þØÆýñE[ ‹ö#£-¦ÈÆ6‚ôËbçømTÿ¸ÅéÈE7Þb‰ôÛ†-ÄHG: ò~Ú¸E!y mÀñ}’èã"é( 3Ò/s”d% KÎO“\d%ë‡ÉPÒ1·H*áISnr”î¤@©I6Ö2ºx¤ûIHSò~ztå?l±Êú±PŽ¡¬¢.ãçJþã–ÃT–þXXÆ0ÖQ{ôŸ6lqÅNjc!²”_!²Ì&šóœèL§:×ÉÎvºóðŒ§<çIOÿ³žøÌ§>÷ÉÿÏ~–¥ þ (Ê)Ђô M¨BóȆ.ô¡¨D'JÑ‘´v”„$ÜpÅ/öo‘(FJÒ’"Á ß\ß7¢ ‘–ô¥0M‚'ßF$À´IpCtšÄ4¥îsJ*Óm`¥‘D^‰öù# %mƒQ¢ 7˜”}.@ ´£næ#EÂTÍ笺#K) ÆJ>¨ŽTš±I[R>ITYßÈ«^‘*‘H´©ãÛ†OpÖ]ØBrpbuÁVˆøu¤@õ ÝZ‚oÜA3È,f7;…]ðõ!`¥+ø´ARmÌA ˜Aj_ Ú°Ö ›ˆ-;Óîÿ¹µ »Àì "`ÖŸ]ˆU€îEqjÝ…%Rk $³°HpBÚ‘6ÖzQ|l6±Û‡`vÓ5ˆ ÝzVï¹t¦È ’Z9DÄ®ÄýI0…‰H!¶ñIɽê–àëM¯@Ökûv×EXk{½mŽ4 »PHo2á'È ¾ùu«L½[À× –ˆ^€a‡l#­YÜž6ä0Ò6HK"‰@*SÉàY7žHGê]@$½ÿ@Â/ì0™ÖvÇ„lƒáÛ†K©êHq¼½oÈ)؆C‚âî!3#‰K•œ½ùf¶"Å]ˆ`­ë½¸ÿ»ÎÈ„²eˆ\¹ßîvQÛ]„<`Îq+`»W]lCºí³œg $Ìù²¡ÁçV'|ƒÄÌÈZû‚;$ÍN+žãÔ1]ÙÐߘ„¦°YFÏ@ sjC M]’Öx{.EÂJ7±‰)\aW˜Âdþ¹Ð‡Nô¢ýèHOºÒ—Îô¦;ýéPÏU”!ù ,²ç ÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§Ïž$~ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ë+ï¼ÚEï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ªí÷߀[¦Mà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.úè¤ófK騧žê>ª·îúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈSæOòÌ7ïüódþýô2mCýõØ÷¸ü@Ògï=ÀÛ„Ä÷äÃôBù>€þ~ö®ïþE’ GF§¿ÿ}÷è^c.ëòÞ¡Ð ö­!ù ,²P2ÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ òÈ… $§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€Là`ü¡À:Ð' | ¥ó Zð‚k‹ A4ø4[ØB’pC-$¡mä(La }¦ 7 0Œ¡ “ €m¨ð†*Ä™-’ ÃÊp $(-ÿpHD–Up Ô{H‚$´Á OLB $lÃDÄâ a&‰&AQá6l!€º!ŒEtÙ cèm ‡5là 9(€4ªlK@Lx~#‡ÑF b8Å‚TÐŽ##B ÛpBC¢‹9¢"èB&D‹[YɈ2¤‹0¤a'ù±HÄ0ù†*WùÇ"R G™IŽi#†È.l!98¡—º°á!‰(ÉȆ|ì#)5öÀßøÄd0ƒjRóšSøE+iÇ%"A!˜ì˜-b¸ m¼` ˜A:_ Î¼@NØ1IyKrR™µÄØÝðÿ‹\ÓŸÕ(5b‰mÎÓ˜¡TÈ2/æúc R¨f:'ÐN‰ºSñôãAkÃd¾…‹ñè¢@™„]PÓšý§ ² ƒb2‡KDeëøH¤· cAX >úc% *Pï´DIØ"HmgRÓY9Ìs‹ã@!iYLÁüC"€Ã(Ó2žQ$€!Aôh§†ÂðSP©@j)Èó©ÜF ºPÀÈ•†·"ÇÉH%À„·°Å-´q TvuN·€! v!‡‰V´ì|€f@l ÄÀ µJWærÜjÁÈÇ$Adp#*·HC‘ÂéeÔã&ÒšÒ”ÿR”²Â@Þ) Ö·õ lñC"ä·d„­UKðM$€‘,dbÁèY¹ºA§l²Ä@´Ê6ÜA KUj;w‹VœÓÖð­z};ÉcFB¹Yï=SAQÖ Su¤iÉ#ÊѳsÚ†)à†=¬U­@þ(‡¬7¸êcq·_ázpÏ=áiñ)GN‚ô–‘ȧ›lÑBFâ»é´(ESŒ['|£ÿ€¨Q=h ßÎØƒÛ¨$"aÂYă7þ¬ì» &Ä”!¦i}I Ì: †n˜íIŠÒ>`ÁR½*p·,\ Ë’ÂA®`Ã@Ó¢¶¡Ð%MÙ†j1ÿ±g𜺻 )¬X¼Iˆ ¾ÃüÆÂt¥g—8ß´œ½ª,ëØ_¾*™¦<|têY‚_8Ák–ûüç—¤aýkg«jWÍÂÒÈˆÖÆ?¢ FID‚“1œ¶2vŵd÷,C?ZÐþÇ\âÉCÛB Ru#¢ÉéÀº§ 4ž–h‰KLY¥·•Á•ùÜëN[ÑU5bâÊ9ŸÔtp ¾ÞvË€×=ôu°•lÚ22Ýu¥˜\‘)åµVy›Ž··•LaeãÓÜÛl~± ·óÎ.îs–Ål.1 ’,f¾ƒïNâ)ªpã.¾»ÖˆJaCÿLö IhÔ+æ¿Èi-Uˆ]‹-qŠªÜÄl¯0ƒ+La»ølýØ*þ£„e®#qÏ]Õ[lß&v ·Zc°ÀW¤)Ba¨ê™;bû€ŽíÚÚÐÚ q§hBÏž2ŸÅþX}¼Áš¨CçïVÿ1àpƒ4ãÜLÙf3¬Ì_§v«%¬aßixÄo£»cþ| ÀÜßë?]cýT–åñ¹Élû MÔÏï‘ÑmY,C‰y5OŒ=ì*1mú²[|^±mHB$Ú{Ô:{òpE¸ËvèÃâ ·þãa&à„ºø4ôtf#©3îFÂÕ-×oMãŽÁî{ßãÔN@!ù ,ícÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öد d§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùùðÚè·_EîÇüg·á†$m$aûã'a þIhƒ-lq¶„ñŸþ"Àðïlâ‹Ä B7DB|B‚åC‚$&(”@„‘pCþÂGÿiÃm ˆK0À’Ð{ ŒÄ-Jè@  ¶¸á÷ÿHpÁxðH0ŸÿzøÀ¢¯$ˆ¢@x>Ú IÈ¢$‚x>š­‘Ø"þ|(¿2–ÐŒhL£+b¶5ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ÜÜ?)(äÛðG" Ù½ FQŒ<È6"áÃ6l£{·ø ¶Iƒ RÛ°»7Hm’ ä ·QAR"r“,ˆ?þ!A$$AÞû‡6HÉXd•Wü ÃüVrÒ—…$¤Ü€d^Ï” t¦)rÏ·H! bxɃhÂ’øž.«Æ„„Ò *‰¼nFDšìŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦©!&NwÊÓžúô§@ ªP‡JÔ¢õ¨k§û¶¡ I¤P[Ü¡*§ªÌíM2 ȪVµ*$¸¡—T­jõ‚¸Õ²ÄaUeŽ”ª(n eÀ -¨Â$t°¬%€ä,à #kxÊ eõß1ùŠ¿²J"­bUÑ7~±Øo|ƒ¯ b °ªUK&“ªùæV“8Í´²HM­ œ€Y‚¸S'Ö|R ´šW<¶´¹e€„nÿBvE.À ¢‰KXâÔ©„ËÖ™ @I«Íª„»×0÷—‰„V9{ÙÄ¢H­ œ „âò„~E¢,ÂùË©>ÄZ%!l[”[4áµjÕ‰cÛPÇnBI’Ð*yàØþ:¶³ë%ˆt³ZÄêz·DÝ…/#S[“[ÄÁNˆC{t ­¢S »Ð…äà„ kÀÈ€€ËòÆ×BÂÀ-Z`¸` a,c›(¸@ßøÄd0ûx¸ck“±ºú†.8à!*€h7ÉZÕ†’_ … Ìà_ó dà„M¹ Î*MlÝ ±Xÿ#ô*!‹ ¶1J”ázÌgÄ¿8ó@KÛ‚˜·CMnFvñ´¡Í,I”¶‚¬2õ3È4˜5=ƒ d·e¤‚ÉHh5Å!¦!­‘]|nø¯J¼'C8 ¿˜3½k 'ıÍ=´@l¼_$SF‘àdBšºæB$Å|y2Aœ 8aÉ,)¶”’k‹;HÓ`³Bä hä÷Ɔ>±dV;E_nc‚$X³/µÇâø-XÊ Ùw V?I«Ûø±À})˜Ù³1uVÓ iÆ 3œ€=lAb C:ÐÛÀ…mq h‡eN( Få÷eäàÿ=É.¶áè[X"JÚÈjÀiLošà18|LÁ¬î Â~LÆ“ÀÈ‹Os %˜àqsPØ,vp àikäÅ(@ .1Èæ"„‘ôˆÇp\.55«Iد3ÍçLD S ¹ PÃLðçÑek÷»×02èmöÒ3Kt^½¡Tç±r'Ø#.ØÏõt‹s7Aásæ ò‹;äS¨¡è ¸æm´!«êÈè›íÀº3ðæ4¡@ÐKYX™,üÈ à.‡Ð‹$ÕO:;âp‹^ œæyÀ åð„Ù¯žõš@$Üi÷¿C&†‘Œy-‚„Sšݦ—¾ÿYâÁ‘ä¶ä†Þˆ¨UIþ)e3«×ö2˜åßi_{Z2xõ/ìú-PÖ'“¤\%æÿ3@‘‘_x—_¬GúSbLNª„GæÎdu‘o°A‘o–ðX)@tÊ4v 6‹·$Â×Å×v,(s'Ê$ðvz~ww}Ó§z€Ž{qAc§?͆H³4KËÄ'H3wäöYÔp ÑInðxU‚^ßnš÷eŸ–Y…ß° ƒ¥V†´`¨ÇpKCÇHQäK1Ô€§GHoU\ñ îuV¸’&Rp K–—Pbg(ŽÐÿ𠻀’ð Tÿ¦%'ƒø×g”X/ðZ5ƒÁf†E—U´fl‘Xè„UkFÄt{—”q4$[â÷™$ &d {HÛEOˆHð´ñ?’PmàmZ¢‹\uSf6Çváicö$0]œ4j…¸2èNg(…‹±@Tt›$w6äE@ZU`^u-PT×(¹5aþöTåÔEØÄYT†~]Blß ƇŒ÷ƒ˜¨Uä\T…„ÿP hÇp$k8k¶sà*`ŽNàU7éhè×q‹¯% %XºDCßbBhmð ›pŒ›÷…ÿ¸Y«ÄW”%Ž –!6‹áoÿ1ÿà(pL¢¤ ÿc&1ç‰` ºF‰<öi-¹UšV‘§|@Ò^R° qPÚàjr€¶`Hˆ]c’g€’œÆiŸçÿWÍtf§‡n‘t7b“Q“¡‘@—WÂHi&•w ßöcp'Rð´ D };t ѤV f@l@r‘ !–™&ɵ@x¸ ›0Wà™S°eù ) Kùõ‘¶àtƒ•™q)—¢—&aÑdjR”À`¥…ltG@«N—DH; p@çš 2;‘Ž”I&ºèZçäUñÅt©J…–lñ¥\énâ‹—[»5*³Ul˜ÿÅTä‰KÍhH{un@t Gœ ² ’æí‡–)*ïŽÙI‡É¦bŸ(„&WÀy[ ò rÐæˆu±òVÎh`U¥ ™Ä˜L5[%°‰î9 $.p C™ ³u›:åYÝôBo‰vˆe¢S‡X Y‡uY-›ž2ba( ›¸W A†Õ\’)vRŸ²¢ Éå”dAm@_Ò8]·P¢²ªr 6Wè€_Yn K0+þ€EPºp`ÄIe¨raò µàTfŠKʤHµ¦-qIIŠFþE˜eä¡åµ(?/Vu?/F‘ °§áI~eG>Z>ÛǦˆŠ1…Z>Jÿv”xèdíó #D) ‹:>Çåˆ)P)àHß9>ß` )p©ãs s¥‰Ê7}H¨Z>q¥­º6»0$p »@«Þ£)M€uMˆ>ÛÐ @*À«Øc¥’†Žé>Þ ŸZ«‚ÃZ>Ëyx)>Žüµ Ü?–$Ðaò³ /†T—œåó§@jFV¨äs{ð£¬Ôš¯ä‚Lǵ N ®.ªÕ1­s !¯øz= ¨¯ Û°Œ" àå°r“ˆ®eF»à ºà[euyš°Ò#¦1zÊ®ÕãKtÆ_rœ*-ŠŽ;>*@ȨtZ §e‘0‘;;!ù ,íTÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÔI`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh×ÕSÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùÿR„þú©Ïþû¹_BID’D%¼_B¹‰ÿI_ RÌ/ Ÿý̇IØB  `Ç—7Øâ‚$Ú‰ü¹ï{$ðŸ$P áþÜ € …-ü ÷ ÈBöï$$_$‘–À‘hÃÿÅW‚ÿ!ä‚‘0_ýè—Á€ù’øB7´‚ð@í—Ã,zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷¸%Œñ| ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ù(@2ó™ÐŒ¦4§IÍjZóšØÌ¦6‰éG…t“|”„$Ü NmlãΟ6Ü€¸3‚‘8':½g‹$¸SŠ )-ЙÿÎëi£÷œÈý¬˜@€THg?¥÷ I4 ’àçB·QσºŸ>ú¦ÚùN7h£ ÙFšÌ3zÛà(’pÎ},T!ÿ¼g $ª£\Š÷lH òR‚¸A¦&í)òìéÎ}ž´"ugvZ#X*÷Œè7¦:U’¦ I*"zTÙôQûÐÆ=ã0Õ;ØA rp‚%lñ ‰îc!ÛÀHÝ©Ðâõ³îDÁ7®0Ì௙¬°‰|#¨ýüf7‰jÕ®Ú© P²Å=wa‰Ìà—½ì@^ …KHT¨kQ™J<Žºá}lB®`X¬"d®Ku¬ðüqÏÿLA Ð,A&°Ù)xmHO·qϺ/©,õ«_"ðÖ …ýb òͺ3¤e3¯*Ý€V`Du fǻܡ­Ù%ˆd0SÙžÆ} õî?¶A*Œ¶îüÅ–[Á¶ Û@¯{B\w¦·4H€- Ù ò¶ßØ-@ìB˜eÈò[×.Ô ðh@ÅZµ±Qì ÿv‹(®tûõ¯B¤09\â‚¶h1B¶^mÜâ‚«Ig¹[À`ˆÓFRÛp)d¸¼ú•‚4a k¹ –ˆ?æ*‰_™5’e¡UºÏù­em ÚTà†=¤–ÿ¹inÚ*‡8Üø‚:HžEêNIhÇ­!n º׋y© [ç;›ŒÙ DÆqÁ7 ð9ØÂ_€$¢¹ €¢d }°]{dËW=¥fwºÆ~…´Aà„o°W^ÎqBø¼UgZ4éœ/  ÐV8 Hè¡ã*€êŽÍŸZò&œ¬[„È@ÒîœiKELT£¦z3Ìþ4 ‹=ОG&w’³ý 'ðW!s–é|ýZœÀ¸¢i1}ýDžJôÈßÞ×7>mï cVµÏ-¶Ý moW'Hmü™•JŸœ.?÷W™UdÓn"ª%.kY  ¹ÿx@¼ßÙÂyŸ¸ IEÅ_sRglÍ)øÆxMi[³¼åç.Aæjè€ÿÈãv*ð½­Úwdå:½íÎHN¥“AÛ0í¿>Ù¹p´þ‘í–Ÿ4Ü!jl¯Ž»õÀœvˆ±r …)XbeoLý, [\cºJ¿EP“ÇØüâw¸Ã øz…;ü¢­çœé smü]žV-¼ˆƒ§ô¢'¤Øÿ5Nm±éÊõžVO^¡£ Òˆ—›Á°w¨Ã¯ªUìnC`Q·š^lƒÜ·ø@ðQ«®™ò3/žA SÙÆ•Ù>¶ê6˜}|–ÞžAoÍ•?–_‚ÔÄ÷¾.}¢JïI|O(û»Ú½\ÍOé_ýÖg;ñ´švÒþ›JV¿];½ñÿœmÀAüÓCÕBÞ‡=õs Áw}Ò£f¤€QAÓ%Уd‘ Id¸Mø°Y 8‚Þv$x‚-Q (¸‚,Ø‚.ø‚0ƒ28ƒöu4¸56wƒ:¸ƒ<¸ Ѓac@8„Ïâc¤D˜„J¸„Ž"‚Ø!ù ,ç5ÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§PA’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öؼMDöÙh§ÍñTj·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè§Ÿ|ê·oP H@B m ŸD’D’õKr~¶°Eý¿ú¹!~à›þj‘ƒÔ/@‚ð÷À°M ø^x$ø|H‚$À>‚`*‘RHb…Þ“` ’„Ø¢…ãCà@ð 7\|¶ÈÿÛ` 7ÈO%,_ "q‹"ê°{¼Ÿ$ц6ЯŠ%0ö§¾$ºï‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£s¤=úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšqùGE´ù½&æÏˆ’ÐÆ6þÁMïiã€È #1ÎrbÏIH§CJ  r¶È›Â'A´ÿOu ñ~Få9$´“z‘ ¨Dè} `ð$( Ü`Ïè! n¨§C ²64 äÜè‡@ZªmôS ·°ç7RÎmD%g ìéRåmã¢lÃ?üÁÒ‡øÃ 2 éòNj‹ŠZDò©Hƒ—Ð JâßXiO°Ô‚ Õ©F-ž6ä‰olã–p‚ä`‰K|#«å”jA€ ¤´ª¹ãéBÓ™‚o\a38È6Uª2ä1`V…g yîÂ/ 2$ÖƒMÈV3¨ÑâáÔ ›˜ r…¾ÂÕ£P*ñ&+€oLA±yMÈ Ù}4d$ÈàA}SS~ÿ¹“­IØ^0Ô À·‘_¹YN}ö3;ÝMý:0œJ®B^p‡³Âµ°˜)\[sUuÖ`òüÅd ÝlV ç-­u² yFV6íM‚8šÂ€Ý"HØ…^P^„¼` —PéB[YÛH‚!ýÇü¶Z¤3 ›àoÍ+lV—°Å-Ø‹S[hc¹·±çVgØ/m\µ w@-C\ Þ8AË âAŠ ZI4QƵù‡‰#Á¾ïökMŬfℳÊ!Æ1Ž ÒÑt†³‰¶!§-b IÈ•_²È9Ó‰ï6!‹uÁ7 ð².Ùù)—oår"ÿ†?ò&žðe…4áÙýˆÒä*xɱñÇ6ÚÐÄS`W…°Š"ætÎÔ¥Úi?‹ºÝÔüã Æ4XԪɖ@¼ä]È îÔA¿Wˆé|ëmîkÃ[x”Ä?N'v!‡èdµi´:íWNĽ•^Í”eÍN6e­³A+Rû“×µ~O=A¬©uµõ@k]Úé'EƒM»öÊÖ CV­³ ír’¶ÀÀ[i`Û° Ôr» y•ž³+¾ Ò¥hEë;|bWâ´ƒ¤ÜýZbõÌný,[˜Z›‚–'¥×Ï™þâw¸Ã ® ;ü"ª.ÕÍbC«ã”ŽSª8ÕîñÌ-€q+¤ÿx®‚`ñBïPžð.[§8Ø–V¼SÌówŽ\rëî¤Oݨ8‘žÒ˜êX½ˆús!HPµö€ØÏ$ Eûõ>ÜCÔâ­tǦ{\ û¸µ€öÀ½úðFÝ×^@±÷M@!ù ,)eÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðR=Üo€ ñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„c ÌH$ËD$n@BÄ\ %$!‰-nàF&Nnlz%Q¹È¨·áF$Á^²æ% QÂÊ·KŽÐç³~P¨“÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LÅA‚œsdÛ¢6Ág Fâ4%àAH·Ëi#¨IBSÓB5u Û@ÿ2¹Ô‘€¸Ô -+Õ9‚(µ‘DæG¼Pó— eùÚÖ…±|<œ‹55xVFí£ H›(KtB5 ¾ã£_ÓB Îš–<ëM•×/^¤ ¾#A_ÕB>*V±‹¬@|ùƒt¶!¶ðÝ*ÝRؽ^¶®ˆr„ï$ñÏVЉ„ïÊÊ–ÿ&ኼb —:Ù=Ý•‹ûâä 9Èaœß° kmjÙ’p±Sá`k‚o\ ‰Ã7 {ÖÄÞ¥|äS÷$A©êõSÔ+\aÉ…mCÌ›„ñV¥‘C @`w N0¥e/;Æð>'ÆD’6|§)Há3 È à„MØ!·ˆØRÁb .pAœpñÙá—%åe ?•À‡šÐ0$Í6aìMˆ%â«Á†¸ápqË\À_ˆx ".Tà„øþ#¾Ge¤“{«’„’hB þq]ÐXHÛ8va‰DX6H…ÜDr†ùÿpEµJœ ‡¤`!&ˆC\øQ¼£$#kÇ,Î’-™_")üˆƒtn6‘fœ¹ gÖ¢YÇb Np‚ >ì„€82BûŸÖzhU‰ì ¢€#!ÕwptCä@͆HÈÐuJ‡÷»gïY!­Mvrñx‹Ó’.Ö*YÜ%U=$ßmÃÌ‘‚…/|AßÙW*su Ð# ÄȪ¦¶TÐ4ÝÿÐ…#Ÿ|Vëµ5%¿Ì ‘“´`½þ ™ð ¶ÝÄß"äªhvV:Ü‚q» _nº BmlÁÀ…~v° ²ºƒ4QzÙÅ%HKLAIÚÿ-ýp|é…Ha ¶HâV¢Öôù*®² Æí„T €ä¼ kh_3#‹^÷’²y8'ìà ù…6×S‚Èâ j<œ$R>•KÔ9r»>ñ‡`s‘ÎþâŠ9Be(ñpq¸EË2w4‹³êâAÞº¼›Går 2¹S½ó9×Ú"ÿˆ²b™XtÔVd±“íø‘¶á\'èê™ÀA^ ƒo  ñ›+ÈV¯NùùˆR<±Cüp²;è!Nú@ü,‰ĺ(@q¡Aèï`Àˆmñ@$ϳJAÕ_Vð¯“y Ô½ Áü"@r® á{$üÀ¾ç.øþÿ— àäSIPÂYE8¶ö$OÞ…7v±‰' I*OÁ60¯üØYà³qE¡zd7vǶ‡§Màd†FpXÔ¤8Ü&UuzWAQ…%a&9Ûà| ñÿ'Ÿ—X TqæÞÇs„Çs hæ·*@o tC‚¦X&„V‹Õf e߃PvÕVAfVi¡yÁy#H‚ÔfKdmPÑD˜€A„H† HMΕ:3DhÿƒˆÆq ‘[(ÀZN`{Sb^–pHxöM(<´E¡r[†srPxM „ñ‚¡Hy’£E¸õH9…ËS|=HG€ÿçeSòcô³ º¦/psH‡ç¤Y´¥‚ž'ß0 g……3¤q—E˜% GBUœõ »p†ßð_TÒoK49†–° ™($PhÑKD€AáM)Àd‚~&዇ƒ«tY@õHÇsHŽØìF?þe%aØt߀m „ãˆf{° Ûð @qÕ[ÿ €y.ðz% q«‡…¡h6„hvŠn†â•ˆ€fJ’Bµ`Zx„†JW%5¥rKdé59&w  ɵ Ô‡ÛpU¶p µ` Ú`p2ä;ö!)ЂäˆᇀmpZa8ŠU•Õl‰ÿçˆQ€S‚THð ›0W0W0›_ÉDuøk[æBtWt8£óøa±Gv"Amþ(“ª¨Xn0`º4J´h‹[‚‹1yA}T T’ !‰Å('™èÆ‚<¹0É•4yV6iJJÕˆ¶P‹q—NÒ…%i IyZ‚[Ë'žÖT•%0÷È„éõ¨{„¦DIM%$PGai&战©”>†VdA9•ré(©’}X1¨—C@'¦õú0< >ydŒVU³E€=DAèoÆ9!f•Xè‡Ñº÷H 6€£TI` % ig²‘ÿuoA?4G¾Sc¸çZsinA–(¡›XTHCôH3‡Nà937&YŒ·l¯ÄI©ctJñ Ã5 qÒéóˆjÈgÐ3‘/§ “1@8K GVÖ&]˜: iAräCš5Žõœ>ñ íÆz©V›ªÖs+!b6:€ì§9gCñI]nrTü3BÅ$9X¥p©ç)P b¯GŠ2aɕեl²(äG'x$T ñ—UᢠP ~(idúHÉnîÆdybD)z%°},ªçT‹Iº¤ Z™ÔYe×§HÖ|âCsU¢[á¢)@F£)™™ÿó Hª¤Lj•{êÔš6nW$ Äpâ ¢Jl å‹„`‹$”¯ [ÔÚ-œxÃÚBgeD¢@ü‘»-êÎ%cWÅîÅqk8Tž$!Ä@Q؆0Æð Dy·À-þ±6(oï dH”Oˆ·hÃïÚXIVñ~ˆÄ?–x?Ix‘x9ÔÚ…˜GIDÛ°õ2ÊÛáî‰LL‚ì¶aIH‚®\ØrÄbþ£ n¤@ 9ÄUú#|W ä?Ü ³%Ú∿Äã[©L¤’–n€ÿq‹IŽQŒŒÄ,±æGd¶¡DÔ$Büñ»' Ä•npbµáÿ†÷9ÒYÓÆïÎF_&D ÐÓ†2%á$ÒSn°EAk¸²nRô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXíÏ0³ÊÕ®zõ«` «XÇJÖ²šõ¬iÙ*ßlÁLhc¢tã'2H$hÑ¢lë"]b»k’ˆzrR3ˆ;úM/ƒH؆ZÍ& XÏwGíÖúRÑ,¦ Ý„7;dÔÈd£ñ¼KX¢ICy$PÙµáÒnÈ ¾!䇸#¸áe6iì0¤@ .(n¡"…oH¢»8u£ÅKÙ¹a3 ¶¨¯LЦWÚxôgx€(À*5D\ …Û9A ÿ—oA® – ÞÄV?e x;Äß(€Û*‹ƒ`ßZÔ¸g M€ðÚ Åmˆ RÀÒsÛ°‰»Wýë°mi;9arO†×0>úFÆíG$,Òð¹†AˆMNM\Âò~_Òwÿ‹P7¤ €<#²[i–&í·:FŒ©pk.×%–ˆ œp¸+ ÉÛƒåðÈú ^·žà"¼‡†èFW=F8ÌüSÒø énD,êDãz;J”µÄ%ļ €^~‚®ÿAž `Ò\7íkçˆâpò“û±×Ä«ôõôÜüòY!2Ày‡ÊZö3ß@{¼6€‰p!ANH W‘U}Vridc†èDWü7[Âck›q]ßÐm†æ‡3'µ)çr(8.gâfMßVBkÐ}Ç»ð²Ck&NDxÀbž±CØkçˆ&ʇGˆ„äuGl·y1L»° w€=›p% Úp ™GE8X´…qÆs ÁöJ³H¡€k׆#w燎†+ˆq ÅåbXÂY¶•… ±HaEH°oÕCHDY;8€Ç•„ ÿ€·p17ˆÖ]×G%øEDÆó»%QgØ<(…Ñ·v¶×—(NºG´¨¦‚²(uXm ±ŠT‚oÚµÿ ©ÔX‰¸LÂcfœñCD´ˆ¼öKx(Ðh 5@Ð'{uµ@K·€Öåy]’\ •?„mp£„DÔ%å7؆†¶€NG &DÄC ± Þ° ß° _¨%2(½…¥ Ÿ•CDTŽ?8x™ÁßÀˆT¶0nÐHŠá£‹XއD‘C£XÀYÉdŸa Çc wà©‚,¡eïØ[H` ä;DŠR’\þÈd¥ÿµO6ùZ1LÛÀkD”E8Êc‘ áPxD””ØD|i& µ †DÔkŽØ%Ù] HneJòCŒ¿…êxŠ`”&‘rÅãFxÉ„âW÷”h}™LÅ…lô^ãæ(€™h‚P÷”•¬¡ŽéW•ÙfiLÄÓh§¶÷» (ó“Œh´iR0$rpƒã–ÖhÛ !'ûh2¹›ày!ÿ·—'¡›ðЍ†™¨¶ * }Í 2¥É¡zäë(wÐ|Æö)ð^Í· È)GxŸr¢˜“F»à §‚I˜Š.q\xˆ‡(I¶% M¡)ª¡£œ(PhòyõéQ–w1óq@ º ñž&A–ªçy.j'Òe …ñ“@„ð|s]kGh#è7:pƒ¢*:£q³ -°t;:¢q¤. ¤J 7Ê©£Šç7H:‚ €7Ç9€ÊèÚ¤zs Æ ‡†3'óW7»À…™7Ê¢Ñ7o”IX§wc¦êXzz7›¢~3§xËø§lcloúÿØ¢tó Þp º` º0g:¤ys )¨sƒ‚¶ðhZ¥jóšÊkéÇ£žpó ŸúCz‰ˆ*7¥zš§nê ú7šª ¥ 1jê*àa¢oc.ù×)ê«w3˜z]:–«Ѧk#Œ¸—K(ª_#­,::ŸÉÊ©Ù* 1‰p#­I×¥]³X,÷ ·œáa«‹hI@1ÆkãŠ7ºà(€3ö7)0t\غ6=f}£{)!W7J0q±Ìi7&ƒ$0{zcl´èƒ¢Rf\“ 7¶  ©å…›Vgª7›e½ ®i³¢ 7±2;€dZê¨'Û6¹J®ó³€S±a!ù ,±”ÿH° Áƒ ’H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J‘Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵkÕ…^ÊK¶¬Ù³h):J;± Û·pãÊK·.K°O°Ë·¯ß¿€çl%¸°áÈ+^Ìr-ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»öj£¶sëÞÍ»·ïßÀƒ¿Å‹W¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿þÄñÃ,a¿¿ÿÿ(à€3Gà&¨à‚ 6ÈF(au·Lhá…f¨á†vèᇬéâˆ$–hâ‰(Ê·WŠ,¶èâ‹0ƨԊ2Öhã8æè”C¨ã@)äœùHä‘H&©ä’ðÙLF)å”TV)T#Vf©%v®léå— % ˜d’¹ Pc–©¦€""†åšp È_œtÖy"”væIb—zöé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«¬qx.ëì³ÐFkP³aQ‹TÒF‹[¶Üvëí·à†+î¸ä–kîArœ«®u¶¬ë.IÖÎåäHñ¾kï½øzÖîSüµY•¿ù,ðÀlðÁ…œ7ìðÃG,ñĸÎKñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒm[oNóÆ0ÓTWÍØ¶µ>m5Ð lMUÔI²^û2¦uzg{}à&‚¹à’&jÇM¯Ütóœvµ¤M=ØCÝÿÞu+¦Masr6Gà½) •.ùÝÛd9Žøä”WGmá-´-Ö N'畇.ºU’+Æ·T¥ ú謷N²‘°tzJxí¥¸ë¸—{;r»çîûﮦÞìD ñÀ'¯üòÌ7ï‹)ÍØ§ ±pB£AÖG?U¨ŽR¢ßó><úñ€ dþö(ÈBB‘†L¤"ÉÈF:ò‘<£ãYyJ¢Å’Ìä¬0©É^‰­“}BUäÊ•¥ï‡·ëãXVWJd©²•ÜyàÀJ# @’*i,7SÅ]"* oÉÆg8éËNÕ²˜Á!&2—9¾¨më•?9&3§Y\ŒaÖ¤¦6%¥Ì¹t' Á“4%Ò;ŒøkuF¾¹ÍvÆ&›CŠ;KOwÚóCå¼§>UÿOÄô#ÿŒR@÷IЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgÚRÒô¦ÎʧO؉Ӟ"k Á–M?ÂSŸõWùêQ—š¯â •©PªT§ºœXPõª-ÛËS±ÊÕ!¡«` «XÇJÖ²šõ¬hM«Zך²õ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆÕ˜R šS2V9_}¬d'KÙÊZö²˜Í¬&‹ªÙÎzö³  ­hGKÚÒšö´¨M­jWK¾Å²öµ°=X \Ûºÿ€¸MBÔX[ÊXk!IpC„+‰ÈöV34¦Øª( [S n=îcJ€„æšÒŒ$€9§6p ÑÍ®`ðò܃ôR¼—©"~š5FôF¦]ØuïeV”ØEB¾–‰Dy b\üRf· î@H°_ÿJ†?nÐ/ f+€û¸2¶ÜnÝ"¶ÈröÁX©…$Ú ¶ ÃA‚p©[‚$ôK1V¸K[›%Å.Ž1|`,ãÛøÆ8αŽwÌãûøÇ@²‡Ld$¶·È|ù$’—Ìä&;9ÿø‡?ðDyp ©r•² œ©Ë™2•²å' å·8åàþ±]$AÿÉVîå›Ñ'`¬(ñ5³O¶Ñ†6 Ngª$´QÜ;’Y$Ø×W£,f¸ÅÍÕsRþÑ®ûFb_xŽò6æ<>§OI°E”«ìÜvšÊÞ•ôP L7 ¡]À”r•ÝÐh”à¾ÿشآìè$ˆyÔÚ€ƒU ”HÀÔ}æs¬ÿ¡Û7n£ºŒ~î• ‰3»mx£Ãàl–2 ÑwÔ¯6ÜPÞà$ ‘Ð4µRh-ÿÔmà5±òî ;Û¶ A£Û‹ç)· ÐèK¯·o*{{Þ;ñ²~@n7º¹ Û Á-r]ÞûúãÝI¨…¼ëÛ`79yX†V®+}Ç‘Änÿ°ö-$áqö|[ÞF$܆Hpá8?޶²óœû¼7/KÐÁ“çŸû´Ñ9ù¸Ñ—~œ¡3]+J?‰¡ŸNõª[ýêÅì9Ö·Îõ®{ýë`»ØÇNö²›ýìhO»Ú×þ2¤³ýíp»ÜçN÷UÝé2¹ûAð^w²G½ï€¼pþ.øÂ^7?¼âÏ›Ä3þñ¼ä'OùÊ[þò˜‹Ö3Ïù§l¾ó#q;èGOúÒ›þôú<ê7òÕÿÑñ®½ìgO{û »=°¯½î—ûÝûþ÷ÀgKïƒOüâÿ(¢?¾ò—/Õ3ÿùоô!2üä?Ê·°År%1hç×þÊ®Fÿpkï¯>ÊÎmÜøKÐzÄ=`WÞïø ,™#sãG‚ùW8ü@EyØã÷f¢§ié'ãw^”ó~Uñ Á€‹BqnÐ~¡i逓Ã>ý¥è(šöUù7uH4 ¨›a7—_u™—’kÚ°~ 2ðÒi„ f+ùÀ(›²ñƒUŸ Y>I‘8Ñ^N`Žc ¡qœSâng2~»@… ñŒé€ð)ÎfpFøv8%ß ɘŒ}‰›a£'7j‰V‡!J!•»)¿ö.i —ð3°˜¢6ë—kÈfy¸3ßÐ`©.€£¡£;Ê=jæYZúp Aœqòr¡`¢/°G)jeò)C£ƒõI}\ú_Hw©¥ éwª'ŒV ¤ ’a ßœNÿJjp³ø’9SfaJû§Qfš‘cfJ˜x$ê}iNú)€–›P•BЍ 8q+B~œJfÿp_:3e–—1¦¡ —° ›À«a$µöÞv ‰)£:¤‘¥fˆ”6~Š˜¤ *˜ÿ°Ú€‡‚Ù\:¨W‘ª¨Þ ®ßš/*Ð*à犈 ÑÀ¡¡¥•:–º:š#ÚHW@{@‚‚`”f pXær”«>’óú7”‘†>Ù¬b )ƒÚ™º¨A(jv†•Ö‰F˜A3¡Q©ãº©Ù©ám·˜¬á®¡²‚jƒ¨doÄ€U¶ [ÿv „«Û.X(ž!³©ß´ è6:Hœœ³‘1¯ ³ù¢MØâæè²ÂƒM(n‘7qØ:8w_Ÿ˜3çZ®éZ"+x{ÚQ€ ›´„Ò’FH±&Ke[;mE˜>{2Û–~k+»pjAé*Œf‚ä籚¦ W)^ƒúw3û0Cë À¬ñ¶%¡¦**µ©(Vk„ÙV·üêeÚÐá°{;2Ã7¸–äY²á´ïzZ:»¡K°Û'c×siƵ͓ ›µZ {¶–‚}òG~À4sÞUëç±6Óº"!˜ºÿð –ÿPºà¹$Ñ»v‚~Ë §€ J3 9ÉK\ú¾•K|Vòh+š†gâ°)gÚ2bVbf¨3á«›° ›ð¢¦Šµá‘åÑ—nHµÁ›[)ç¸ gsµÐ¾?s¶º»ÑèèJÁ±J¦eÑHËœ»Á1ì´€´4a¦Ž(b]*=jƒ(ð ›HuN ³uÄ˲+a³Øæ˜àH»V6nÀN ÂÅ2À(³eߥ)P-`¾¹4»ð )àAËhZæE §Q¶ û‹™6 ·4\ä9µs<bœ#¶ ÁÑÇ Ã€àP™›Ç`Zåÿ ĺ0¿L0· èÉ8L|£È‹aŒ-p¾ÊÀ¿à˜)à[Çtœ˜Œ^ †Å›Ê!²(|®N` –öv‹à‘• 1¬V#ïkZœ!ŽÆ±ÇÑ»,¨»™©Ìnk@ÃÜ"¸á¼Ëá¼ÖüÛ¬¡CÑ˃Í/!Î.ÍŸU¿Ówr–Ë€]œäŒ.ûÌ»Kæ|\Û` ¤y [ˆ˜ÜÍ ¶ ~‹«@Ê‘8‘™6lÐQQÏuÅ€›Ð‡üΰT̲±‚‹iÀ¡Ð¾„½ q¬Öì‚õšÐáÏZ¡Ñ#Ñ,BÒ&Aœ­¬Í-MWõÛ ÿY Çå1Íå´1Ý=}ÍgñÓþȨažjÒ!Ôá¼ý<ÊŒÔ0%´ä»¬+Í8õ¨ž‘¶劫 ÎAáʹÊPm0:-!ßp `Ùƒ\›Le}\¶0Èt=¸.hÓe¡Ò\×é,Rg]œo÷×q’¨ÔËaØ3Õ5o]z:, xmz·  ùª±”’G…rЀÁ|ÝŸ­ZRÀ¬m­— Òd¡×èå6fºØ´‡£bM|eÆžÈZ¦}ýYÛ«·Ê1п÷ ¶à & ˆmy£MP –:G‘8ÍRt¨¡˜¥ù!ªí¡­Qº{SÊ-œ³Ý·My¾ Þ(FÙâ=QÔ¿¡«v½¸-Ñ-:Ým0»° ¿pßÍÊÖ.­{dë(<ó­éy>}{|à¨×Ü™$ØGâ§ãå={Å­D( &` |Ž¿,ÞÞY‡á™Jâ²AÔQâ&¾âUfß]ấ(Îâ>äà6>{­˜ã<Þã>þã@äB>äD^äF~äHžäJ¾äLÞäN¾5þäR>åT^åV~åXžåZ¾å\W1®®™_'!ù ,µ”ÿH° ÁƒH(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ ÊÑ!Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ+W^ÊK¶¬Ù³h3ºJ˶­Û·pãÊ ,T‡èêÝË·¯ß¿=×L¸°áÈ¿¬¸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM¢ÑÚ¸sëÞÍ»·ïßÀÑ‚8<¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿>Å…0oÛßÏ¿¿ÿÿ(à€hà&¨Y 6èàƒF(á„Vhá…f¨á†vèᇠ†(b~#–hâ‰(¦¨"Oy­èâ‹0Æ(ãPøÍhã8æ¨ãƒvíèã@)dz=iä‘H&©dom,éä“PF)¥t5Niå•:Ý‚å–BVÉå—`¢T@˜d–I¡~f¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸‚Öb®¼öêk­hŠlR»þZë˜Æ&«ì²Ì6ëì³ÐF+m­qLkítZ^«mHÂÔmR^šôí¶ä–k.fÚÜ%@¸ç¶ëî»ðÆ+ï¼¹²‹Ô¸ôæ«ï¾üöëï¿‘Ú ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lsÆ·”À»ñ|óÏ@†¯¥Å-s F[UäH‘¬¤³5 =–ÔçQô€»¦‚K›\íõHE-6Éa§¥óQ–@å3GkuöEm X6ƒ!«Ùr÷wRéBÿTöhç­o¶‚»¸´@Hƒ4\m[í¤Ý…G.yWOvxV•?äøäœwŽ0» ´7J=‚稷;:o«§îúë•n>^ëA½-í°ç®ûî¼÷î»I¸ÿ.üðOüñÈç$;ŸÆk×|òÐG/ýôÔóÛ|Õž}s™oïý÷'>ÏŸøà—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚ ÚòŠ’Ázð8Ýû GHšðB%8¡ WȺ°>!|¡ gè• Òð†8Ì¡wòñð‡@ ¢ÿ‡XñˆH, ,’ÈÄ&¶Ä‡NŒ¢#bÄ)Z‘ˆPÔÕ·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£Y•ÅëTQ.o\£çHGÅÈ¡Ž`B‚UâˆG€¹á†ãcSÚØÇKA®ÛÁW¸P@Hš€ÅvAi"-#‰I¾IlÉGgbhICv29œü¤(Õ—B†ÜF\iä(WÉUªŽ8A%+gÙ°P>årÁeAšÇKZú²;®ü¥0¥ÌaóIÅ$L2-²Ì5ó˜ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ h‰ž)ЂNŒ 6‘¥AÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’Š ¡&M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP-TÊ¡§iF5ŽB“ÊÔ¦:õ©PªT§@[RõªXͪV·ÊÕ®zõ«` «XÇJÖ²¦ ’fM둬ªÖ¶ºh! ZÝ:©•€wÍk°G×É´ˆq% Ø6È}µL^B‚° m‰­L` Á, ld.¼vh^—ºÙ°TV)ìB"‡8€…°¤--W*9&ÿÈÁ³ €"a·»Ê¶1¨Ö`ЄJ„°lý­\*‘· £UncP‰X"(ØÕd¥‹˜1¹¡Ið¬@òÊÝÆ! +ØØ–7,£]lQß{˜õ–½Y-}3ßý:¥þ °{n£KøÀN°‚Ìà;øÁް„'Lá »p–‹-2Ìá{øÃ ±ˆGLâ¿hÃiñ‡‰WÌb©¸Å0ޱŒgì#§ÅÆãq/ÇùžÐvÇ@® Žƒl ¯dÈDN²’—Ìdö¸ÉP޲”§Lå*[ùÊXβ–·Ìå.{ùË`†Ó“ÃLæ2›ùÌhN³š×Ìæ6»ùÿÍp޳œçLç:ÛùÎxγž÷Ìç>ûùÏj3 ýAÚ#†>´¢ÍèF;:8‰.È6ý$S:ˆ/¾´¦7ÍéN7kÒžuÞ2-êR›úÔ¨NµªWÍêV»úհ޵¬gRdÌ‘.õ?vým¤+n„$laäKóz×Ûˆ_€f7 n蛣ý[„—!Înv,ýgjoCÙ@ Ýì6\;Ü%6 ©í†poÔ ö?$цpÿøƒOε›ä„l·Þ¡¶6ÚílLòYÞ%h6Òð€oƒ×·è÷³.BDÄâ\òÂýÇ[C„×DÁãMBŒ‹ùØÿ'Á½'Bm[8{Ùv¦¶$œ-‰oà8·¹D¨-òf#µÎÔ¾Çÿ!;8ArÐEÖv~ìž@ÝLqÛôbj#AÛ¿˜‚f ƒ Ì€ëSØ…Îr\]ÜøŠÇ*¸a Ô×Ûn°kXƒ€r„™òÃÖÍö1y3ð2ð(²€¶0…¶lÍmDZ ý6ú…Kbr0z˜|M@8X(_—€«÷ÿW=fiHl‹çsn˜çwH^%Ðxûÿ$oÕÖl)à†"(ßðlA}Ûׂȡ†% HX çO‘×l$…ÖÇu°.ÍFÜwÛ—pO—ÔÖ„%oΖk8w/@w3ðÙ†‘{IHX‡¸ÇFû×Oc¦qÇvv’p 8¨z\çÀ˜m¡bUçŒP ÚÖA¨,R''ìÖlM° Á'«H|sçw`sá†I ¶}÷s ‡:–$l×l» <8>hx»ðdá¶°ÇkÅÇ= ©j÷#W…ñ§…¼¸ÛðpÚŽ˜=&~Ëç=rè)A7}v y}s  ÿ`{ÀxŠƒ þ€© Àwÿ!‡:¹;©=é=é#±ˆu›0W0W0{ v6·,93—B¶  {²Ø‘pÖÐ$„Ȧx2˜p.¸ θkÇw¶MçlH}½oÚ0•àrHðpU9o—g ç…4ו çk€ÙÐkΘ|Ê·gǦ†Î†Ñ{·÷4Ùk’y–ýugÞvv©‰e© 3I•Ú qâ6’1§ ¹•¤æ–_ék¶ ~á¸n÷‘p“' *æ–Θl¥ ´Ih—B)m@nmоŒègA‡•Ç•mÛFiÔæn°|ÚXFHr›æm ‘ .ø=[Ck²‡àÿùPg 0ž±VŽJ±Žã„´"žî#šÓRž3‘pŸè™Ÿú¹ŸŸüù3îùŸf!Ÿ rž CŸ ûÀT úJUßYʺ $D“µâŸ ó "öI&š%Jú¡¥ž^F r¢*£ùT#!*£6J0z£:º£ ‘£<ú£j棭Öù„ @z¤H𤆑¢JšMF:6(ؤR:¥TŠž.Z¥XeOZ&N¥B‘A¹aê¥d e[ªgZ¦j*Pñ7mªc÷¦Ú‘¦kz@Z§j†xº§|Ú§~ú§€¨‚:¨„Z¨†z¨ˆš¨Šº¨Œ":'tÚ¨©’:©”Z©–z©˜š©š &?‰zŸz%!ù ,M`ÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë‹I^ÊœI³¦Í›8sêÜɳ§ÏŸ8 J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jè¡¢€è¢Œ6Z£¢ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf›&Úvëí·à†+ni’Œkî¹^‚î°ê®ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG½ERWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜ËË­@›gî9¥T.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšP=¡;¡ ç"´ð Z¡ åC´Á ’hCLÃÎ$ ¶ÈaÿÚ` [€%ðám±C@D,A •È’H4Q RtC$¨¨’$† AHC.² ’¸âK€ÆH¸A‡f,‰¢HDmØ¢ c ŠXD5ÆQ$9”D$n!)R µ`âQB‚-dŒ!©[2…C¤¤J¢H‚N ˆ~Ô¤H’([¸! ¨”„"E©’DB•9$%+g©Š<‘–¸Ì¥.y3Å]úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒfý¶¡ ‚lÃ×€? òlƒ þøG7 No DßÜ¥6¤8nF‚G€ ¢¶¨gLÚÿΘL¡å-`‹m†“œØ€NøcˆéÄ£?J€GlñÙ´Eæ™ËjâQé,ç6’à†q d F܆%µq òm¥@Ú@‚†âr¯DÉÙMKÚ¢œçÌd=I@Èlq)ÜMбmz£Ý\§$ÄÙMˆ•œH¥#)-I‘$ôÐ$¸jƘª!ª~²¤âTêTÉšVŸ ý‡BçÔ_B5Ÿ®¤ª$J° ±’³¯P$g;o‘IqÚ‚ ¿¼ãB!Î$‘ªÿ8ì79#þ#‡n@Bª)N+jï³ÔemaSU´QÕ¢$>{NÕ:Uœ«5«4g[›ÿ„¬1iCmKÛÞúö·À ®p‡KÜâ÷¸ÈM®r—ËÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯xÇKÞòš÷¼èM¯z×ËÞöº÷½ð¯|çKßúÚ÷¾øÍ¯~÷Ë_󵿰€Là©¢N0¸p«à;øÁް„'Lá [øÂÎ01ëÚ\ÈV’„jÑÙ[k#³€ŠUœ„HðV™^eBV¬â=“ÃùGcÿQOÒ˜"7lƒ“Hc áÅÂô°$ŠÜ†r²*õ*jL#aÊÕDˆ‡·Ñ'Çv¥ê6®Ìâoîã¶í„ì:W,S»î˜ÿ+F°C<ì6ƒ—–²<+¢ä”•ŽÄŠËõB"}V±“siâÇa’p‚ä  $k²]V±¥ïÄ`UAÖEPq ¾!ÌàÔ2˜Â/Ý΄@V§*ždžR`«¯x–x0^¿@NØÄœÕ¼bŽòißH­Y*+«Ø ›˜‚Ad0j[â yu¦ÿl''X¢(„.àHS‰sâôÇŠ¿1)L  ¼žÀ ‚m(¯xÓi*Á Ò¥Ò‰±ÿDgïB!¨žÁ6¾qgpšUÊå^MÑ™em*Ç.T`Qe)Ï!× ñõ äPïrڢƪÿi" 8Jc.z7Ìfˆ ð 'ŒºÐ¤2ë?Vü‹€#„ÚÔ–‚°òêm¬85]>*; 7ØâOo¸qà›  %9G^Œï7QõºØ¸ ­'¤×3zÌ/]Ψ¸â¥)AšOE½Z7ߨ Üð )(Äà›`ÁÇaT|¼…%.qr€Fû쨞€¤m …$ž´R^-jZçož\¥’§Ôc# K  sð;D`*>Ú¢òK@î zƒðúö3pÁÚA\×4Ó’øïi”ºU€ÆY:…/•ë/è¦ïá@¾ñá÷êE„¢¢ánš !Y.×ÿf¹ €ˆÛ§ÓqReÕUçòÓþì/@»îK€~ó±\™vqjþ“,óxÑÞ×fËÑ!Ø&È&õ÷&‰Ç|ÏöxqjÕ&}ßô——§} y§Á{–c}¥câTg p*àR¤Nð)_'Z*Ö›P{ð†v¿6}(‡d¯&e÷&S¥ôd‚&f“T‚®q'¨ *¯¦ 5ö -Ñטƒ`öjp]wÝTÛ´E^Ät{4På'KhnÿphJ¥be‡ òRP…9ÈPOTG7ŽUSÿpKád`µbúÝ”††ö 3ç+é&NR¶xÿñn¦}º°s4–D6õj±'k³Ab·’&iÀh¢ö ºfñçk{° ÝTd–h‡Úöli’ˆ€q²Ø‡ˆs™²e÷f1t3` ßÀZ>Æf µcâä„o')*ÐÍØŒa„lÂjæv²7ƒ¥(§Æk3° Ô§Š5fµµƒ,¶'MPýæêX‹!kòZÕx  “ A—vs‚øs%°f«% Q'‚µbÖ—chÖŽy 掅ထœ’g5öWp3pSŠ…–†ÿ Š•edùtM!XU(Çhö‹¹•c<&NùpFZÈS+Æ}–Òƒ•ÿBUèÖ~ÈM…ˆnäd vƒ–‚hN]‚c‹()ì(OÉ 6zB‘Šæ“"ˆMw Ž-ÙY+¦‰eR’ßpŽp† ¡qÑ”¹XÇ÷d‚ÕWéäÛ‚ÍP[¨%ÿ° |É—x&†˜âaÅf÷ƒTåTPG’dFyÉ%NÀ‚QÉ Y(æqf[…(fuYM^ö˜]R‹“©ÈoA•ˆ’h~FZiFU¢¥g`Tt‚–˜‰h²e1Qd@ B–ÁŠ6Y&¸5š'Ñ«fh›cÜVŒ±Vb²{A›,™ÎØéÔ!‹²eï:EPnÿ€šWR²dœ•èyê‘.0œá(•NDp;VM¯ôJ2É*‘T§܉li@õW>lóIsáGÛ`*@r@ƒD}™ÕW¶y'iå—g&y§´Öê(Ô©' šabˆqPßp€8!‹€GÐíòƒ;t‹Pš ÔMÍ(E)Ð'Š¡‰è–°pßÔP´f mÀ‚ÐÈz³M븎r° ºP)° vPfIŸºqKáŸê™pz·ž 6Aäù[•\"•\Ô'NÔ—\†¨œÆÕM»iràf\&UW¥‰¦kZ¨ÅÃlC:[S9€Š§BðiC‡\w7\ˆI§{٥ąQ»°©»p^Z\Nꌆ:ª¤Zª1ZÄ5§iˆ“Âå‘…v „*M– bú§¦z«ÈÓ.€©¸š@?h§ŒØÿàsÅÅTj¼º6jÇ*\ãF©›½Ê@b9­ÖÊ;™†Í\By Úp z­ «ÁU¢À!ù ,éeÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§Ps’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒW ¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙhIœ@S¥íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ßdÛÀïþüÁ_BID’D%¬_BqC$˜„ô•€÷ëŸð§?ó!A¶pÃA X@ðµ- n°…?ì/ý“Ÿ÷H @I ¡ , 8Ƚ°íd¡@V(‰Šï€1<ˆÝpBòµAIa ÿ ‰6Tp|Dˆ#a¾üáƒ%8!ÿ°6ò1€HpC”à>&êïˆô[_ÃHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£öhdÖû‡ %!„l„=È6¦(&FO@þA @nІl!Ãæýã„"ÈD¥4å6ö'=úȦ\H) SBÒ›¼˜&qÄKÂ’”‚Üß6lùmäÏó‡IØåBü¿aÆÒ˜m&ô©[¸™Ž<ˆ1 I`Óš,¥’K…Ps*‘„@üaÃâz© %AÂYÿmܳ„8d#qÏ=nó È4¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zŽ©ä-l!‰JBÚHh÷ÂZLä™p@ "¡Öë±Õ`4H\ŸYiR­Æ„kžI‚ýíp…{êú<¶Fb¯I„/V&a¯Lg)÷qY¸f!l]d\óª<¶F®H¥B¬™Jm”®d,ñº$ÿÀ€í$HnÒÇY.“¯Ì «Òׂ>D¸’€+igÖÇ>S߈ntð `Î2¹ÏE`á‰]XB rp‚.1]ì#!Âý- TK¡é¦ ¼((Õd)ÖξW 3ȯ ò;+l »½¤?ÊùZÅB¨‘Cšé9ìB i=Õ] { Kä3À0†_ …K0D¸Ú€«_DKü#Mø†\@€¸À-(\‡ê–Š­¶€þKýúx2¸Â‡g)€6ˆ†Åì‚_ÌÁÂÑÇn ?—½ŽùGaëNòݶ¼-%n«ò¤»ëMxù´«í)pùñ˜¢ûXùÌ#Ș߯¾ñÉ„Œ}òF.öÒu¾“!F¾ç,PË#¥Z×-òuƒ»Ê/†²ta)jÐÔÆo#v‚L` ó \ðü£ rÝm¡ÌgFïÑûõî÷Fz?ð Lyÿ9™2ßÂgqöЧ¶µ[@jiG¾è7§¼Žy^h_ ?ßoŠåêúMÚÂè8zhõ~ô§'¥gW¤[ð¦c”E±‡~Ño`GjPFj˜kÿ€]I° iGk÷l÷ À%[ùän`\y÷qrDWdLÄAdY· (px]g Òæ~-_kkYVÜfhßöûW‚Fdj†}Ž‘fýCH Ä‚*˜KÏÇz'Èí$ –Pm0ø* õ'x{vf\fkX&ÙVJÛ@» ÷'3ðeö'f"È|qåw‚”PåF÷$W»”z dQW@¬ÕBÿ1Y•a7Ö&mð —€C7“È%aEOÏd C—‡xxhúG‚P|·k ‡ÚÄ[ÇåˆFÁV¸¤v‹.à Fe+Q]m( &ŽõLïåevkb&ÿXýHûp‚•YüaZQу/Ö @*b'QW†&¡WÛ`aŠ3 w  ¦ÄŒ5`³”eÁæ´gˆ{-)0†¿ø¹uo¼' g&©ÄyÖ(Ç_÷  ÄWrÕODzÈfŒVJ×Öщag€bœÇw&ApÛ˜vV‹^2aϤ ö?æx–° ‚ÄŽ†øZe‡KðÿˆÅ5O±nᓘ@ ”«Q"Ño¡. *Ð%Aj.„”9KßÐYÎww0W •wð ¾XxM÷|¼V@i–±”c݇¦…’¡ÜØçxD©(hæY~츸äL8—“¦zóøFùÁXgùh’høb*·UÆ–aò†¦ô[Å&’o(“J'oÉå|¬µIܵ˜ô!HÒõ ŽÙµ8sÑÖ()@pÒ&M²ˆl.Tß° )0÷&fJ5™—DY9™VJ¯UL}ÔHÊEÑݨg©)úˆ‹ž)ËéÌ 'ÂU`‹Ä¤H¦ÔM3iMÎÿ¥XÓ ٜז–!у~„±t£9&lŠ|5b°fNGÇr¨Užê{”5Lßx·Ùp†r`aM]’ÂV» í¦[pXxþ° ÚÐjMüù¥4`ßPe…©ñéòÃx=Øb-°‰Aº{N'¹ù’ydµ€L99`–cÜÕ›‚YJ Œ%!•Ѹ•&©h‘H¨DJƒf8'lu ÊW¤EAÄŒ£‡~ù=ŠzgØøb&Š¢ _¢Im&É'wU‘‰•Z‚ƒ<Ú)hhK¹—HxºÜ´ ¨)º×'¡BoYn¡è1—«Ø[[Jìÿ×b.Ð~Öfk¨¥ÔuonùbÕH(©d£¶0@ñ4£ RJD:¤¹h –%` Àw ¨j ¦6eøœ–á¡ùl,¦.öbí‡gÑö¥-°ƒ˜z9»åá^ÖɃ¤)eúxZj¢ægØ~'Ú¥ƒ"‹R~Ã&Þ€L‰«%1†1®×«*j0©hš“ƒII0LÚ õ:¦Š{ÓjªË: ñ*H ä-Ú¾:c“ˆ®Øú8®‡I‹Å­;Á¬p­‘㓽°†š=Ä´Nôj>¹UJ Tx «>ÃÄC¯8>¦¥ßBß±%’–  I0DU(>V÷G‰°àS]ÔXqJ>a5°(Ë£ÿp¯åSYAg6‰ë´íS»UHášßð M+Ö.0ªä“¥á¨>lµ Í™>aõµ`›J› ¤êãµÊŠ>lu cë¶Zª¥F ´™v º€·s·ß#rÝù´ç%œš‚{´„«³çS‹ ´¡Y¸ås ’ ’ a´M×ÿ ñ¹=°g~Mð¹íCy $ F+>rÆ6´º_å6R[>X§T”±é=8mP‡ç3`¼µ ÛÀl»P„ƒ š­Û¶Ê >ç ¸ É¤è#Æeô#±±[8°»;!ù ,ÍdÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWm5¨ \­5h!õÖ`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwWÞ€% 1Q mDòI´!I$I˜/€$Í'a‹-é#Q~ún Oú’¨E ’>ã‘Hpƒû 8¾‰¤Ã` ÖW$ÐOxŸ$A€"‘`_B&(‰/m€`“PIL0yòˆû"á ÏÀøÚ`‹þQ|Ì+A$ÿnÑï}ókCЧÄ0 ñÃÃGÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈFílƒzþð]ÿÚHÇ̽±ŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌfˆïsC$$¡äùà I€6·¹ÍÿEâŽÀûÇ-ÂMmÚÏwÿІ B‚öIS‰à+gÆ™»ü#„:ˆý´aÿÏø£Ÿÿ؆-²ÉÍ9Ú. &ÔaP{n#…ÛL¨ì*?‚S! Uç6KÇØQT‡Àç>2Ò‚4Ô õ¨=ͧM|F þDDagOúi‡øFE*Smtuö¬¦6ªÓoè"E©6/Šºìã%0ç7t!9H¡ªšx#S1ÚϨ@¢å‰DbCTÙóÛÜÅ "ƒÈà »8jG¹šÎmâ´©ö$h´ñ‚‚L`˜6ñ€Btê+­‚ºÍ_ÌA 30ˆ[g`‰_8¤ŸÛØæVÑSÖW%u¨›ÂØÀ– G@IP‚º´týä lq‡¾ÿ*dmÕEjéj m"¶1ÿ KàY{nó3Âm;9\Ö¡Ú$ÁfÃÓ†àâ º®CÚ*Â2 ^­æyÀ*$ļ¦êgo¿*ÞÈ äyÁ ^àÝïÚ¢m¡ž¶ž Áí þ‘_…ìWJýæèîw¿[ôÔ º`HigðÜU±A¼ ±À â]ƒû;T'¤­2xT­{Wƒ0Á-®B<© ÚB¶¨6!lÑ d´} ö€Xø 6ÆñCµIMÒx½I±"+ÜÂ×·s=È~ýAPHysýÔ†6 `]ƒÀ÷½€•Á?R*ã~ÿ&@5«Ü„LV/X3›³ÌZn“Ï¡ïM¯  àÌS>ô|Õ¬Cø6!55§‚4Œ©~z8 »pÂ@ hçY Üt"Sýù‚þ´@Š¥f·¹ ;ôx A¾C™Cíe‚ØÓÆk^‡zG°u²–Ø…ukOܱŸJ5"çvËZ¨w›Ú¸Â~<ÌwÛØ†u5JMãðgµ+èæÊç[ÿC¶%øÆc€âä®ÕÙÚvö-ÄŠ o#Žÿ\©¤UP´îøÓž´÷WnƒŸÆ!qzì{B›u<Ýfm-hûÚÀ¸L9Úð¶Ôu­îÄ2ÒotôÞ8ôŒjŸmúÕ¹@%]CÈ»ãÔOxõÃ)¸µožß¤ÚmÑ×øTó›—€ÆÁMz±ßÈ`qМ_>L Êk†öSÕD0¨ˆ ôžê³Ü´8•^Ó…~üv݆lC*0 ee¯îj '–s›ùj‹a¤l@5´Ã¿=ˆ„^_§$ð~jh@û+ iâøe6ÑË5¥ø:óòÑkNlË)@óÈ똽èGOúÒ›^V“?½êWÏzÑD¾õ°½ìgO{¢1»ö¸Ï½îwÏûÞûþ÷À¾¾È+ÿe¾ýñ—ÏüæwRÓÏS¾óU¦ùé¯Lú£ !ù ,åbÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõO$|-6pöØhg9QÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè§/êIç‡ ì·a‹Ùe³/~ $ðïF$·¨E `>$án°E (ø nhƒ"á†üo|”ÿJ¾´¡‚‰`ø(A„´¡„ßã "ÂðIb…™_Ø`¾³ ¤HDR‚$ô‡å[` ÿ"!‰¶ãsàm!‰ÿñ¯lå#A_Ø>R±}!`ûô‡Å.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñp,Ý6̧ ‚üãŽuü‡A¶áÌQ zÔ£ïˆJë³R{K|)0+ª³Ù£´ 1´Í#l2û4‹´µ%HÞ e»° lK>ÌÄRÿ``"h¶g;I7¸´ÕãHFÈO¦G¬Ú´ÏƒIvë >Š=”KRÚ®âƒK+T6t >² rn;«Dwí£G» †ß³¥d›uìc™u{K"صE¹5zKs¶ÜS´T5h››O…¸:)Tû ‰æÓG^«ºÛú³®»»5:³ê¸]»¥Û€|È×­Ö™–P[ö“‹{GGô—@µnûdjù¼€ =ޤOʸ Q¥K>µ§©·ePĪ»+½ÊX½1Š¿;\[ª(ð äé´«kµÚ Ï% N`½Þóv6uß¾øR´÷£¸ÜCz’tKÂù=Æ4 P ìã#¹!vpvð¸ãc`.ð¾Þ“HX„†Ñý·½ÜûzþôŒM`‹‘µ½%^ õ’({½¶G¶þÛ=¡×~3Üsº=E+Ò•N0ÞÄÁµê´Â!ù ,}cÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í‘nêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×l³x ”óÍ÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWêr²ô¥0©LgJÓšÚô¦8Í©N³ÉúÔdáü©P‘ÄÊ}¬êÖÙR· KðÑ –Ü/\‚´ÀßȪV÷æ'€ 誜'°Òmþ8eÒ¸à­.X›óºùî}C q«^ãÚª g—@A 61!p}«¾Ø2²Mk€ ¢èUrˆC’—6ú¹À¹j @€4á.¥‰íääר$š>,HRYÿ¨ H –:6Wþ#±µˆ FKD–l®Ü†ÿ1…€"Ã@ °šÎPµ¶ 20ÉéÛœÖ.ȉePlB—ØÄ%¼‘ò ¤§&ãí-,! ”À|Õˆ Œ«'Tw%¤Ó/ “Ø·–òkäýˆ[ÃêÖ]¨мTP5“Z‚—#pu« l’Ÿi5«ÉïÊf‹ÐîUâMIø{á8cîueüþa‡…´@¸(q¯@n¡ã”ù IøÇšò_ïÌÝmO’€ÕJ÷½6ŒrA䀸 `(ñÉ|»ÜšDÀ@,aT‡|ƒ—ùF$œÐ4¡ÿ«©mÈö‘e™¸à@„)ÒãܘNÙM™gV£yБAžëµÏ¾õª–@-pBåƒì¹ "^h3M’½ºµÒO†ˆ$$±Ù;¼¹lŠ}«¦ ‡$`¶¸4b+;]…pºj vAXߪ‚   F4bã,€[ÛIÖ©ùâ¿j™hx҈Ç‘ ÜÈÁ )ÀUc&ãH0Û&nM¢öšÀb'ç¶`5¶¯èfÿy&-–.\å̳nÛ')Xp\Å}3;4WRP·Lœüƒ¤¸ ‡™À[²p½5ܰw£·sÿÆhÆI|f®Ô†"-ë“wÍ•ˆdâÃãVCWêbã<ÿ©¸Aâ:r“¹–"/ÊÅg¶ K”@›ø[„ €&<7Ðy³òàâ­ò¹ }!-›°»9I'}m%÷í7ü7ßþcê€y$”*¸W–@߈wЯÞXdï ¸äªÚ‡Ta¼¸o×0Ü?x,½®ÿCšÛhûÝùßy£Èvsåýò.€øív¸C÷ìàå» Ú“•^äñæÆ£'Îðy»á)³ìqÊ[]ï{%¿Ñy89ðªDá³þ8”à¶ÛÒRÆÀ¸{Ë¡zLâ§ãíívKRëû³ùV€ÿÈ9±ùæJ' àöŽØ/•\ä_‚êkÏ>náÛ³úmœWÿŸ[ß\ ƒHaòÚÇ–Œ•\ì‚Öóÿ s0s¼]"ª)¸ƒ¢ëÆÛ¥öy rVtpsu¿uZß0ǵmyJä†}wó »  »° X¥7)Pü6È5!ù ,bÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Z‘Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬ó„ äÔÎ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´ŸBí^SDPÏŠ—ð³ßº @BnHÒFž„-’D¶Ø¢7ï-Ÿ Ø0¼ô~Gr} ø.‘€Ï·öÔóN‚ñÉS_7’$a>AðGâÆñx/¯-mTBôÑKތ׼[ ¤¶ Þ"!<‚üŽHHÞÞl1?‚÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’š ÛHJOÊR2iCÏ\¡- X74fqå€NwÊS$¸!“uSäNÂÓGÊm“7,‰w¼ßíÔps×GÍBî£ñÈNS9(„¦¦²¢NI6L1‹Û<£?@é­à•k›_ ´Æ}(¤·¦Náʶ=J¤ýÛ«mqo|j¥QT  i‘3JO§ýƒW "VTÉR!•=ˆX'iH蔫akÿV‘Qz@eÍd "…)´¶µ¥ú‡0Ãç‘3ÿêU±±)€@à‚ÞªÀ¥Ê$j?ÂGè4𧙣t{ÞÄYmf1õ6Á ÙìB(éYÜâf–€%Àº“È‚ »/H©SìŽæß@B ¾q ˆ´@PA Ë©Î:ïShÈ/ rF ­¤¹…%J€9ÈA Q€\Ђ¤@ß௦þQÀw‚@&PÛæÀ»¡°Zð8¸!-¤²÷ `I)#O;ÝÏ8"Ðõ‰]ÍJà/É?œòáÔ8  Ì@ 2å´àÎ0u›„]DÄË©®g‘kKÄ *@óuc² þ‚9ÿLÿ0±tA$+ä»°ñvËBд!‹¿k‚EzûbhCÃWL‰\@€ô–Å_Zc[ІúŽø 8€ ðË…HÚ³‘Ð3f ‰3¸î‹_üf %?.Á‹Ãd œzvÎy€ ª»Íh†w µfàS›MLAHÀd`+[¼Ô³mhuBf°é€2&ˆ³'jѺ$¢>É©É4ÓǦÀÆ™>È\`í·Y!µ6°$ˆí›&$À³$ø5A²ýHƒ‰Ž×À÷6˜­Wû´DˆbŸ r €¯gäÍÌ"ÁŽDÙy,©ò˜Ø €¤[!/ص[ÍøÆ„`·Æëÿ‘6›dëYIÜ¡!w«Sè­Rî¡P3sø±@š qŽÜð%«ÓeO¼ /D×ÿÞ^·9d1´ÇÙE–Òc†ÜQËq*²N¿1ñÄàì.ˆ`õ1äœ<ܘ7JÐ'ÈÁ qÐwvÿTà[ÛØÎ¹…iG•  ì[ÈÍ%#ÌB–`¿v`Io/÷‡XC ¿“rÛ{µd–ØÅM=[ ::ÛÆÂ%³eâç”&À8%ªvoRvDçr:ãÓPt¯d°À7^ €¤–æCqg¾=MÌ¡Á›8}ìÿÙmÀ¶ ÞkîkÁXH"³—õ,vù-›™%N°„ÿ$Pð¿ˆäÕ.hB’à'ô’ †Ž¡gß—Êw;ˆrFKxZ{õð58ß K¯qã\&8‰Ó2ŽÙ‘Oâ_™7ÙF˸7ä‘ñrŠ(Y-J°’à‡cc?ç’Þ’‘pÓR—a'8N hhöŽ4”B)˜¸s„sˆZ!ù ,/QÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃGŒÿ‚W¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøynâŠËx I$Im”ðr mäF$›'qr•@ä– ùä*#!‰-nä¹ç''á†-´—NmDb9ã#“°¹$H4ºçHØÞ;æ­/Pñˆn²èÉ´¹Á£Ü†$IðÞüê‘´ûÉœ#D{$(`úäIØ^Bð• `~Êä/ïFJÈLþäÕ7®ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðLŠ?ZÁcý£yÌ 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6º1N)x£_² š½O1.0Õ'f ƒ9úq4–{ÀÕ4Ë\° þ°Ô Y¦[lf>K¤¨òW$ fyÄ–lµ dŒ /ðÌ!9倛24Ú`dn )P"䔈ÉdF|§‰?I5°TÁ£:©™oD–ŠJ¥-£ø² Å$Ô1I‚ðR•ÐtQ)£y¢&ÜÌš˜¤¦6·ÉÍnz³U™Ãæ7Ç™˜K’óœèÌ%L”I"ðŒ§·´'ÏzÆÅœ2{¦Ë`iÏ~Ú¥þ hù3‚ª+ !ù ,TÿH° Áƒ*\Ȱ¡Ã‡#ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ(‘@óÍJ €Í8÷<ÞD>-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´Ë­síY—€ÄÎ%´!xmHI» IàIØb‹ïHèî{ÅçMBï’Ô’„A¾ëMH¸‰$Ùó̳@ä}} !q¼Þ$! ·D‚Í‘ð}=B% ÉýywßFùIB $‘¿¾EO Á‹„Æw·ÛÙB ãkƒ-ܰ3ÄooÙ+A$n1Áê xÆkCz'Bôý ÄcÜqǺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"Ñ@þ8¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:wI|¤$'IÉJZò’˜Ì¤Ô"YNä𠥓þ±˜ò”vó¤@þáSºò•¦¼,g9˹Ñò–µ|Û-B˶¹²•¨ˆ*?ùÊV® –ŸlH.͆̋¼mÏD(•éʰyò”ÆŒÈ4 òK²E“#ß[5—Y‘jzmš¸4g9Õyµa²Ò•߈§<¿ñÍm"$’ìä,·¡ÿ‹)ÈÁ rÃ&¶LŠäSk®üÅ"ƒ+Ä3–Ú,¨ÕöÁÍÐs ™Á@^ €øS¢9h;`Ê_`t 20È RjQˆd˜«)ÖNy)0Ä£–péCDj5SnCmˆ6¡Sjõj¥ü†.&0ƒ  `ÝhGïpÔ…ð”jʳÄ€šÒ†p4"ʳ¨5åÝApêB¾*m8$¬aÅYÅj‰'U!jˆ"V¸nM¸ZgÕ†tUü[ˆ$âJÖ²ZB@ÍkBØ*¤± ëX»öM4õYhDe:ÓŸ®T¨—0Èî`Óªö”¤ÿ¸Âšª ÝÜ`»hm^µ§…¬d+…)x#· §>ã9ƒ“äSøÅ6Üš\Ò"ô”—°©A¤p SúcÙÝî0[Qëj-© ôìIg°‡]ДÔÈnÊßfí—¸4¨wí)ÎtBÔ!µïÖ”{O½öVÀ'‚Oë¿æ;ìÍf6„ †f/éÛJ »VÃþÍ/…Õ†ÍYz›ñ1Cüa[nX”0ޱŒ#§âÛøÆ8αŽwÌãûøÇ@²/uØ!ùÈHN²’—Ìä&;ùÉPŽò®ZЦ€!ù ,±”ÿH° Áƒ ’H(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J‘Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵkÕ…^ÊK¶¬Ù³h):J;± Û·pãÊK·.K°O°Ë·¯ß¿€çl%¸°áÈ+^Ìr-ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»öj£¶sëÞÍ»·ïßÀƒ¿Å‹W¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿þÒöóëßÏ¿¿ÿÿ3íà€hà& 6è`uÛ<(á„Vhá…f¨á†¬ Èᇠ†(âˆ$Êça‰(¦¨âŠ,¶ˆÔ‰.Æ(ãŒ4ÖÈ”CÁhãŽ<öèãœäDiä‘ò ù—’H6éä“PFùS#RVi%v²\©å– % —`‚áO_†i¦,æØ™lö‡_›pÆ9¢ŽrÖÉášvæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äklpt«ì²Ì6KP²]AKTÎ6‹[µØf«í¶Üvëí·à†+îArŒk®u¶œ«.IÒÆÅ$»ëÆ+ï¼§¥û~ib•/½üöëï¿,0¡ûÞ8ðÁ'¬ð 7lë»G,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐD Òµíâqo8íôÓ]kÒPçœ@ÕT-ÝQ™)áe/cT£6Ön"˜ .iBöÚ#ÍöÛ'»-iM“¤5QrT7Ü‹iÿSØ›œÍÁwoO¥KDy¯d6Y‰îøãÓÑ ¸G ]+uB{Çy9äœwnUãˆÝ=è›{núé3©úA¢«„×^…£.»¹±/Wûì¸çÞ*èàµ~ïOù®ûðÄoüñȇ$|òÌ7¿áòÎG/=N ‚ ýw×O¯ýöÜwïýÁÙäÖ÷I~r“Ÿ¯þú1†ïŸûìÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHB#',¡ Whš²ð…0Œ¡ gHÃÚð†8Ì¡Æ\¨Ãú)<ü¡ÿ‡HÄ"ñ%ð;¢—ÈÄŒ!¡‰lÊ\B u;(ZñŠDDªH[`ñ‹`|ˆ!òº0JÊ|fŒâD‚˜F;¡±F‚_“>8ÚñŽxÌ£úæ¨Ç>.‘‹~ ¤ IÈBòAãcZ©6²Å‘ˆŒä«)Ilq­’rBUƈI“/‡U¬ãXJ×Éa‰²”ÛiWæ@ʦ셑+i*5ã†Y* oÉÆg iËMµ²—Àá%0‡é=­]ë”u¡$1—IX¬iðû%3§™(eNF˜¹ámƒ ­Ë€Û‘hR–?Бü´¨“›"¶°9R’>w:çú>·Ê ö„¸àS_‰pYiK¹\ oÈ÷—Ó&íÁûÆ~”wäê,)ûA¸.ÂKjêSÈûðøŽ4ÆA"†2¾t0~)M@Häs>Á €>¿—õ—Œ—z&)Z'ágÝ÷$ Øx~õÓt<ÒX‘€Ao¬Ç x•udµèwá(—f¶Ggr‚¹âÖæ2ž§é×*X’6ÓUw/¡²B~%ƒFBx2ya{K×€|—h°b„(sƒAx(å’„À…±,Q€á4b…A‚¤A…DB«§tÁ†¡r- ‡Kxd?(‹Sshpè~±Ò|5ƒAx˜IXy…¸„!tYˆÅÿç'€ç8Џÿ'HÐd}H…ˆ*~‰2†21‰‘}e~F†£(fhM¶¦†,ñŠçò~z2Ø~±‰f7¢(cºHhÁXÃ8Œ(Š7!‡ Ñ‹…÷+D¶ŠƒŒ)ׯ(høbðv‚$q9.Àu±'zÆèBÓ÷„‰,FŠ QŒƒ7=(Õhx(Õ(„ÇŒ-¶cRØŒš8¿˜öh]·€_IG„±ÁŒ|ç‘G+ñ7FlØ‹:aŽ»ÆŒó˜Š˜‘)–.2 ‘a‘8ybçÖŽ÷æg iíØ²$’ñ„4±’sƒ#Q’(ÿ¡ŽÉ‹¤†“A“mÆ‘s!tLa,‹M”0©réã“yAШ'¬ç“ôøT©ƒ3’‚v•¡•$6~Xo/(‚ñ‹Ý¸Žf”¡–NÆ•1Œ¬'”;Y•½&z9’Pá–p5uè8l=H $}ùOY˧–)IžØzYrYÉ0(lؘ‰9—WÈQIQû‡¢÷—†“€‘™öó™Û™Á:Yõø¦ÙY²>µ ¨é± ª0ù)¹ùi Á™»iq%g^hƒ¹j½Íù¿ Y•œ uéFeÔÉpרÑé\ÚXÃiœ¥ñUr t Im²&fJ@½gÝ™ï™RW#†õÆx—WœÉÆŒD‰áÙRjXí ôiRDF\Ù‰o€ ü¶äf öv›â™ø¡r™7 Pˆ s›{øo™÷|ÊlPv ø†ŒgV.џΖpS‘ñ©Bω$!Jlä÷¢¿†sirž„4™yb£šû9AêCú£FªoIz¤LªYrvƒKÆ£Í!¥MšC1Z¥È_Xº¥\Ú¥^ú¥`¦b:¦dZ¦fz¦hš¦jº¦lºlTÚ¦p§r:§tZ§vz§xš§zÊPOº}ª'!ù ,°”ÿH° ÁƒH(Ç#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ *Ñ!Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«T^ÊK¶¬Ù³h)ºJ˶­Û·pãÊ»,T‡èêÝË·¯ß¿8×L¸°áÈ«¬¸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËž-Ú(íÛ¸sëÞÍ»·ïßhA ¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO?¨íúøóëßÏ¿¿ÿÿ(à€h eE¨à‚ 6èàƒF(á„Vhá…f¨á†vèá‡)Ýâˆ$–hâ‰(Ö”WŠ,¶èâ‹0þ´PŒ4Öhã8*hWŽ<öèã@–·cDiä‘HæÖF’L6éä“P:7c”TV™Ó-Vféã”ZvéåI|)昊Hæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무ÖjkS+ު뮼ºjfX¿"•k¯°†Iì±È&«ì²Ì6ëì³ÐšG´ÔB‡eµØzìGÛ"ÅåIÝf+î¸äF¦Í]|[îºì¶ëî»ðÆÛªºI…+ï½øæ«ï¾üö;(½þ,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4¯jqAÌ›Î5÷ìs_öR:ìÏ-§@ôW'E²ÎÖ\´XO›õÑüí˜ .mBõÖ Íõ×{ÎGYÏ¡MÙ© v_Ù f¬fw¼›ÛJ ‘Ø£ñÿmw¼×þ}â ’pSº=5“s îøãVù=áZIþÐâg®y¿ôv~Þ)í(\›—^-轡núê¬;йxª ŶX±·nûí¸ç®ûîÕÎûïÀGè{ðÄ?Óëz¿òÆ7ïüóÐG_.óIH¸õÉYŽýöÜwÈü~ßw/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ úê%ȳ 7híqðƒ ¡GX ð„(L¡ Wx²ð…0¼JcHÃÚð†8ŒIørÈÃúP`$Äÿ©4ÄìpˆHÄ!,’ÈÄ&²äˆNŒ¢!RÄ)Z±‡P ¯ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×H©,^§Šq#çHÇ:Fvì¬"Ç<òË ,ÔY™âF?Rªq†ÌN¸Ô…‚BÒ,³ JI!RrM{dK>:³ÅKN ‘žôM'CIÊñ™!¶äJTYÊVnÅ‘íšR$]IËšÒ)”ûH!AËZúR6½ü¥0£ÌaIÅ$L2-²Ì-ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ5Q3JЇ ô&¬,¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ i *Ò’.Œ¤&M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP%tÊ¡GiF-NB“ÊÔ¦:õ©PªT§ª¿[RõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬+µ*Z!C‚ KZkgHÐVH©r•̯ÞÚIØBH(j^-³$7Dâ®%H‚`6 HD\0YƲU¶ òrÊêY623$BûÙÍ൴‰±$CD‹ZÅ$Á m˜Ò}*ÛZÄÿ´Á ¿z­gkÛX£Db±¼- lÝúX$<6¸®€qÿ‰ã"×1‘°EsûÜÆä% ¶hèŠÒêZ% »õnb–*Þòš÷¼èM¯z×[ÃĽoAäKúľÁ¯ôËß÷ú7¾ÿe¯€LàøÀN°‚ ”À1øÁް„'Lá [øÂΰ¨2›høÃ ¶‘‡CLâ›øÄ6âpZT<ò¢œú­‰j_LcÙ°¸ÆUqðJnŒãûøÇ@~aŒƒLä"ùÈHN²’—Ìä&;ùÉP޲”§Lå( ¹ÊXβ–·Ìå.{ùË`³˜ÇLæ2›ùÌhN³š×Ìæ6»ùÿÍp޳œç Ô+ÓùÎ6±3ž-¢ç=ûùÏ€´ ecçm š!<>´G¬èF;úÑÖ•¡#Mé·1ºÒ˜Î´¦7ÍéN{úÓ µ¨G}žI“:Ô¦6u§ýahNúÒ˜ÞÆ¹àêO´À6`]iY§ ×µ®p'vk\çúÕ±žµ±­iVÿzÙÁ†(‰­ìe3ûo.8˜³MëK«úѾîv mø5³ßvt«p [`¶ØuÏ '1_Û5³H@¼uiC·ûÚpw XÍëGûà»ÆÒ¸’nHXÖ“ÖFÃÕ]YÛââüö4Ä ¾iCOÜÀ¿8Ž‹5ú­%Цÿš-°”hM_üâf“ˆ,2s™µ`(7—Ô "‚¨üâ:ÞôÏÏÝrŸeû G7˜ÊÛ ô@›œ!È ö°ßX¾}´Õ®~õýfú wøFÕ¹ŽuýåvÁß0ïoª»Ý7½ø·g:í»à»÷ùÈB¹@o±´ÿcí”ç´ç³~êÒ÷lî¦4çSÏúÖwE®½ì3¢y3Ã~öæ­ý_è½)hŒô‘æ¸Åp`Ýã~ÍÆ—Èê!Ò‚ä‡Äù/¾ýñGb€ª,ú3þ®_Pá§Gú§ÿÜÄ´ß/ècÿ$ûè©ùc³þŠ_%Üç Ö¼‹x‡üANèLüöñówªý^ñ~þ7€sä}€•K¸€ Ø€Ïç€ €XRFœ†z¸Øë%€‚ä1c"X‚&x‚œf€(¸‚5F~c’,ØÓVAƒ1xƒ'æ‚N¡ƒ8؃û$v„!„BØ<èƒÔHèe§µ„Nø„P…R8…TX…Vx…X˜…Z¸…\Ø…^ø… r„`8†dX†fx†h˜†j¸†l؆Rp*øp¸sè%!ù ,MTÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë‹I^ÊœI³¦Í›8sêÜɳ§ÏŸ8 J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jè¡¢€è¢Œ6Z£¢ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf›&Úvëí·à†+ni’Œkî¹^‚î°ê®ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG½ERWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæì Åùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHÂzR € wRª­0'Š f¨Â⤅8¤HbbC™@†4œaÿ䀂Ê$‡- ,„%ž@ IE Á,ÀŸÈ8q °CàEr‘$B)I€B9ÄA(Z4ãI‚IxQ C$Ô($ÎÑ$ˆÃЄJD‘†DI%R@€B¤Œ‰< i‰  †?œa$KÂÇJĉwÜäHÒ8ÃK²1“reIÊèGU–ä™t%KZ)K“ °–¸ÜÊ-sÉË^úò—À¼Ê?2Ì`ó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØ´•?²ùbró›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGÚ¶[ô¤(M©JWÊR±¥0]–7u³M›hC I@¹Îi üƒ¶àiþ!‰—–ÓHø‡6’`‹   ¦à\ª6þ€& ˆ8·™IP5¨¸…6´øÅkF"pC~êUEQUHpª5ÕS· `˜Ã4)S±I‘Ü­ÿ,^ÿѹV³ <È?"±Ø U%0¬4oª µ Ö±˜êOA¸ œØ¢7½ëZ‡:T[$ªfMÂTÿáÖ:V‘Mj‰7ÓÂüÜ¢ ˜ê]’„H˜›”½-`ªþöyÞ¬-al€$´¡IÈin£ØÝS¹€Q«Z%a µ.$´´ìnÓÙò  ³Ò¬xÅYÝËŽ÷1è= vA§Þö*ö›í½,^Ù_ý¾7›ýõï|§Ù^¸w Žf€õ»_[W°w­.7%àÿb³¾ÿ00„ñ+àëòW±N°4k+`søœ Ž©ŠWÌâ»øÅ0ޱŒgLãÛøÆ5VŽÝ§‚ûøÇ@²‡Lä"ùÈHN²’—Ìä&;ùÉP޲”§Lå*ë¼Vβ–·Ìå.{ùË`³˜ÇLæ2›ùÌhîH!ù ,,+ÿH° Áƒ*\Ȱ¡Ã‡ @œH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£J “Õ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿíwý-øà„þ“U†'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀŽ Œ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wè.mðð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ØŸmÀ€ü£ IÈA²…, ?²ÈF2RŽˆ#)IHZ²’‘¼¤&ûçGšt’þø$ EùRî/”2ñáÿLÙVêÏ•QeAdiLæ”<É?’Hý¡²$ÚH$mÀÒ~Çìˆ-¬B[$ýû%Il‘„H¢  e6ý‡ËŒä2!·@Â?‚i [,²“½ÌŸ4GLmü% AgsŸL¦Bnáÿ¶˜õ@=µ”@Ü$I$7´áHÄ;ÿñN áßÄ_7E²PÜ‚ ¨v¹Ë‘–Àú”ß:A‚„‘Þ#¥¨H)Úg&4#°ô‡’@D§ÿ¨¦’pÏhv’’Û(*D2*`>T¦<­f5ÿA‚”Âo£ÙÆ?´jUƒ n Ú(;G*Õ þÃíêûÖʶv$b¥¨þ1W¢– j]_> ÂÕ­nU %µˆ-:ÖÀ&!üÌ«ûDÙÖm„Ò˜¡´iEüÒøƒ¡ï¼…™ŠÌ?æ’¤ŽÕêH¹ºÒ‘„©¶@ÚP‚$”€¡÷„¦/ÚÆå¢Ò±TlSêPIØÂ ‘ȦnÙ· tþñ¯ˆ<îE´a mÜÂÎ5¤Q1™Ôܺ²Ã%ˆ6µyKÏf5°Çí+ ÁËÙž·¶­­z9«¥jt ¢ôëwÅ+ߘŸI/v½[Ìånò½¸…ïVo ßÒnä¾ê<ªuq©^‘¸¿¡o_E‚`üx½ÕU{¢Í ß̵…oG,â“øÄ&N1ŠW\Îó/©I½…-dLcçÎøÆš¥1Žm¬ããøÇš 0É«®™HN²’—Ìä&;ùÉP޲”§Lå*[ùÊ qŠ!ù ,²«ÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑK „ôÒ~… LG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺ0=þxÝ6^Ã×µ’˜!ë´”ÀùÇéÿüa‹6üÃnh6J Ä$ØB¨!ê’0m( žˆ9)&$†ÚHB$þ Š€ÒµªWÍj@m·Õ°fZªcMëZÛúָε®wÍë^ûú×À¶°‡MìbûØÈN¶²—Íìf;ûÙÐŽ¶´§Míj[ûÚØÎ¶¶·Íín{ûÛà·¸ÇMîr›ûÜèN7º[p¶€!ù ,´ÉTÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦L6sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕX¯„SÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  qåçýc€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ Ö†ºpcm@$”§ €ÚHÞ-’ð[¸!yÚ(ÿnÑId’ÐÝ6ü± „Ü  €„ØwÛ8 RIü^€6n)ÚŽ‰h,ˆ¥ÈC!~ñ_Ì¡í²HÇ4ñ†¨! ÈGüCÿHBi·Å%2ˆ€¬! áè8Â1 ¶ ›˜E?n#%€£ðÃf2‘” 9Ê!¶Á ŽüTÉÊ”@ޱ£¤pGZ ÀÔd°K!Jb—¯+à@r˜F&jc‰y”²øHü£ ª¼¡$` »J„‰vÌæ6´áD’LB¨ »Qš“”ÛŒ¡#Ë(1ÚN›´Ôæ$k؆$$¡I(ã-R'Ǖܱç÷É0Ï~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨFUè&!ù ,¯à%ÿ$!° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¼Ù-:÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`+DPØd÷‚ ”­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ W˜B°°rÿHH …·—lãv.4ˆî`‡9Xb=´ÿ}Dñ‡AÓùÏ€ô¤ü,hÆÙÙ}1Dn¡­3B €gà£nBÍèJ£L½‡.Ÿž-Íi—eºÓ 5²>ýiQ›zc›îë©WÍêV»úÕ°f¥«ú7×Z½©¾ž6r,‰Rcïm½…6n­`×Zzè {½[;{†üÇ7 2mèÉó½¶µ³­¤æz¶ö¶Çý¡b/äN·$ð½þ£Ûé&w¸­gHqoÛäÞµõ,±îx{µ0ÈR•é JÂßäFïô’êÆf#üÖì¥w¶kïqWüÝ §Þ»mñð[Ïûzèîø?"Ánê¹±ãð4Æž?Â}ïmw[{µf6¹·±ëoS/Øö.¶F¹ÃÒü çÕF³‚g›_oÖ±N:ÅŒ¤€!ù ,´qÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç C~D‚0‰-7JHIRË—.%‘|()‰JnN¦ls«¥Î‡Hl éfJ¡Ý´aX©È„I$ ¸…D©[M“0œù´«×¯`ÊK¶¬Ù³hÓ&4j-Çš£bˆ¤f›¢s6H"’­¥FlXaP³&¯–ˆä&±¤ÂkÕJžL¹²å˘3kÎÌõ`€‡Ÿ>Ðæ¯ÀÐÛ Œxؤ̃‚!Ze;l©¶ª.IëÂΛƒ N¼¸ñãÈ+ºMx[’$[Ο?_®ð$tàÝD’Ø´6ß{_ÿE’rCÆ[kƒ*Ég•*G/¤ž¼¾ýûøóëßß;ÔòI؆Fôx©&QPRdRN9!ØKJU¨Ú…6HV]bh‹„ùÇ߈$–hâ‰(‚D_At´bjÛ-¨PS¶ä…„1–£R„½ØU<êx—™â‘H&©ä’ȉhjAI‚Q®$“9‰å–\véå—©Ôâ˜if™hž©fšl®éf›p¾)gœtÎigxÞ©'F‚é矀ʤ{¡fh¡ˆž–¨‡*ê(£‹6 飒V饔b:首fê)§šv j{‚–jꩨŽh™±:«ÁÿÊf«hÒÚ¢­,Öúª®±ò:ë®·›k°½ûk±Ã&‹ë²Â2[dªÐF+í´”i™–”ÔRdm¶Üvëí·óéz&²ÁŽ '¹Â–û«¹ì®ë®«íÂû®¸óª+ï½ôâk/š}‚ë￟Jè£a»iÁž%ü¤Â£6,êáFü)ÄKìp¢Û¬ñÆc)¦²Í†Œ¬³Ç–,ëɾê›.È#Ÿër¼)Çl,Êû¶ØoÇ8ç¬ó}$õLªÏ@ÿ,tÐDmtÑH­tÒL/ítÓP?-uÔAïlõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå“€ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²¦î3$0«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p‡KÜâ÷¸ÈM®r—ËÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯xÇKÞòš÷¼èM¯z×ËÞöº÷½ð¯|çKßúÚ÷¾øÍ¯~÷Ëßþú÷¿°€LàøÀN°‚Ìà;øÁް„'Lá [xŽþ¸°†7Ìá{øÃ ±ˆGLâ›øÄ(N±ŠWÌâ»øÅ0VÝ?2ãÛøÆ8αŽwÌãØùã@rr è´ä9¶Ø†@2l6&7ÄÉN†È *ä Ù!Ú„6”,%×H=À rBÄ\[TÇQ.Bf„Ôˆÿ!YNÛ6~ämÄùʉ3AÚlfüCÉÚ¸E ÓÜÏšÆS&È›b‹>“M*QÿAX W®´¥cä¯Z1´V,mií³Íl^³A4Äm$™l¶@¥ÛäÝlc;µò6Ü“ä$@bþG¬gdòhÃæò?UÝfDÐöØJ„m€zJòÀR‹.ƒšÙ% ”°æDÂÙöTPj„dè|¹Ý_ŒS¶Qåz ™ÞRaõ@Ô } ÄßWÍf¸üj´ÁË %%£dÈI ³mdƒ¯ZÖò@ýå"×Èãÿxm$1éI ÙäÿÿˆQÙHà†Gâ×ÙvÂÛS‚!·žŽyÅ“dmÈzL$P¶?ãMô¢Ç{ÕöNz6ƒgÛ ÷s¬%ñpêôÞó?,~¨DÉ×hÇò£„êJOºÊÉöíÃ<ÛëþG¨rsf™<74šks±»›Ýïü¢ Bo]§}ée;­eî¬ %ÊN¦‡d‹ÿÙÏJf¸£ h6ºÈÑÖÆÙXþc€$@&ÁMxãm7Ø}ç@Ž5Åg|óTe,‘¨3ºÿýW }l\ÀËý²› ûÚ9Hh‘ÌÑîöÅSzæ/7ç›Ýùøƒ@„B8„DX„Fx„H˜„J¸„LØ„Nø„P…R8…TX…Vx…X˜…V}ZØ…^ø…`†b8†dX†fx†h˜†j¸†l؆nø†p‡r8‡tX‡vx‡x˜‡z¸‡|؇~ø‡€ˆ‚8ˆ„Xˆ†xˆˆ˜ˆŠ¸ˆŒè\-0W!ù ,µ¥ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(+–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]j0Ó§P£JJµªÕ«X³jÝʵ«×¯`Êíé´éÁ²ÑT;­@·cãÊK·®Ý»xÔkoE¿O,°¸p F|¶qß½›ÅK¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν:‰… º‹ÿO¾¼ùóèÓ«'O`½û÷ðãËŸO¿>ùïöóëßÏÓç6ü(à€4á·T{†¨à‚úµÂàƒF¨›Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,rØ^‹0Æ(ãŒ4ÖØ•Ú¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\vyÐJ^†)æ˜d–iæ™h¦©æšl>ED›pÆ)çœtÖiçxæ©çž|öé矀ªP‚‚j衈&Z˜¢Œ6êè£U…餔Vjé”9^ªé¦œvºc¦ž†*ꨤfØH©¨¦ªêª<‚Êê«Hnÿë¬ôÁEë­=‚‰ë®¼nFh¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ¿¬ð Ø0VÿBÃÀ¾HñÅg¬ñÆwìñÇËòÈ¢ÙBò¼Ïå*H)ŸìòË$›¼ÔJ¶>U3Ì8ç¬óÎ<÷ì3L7%éÏDmôÑH'­´]+/íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí7›·,SÓÒ ý÷ሓdq²‚'ÞqŽ×DxF’œd Ì¥5. æ‘ç·Ig.°¤IçksNúéèš~•ê¦þÑäB±.€ë¨‡¥gºÊ6Gí¸”. É.Òç` ÏûñÈÏeXî}gñâ Ñ~'ôÉWŸ¼ñœÁ•êÔ[ïý÷Ⱥ*þAÚ›d ^¾ƒ¯þ¬é[×þúðÇo%öó•?ýFÙ/ÿþü÷ïÿÿÞÒHÀì°€äÝ›`uÀü40Œ 'HÁ+=p ªàºd¥Áâ0¯ƒ a|.8"Šð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠX´þ²Å,zñ‹Ké"ÇHÆ2šñŒhL£×ÈÆ6>GŒnŒ£á(Ç:ÚñŽxüŸ óÈÇ>úQXHpû$=Œìqˆ¬!$ÉÈ5²‘â $ÃôÈIZ‰‡äÍ/ÉÉNzò“  ¥(GIÊRšò”¨L¥*W)”L·Žb%+gIËZž¤r¶, ¨RÉ\.,ƒR¬Ù&½Ò=_k˜ÆÄNÂh‡„b&E/®DI ’ÙARSNI K6l#Ëk"Ê™Þ N7ÃIN°MÎbÈä 8ËÉN¥DS`C{g;çɰqÚDžmùÈûÞGÿÏ~öŸþ ¨ù)Ђj  £A¨EZ&†ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§U!(P‡Ê1‡æÄžDMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«`­_XÇÊ3¡’õ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯w4*`MÌÁ" †M¬bËØÆ:ö±-R#KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚ«M¶´¨­ ÚàI´!›ljï·$ÿØÂµIhƒ-LF‚tÎÖ2¶…-mQÙþ*‘î@Hà†H73ŠH¸ö¹–É$¡\ôv»‘pÃk±›]ÛjÃ…­n v»Ûî’W.˜»n$n!ÞöV µ°…{ßk8Wè#vù›âÚ— ¹%pft[\ $¸ ¾ ˜lá†$XXú°eÐ'€Dîõ­†Gl¡ïœ–Ä(N±ŠÿeÖ»øÅ0ޱŒ©äƒÔØ 7.HŽ ²ãôX ?@‡lã"ãØÈ:FòŒ—Ìä&;ùÉP޲”§¬TÌQùÊXβ–·|ž8ä`H˜ "ÉÛxÙ g.Hšƒ,UmXÿ’ó@Ü<ú @¿Ið°¬þá —`»\ÖÉn·+g!ç¶Ìþ(€0×gÛúc·KÍ6n‰møC7¾E¤'-‰ù D–D¤oñaÌQZÔB¶E©Ÿ æ” Î¹Læå•ÜôýGV²»ÁÊ¦ÙÆk“k‹m@fãvnÛà\7·áÙ•s-³“ H/;&{¶x1½Ô ¶šÐi~0€ÜŒ @Å=7 s£Æ¤i%,Ú¶––•xóýhj×X¿ F‚¬òm]XšÕ`.A- ýt X¸@ôb æþcíVMžukðc d¼Ï&ˆ°­ùiWwº¢ÿ&A #íà;H¸ŒK¸Çfp§¹Õ–6™/Þçï ;`6v™MCaæjƒÞâÀx眄ÿ DÖ¢†ôÁ/çÿbüÏCOj«_½ †s@ó-Üë6\\"îÌ6Ö.î»rÛ@B6%1kƒüµa‡´ží.'×î“¶mSýñð~Çébîô@hÝi7È=ÒÜïzSãæðRŽ—ü¸3ÿaŒ] á5YrYËZP³6¹•>ý³³ªH¿«¹ÌvÃÐAýamœY­å¶˜o{癓fÒÍÕ}§ÙÛ÷ÆZÍ¥/¤ƒ¯ H7¾ØwF¾$ìè³þæa=ëy³ýê{W1Kÿø”öÍ2¶ù×?œñ³ÿ)ê/ õßOÿúÛÿþCì>þ÷ÏÿþûŸo¾÷8€€¡}€¡€vá€!X•1u6hxñúÇ$X‚&¨eˆ'8¸‚_v.Ø-x3ø‚bv‚8˜ƒ ¸5(1x!ÈWû¥d¡:ázv{„3~3a\AÄ„ÅXá~ª!…cd…VˆZ˜]Øg$§ƒ/¡?˜CH†`Q9™²…•UX°‚mt†¾á{Gi¨†„"‘Máöpȇ;…@„…„˜#È‹øvÿ(’ÄznèFH=h—øN9V‰‰ø‰[Q~ Ø×7ЦH¦v²pŠቋNJ/±Š!‹°X‹Ja2©8‹¶øv ½(¿xÁ(–°‹(q êáŠÆ˜¸ŒÎøŒÐÒ8ÔX›ÒŒÖ~˜k¤ŒuñcÞ¸áhA¶*ÈÔˆˆè8ƒ¨)h!ãUæ¸dñØŠU<øóø›hŠTØ5öë8ABÀøˆRûÈw B!ád yM³åAr@n` H#ÒU)I ¡#ûÀGI%N)  `-“$éQÿ…hå¡ *Ð$Y\*à*ÐP’áKÕÏa.`.à-P0•.À’-0•69•ð ë(Isà@ 0•>éIYp–*’5é»  šF‡P”’h•$P.à-`W9•!9•5I7I˜.Ð`ùTNùsàV™”=ù“kIgI•G™”šé*°˜Öؾ•|I•€‰•ZI•]‰•S©˜Ùø"N™f‰– –dÙ–. py–Iy™žùŒ i†¹—-àMPš‚[Y˜‡9•ÄÙ›xyM7† AdÖ‘Á’ ™>Ùgi•—i”HÙ—·ÿÉ™½ ºÀ<) •Ti•ÌyšÊ©š}Ù`™_ ’@ŸmÑey™iY™nY•q¹›œi -—– Å€¡ Ò¡—NQ à{¹šÆ™•@˜©‰•I¹ž à™E cc™žÐIY]ÚI™di™„™™ã¹™,iN€ j•ú9š¢I˜zšðÙ£ð¹¢x‚c©léÝ›.Пµy–ºù¢NÚ¤»0AÊ_6Ê–T™£Ä¹£Èɜڥ\ê¡>6Ó„]SÀ™EZ™)j¢+Ú¤Mº™n*—ÏX¥8ªžU˜89=šœ>º ß°Kõ9¥%xfZFJ–H 9´iw*SÿYÃé¤.à"éÀ#cG4*R°ž|9œê—“A¡s›^º•ÙȘdùÒ˜Xã¨DJ¨kII $é¢z¢) ÄS‹)p£X©ž`ᣢ©ªV‹#Y¤GZ«‘«ãy”¼jåY.Xf‘†[PP”Vꩌоsªª«ú.›H?⪲kõ¥Dy¦JYm*žÒÚ«Ÿ(ÀºšVZ¯Šz˨>*•wð  –ÕZ/ïXi'ß ±êS9±wÚ4ë$Ðz–Gy™@Ù•s’ÖJƒU’©é±ýÊ©T)¡±¨ 1œR¹¡[i ßà„rÿ°@ ñ+ø›N±±ª¦K–¡ ¡«o*2-q©·¢Žñ;ƒ²ÿš˜0šA¬ 1°xš£ðI³a q ¶Ç‚9vÉ6[›‰*N@.{›lê•ã™t»"k’0h,“¨6PKµ1¦ñ~Z€;/P-i˜jKŸ ëƒËõ•N°•-îJ5>Ë–Üé A´¡Ѷ±Õ¤C™1 ²!n*e›p $à› ýÊСª©ŸWɵ!ºXëb‘*­*«J¹¶ Ñ»LŠ•?‹´õ©ž‹- JÑ›.}I%à¯~˶¡´S›œ2k¥ºÿ{fŽ0¸ñ±rð†¹©†‹,{ 6Sé¢?+ºñ¼A¿C+ž’Y¤Ì{ƒü‹qp«á™eS©ž³;k¼ á¯y¥.0±Kiæµß° ƒë}ï ·*j™òKöKùK¨l*ÛçÆAT¨M ’ +…‹-¶'ω3Õ{½ÌXûÂp¸ ,}éÃ[•*³¨©¸›`›ðžË»NvÁÎê¼ÑÂq™ôJºÛI’)`–+áÙÁ6‘±€5ÀÙ[¬"Ñy ˜$™• 镟ì{Ã0ÁâÉŸ*Ê–gy:|0¶fxz®6ü`,…<®áÆÅÿkkÛ>}üdP|Àó»òû¼ÐÁt|TlÈTFÆ«)‡¼p¼ew뙼ǭdß0r0v00;È‹lÆ™òÈ ±É!Æ eßÐ+žÀñÁLÈÊ/ö lܡђCÁ½æw’½Ì’òú¼Äì™ÌÉÁ³x ÍÌMö +jËΫ±ÁÃS6Í,ŠÎqÍn»•\Þ<ò¬ð|YâÌ’¶»Ï$Ð‘ÍØ5Ími¤)ý ¡¡s§Š<æ¬ÍëÐ!ÐmVýüÎ!‘Ï/!Ð Ò‘µÐÌÌèœÑÒÝÔŒÐáÑ”qÏCaDÿc²P’°`™•.I•¡ÒÚ‹Ã54ÃEâr@Ô¯‰§8Ó áÑJ£œVÛУWáÓ.­ Qý¥6Ñ Ä"ÁÕ¿µ™¨|Õñ 5™$é-Ò8ÁÖhe¡jJ6 %Qš]‡«ÒnÈ×ô¡Å o©¢Ì0±×Ïz†½0s %»j˜ÜL‰ýT­VôÙÇÄK B-Qi¶ÂáÌ9áÓ“ý²`Út¹Á1ŸºÏ#AÚšº_ÁÚLU×1i™E«8aµupñ°g)”kûžý ‘0™]#Êì§Ià Z`韰mMË-RYeLÖq·¼¦¡ÓÇÏÿMeÅ=|\Óß½RçmŒ¼ ì­¯^ŒÝÔ*»”ûØ ÝÒ¸ lüÐùåY—™,êøÝY»¤ß,Éߨ½°± 7Å ñÔÜX‰ÿ]ŽéRî=SÙØ½ –ž— ñÂ:œá|ø ¶¤?éÆÑ]àÜã)u ˜Þ¥!öRÖY¶0™v,Ê ]©!áðMØÎ’ÀO`½‹„!vpvº1¼Ž@É™D®WN.Qߊ•2Α‘* lôsf!ÚwÚP¢QŠÔS[䱦[¢(þŒâ š¶+ÑW€—={ßi±R¡N°©<[¯[NDá„%{iëæ›•E9çϨ>ÙæŒ´Ø|"éŽ>÷,Óáé›ê¢^¦½¥>ê¨þ[™hi†éÛáê©~F‰ëÙŽ´~븞뺾ë¼Þë¾þëÀìÂ>ìÄ^ìÆ~ìÈžì}ëÊÞìÎþìÐíÒ>íÔ^íÖ~íd¸ê¡íÁír!ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«N `!‰Õ°cËžM»¶íÛ¸sO}­»·ïßÀƒ N¼øMÆ“+_^ÕóçУGÎôu騳k·è|»÷ïàGwÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_.ïþ(à€h!hà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâgÿ½(ãŒ4Öhã8æ¨ãŽ<öøW>)äDiä‘H&©ä’L6éä“PF)%V1Niå•Xf©¥G×méå—`†iVkb–iæ™húH]šl¶éæ›&® çœtÖigmÜ©çž|öY"™~šâ-‚º †&êaŠ6êè_U>*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf{d—Úvëí·Fº•¸Dq ®¥Œž«îºì¶ëî»ðÆ+ï¼!ÅAï½|Н²änÔ/QˆŽôï¾l0BÚT'@À7ìðÃG,ñÄ1\ÔÀg¬ñÆwìñÇc‚,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õ¤ÿ)ø“Ūa=õÖ\‹„±¥ævq bÛ$çG‘œdµ5}Í•ÛàÁ]¶v»Ì¥K›ÌtØz÷ÿí,ßcY=”%Li­‘áC >â~k• ]é&vGã1~T .™æ”«oç ž-Ù!¨år 9謷n炉^쮹nûí§Z¬ûA–›´&‚!à.|§½¯VüðÈ'ßbê‡F¥8WÇ+/ýôÔWo}®Ñ_¯ýöµeÏý÷ 3ÿ¦÷Бþù觯þú3š/PìûyüšÑNÿýøç¾}ûçïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…®FdÃÚð*ö»¡wÈÃú.+ù¡ÿ‡HÄ"q*9<¢—Ø6&:ñ‰PŒbû'Å*ZñŠ—"$°H#*„Š\ #a!Æ2ŒfLã ½¨Æ6NI¢çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ uÇä°Q-‡¤"Éșȡ‘;B‚T Ih¹…Z£$k*IªÕqÒ6c Iä<ï'Møä\¶¨Ê#I’,ù`Œ[¹'OÒr3³¼¥.“Ä„üG“(æ.‡‰RZ P§$¦2#–K¥Èîp)ž1—IÍÁL³šØìà5³ÉMmó.ߤH8q4ÎnšóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZ4*弨F§•Q›s£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦ÍéN#ÖÑúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõ…½¼ªgÒ¦UÐ|´«` «XÇJÖ²šõ¬àj&Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷Ê×¾’P%HB"‘„6dÕ¯kX ò$7D±ðCì]J@‚ÀQ°„•,] [\Ò ð‹¬fÙ›$¸Á¨=¬Ð†H¬ä«£U ¢HàXIÿ¼r •…TÛ³T¶ —Tín@ÙÞ¢…•Ä¥-qâX7ÜÖ¸ˆlƒ$’P¥t6m-tÕòX„ –«Û]Ë`ÛËHÒ° /[À‹7´A êKÚûÜøÚ÷¾øÍ¯~÷Ëßþú÷¿°€LàøÀN°‚Ìà|5¸+¶x°„'Lá [øÂΰ†7ü•ÅÚ?T£ÝË Ä&N±ŠWÌbðxx,/Þl[¬Ëç¹4Îqab¬ã¡Ìï$<Lä"ãÎÆFN²’—Ìä&;ùÉ€D2A¤<*KÄÊÀrƒçp.CùË`³˜ÇLæ2—ÅA3EÔ<6KÄÿÍ€³™çLgðl/8®³ž÷œ—ó™$yþóHnZA—µˆN¯¡7b‹ÈÑA^4F>+Ôv6Ð’æ¡§+€HØÂµ•Î4FX‹]$ÀÓžý-¥E-ÂV–ƒE´k‡ËjŠt¶Òµtª/éJÂYÎ1ùµpaD?Úµ¨ös­éfï:шˆ-ˆ éMO»ÐÑ–¶®·­\g["×F-±‰ý톼ØÙè~H¯E-nt+!ï^6¢sm L#¹öδ±÷½î‡hYÐÅu¿Âc®ܱÃ@n†#ü"y °>‘Süâq½3Æ-2ñ{üã  æ’€|‡Ü ¶ÿ Á?Hàa‹¯Çå¿g£ÿ! ÆÚgàú´þ¡$`»ãp:[lÜsmü”M‚©qŽp*ÃïèÀ-´€Êž| $@Ú°rI=Ë­AÓË €¤¼ìÿH{–±>öo¿æ·hMÚç¾´K÷êhÃsiþHü# j'H}?sŸ¶ësÏ2à¿r¼ Ä%0úÚÿþ÷m4sOúkô¸Áó×F Úží×øãm@çG\÷ÁÆÛãÚ@=üñ ìRǼã €ÂZ–ïîX÷J"üîc¯KB÷Ãô£¯ÒSÿúØÏ¾ö·ŸÍsß8¨ÈÿݾOþò›ÿüSá-ú×}[²!.x¿ü7NºùÛÿþøÏ’ËóÏÿþ7fÆþ‡%á€á~4Öä§æØ€ø€ˆaø} è^ 1€Pqø½åKV ¨ P‚D6(h°‚.x`$è1ø‚4rHg3XƒguƒqQG!³VƒFä}´B„÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢•_3ÊÑŽzô£ ©HGZºm Ĥ(@JWªÒ–²ô¥.iJbÒh‚S àÌé@tzSðt§> *NƒÚÓ¢’Ô5MfRq²TcjC'Ûèi1gšªÓÛx*DnšÕ¦rīôêC¶ñ²ÖTªÁªen¼¬V«pIT‘)V‡˜µ¬eÈ87R×`ºu¬O…kT»׌Ì­~miCÐ /¬Ž¯ƒÅˆZéªÕ‡Dbˆ˜mCd V»"V˜}UH Úp‹Øâ²šU¬J÷j‘ÐÚ«•eHƒ×ËÿF"«·Ð;ÛÞê— q-Bl!Õm ¡ þc.ÓêÛ^þõ!‚+¶a‹">·"s=¦pÙ––à`tCY?;VÕ²Œµº.të\R·¶Ènku:Uó2ĈýÇ-HÉMÚ"¯!ïA&«ÝØ®«lŒouo+àÞ6Ø–ÛU!áKV[¨^†µo0a‹h«Õ®Ø ‘æBXñþ€ø  Äe®R üJš6’‘o}MŒm´‘Šæ+Š©^ˆà7Dd#lAãuÇ­MB-þx@·8cAл³É ‘D–Û ^øRYTöñF)¢cbFØÿ $ø‡6g4ÛYÚøG[ûæFr">γŠíüBû£ÐJ¨Å@ÀŒŸ²Ï¹,¡ ÞH^QÏkŽˆ—J‘[´¡ ….4þ1êQÿ£Œ^H›Ã:ä…P²‰ãŒ‰@HŒ@Ú«nˆ6ÀXÚ€:¤¾‚¼X‚œ•²L”„-”Íìe;»Ù’ $H|Ò$ôÚÏÎv³™ÙdÂö¶È-¸ÇnmŒÛÜᦤ³,ÔBÜå&÷¹å­ Â"“Ëz=¾2gXZ» Ynê¾÷ÎmD d7™QhaAhE p±‹1I R‚/‚Ñ%IXÏè"®± (@ÙX”@ Z¤cKæXÆ6Q0IB-Ò˜EIÌh@’ж¡MD¤KvØÃJÒ%q#ÍxÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.K¢]úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÖKN.ô¡¨D'ª/À¡ÊüG l‘QhÃmø‡"â_nC%øÇ6’`‹CS¥iü,jGØ¢—ÅÔ† e* @Û$‡ùË&A£¶é6Dºs$ø‡-`ø‘VUVE‚$pê˦bUcÈUÿÁR`úc‘H‚?D* ºA£XEGÍz‹EŠõ¨xÅ* ¸ÚUmÜ ·Y›FIä˜Ûð ûH4–¬}£YOê$«8k‚HLF¢c *d:̹zôµ@”°ÂÚ” ¦õeUÑ*E7a8’³Ù†0g Tmü㬭ªU1KÑâ~¯¤ÆM®r—ËÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯xÇKÞòš÷¼èM¯z×ËÞöº÷½R€4]ßú6ÎÒÄoô!ù ,}<ÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæôNÄùç}†  —nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ!V Cª žKjØ ‰„ÿxÈ$¡ nˆ„$lAÄ¥$AItƒ-$ц4Ñ(HpC-’0‘Z¸! %@B ®(‘‹V £@ŽHƦ$A;lãR"!G¦ ±Ž=¡áiˆG¤pñ Iøb2F5š1ˆcäN²¸Ã6HBaLâÙ“ØbŠG”$%}‚„%&QmHä&yRG†ò†$àã(yÒ†U&Ås®Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎr>èæ,¦?²Îv²Sîˆ;×)OxÚ³žñ¼§>g¹ÿô“ ÿ@@êÏ‚ „ 5¨@Ð\þãþØÆC#:ÑmDô¢µ¨Fý‘Ñ‹Z´£)E3:Qt®’ž íç6.ÉÒ–ºô¥0©LgjÒoØÒL¬‰-LzË•"ä‘jA„J¢>DUª©<±‘Èc —ÅcüG‡ Ò_ï†X >HZ½úc —€Ž&ð64å~¶¡ÂžÈ?öË[˱ÃNì6Ú€á´á2Aî+d2cØÿ yuñl)Ù^æt§ȱÝæŠD4~.A^,[וÅï-ü! 'Á«{©¤Åš Gb¥-Ýë}ç<Èø ®ÿp³…Åê×I³TK,õ%¿ºe=_ú«°öë-ëi<’UÔ‰´ÅS5-^ûZ×½ö¯ãŠe£óºˆmmi)êIŽd¢¦£lJmì—¨¾p¾q KÌÁÛàžƒ¾MnoÛÜä>·¸Ó=[|#ÚÛ·îK[äø‰—°Å%4qKì»Ûûî÷¿ýÍo‚ßá78Â5a ]€òÂÚØ„ÁéÝÓ—€Å,´®3ÎñKjüã߸_ÿåxCÓÞÿÆ¥¨s{IK°Ôå-¹ÌMíRY0õÞ…Ö·%n© ¿˜æ@—i¤¿záûÚ"å¶lr+YšjkÈ‚é,}ú%Sm ©O1êPŸzKPi àºè÷,½![\8ç"O;È=òµ«ã÷ À¨€tY¢ËC ºÞM-@`ŒÝ¦å–-€“»T㙆)âCžø—¢¾Å.æPË®·RTÏ|Ö¯®õÎsþóšï<×-܆]ì\–ÞøFŽoáï¶»ží°{ìݾWÂc´4» ˜Ý HÜ»LóláK8Üîn ý?Z¿øØ³´•I‚ó]úÈÆ·TÉ@vAË®?Rš=ÿè/YEO± ‰iª«¸yª×þï6åÙéžïÙwœŽH€½@Ú uI(‘¥O´D´ÇD–T®da$€NsP“€ÔgD¶à¨´F¶ÀEf$E2õó'Kº7IvÀ€Óçq;tx¶0F¶ mKôDRÔJÍ—v€e-6J¦b~â§ycDu—DC¶À~ž—y£ÇƒvçwwÔzö§h§q&HG‘àqtg²·qH%KÙ ‚3%Èt\æwI% }K'iØgaÒæJÿ€„Á|Š×Rµ TWi}w tÄSTvi‚LäfF%ƒ¤Wƒá×~›—gm Oô$ÿ EJwD~f¶D78f6ˆ”ô†–„ 8€Ljž“ƒü‡ñdS7gæzW¨‰”Ô](|S4Úðdè'E:Hs4w²Ôs‡^Ø‚-èYˆC@ÿg}ÖçˆVKógƒˆ8„b8‰Û÷åC–ôRâG€Í8KþÐdL¤„U¸vUDC­¤eð„Ný$€¯lº‡F¶I~×J ¸wÐj4ôP hÖwºèfn fŠt Hi§Œ['QIWÅuaˆ;Õdþ挦 ûvƒ›wI:¤`…Û0I%jYjhz³¤ ¡Vˆ X…\·kÔ’A츄؉“'xºÿG‹3å{¾' ’`IG/ø ?©‹xµ¤thˆäX\5DCTº€ŠŒ—qkD°|”WKº„Ñ8~SGfL…NR–ØRV·Y9–VHYK÷æ çor—t)—sV$r÷ X8—~ p5 —0n·Ô•–  ßÖ{‰ nŠi Ù{Cd–%?VƒŒy™ßÆ}Gin¸Ôu$P`Ö°¡)¡mpDþÇF™u|ý$wÆÖK–6umqmµ ß `SV<»èCµFKÚàšÎ¥e€€TtÀ4ƒ4x]‡…Á”’–ÊùÑÉgÃÔl$ÑdPœ¸´lÙ%j$°höC¶e® wdˆKÎùïY¢&ñøKBæf¶×Éè”}ƒ½ÔŸEˆ€I€’NA˜aÐ×L,¦g(EüÉQÈ9QA膠дeêh™ mpJ(öFÕôP·PŽ)–¢¸SM'Ø¡#ÚùKóéŸÇ WJ”£K$Éi5JLG´ˆ®èV.™Nzûe¤Jº¤LÚ¤Nú¤P¥R:¥TZ¥Vz¥Xš¥Zº¥\Ú¥^ú¥`¦b:¦dZ¦fz¦hš¦jº¦lÊ? ¥.Ð>!ù ,yTÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®9]@Âæ ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WÈB™t®…O)Áç`¼p  ¡QdÈC” IСQÿlH‚" ˆ „HúP >d%˜øŠ8¢€E;°ÀˆT Ê‚;´Ás2 #O(RÏÍP rˆE€D5ò ’#ä‰6 $vÜ âàF4¡[c yR‰àqâ"y‚‚FZ"(¸áß8É›às•@ãçœX‚Næ„n<"7iÊžR’­$‹hCÏÅò'œ¼%Q°¨Ë^î…—¾ ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6· pó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžø¤â?òÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'Ê=[Xô¢·€$æyQ‹ à¢ц$@ªÎ[xÔ¤E©-TªÒz´œ©Lg Ò—Js ñ(FgªÒŽöô¤¶àæEGjQ¢u¨H-ªK:ÒnT!O¦7 ²Ó”î”!VÍêJmJÍ£Ò´"4åê@¢ªÌ°#a¦6l±V‹¶µ Ú©\rÖ³ÒUme«X“WmlC×X©2 “ÞB†H\ ²Ocþãû€lI¶ñÊRV ûÄé>;L;ÌÁsð,hí0ÒÄ´ígC; Ö˜sØÄ,q MÿÜá¹mnq‘ÙÖöÀµ­2ÿA[’žd«YMæ?bkQYÜU vîs#òÕazc ¥íG3BØ‚t— uuéQIY9è¹±kCÈ:Öƒ W£IU¯.§úlC».Iîw{éÍÊ.—·ùé0)ûØmØÀ¾è…YàÈA1±…QïL¿>Ö¾5I)hƒùØÊ `NpP<_Wöµ/Aî†}ÙaœÒd£m0 | ·Ö—þ(°M.z ßÒ¾­±EW¬K Ù2&ÙT-ôWïx¥ ]r,MìbšðØÇ­Ü‹â— ”È·4ò“‘ŒeSjÙÉ "GlìK-ë8ÿ#HˆšÑjÑãØÉ]N0˜oÙaް×".³)-\ß ô{Že‹GRå?¤£vns‹óÌä~˜Áþ•ƒEæ¬ _”¾Ôí‹_ˆLñŒa© [™cÿÆö"‹@’Î6DÀRíð?’„Xc×ÃÌ´&}‘opº Qeê§‹i_;$y%´v¤‹ùØ)ÜA«vȱ‚íÏv™õý«Iñúõ*Á!gͨa;Ì} Äݲ­bëy'„³ñæì7Žyá §$ßÍøIÎÌ3ÛÃ$1¸–¡éßË2ºá|=ˆ_~æXKy!HÅÏ\͆û·#w±½›©ðƒ á©ÁiÉ«|Mˆü!*ùÈ«IqûN|á6çøÆkÞd”oóÌ!²Ë>t¡“så÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡Ò"D'JÑŠZô¢(ûd ‰H27vt%*_÷G[˜Ô•Ü€I ZG¬Ô u<©@ùÑ‚¨ñÚhçf$jx"d‚ä)/ ‰:O @ü‡-°™žŽsš‰D5² $àª: "MÔuÑ–<=È"/ÙÔoò™Dmƒ  d D­^ÔF  Å6àr D5Ý"µÁT<æ1¯–çFAùÌYºAêT€„’ Íüfê6ÊÑ=Š4!]üÇe)ƒÅpJ4 $è¢-òÈÖ\Öbt] éÌÍžN¶xjCê([Ëÿ$¡" g=‰Øqº”%Ф¶ê®¤¯¤3éRGZ¦›:±XÇ[”Ö­r½ª Ÿú Œ…ìãéLz‹Ú6ò‘@îdnkGÝæ²·¹ˆ? Þm¨Õ·Èk)[:I,×!S½Œj?Úb àºb´Ei©Jiò‹[-fó«^±23e|ê,ŸùÞÄþŒð•/-ó Îì׫^$«_UÖÊpXÏ)isiÕ:z7&k;Ã)X3¶Xt‹Dª_—ºS«  üÅ©jQG9~2 À*eÿÁa áÇ@¦)`mŠSçVæÁ ‘hX©[;dú×Âÿk‹WR™zÿŒ/eé'µ±Q£xγž÷Ìç>ûùÏ€´ MèBúЈN´äº¹Gùp?szgªÄŽ‘n –YR[ÞBÆñó¥ÝP+dÍø$ÈšMGd.—¿£¶Ì?i2†Õ|åm9Z‚×ÄÜtåZF^ ÙÕ“ÉãD¤úV¬WŒÖu6¶<\g+R ‘p6T9çåm{q ÝÎeªóÕ^µ­J&!“ÀVÑ~w£Ì”¨$„éû~W•$À5°Ç=¹c_zÍÄ.¶d ‹ØÑú´Õfç½HH„ÝÈ€À¨I‘¦rs*xOa=M~#F©Gm7z§-ë¶Uœ¨ÿõ/uY9ol"öäÁõ´¸7‡îH§Úþ%¯rE™ÞŠ‘Ýš¤e*Ñ9×søà´´kc»Ø`íBRÒ—³9ÔÁmÒœï‘猱£Ég-vk· ~üG8%Aȹöš jÕî.<•zwꔫ¹f~ÿÂv©ÊŒËî*x“z£?N«ntÞI€³K~oš‡ÝæêÎ'Ÿìt¿‘–ÕT«/9²’ðÍDmÇâašS{êt¶påCÌØj"üÈKÏoéóéy1"!³–¸[îqÈ¥ÙÁµêõ^]fR˜þúÂ…YƹS­£ewÊøLf³û°|Ä}çÌ+߃lS¬•W²ÿÁÅ9W3N<ªX%Á-T9í.ºÁ»³CoÃ$P;<ŸÃ•ð/ßó_3dfëÇK¾äK„$l—³—_áw¥’³T®–fÅÖ{€ò r h+åu …ÔEyÅJsg›" vE*кBH’ð‚{‚RÇ1’E@Sp&Ø$9¨hƒReäs •N‹‘YƒŠÑvt¡d…÷Sñ ïc p„aTU’JÁSK?Ûàƒn…èV\5—MPG\(?–PpñM1…dŸäFt…ÿ`\%Gwë³rSÓ÷I% Xÿ0I´ÅU‘ô ;x6NÈ×\W¶†G…o¸JöÿÖu£åpnÐXUôGÑI¶€²PGÞPa8†m¸K6gNxDÕd‰‰¨Tl8k( ßðŠÐ¯(ˆphsI°tb¤L”I©h %€‰y¨G%· I M ºp (`'ˆbW¥hD™„[ÍJ· —àáÁ‚a ‚8‹åFGF…@FHuä¢è‹Úð â˜NâHN` rÀº4‰œw@i$Y]T†.qŠDŠÿ )° …HÞ8-ðÑwPn(ŽÖ˜@»‡m ˆ6AM yeßàÏÔ.à)Phèà¨vï˜i@ÿ)‡aôÕi¤ØŽáŠêˆO™XaÍ#…2‘ )vK· Þ(° º`nPn‰h_„'qWjH“š@*`Rð qôŠwi¤“)H Yn»t ÷(a)è*i  %&…”1•þãIgyö•uô æôŠ›0‘. *Q‘ÚPe6tPx@-9:5H¤x n GN Þ8—%ñ’1–r…mûEÔ—àp?‡dØX_9É“èUÞPG–€@*° ‡Ùp%¡ —Q›—9š »`_¼¹ ßà‹ºPˆZy?-0›p –p !¨ážä‡uÿ¤(ð ›`Fñ2Q›†äM½™UHs¯šrÙßùM¦H9•` 7(àXh(ªIΓš) ›}HG@ØÉù»ùžËƒ 7± ˜û’ßP™±è:Â3ˆ#aCÉ)PxpùD¢0U‚‡‰Jð —P‘F!‹áDJÉCkm° 7n~è„JY6WvI°  Éi‡Ë#.@%˜,Q—AŽÿ¢¨6'Eq¢Ó3‘Ž)š2±’Hf”asÿÉ¥9qW¦Äž !HY-ÊŠè6‹ß pj-°§ä˜ñüæHH¦Ÿù™ì¹ CQ‘Nÿð’HÈ—ýƒ†TêV58…]™Gnt’¡¨©>‘›HP•, ?r`s¾õš†$W—K…** !¥;‘Å´‡"ú>}*ù(›Ð«šœ|vµð‹Õ冷° w@Jç)I£à¬Î:ê‰Wߪë¸?1I›ré*Pªq„Š‘¨ªß*P‘I qi~4Œ·š?à8Xžkøß° ( š*n ŠúŠ(P•AJ@,)qP•06ZNÀ‚MàéʬJŽÉù™N”¬³j)›°Qö·d ¥ZÚyâôpµ¤­­‘Á¦²ÓEÑé_–0˜±A«ÿ1™¯ãJNЧP:Q¨—€zœ*Žä4; +EÛM‹¢´˜ÐHRÇYµ¶a ³æL ÙF;PTZ HejIP覵£jOR0˜sð ˜éʲ] P¤iDx­5´ÑVfëPäÈ^gËHµù™T†"i:Þð v0v0vi ±rp©£p«~êOÛ–s:™+›ÛQ‘®¹P1“t8:¹u«­q 9»û8£;. —` 3»~ú•€}9`ôÿ>èÁ ä|#tžý"a¾ó¹á}Ñ“ÊÝÂî0{)¤ÇÇÅ.&oƒ^ £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxL‹6Œ“Ä<úñr# IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNziþø¤(§¶Qšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™tÛ"4§IÍd ²š¥™CAT€ÍnÚM Þ §8ÇIN¹„²z’èb§÷ÀrF-itòRðÆÈs -€È-ÞöþÐÓ%ë§VÀ»|€#%ÈAwÅ›pS" ÝÞ=÷¬DTpËBBÀkjN ”DÛ"ª²4a ^³ÛDyÒ½mt,ùÔ ED Ð|Áó"YürNŽ”4|ëLÞJòRä%t¢H}ÞP¯wÑž4ÕrOÈ?ç–QàxTm_Ukš¨ŠÄ\ÅZKµ·Ôéíc9ÝêÁªZÔáŒÕaN(N ½:º*¬¬Ò³«pðÚ°žrï­Øã«nÓŒ –6M½iX储:å§€S+VË–Pv±Ikªd©æØêu³  ­hGKÚÒšö´¨ ãY½WÊÔº6W«Èg)!ù ,e<ÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.¹ÀMnù—!Âåœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHš°18¡ S I‚@*·B”€†„ÜPÜ$¡ ’°ÅDÿJ€„ ‘h {X$´Á·hƒA(C&΄$¡$”XŠÔ¢…VŒÉ ‘()NQK #KR8‘´Á Eì" J‰ª1&I° ’Š awt‰úXH uÄa WÒB A„ã"c‰¤¶È$'ù’Z¸AŠHH‚(Û„4r2%l@#máÈSºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©×laJo’’‘Ða8#q !~3“0ee»ÙR˜Ö10ÍfLu踦*i4¡ӚƔ¨.f&pÔ¦æTšF©Q§:Mf2ˆWªV«‰Ô®Nu©ÌLªXêT® ¤«R}ê2“€J"D«Y«@‚ZÌHà%B.a ¾úµ¯}mæ ¿a‹$d–ƒ%«XÄ:³ÿØF$QɤjC -ͬ62KËS²Ûp! І 1´ù‡j Ú(ÓÑ ë@Û€«)‰ÑFB†˜tah°à–š$ø‡-ÜÖ¶Vÿ€$5‹ ]m¤Ðµ®Mí“ÊLØä·þÀîÿἪ Ü…¦?¢(Cì&áïE‚kIàÙin ·hí{÷û4^Óƒ¼k#ñçQº×Ô†®ÛZ$¡•¨¯4e €ì Â·-Hv• €$(!”H¸°€·™Ä6÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽn…,T¦%.1RK(S–˜ƒ%ä°Ì[ØâÚp©·1š ĦÀ©NkÊÓ›ö4§ù‡P Ô¢õ¦A”Z¦Ä©ª@¤š¤Nõ¨Eõ‡QHÓ®Õ«`ýªXÃJÖ±ŠU!FE*V‰ºÕWRõ©ÛðG\ç*׺Îõ€;•‰Wòmôµ¯gýªU(W™@UM݆6À*×ÅÚu8…Id òW°V°~]`ac‚X…Øõ³t+ó“½"¤²9½¬_';Z™ ö­Q­c+€Íÿ&°«°M‰i"WÀu®ƒU m_²X‡€ö± ÜkY²[´®ö² .G:ûê·¶Ø ©q«W >Īn˜¤f—»’âF$·$­d½‹EòªäµQänDÐØ‘æÆPº-1o{ÝëàZľ(Ä/K¬ëCù®—¿py¬AŸÀéóoi]‹]$ø%ö ‚ßë` *·»¶à†#B`ˆ”…vI†78b”è×~!öHŒG²â Î8$ÀDïíÂêÑN¸Æµë¬»Òⓜ¸w4u!£ÒUmÜðɶ€²”£Lå)[¹ÊX¾!L—d@ÉZlc S—–ù¥1E³™Ó|æ6³ù©ÍkVìƒGS|™½ÅD¬ï®Qkê†âMšþùê~sŽ—áO¹.€ê¬×n»¦æ~ì&Y—å·ï(ð¶/üñÈ·(;u¼µüRÍ'/ýôÔWoýªÑ_¯ýöªeÏý÷s¹¨÷Ó‘þù觯þú#š?tìÿZhü˜‰Nÿýøç~~ûçïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…zEdÃÚp)4¼¡wÈÃúð‡@ ¢ÿ‡HDËä°ˆH,â“ÈÄ&:ñ‰Éë§HÅ*> n°"ŒP‡)jñ‹„ÇØC.’ñŒ74#רA/JÆ~lŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€‰—³DÐòˆLäPÖ¦H¡@*jlä·àgBãÁ±+´“ä¦.©IØŒMqHÈdR²3H”´ “pÉ"*‹”„²dƒ1…\å˜D)KÊIJ–¸¼YÚÔÅÉžÐ2—À$J)³•±aó˜Ûº%OŒ9ãYÄ™&2§fRóš”&6·é"kæÅ›çŽÄÉÍršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JQ€j³¢9s¢ÌŒz”Rý¨HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚÔz!½©N¡uÑúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZµˆ9½j^(©ÕÎ ¡«` «XÇJÖ²šõ¬ë(Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷ 2µòu,‘hå_ù€mØ Vâ×Á6%t$pC$nQ‹ ¡—ŽeËJHɺÁIhM$2‹—6$!ªÄâhI+ÎJ"´ù*kႜ6ÿ¨!\-[ÜІе!·º=‹Û‚û:$0rwÄ ›H`Ùã&w-ÕQ :+Ì>—,°„$l»Úë¢ÅJIHBJ [ Ö´Yõ®Q"k‹í– ½êuž@Ð†×  §ñÍ/xà«ßþ§±þ °€LàøÀN°‚Ìà;øÁÆÐp#œçnèΰ†yˆatxÃDñÇAD â©È¶Ä]9±@HŒâª|¸Å0&¡…¿òâï¬P¶†ç×ëÚ”Ål;׸kÝ¢ ÿ(²—œ3ùÉP›ñW¤LCÙ@¶É„¯ÌåÅP¹ËCÙrIŽ æ2›ùÌh¦Ÿ“ÓÌæ6»ùÿÍ‘YÛ„å\:¿)ËCT2œ÷<±5 ÄÏ4D-è7ã™Ï9ÁðÍèF×fÑŽŽ´¤G³æB°Ã_VÌ¡IéI{úÓ‡é4AÄLKƒÚÊÁ¯2 jŠÜ¶Õ-‘]wÛBj$²!¦†ˆ˜kí]_Ä×áuFD-Q/ˆØnöX_ìlz ͆µeøûAeÄÚ&ºpKæ†ö,Û~«@òì²`[Ú)¡6ºòm&æz ïf £‘sKåܯn+½×ÍïøØÛ‡‹Ž÷bŽëºdúßýN¸Â¾‚3üáK¹#Nq L|5_iÆ+^KgãÈÅCNò’›üä(ÿ/ÈS~=kå°ÙwEY,sÎŒÜ ¯ùPnÞßn#æÖÒö8"un¢§å¸@—ÌoÊóŠ#\×ÁöɬÓct‰U]5KJ»¢nº-ëC:.ðTM׫ë¤é|úgP½—¤£Pí´É-€u"t†ÜB±É»bô¾˜¹ßŠïšÑ&ÜÙëgž,ng¹D|Μ&īȇ'ÌÕù£H9ñ©1^v P´oÇñIâajöåÜ-¦pͳO?ú†œ˜õQ€G1oÎ&ßnU×éeOØ¥Û¥‡*ü?ø^.´çcð ›¼%ÜÏ=>BýìrT?"׿~hT`ÛÛeùŸû°ÿø¡M~—¿Øç¿AÀ_œ²+E€û«·èúÄþëwó"}¦ù°mH>І~˜€¸€ Ø€ ø€óá}j‘|j€s4¹áz\AIû0ˆ»`9° ^£~1q€ïáïô —@/Øý§*f=ÿ€‚òw¼×?(&x²`²×è?<؃÷qƒ±J!jÎg{è9hÚç9;(K/˜]ˆ8€íf6©V| ‘…g£‚0Á‚Ú1„Q…ÑSÈ¢×L† á†qhž7"³u!‘„Ô£hz¸|ˆ„ÿ¸W8š#Ah2dˆa ~g4[¸‚‰X#‡Q‰!ˆ/}ØÁ•ˆ‰uG8j¨#•·؆èׂ…ñŠ!Ñ(‘ha#¿ô…!Œ÷u‹3‹vF§‹ªq‡AŠÁz¸˜hA|ðƒ) #ªÃ}ÏtHVó¦…Åö‰`X‹Ô‚á„Ñ‹V¡Ž©÷1ìhÈèó¨èÐl8~zwã| a†Ó(Þ§Ž ÁR ÚEûÒaÚ@Ž8³ôhŽè¡Ž'N¢„‘°fN˜‰B‡>W„’#‘÷g‘ñ‘¡˜h!h S0Š ÿñˆ‘ iÖH6ˆ(¸w‹8¢¨:Éq|¦ˆŽ-‘”qzï5õÈW™èh~ A‘Ñ•á‘!•·“•‘uEfã{ÄxÄxƒÜø‘(÷bø–aƒñ‚d9=hy,épˆ÷Bk™Mù„”+è’Éqz„×bÙÎXf ”ƒ‰d›™[¹ptu•IzyŒ3‘˜Ëñ™(q7oYw$–|8ñ—h(—Ù2¨\™ç¡š"‘™‘i¼™,Q›1™L㘴ؙÅ!›q ¡Ž.`>ÌI¨xœÊéa×)Á ÷¨›GH$°ÿQš!ž•(–Ù 2)º¹&y!)qIƒü·_8ƒ!â³…)_xzäiÆŸé(§g1  ŠöWE³ž"Wé™â©ß)*€‰ß0cÄGIÄ™3Iª“‘?h†8uTƒœ/šíQ¡á{…2€º8:•á‚ á J¡œ6¡ñÑJᦓdY¤a£ñ~Ò ýÙž3˜éé¢Åñ¡"…Hz¤Å8ŒÇ×0º” a¥ᛵ“R:¾·•]ú¥@x“ Á‰¦q¥qJ›¨* è>:wê‡#v|jG¹Fªw Óay‰@ÿÚ/†0iZfƒ9ýNsÙ¿”-Ȉ¸ƒžú© ª¢:ª¤º [ب–ñžr𑱕‰2êøŸ9 ¢ôU<Ê+A‰ª#Asžê¢ ¬¡*¬ J¬Ÿj¬¿ª;q›táY$ZÑÚ´$}r °y+ꤜ©Ÿ®'Ѫ1°§—¼j)Ê¢n2d!z©á­”ÑJ¥-a®aa±˜* ø© ÈézÌ*d‰‹†Š¥1¨Qï÷Ñ(ŠÞ·•ðʘ‘«¾²…ÈÊ­h¨§!¯P›Þú¦²aœ‘©uç•ç',ëê©ë&äú™ª3ÿ›“Á±0šÁò²0³\°AœÓêÄ(®pz!J݉$ûj/ûm°ɪœ±ê¥ käé›|™°Wr¨³C2°P±®È*´R¡¶‡¢EK&K—øX{µaˆ5[$<ö´Aѯ§ú³· j‚[«·.@¶HÒ8_e¶K¨Q‹'KëzQ¸áŒøz¸˜=ÂcG²Å·<á·þ:˜¢;!7ùzé°A‘·}Ò8ºà¸P;ŽÄ:޳Ûlk7«Šñzo;»k …»²h4†€¸¨­"§–+àô¼áº<»ÆÛ¸c!ª2K·šöZÿJuK$Ÿk¼ [(§ë0;¼ÂbÞP|Ò«.¦`Ûû<[½Øa¾²K»Ep¼¿p+‹´gR¼ü{¼CÃz½[ü&‘𱋠 ªó‚À±²l#Œ·Ùa ¶é{%NÁL1¾¡Â,2ÁH€a’%à’ ]$ÂŒšq¿„›PØÁ‚" ; mð%’  ÙÊ'Œ'.ü»ª(¬]£ ç[ ðòÄ+³ Ú€¾Œ›M¬+b:*¬ÅÏɵJé(þ°·³Æ:ü þë™-Áz@,­QQÇL2?þpw¶ÐÅH£ŽºµÑËâÆÛÇrÈÿbÆIAÀ9BhðÉÛ’#¾;ñµÁºXÁȆǭ÷ªiŒT–¬_ƒ‰gùûœìo™ÊŸ¬SMÊ޼Vè­Œ£oÉ¡É%ÁÊI;›¼ü`ž\ËË·HQß»“;¯™õË ÁÃ$ñµÎüOø)Ì„AÌÔŒÁœYÖÌŠPÛ wÃÂØ|Íä\Î6ÍåüÍæÜzÙl!UIG̼Îò<Ïô-£\ÏøÌoa¬#ñœÏ?´líÏ]Ð ÈgÐ YŒ¶ÏŸÑ ­A÷<Ñpf±Ñ½ÑÝÑýÑ Ò"=Ò$]Ò&}Ò(Ò*½Òy!Ñ,ýÒ0Ó2=Ó4]Ó6}Ó8Ó?ÕÐÁÓáÓJ!ù , ±£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^`!‰Õ°cËžM»¶íÛ¸s/}­»·ïßÀƒ N¼øKÆ“+_ÕóçУÿFÎôu騳k—è|»÷ïà?wÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_+ïþ(à€è!hà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ]ÿ½(ãŒ4Öhã8æ¨ãŽ<öøV>)äDiä‘H&©ä’L6éä“PF)%P1Niå•Xf©¥E×méå—`†éUkb–iæ™hÚH]šl¶éæ›® çœtÖiç~mÜ©çž|öÙ!™~Zâ-‚* †&ªaŠ6êè^U>*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØfk[—Úvëí·Fº•¸Dq ®¤Œž«îºì¶ëî»ðÆ+ï¼ ÅAï½xН±änÔ/QˆŽôï¾l°6Õ °Á 7ìðÃG,1b 5ðÄg¬ñÆwìñ˜‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG}ä þT±jWK­õÖ]l©¹\;œBØ3ÉùQ$'UmÍD^sÕ6xo“-Ý.s©ÀÒ&rû vÞ|#ÿ»÷XUe SYkTøPOtxßWeCWº‰ÝÁ8c‹…0CK–ùä¾êËyf 46GZyÜBBþùê¬ °¹`¡Wõºk­×n»¨ç~På&­‰`·)ï«/üñÈ£ˆúvÆ•8WÍ'/ýôÔWo½«Ñ_¯ýöÅsïýôË¿™=tãoþù觯þ‰å ”ÄúÀzÿe³Ïoÿý¿µoŸþø÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺpIáÃH _HÃJ¥~6Ì¡wÈÚe%> ¢ÿ‡HÄ"&‡FL¢2Ã%:ñ‰PŒ¢öø'Å*ZñŠ"$°ø¢&&„Š\ £a!Æ2öŒfLc½¨Æ62A¢çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ 3Çä°1-‡¤"ÉH”È¡‘8B‚T If¹…Y£$R YI=©®“³ØÂPÀɲ ày?i(á²ÅUI’dÉcäèJ;}²–˜¡%.w94 &ä?š÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠþ³œÍè³0j“ajô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚ46½©N—•Óúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZU¾¼*gЦUÏx´«` «XÇJÖ²šõ¬Ïr&Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷ÊW’`%I€e_÷R —,\ú•„6¸!’°Åûk$$a‹ˆµ…$Ú VÊŽ¥øk-Ü„ !«že oІ„ë˜6´ÈSjÛB¦HÿLÖ —ìlÙ"‰ÛĶ»]Ë}{V—-‰-ˆke{\¶w I msÓÒ¥H¬äµ†} W§›IJ² ’8-,ŸËݲüÕšm¬¶[^µ !²ëmï[JÞ6v%=•¯P˜«_¶˜n _í¯€LàøÀ>Ù?²`ƒ4¸ &H„2aTXÎ0ƒ7ì`'øÃ ±ˆGLâ›øÄ•ŠW,/°øÅ0ޱŒgLã×ÓÅIµYplc@’·Çñâ1‡Lä"Y=:&K’½à#×òÂ31®“§œ˜%SÙ(*6‰•¯Ìå.{ùËÚƒ2˜ÇLæ2›ùÌhN3(5Üa‹°YÿÍp޳œç¼!ÓùÎxÖŒ˜QÈÞ<ûùÏ€´ Mh€n£ÐˆN´¢Íhï¹ÑŽ´¤'MéJ[úҘδ¦7ÐG¯ÆÓ/µ¦í`Qs:!¦>µªWÍêV»Z/>ô«²åYk0Õ¶öL­sm,óú×rõõ•d ìbûØìl2²—Íìfó×ÎŽ¶´§-bSûÚØ>ݲ T;sûÛ¯¶6¸5mWß2×·H²°ÇÍîv»ûÝðŽwD;k°rËûÞø¶‹²ó«lšÞÇ5€CüÝlÛAø[^Àï†;Ü̈qÄUMpf<Ú ËÄRq„´`ãæÎuÇ™½í‡›üä(ÿwéÈSžèŒ³üå0¹Ì“ºr΀|æFuyMndž—ÑÞº½ý¢’ãüèF~0Ñc~ñ·4éP§×?¤\(Ÿ»Äê‚\úyž^•¦c}iB§–ΣÞRhâäëGáùØwËu– "m_JÜSÛôµCä탼Åå+nôV7·{ÊñžfUÎDðdG§Ö)Ss‚4þ#ˆO¼ˆ#/yAþè„/IæÛkx™P¾ò~¼@DߑσþÀ¦?}šS¯úÖ»Ь·õÜ_O{ÕP½ö¸Ï½î‹¼øÝû¾¹ao’~Ÿ’sŸ#Ç'¾òƒü¢4ùЯå72}T_ׇÎ󣯽¿sÿË}þ¾9øÇOþò›ÿüèO¿ú×Ïþö»ÿýð¿ü™½ýùÛÿþøÏ¿þ÷ÏÿþûÿÿØD×{ 1€a€N!ù ,MbÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë‹I^ÊœI³¦Í›8sêÜɳ§ÏŸ8 J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jè¡¢€è¢Œ6Z£¢ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf›&Úvëí·à†+ni’Œkî¹^‚î°ê®ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG½ERWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæì Åùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØ·ÇmöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšЃ8¡OJ@5ê$… A [¸=Ê„…8$A âÎD†$bÿ‚(9 À‡2Ñ¡¢CX‰+ñœ5DPMQv`¡Ø’%vhC YÈE”¥1laã ”!ª±Œ%A‚$¼H9D!#OB€8ÄP M¨„·¸G”T"dA”XH” à–H `(76Ò$ H%ÆH%–à’%9c 'Iñ $‰'™J>N1ˆ2üc+U‚ÊYÒr ²¥.wÉË^úò—À”Í?2Ì`ó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØT–?² ‘bró›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGZ»[ô¤(M©JWÊÒ‰±¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«`Õˆ ÂJÖ²šõ¬hM«Z×*"o¦Ó­èô&\Ç9̺’S®øG1ç ÎmêÕ®å¬ë_Â×l v°…¥æ6rØ¿œ‚õ‡cóŠÍÅ À‹mìd›dÙÙ"ÿ@B1mq [˜ö´¤5m5m!IüIø‡6pZIŨֶ¬Åæk ÚÓšÔ´¥î5] €âÆV¸E­j¯ Úâ ´U­r­¹ØÅ:׸{Íëc§¹ÍÙ^÷¹„=ìf»4“~׸yÝÆf­é]ÞòÖ ë­¦u“° $µÚÈ,cÙûGmØŸ¼E~ÃiY[”«(Wg¿9[Òæ÷¿HØÆ6¿Y]m˜t³µ¯ŒÍ wÃ1²ØÓøœ˜=ñ8?¼á³õÅ0ޱŒgLãÛøÆ8αŽwÌãûøÇ@Žin!ù ,\=dÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨ÑŽ$Ž*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅgìÛCwìñÇœ%òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûíkƒûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…›û‡Q¼CÉPÿ¸áP¾q¯[Øâ‡¶ø™$ÿðCIh>üá-~Ä&þg@Lâe¶ƒÈðŠ9Ì¢@tø2.âð‹þÈ¢eDT±Š[Ä¡ÇèE•U±fôÇ@°8Æ9¾Lw$€#¿¸Æ>¾¬Š€ÓˆÅ0ª±)Û†î)H3~Q‡|¤ËüHFêQŽ}¬cË)FŽ8¬b!‰È”Q²“žl$AF‰C9þq‘©l¤(ÉÊ?¢²ªÅ3N R¸”„6„¹DBJÒeo€€hC‘{¤'`D$¶8#ÎNi mÜb˜‚<%ÎÎøÌm—§Í(éJh ä™;Û£"•4J>Ó•@“g ÷ÉÏ~úóŸ ¨@ʯb®$ !ù ,\údÿH° Áƒ*\È!‰†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½ =„¯­!¾,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿUÿ äÏýücôMÀùë¾AÀþïíÚÇ@va 9ÈÁ Rp‚.@våïwÁ 6¨AÎà¿`ºþ7)<`'L! gð;°ëSèà d0 ÊPƒrø…ºî …¬p? ¢ÿ.Áýmë7Üà 8C%j€ Q@¶¾¡‹ žˆ*Ìâ ‰.[ÄR°aÅHÆ&ʋޒEA.!‡+ñ„Vœgà„M˜ë1#“èA) q\<Ôâ }¨EÖÑ\`,c=ˆÃ?r«‚Ô…áøF%ž‚çB¢7éAV\ÿ»‚ W(ÈÎ`ÉŸÅõ 9(²‰R0ãÿT¹ÊppW˜ä q\îB• ¬å¸.!…<Úðÿø‡.f)€dªÒ\ÿÛÄ&6øøðH@ -“ÙÌvùcRégr“›àæ@¶¡p Í܆9ÏÙMsœÈ' þQºÎrš³žèb§;ó9ÎÈsžµ'>óIP~:³ ê¼Ö' "P†2 É<è?ÓµP‹`ŸÉÜßFÍUÑwŠ3•Û|&º¾N$l °Å-¼(FT\…§6$€üÃÚ§<›yÓpS¶ðb p‹v†”¨êÚ8eT[¼s"}èºØÉU/´¦e—PÐTH5•)j¸Œ(mÌ´©G¥V¥W{±U€þQ+^÷Ê×¾úõ¯ ³E@!ù ,^<bÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñª@ÂÅwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´æOí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„)¹ WȺrx!¤ Ã%É@RxÁ r›=` ¿è¡ÿ°Cȇÿø‡žp[ÐŒˆßHÂ/ì°3>à@‚à›½@:Ä"¤¸‰mÜl¹"Ö¨Eìg:üÆט˜1gsd£üqÇ™¡Q y¤£ñH$ìqf}$HÿQD¶Œ‘A‚`‹mÔÂÚØ† efF-jC(0éÈ™ýã’ÿ(% I›ÝΤ´Å !Y³Lêc¶ø‡!ÿQJ˜%q¼ä¥6ìÈÇš%QIüG1IyLS2ò™ÀÔ$0ŸI3H3™þ°¦3‘™Ìn6³šÞä&2qFÍf~Ó˜Éf7yNŸÑ²†MÚ$<çIÏzÚóžø´‰ ²Ož!ù ,]=PÿH° Áƒ*\È0!‰†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI`¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆ÷ÕÄñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´æÏÐÿÔ®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȦÈÀhOh¡–fà³fnéz "½@¿¸ÃÒ~ö‚üÃ1È%nöCÈàHø…@ÃX"g@Â?äÄØ¢f?ü²(Eìãf@ÇH„hgC,È‘ð à°f6”cÿá:â,w™cïȳ1’:K‚´HDÞ Û@‚lq Jjƒ0sdÜ( ”`’—üã?la‹”·¸¤93JÚÑHÂ6ng³Ü]ò’¥DX93#nã¿L¥íøG¬R•L¥ÎrHl‡¼¼™9Lž1³šÖ¬J@!ù ,\=RÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨ÑŽ$Ž*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅgìÛCwìñÇœ%òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûíkƒûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺF/@ _p‡ªÊèšÁ 8÷tÍ@BÛáæf0Ÿ=à—Á tسÈàÿøácȳ#–@rP¢ v¸3üˆ¢ †(€ôgGJðIlñŒ9ó¢Æ)Ô°Œ9K#ÂÆmø£ŒÿÀ™ ¾¸G>þc‡Ä£ÍôH>þgOœ£ö¸Flgþ@¤K°ÆxÒ“ˆ $Ͷ¡/–`œ€6$¡[xR‘2ˤJà[L’ÿÐÆ%qFJOJ¢ŒIØ#"i3YÚB¶”ÄeùÊš]’”–e $ÀÒš†ÀE ò D­ð&Ý™Hʺþ«[_¿•S$@-MŠÐmD—<& Züb˜Þ‘$0¤$f,Èt¦Ø¦KAf£û’î:n¯0¾…‚Ë©b|"¡–Àd#AÛ·æŸJèfEL%(%½ÚX/KÚû^ÂýµÂM®ì’ÿcA– ÿ g~A)c(’Í$MŠq9`^º÷pÇT° ÝÐÍ6”€@ €Vâ3ŸØ$A2cM—’ΩBn0•g€¶' Ñùr+Ä‚hQn'Ѐm°h˜úhB0H€h€3äbÝÙH‘8g’à€„õuN!ù ,‚cÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×l³@ÂÍ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°c Bì`SÄ´Gm»Îm¸!II„»@;ç„-¿'ц-¶è\‚ÝÃt|ð-_BñzGB=A$¸ÉÝØc½Îð»ÞHH²=ñ%¤‰ÀÛMÂñÚØÒAå—À<óëÏ}~$·` ž'€ZØ¢t#Á÷R>ì |³Åõ®GåõÍz$È @¦Ç7Ú I¡$È7Ü嬑áï˜;©9°…0Œ¡¿r&ÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"±FÛÈ?’˜Ä $‰uÛF$J„´!€h#ÅûU‘‹qó‡$° mXPn°Å6$¸@IhchÞÜ–¨=%þc‰gTâ6ºG·˜qwü‡å¨D[@}T^ïøG( Ä$P#ÃüA$‚ñ£"ïøHÒÍŒIØ'`Æûqr(tdÜ’°³÷Ùâþ  +IÙ>ïÍmqÃß÷½H4OŠ!äaæDƒ¨r˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂ®‡†kÄàŠ°8…>Ž’€ÛGáP €_8!xMBß´W¼4!gHA߯wI¤à¿Ø…@ j·ÙI@TЄè2o*@ \à‚¼‘Ô -P@&ßf ØN¨“ƒ@v—„ô”!cÄ[ ò‹_|êß[NR€Ð”¦LÛîø–U‚Ü!p,=Ü w ƒØÎSÕ›$Öj¹§îÍ®Ú,f Š)ŠaßP©RGS˜ÒTni]ÿÕÁmCFu‚F ‚W¼©@¤±«ÒU‚5Á ˜-A\ÿJÚÒšö´¨…˜&B‚P³¹ ¦‹ÃdRÀWÀÿ– µMí¼.™Û¾IIåFzÛµžJa JMÀI\†´öl[UÈ›«ÛÅA [ *+;|ãß/ñrÇ] @ßpOÉ–Ýè:Á’€¯.þ±À`y’(@æ°Y·Á•¶7¥-nh‘fWmýˆ ¤@ß½æöÚÐ_Yràº%á–(.&,8x´º >ÓOû”X2ÖB)üž6`ÉIêŽg±Ú†€ÿ4•t±xŒY?Ý‚Æ6fÈñrì¶ÛxxóëÝ÷ªH‚ ”DV[$Žü@Kø#Ê©E¨,‰+ ·lÛØ²• Jð.dm8rpi¶mÿweþ²BŒ\cxYÎ^s³¹È戤¹ÆÆs×Ä €ßzÙÎ á+D%aã$Ü9lS®ñ+û\;ä˜atÝ€e®iÃÆmˆò7>q…ЏÁÆqÖñÔJPc$Ä™Ãq¤Y ÓNæÊáÍ5C^Ы[ úÑÑF$mkÃ8AÇvÂf;[,1¯y”ºP¯ò?ZÕ~u²>]çbcdAööazŠÙÿ*‰§®5x›;mL@!Ús$Ä o< È¿e1Afð~#¤5~6¶ûRae…[Ðw·)Mµ7Ö˜‚d^§à‘ÐZ·ØßÕðˆ 8H»âïKÿÙÌÿ@ó„YoëpW>ÚÐtÖ˜q–DyÁ?&!€È€ß%?ˆ6ÒÍE[Ô<1M¥NYµÝ)Ö¸ õÓ¸Bdð]Š?`WŸö,1Y1ÒnˆzÊbó(9a»@û&`.ó5J!2x€Åÿ!‡Ÿÿ\3À¹A†^㢿]KNPzÍýM?[¢ :Adðày¿ú_½MÓ[/\–¦‘pyÈШ»Ïg0Yƒˆ¹X.ñ]œèìÕ:H…ùÃ;Mñ‚ø¼ñ5~|ä§0¤É˜4Âý2âd¡ºóŸ·ñ^ë>ƒçÖ6î|\øŠéhÑZøµ}7eq_c<~ {h¢ÿ/ÃK.ª§V¤>¦'¿ÎØë6®L[¾âûü~éq²Ž;"sX ¼æsß@e!fæDKt| w5bjw”X*5:7l¬vmd”VéÆy ˆä—-ÜÖD~Ž4SÐx%a 0F#t D¶GĶ«7é-@æh0hgI´W· qoôFø@€ö€'(ßuú§,ÖO·nĵÚU#´4FFKÔb‘Î7|«÷]áU}Тi (hId sPþj[X^XN´ ºp umÕ"Q„ö[û gû°eDJ¯Äj°$J*j9V„h¡ˆØBkëàÀ¶R—„µµ…œwhd㈤TlYUFçDo†…7˜²EaÚbIG6sÅÖ†?˜n7ŠF¸.n|¸s<©æ{åGh¸3o°˜jð\á¢gNVKï<´8<'ÈbŒØ5t 1d½˜w¤)ð kW.Räˆ?…a‡x¡ r ʆ]Øs’`KF—…¹µŒtÁl!_‚H†s ¹¦KÅ—7q r °8=Upi7½ÅBwdEî7‡I€‡±8ðørus?‰ó·8ÿ¸7¥ »° „G2Xt!¹âhB`WY5!ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«NJb!ˆÕ°cËžM»¶íÛ¸sO% »·ïßÀƒ N¼8ÎÖÆ“+_NÕ‘Ü6Ì£KŸÎùRÞ¨kßÎÝb«îàËÿ'í|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ¹¼ý'à€hàwYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹g­dŒ-•ã8æ¨ã޲-Èã@)äAä‘HŽtK’L6éä“PF)å”ÊÑHå•Xf©å–¹eÇå—`†)æ˜/yIæ™h¦©æ[¯ÁåãšpÆ)眿½Içxæ©g‹vºe枀*è †5B衈åJ¢Œ²×'N²4*){Ûø餘Jf¥]†fê©d6~*ꨄýIê©°-Šêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð®hj¼ôÖk¯ˆón•/Q!ÜKk€þ,ðÀlðÁ'¬0Nr,ì0`¶ŠqˆHL¢UލÄ&:ñ‰PŒ¢§HÅ*ZñŠÊa"·ÈÅ„h±‹` £Ç@’ñŒhLã­Ü Fõ!R`øœ×Æ:ЬkÈà,²ÇhÏŽB" ?ôÆ…ÎŒAä /´$4r‘*¤A)JB’DœH.!3~± ‚t‹9Iʹý±”¨ä`냆˜é•©ŒeÇ7²•|R–¸” %sÉË^úò—ºÚeXn)¾À˜ÈÔ1“)+À13I(Š$Ÿ‰°Pò0u£ì ò¨É«lr³K®1¶™”ìÓ$-øf^بN,m’,Ù`Ì2Û‰'rÒ³3ó¼§>»–ÿ3€y³'öܧ@­rÎw½¬ Mh”ò©†¾M¦ ¨CN‘M!74‚¥B7Z„¾(gÈ*9JR Q´¤(=’Gñ²ÒŠ´H/M©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR/˜3é à¤9y§ÇBºÔªÊª5PŠ™ÞyLZõ1üªX‰ÖGƒˆn¬ò*Zë£ÖµîÇmT•‰3ÝJ×¢•µ Y­«^‰5½h4!sHL÷JØ4ŵ(ý*¬b÷4ÍÅ:öWyµÉaKÙ\ v!ýjìF&[ÙÎÂê—õ¬h±µ ÍŽö´¨M­j‹Õº6aÙ1íkgÛ®VÿÒö¶¸Í­nwËÛÞúö·À î%#+Üâ÷¸ÈM®r—ËÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz×=¡ý®a¬)ÞÔØ¶¼èM¯z×ËÞöº÷½ä,|çKßúÚ÷¾øÍ¯~÷Ëßþú÷¿0iL`&…·À~à@J„$D" møg‚çâ¶Ð ‘À0y'œ—M•€ UƒÌáÀ A¶`gA6ÉÕï% n°…ŒG áHHØÅnY 0,‰ó Ä›DÂq̸ l¥ða"×epNòA0ì;ù.mD|T?¸ÅW¶K$6,“8ÌvÉŽƒLº´2ÿÂhÞK$‚7´A qîË;çü`+çùϪ% MèBúЈN´¢Íh“øã 6H¤ 2i‚Tz —H¦°éNCúÓ’5¥EÝèR›úÔ¨NµªWÍêV»"w}õ¬Â*뱜µÖ¸Îõ"ÿÁiðÚמֵ°‰sÀ[ûØþ56«~]¯¹†…ÙÈ­2mÒ 9Ú$Sv¼ÈŒínë&¬Ðö¶¸içì°”{;×÷X7=“X«ûÝ¢97¼¥ân‘´uÞøÎ·¾÷ýÄjóû߸ÀÇ1¯¼ õ8T®ð†Íß¿HÄNñŠ[üâ\ 7Æ7Îqéø‡ìî̦5ž’Ää ÿ!9Ê;Îrl<2Û´oa Ë!·ÐÆ’r~‹Hÿã2¶ÅÊ[®6€Ì.—’0imP?÷‚ ÎF §›è]µm~HÂnðú¯?\ó®gèÚ°EÚmáuN`“ÿ;·±nèhc˼ÞÚ0v¤ p’ø¹?àãŸä]¯”ÑÃ*‰9³WÞò†ä/2yƒD¾#BÞË €[³½R‘ÈÎÏ·±å‚0{IìDB€^sºkR¼–¶é[ b¥ÿyÜç¥{$xéÑp†(Ó3tæ¶aë=³µq{ÄÛH÷¡7ÈÏE‰¼ ŸÓrw=D6/û°²}I¹ÿyÿØ‚w^ÿê‡o²öwÎNùÉýÏ“ @^Ûbdžÿ Ìô£¯Ÿý°'z7|LæwlxÿÀ|ÐñkÿðhH°†ç‰÷hÿ ~ÿ·Ç÷krg ]—yš·c¶ðaÛðÛ@«—€P}ù÷h$€bJwy®Åp—Ñ~Qzø7wgN“€wåÇlV'R0xÒGmÚ@r1„Ô€ ¡mºuW*G„R8…›Q|a…T˜…Z¸…\Ø…^ø…`øCXh/†´5†úQ†Ð…†¢rf`lÈonø†tX‡£"ƒ¡†vXzˆNCq¸xHs˜BÁFè\ÕÖ‡€Ó‡pÿ1„f}á‰hƒ˜^ÕvyòÆvIp Û`tÈ$…D˜r4X€_B@ßpEî¶d¾Q¥hŽ÷—¨™ØC~–xºu÷–% #Ž(D̶ lwbu¹È#$çg>m•ò‹ a Owta7ŒNÒŠS”/á–w6g·˜#>æ>VàAt‰Hp@ƒ‡á#¿öÎÆ7HT9´&:I16"QB=ѤDwµGÔøcËÈ$ò5C¶à︇ˆÒ±4ŽØØ$ €1+aÑŒ“] I¦SI  *Àᑱ $ùI“N±‘踒‡W–…¼ÿ¦`:p“SX|é&I“!Qõ5‘‡.àD9W×CÙ”“Ñ’Ry#©#c•$y;VÉ”A•IQ“挥–•a”O–'gz€”PW§bv-9“`¡“Žˆ’ç8x&|I:Éab ’•aMéjˆ™ƒù‰f…9‘9•R  Àd—t˜••1)ĉaŽU9š]I¢©lyÿx³¹;jY±Y`p¹“Y”Qé%‰d±™AžI(HYC­™¹9Í –@4‹é,ÁHh)¨ Ä9é^³ùÙt™ÿNc–_òœñš;1“&IœêI~Ô7ÓÉ$iä {ËÉæ(š½iý‰ê‰f≙™oÙ¹:zO97ÉI(Ý™ºž¹ z3Ÿ%òq ±”ññŸ*&7 áM` “ Z6'Â9+:h ×à…1ê–&•×Yº=sÇ(õ™‘V8Z¶¥á&¢©Iw&™ µ83  ¹v£qŠ–I…Mš ™±žá¥ý¥¡¤: C7‡-У a¦®éI¦.@¥ö%¦"a§¡üÈt꜀•h}zsJgq ªšq¨*`ÿŠk7ʦ%'‡ © º¨Èæ¦p ©2¡©âµ¥RêxÚ¡ ±£ª aªPÔ¢’ŸÁ©²f©áªpšÇÉ£0«ˆÆ8·TšN¸ú¦”©%i—a‘ µÐH>§ºgx@ã©H±«|*Mª>é!Û`cûuÚª­›¤¬Ëú­ÌJ4¿Ùy£ãªç $ɸ­ìª­tv à¯B“®'‘¥GA¯%p„ñú­ÛÓ’+úš+*«¡¤ƒÊ•€©:vÕøvµÀް§{þ°$ìú¤+x˺A¨*Õz!]§­m0mËim­o§²à†þ tP7°½ÿvx1KÛà{P·ŽÒ—³1ã¬EŸ@¡žd:$4»w‘'´:z=ëo 4øJA ¬éÙãZµ"Úznß¶bk~5ù±²uÝZ¶ ²ï©#+(au‘ß° —` R R` —ÐßÊvr{Sû>tʵb¢wT§ið »p303¹20“k¯S°FuG(¸l«2B;ok†»"'k#:yr0Rð303ð‘;/°·K‚¥Ë€¦§{$3‹ŸŠNŒs´X;¨Á•£;'€Ûyñ w0¹’»ÌK¹”{ÿð àêˆÛ|²ªz/Ð#˰{ÿB³mpºR»æûºè{¾a µ{²'ø³º{2z¯ëñ¢Šq½ĸ“»¿ÐË¿û;R° Ë|š¿8kÀAsájVçF‚g¥ nQ ¾9A´ë1†Û[PËUß` »® »‘ »¬ »ñwоT‡À¾ÆÂ‰Qlè'–n;{t HÿàLPç±(»>A•WËÅKÌæÃŠA³µ0›¹ÐÛ¼N<¶Þª{€ëŽ Ü‚×‘Fv9¯ t{¡˜‚°'{I  aÌÃ/¼0ºHAÁ/R‚PVw°ºé[Ççûq µ«­.<¸Œ!{Q|WŒ{7‚ÿà{°çÿÛu$tW¥99W³Ì&ý[Éþ Å!—` 4'c œ­ÆøHÃÉAœzatÌJáú}Û}hÿðtó "l$Œ¢u);/0ç;ÂvŒÉ˜|Žš€b2f̈§Œ4gyAWfŽQ~ÊÌ&{2gŒÇkü§¹'rË.!±1ÄPr­TwkÏ[αë¿`!›ìÉAÆ^—vtìBƬ¡w„‘6~°·±^çlW7§ŒlÁ Ñ¨ƒ•µ<¸  ZÚ·‘P)€Ì!\Ç.ð élN° ¥tÚ¹’°v8mÊyÍ7<{ÓŒ¼?Çv+ ÙFÿ|&àünŒ"â n sAɗܼNð H'O@šLÊî Ï=]V½§‚!ÍqϧKòs®ükfÌk%û¤jÜ<agJW0%ܺý „—Î *zœæ—Ìb§ré%£ÝCÀb<ßÿ ’@8/h½»ÒqœM‹ãcÛ3µÐZó}„œlÆ¡G1‹g+|Îêc â)àõr²·'Lëá£gÆÖ+:ˆ\æ9œ­›ÔèÌêÇû.И).ûÀ³Ð)–ÞÏ´—wgµì2¬­5΀úîëó:1ÙÃyWÿ$þvP¨{´×Éf¬ IKê+¯%£éJ¡æ!é+rð<­là*:fœ¹hKµ[éü¶Ó(;Wà>‚ÆQÛúæ+ë0û¼ Ôÿî/o˃Hav&e‘†¼¬SŒæ&ð(³®`¾­ F°#Oòàr¨­zà:Ñîæ6ô#/1:2/1Ñ(ê& # n1ñÄ-1MPàêQó7õ£o;å`1’lÏ^}•Ñó˪vO7ÿUr0ŠÅÙ]Tr¿÷³ƒÒêb݇)joøá1ÚP ŽOp?ù&ž¼ñæáê–/VI•sÏBN¯"µ*ÏehôË¿é*¤“Y™îjôã\úÿp_ù¡û·ßû¾oŠŸÁÿûÄ¿h;ŽŨ´_ü[4úÌ•?úüÒ?ýÔ_ýÖýØŸýÚ¿ýÜ.ßýÞÿýàþâ?þä.Ë_þèŸþê¿þìßþîÿþðÿò?þÇ?õ/÷/%!ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«N `!‰Õ°cËžM»¶íÛ¸sO}­»·ïßÀƒ N¼øMÆ“+_^ÕóçУGÎôu騳k·è|»÷ïàGwÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_.ïþ(à€h!hà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èb\­¹ôß‹4Öhã8æ¨ãŽ<öèãäDiä‘H&©ä’L6éä“PF)å”Tb5c•Xf©å–\zt]—`†)æ˜fÅHæ™h¦©æÔ­éæ›pÆib›rÖiçxØFž|öéçŸ%š è (ÞBè¡Û Šè¢Àè£þue¤”Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶I~Éí·à†Ëá¤[‘K”·âbêhºì¶ëî»ðÆ+ï¼ôÖRöæË—¡ú2kîFÿ¥¨H÷kðÁ#¤Mu œðÃG,ñÄWü˜ÃDlñÆwìñÇ ‡\¦È$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWúŸ‚?aœšÖUwíuHcŠî×§@¶Mt~ÉIX[3QØ\Á žÜgk·Ë\*°´IÝCÿÍ÷ßÐú=ÖCYÂ×!.á)xVÙеnbw<~ñT 3$¸d›[>,¿ž3˜¶@fs„ ™ŽÓMää¡·îºA 6zU±»öúí¸§êðî9nR›†ûðŸú¾šñÄ'¯|‹ª'ã\!¿üôÔWoýõ»JýöÜצ}÷à‡Þ|œßCW~øè§¯þúì×x¾@I´_,èòkV{ýøçOÜûöñ¯ÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0„Õø02ÃÚð†W¹wÈÃúð‡pY ÿ‡HÄ"ñˆSÑ!—ÈÄ·5ñ‰PŒ¢è¿)ZñŠXÌ¢k¨Å.Æ^ £«(Æ2¦‹fL#É%ªñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úQ'lTÕ2È?òˆœ‰Ù#$H¥Œ”–Z¨5H²&’¦b&mS°¡ 5Aô~Ò„MÎE¦T’#É’Ƹ1•}Ò$,7óÊYÚriBLÈ,‰PÞò—½‹˜™F ^ó˜Ëª¥RfÇf„ÐD¦4EãËiZ„Õ¼¦6A”ͼtÓ"ßäQ8·IÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑ©Œ³¢½ÖEqbÌŒzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦xÜ(NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§jÃ\RÕ3k»*h:ªÕ®zõ«` «XÇJVq)³¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÝÙYóÊWµ¦Ž$A öÔ׸ü+ mD$’€„=¡2~…½Kl!‰=!°!ldý3XIÔ²ÑìfßB Á ‰­¸:Ú§(*~V%PÙÚµÿ˜é:’@ÂØHðš¬Ö-´h RHb¸¿M‹iQûW‚$¡’(nrß²Ê$6nìtÕò%[ ÿiƒ-&ÉÚíN¥‘¸Åx«kÞµ8¶ m,|cÛÞ´ ±õõf~÷Ëßþú÷¿°€ ÒÄÀApALÄÁ°$Lá[8Á&°†7Ìá{øÃ ±ˆaJ¿›øÄ(Nq]¶¡â¥ø!,HŒ'Œà·X(ÿðî@tÜ0G®2ÇmC‰oì“l#sn€lâçmXˆ€6Kä¤49¾ØÕ†·Ñ†I ÊU ”©cÅV– ¶¸ï}Ã<”mP6ÿ ^€“¹¿m,V’ Aœ·Åã°¼xYÿô-À¯@ÿÃ Žœ2óÌf ÙÀ¶HBæœ,€6ÄïI„#AßÊ ÷§•­l"ÁâQ‹ÉñÃò×þ,­ÌIÂ,Î1ž%¡å ûC’p¬ÍkÎH¸×ÀVZŸÃ2ìì”7ØÇüµL‚‹ìf?¦ØÎ6ÊKíh[ûÚØÎ¶ü”­ín{ûÛà·¸ÇÎ cØ"æ&·º×ÍîvCˆÕ¼IÃmY¶ˆ„b½ëäø#П÷B.V¼!?8@mÁp9?šáÞ5t½ç4<Âe_lhŠ‹„Ö†°6‚›qÉtâ4ÿV°›#^rÜbÒ)ׯË|‹–cT½!Gˆ-@gsÇÚ€Ð%mè) %Ðò¿"‰£ ¤†>ºÐñÜs‰ºyÆÊ¾úƒ#ch€Þ}¬¡‹‹JïB½ã•@æ0¾ ¸ß™C{Eežó„¼¼î>tÓ h7€ÅMGåÏÛÐoãwÁÚ€–K^õˆJ¼ñL§ìŃà6Ä(Б€w×–ã‡Üðñ9mñš‘ÿòÄã’^ˆO{1ÿØû铀ǒ€öBO:ÆŸ^Z¡“ æ9þzÉ+ÆÆ%Ô´ñòjˆW{1^7®6ü€µ½ì±GúîW«ù#€Nnºÿ¤¹\}¹STõ«WH$®Þç+æFÿzà˾ÿÆ_»-4/e–w%¨çPWo¯Ö|“Ñor¦e‰·0šedû·0U×v2¶{´‡åyÛ‡w—‘f|g`÷7F{…'e Yûç]mp†¦]þ–QZa ƒFÿ ‘FuFvÚ`yÅ÷HÐÿ`y~p HÇp–—r…sˆf<7qˆ%à{n qPvtJ0v¯pG‡3FzG‡~RØP¢g1rxWGÆGk¿6mð÷#5yK'/Æp†v W}ˆS(7gÇrèqqdf¶~ÚPx…hˆÿ|މ’8‰”X‰–x‰˜˜‰Q†šØ‰Žæ‰%Á‰ 8ФXŠèó‡¦h@õ‰»"qþ`(f¶s¨ø7î÷+†… ghˆ¸v©8pçf·ogqµÈé¦`6‹&•q¸`愚X7ˆÎŒ0¶0w8oXÅCÌøz¸—adAHXð÷%Ä·‡Pöe¶Â¥`M§x¢8àè‹”.ð¸ù8Ž´E|¶öu¶}µ¥Õ-×vã—yª÷e­ñwóx# †ïò‚GX‹wØŒ“h·ç°'ÙÇ/þàwNVI€-Çi/öb™gŠ%PòÑÂŒ¬Ø`5Ö‰ñsÿ?Ch&ÿyq'x`æu¹ˆÙGi42“ Ñiíâ|Ì–÷”6ø)¨|ÿ@{Ê—“•U\(™WkIò á[â\Í×Q™9)ƒÒgyåuh8z½w…H)’0Y#ÿ`– ‘ßpMPvp àÒ~”5qm‰:I…SxG|-g`vkBˆ`c¹—4ò Ú IP’ NP N.Nɧ”\÷·gG|‹''x!G‚LçKr ƒIJÐ.`6 .ÌÈ‹B)øæ–7葃VhØq”y‹iw‡:9›i$~I )€ .ÿÀ.·œ qœÌ›†ƒZ‰qÍh–÷“IXi·9z¹$±“*pš.0ž×B‘bé‹géš”÷T6aŠöuqÖ‚ÅGŸµ&†™Å`ÙY%ÐàŸÿ‰`¶€œ4©œ6iZ—5HHy&y³-è™`fž>³gà¹Ê-GkÓØ¢R™*& f‘¡¡Ú"q·^¶6‡FŠ4¥cBjœº¸0’g£]“¢½¸`á-TZ¥çLUêV\Ú¥ á—bŠ••­ P¦a *€10£lºs KsŠYz§ѤQ¥¤§€ªû¨¡Z„z¨¡`ÇÖ‰9ÿЍ ¡¡)@¦¡ŒU*žN÷¨!ZWºð (àß ©fá :7]*ð§I  Žjãy ¥d †i†ÓªNàN¦* ¡S ™Fd§J¬]§­z£Š/Û@ªÇ:.ªÅ•†:VÆ:Å)—0ª£J¬ A©±Wýõ}!!r` åZiÑ©c%§ÍŠkJJ‰¤áóÞ:‰ìe‰ìZ‹Ú®íj£šIð ‡`ñzžÇ`Õêyú—Ûå¤ùåšÈ«ñ®O1¨jÕ¯ë®p¯6r ±"놇V +-[µj™àÑŸÿq¯/[)«[-°³ñ !$É%f~JÁ”õš\@+R0O+•=+OK) wY&;y“³ Q­KúÛ;«.ú)TJ›-0Ú`6![GdƬ¬a ¹e x«b–);H][`Ûa6OkSà…ËUKË*ø†]úV ÀwzhÇ­ƒ`M0ž‡ëÿz'vV\R'u_æš›~3“šLa§i§ëtAh؈'“¢®+"«c+aJ)Û€{RG– ð•½'uIw»œ;n F}G7Yý¶ºþ6h§«zÖû¼êF¼'‡¬ÿ;þÐË[’Îë2»K/þP…BW8¸¿¶ A(t`˜rˇ2Ü;-ƒÊ¾A‰q+³hvö…à{¿.#§‘›Më!þ@¼$hÚÁÿkÀ²0½xh¿ù›mÒûÀ¶ ¶0ràäº Œ(wû'tŒ»“¾ðÒvB· £º S03 5\à W° Üq;)tk¾"É \-¸·Û—–0Rð4<N,3 N° ·+gGüy*1—i`,Lã)´'a¯ôEÌ''¬xÜ—wpÃ6LÃa¿0€Mvt<&Ä#qßð§ñ¾¢õ ¶ðM Å„ŒU|Åi0t4ÿ¹Å“¯áâÂ÷'ß° n|à ±¬˜x@¬Åì–.z"ë¬ù’yþ(ÉÿµN<…<Å Æa´·†{{fÀÁЏ|¹,ÀºÜ˼üË·ìËVAx¨rÆx¾µ0ß° 6üÆ–¼R`ÅxÂìåoÃXMFk3­-¼.aÌJ1¹8² ½7cß  4ìÄê Å ñÒ¼z´ûy¸á]¼8º·ôr¹Ç¡–0ÍìÆ±sÎå¼cÎwmG[ëk&Ò·¤ßÑÉʱ0BGÌ` w éüÄNìÊp/0¯f ¶ —•SÇ/’vµád>H¾¿ÑâÈYºàÿÜ5}!ìv™s –à4ìÌ0Nû vðÑÏ®qäW{;Ô¶Ñ“RGtl!ÓE¢±7Ý"Ó't‘  Ö Òw ©LÈí²ß@ÔA;/0"í|–°Ô¢qˆf°¡Nv ]X'W-¡{"9ývg sÐÏÍ,Ðß@ÿ FÃ7 ÐηÔoç]ì‡rµ¡¼ø·w'âÍîmÊß°Ä„¬ÊN<Å.ð ¦eÖ0Ú{pŸÇl­iacy"‚¢Ùe‘À´{­"µ0t¬öÌ|Ã?Íʆí{‰ý6,¿ÀqÆ7¿}f˱!k%P ¶°'ö¼»ðiP±Û!Î[ÿrÂ3b°3¼Îê,¥ý…DíÄsÐÃ×{¼ݶñ½p’× áÝâuB÷ÛÀÍÏ•ÜÊÅ}tˆ‹·°[ÏöÛT(ÜÍ'ûÐÚÊü¿° £MÈi}ÞR‡»@ÂÎ{ÂVß°±£’àe±à\B}Õ¥¹EÝÌ`Ãÿ]¼Ö¬¹‡{héáuCßaã:;$úpt¿m°NÞ3`á§‹VÂ|£ŒlB$^"ó[ˆ¦ rð´,nÚ_÷uwzÖ¥ÈZ1dÊÐý’Æ,f–z,›° WpN`Ú„„Îg”E®Éü‡Á0­*"ŽnâÀœ±ä%bxô[¢Æ§` ó”…tÿ0sšK}ÿîžZ1sn-pî[ác”…è’Ðd.—‘ŒÁÓè×BÊÕÇÉ¥3—yà7àه N1Ü—œN-ß@{ çšž€1¶0Ah™z÷þXÀ|0÷ wN`S zÞ%ò{t è· Ö†Ê)Ò uö›«Q¶nãÁíáíó1¼ÓKˆüŠ ·ˆñ‡tÛ›äô²7¥qì(â½ow¾Êù†˜žŽô1Ìšš¶Ý/ž>Ñ[Ɉr&»Rw…W¼1D@ŠðÎ"Yxº¯Ñe]vY³ëpWÞêàFðÍ{ðÃXÏ.Ó7¿^%Œ´ªŸPçî`ßÃbê%Øî…kn®‹6òÖr ®ë€›¸}P ÿ±¸Ê–à«•ˆòêÑðó¤ ÿ‹–íáòþä2 ÈLß‹·j4 û0.ÀÇÇh§uÊD?—`8)pÑŽŠŒðc¨^ﲇÊê)`Øß0mÿDuî#q Ñ¨9öá¢è*×ø;6(rúÅQ„óC‚ø~/vôù?ù”o¥\¡ø•ŸùL…·^]Ž˜¯ù â¢ß®P_ú¨Ÿúª¿ú¬ßú®ÿú°û²?û´_û¶û¸Ÿûºÿ¡¿û¾ÿûÀüÂ?üÄ_üÆüÈS wËoÍÿ$!ù ,IdÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë$.cÊœI³¦Í›8sêÜɳ§ÏŸ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñŽ+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈N–\¢Œ6ꨌ‹>*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«-‡ lëí·à†+IBî¹èVxIºÂ®Ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG óDRWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnù嘻ڭ@›gT.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„( M¤RÈ$$ ,ÄÉD@‚$D I Aèb(“ I„-ÿÜ@7´‡4©¡„xÄ$4‰1I܉‚TŠ- b Pì‹,ébbD0¦&IX!AÚ3žQ!GtcI&"‰1` 4@$Ú(G“¸Á ?lƒ$`ØÇ‘,ªŠT+Á ÙÅB–$ µxaÍ%‰6øÐ‘'‰` sùðŽ˜< …ÈÇPž± –4¥*WÉÊVºò•°Œ¥,ôƒÔr–¸Ì¥.wÉË^úò—À ¦0‡IL³m##·Ô¥?rL$³–ÿ¨e3òm,S¹Œæ?ˆøÇ‚üÃ\@B7¹( `m ‘0MXFS 64ˆ-H`®mhCš×,Áâÿm$ó•µ´E§XtÑ ¶ð§6¿™„f&AŸn¸ç,·DmÄ“ Úð!ІcF“¢n¸¥$"QÇFrl™#BçUZP.VÓ%°…@þ‘Q[@³šÕt¡Çþù!¤‘†@)}ÇcÊTþ¨£?ùN¸°Ü†Tµ!Ð6 t –¼êL„JSÍDBeMl:óªÿ¸EW½ Ó{Þò¢0+Y_jS‚Dó’èæLmaÓ[ncˆ„D‹IØ…ð´°ˆM¬bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGë?­’ö´¨í¥^SËÚÖbÑ´®­lSÛÍÿÖb¶¸Í­nwËÛÞúö·À ®p‡KÜâ÷¸ÈM®r—›ª Ä (ø†¤{Îo$³¶ÂÔ†’PIÈ¡Ž$p8{‹€.Ho Ðà!¯#¿¡ $ Np€ P¸à°ÂDë-š`ôª7í}&bé«‚û6Á¿çõïbÛXÞó¦×ëm¯.øR·˜ôµ/~õË_ÿÊ¡ hÃww `K8‚ l` #Ø-PTÞaΡ  Az€&˜þÅqR ßè0vp ÞøÂƱŽyì^aNa¿$Hò}ó»ßþº@)@°„ßVJîDyÿÊ-p€• üç¶7Ç;v†y ú%òƒ÷+€$·`Éúýð/£ c Ä ]ž¹ìcçÁ(BTpèA3 @rÔˆ=;˜M 5i+KÜÁ—°„¢u)‚¨š ¬vTà„6Ã’ºM˜5Dô{á`ÏRMÈaš ë‚$À!ú 4uåË(™Ê‘fH¶páã²Ï*à¯P;øÿ§ Ñÿ€]!ŒUá\>5¸ÜX¿˜µ¨~X>]&kÿðB¥èí¤K2 ’ÐŒÏHM}è|È=ƒGIàŒM…RRhW± _„°^ºÐ¹>ÝXèh‡¡M5õ R@D8cK溠=±XÓh]Ö(ˆ q »M»€’ЈLÑ‚=¶lx=‰÷xŽf(†Ó´ yÕDN0{YAn§x> u t[Øä9‘&‰'rh“ÿ‘Œ+A„%@ŠÞPJGu Vèi@ш÷˜V‘mõ›° šð”q”øs“Oh÷ø 2Õ9AÄ”ÿ°u®W)i!Nç'Ëd„¥X”9A—@ˆ‡‹BOµÐ“TAµ”np„×ø'eI€©S`z)° ¿ im"P”Y}}ùwM¶€Ý8˜3q‹(8•5¹&uš¡H6G$ P™@—ÿ°Ù&Ѥ |÷²9jYÏ9v° ºP)° Ú@‘ëán ›‰‰T¯ÿ©›,™™z2D(à¶Ðœ=¡‰Ð™¼¦2çxõ‘F”ÙQ ¥þÁT •ŸEÓs™&tõ¡%@™q  ± pY™à¹':©“E±ƒoqœÚQ–»yŸ ºU1MÉ™”ùŸæ)'ÄxpOæö IYKnIˆ3U‡! #Ú¡ÐB›l1–ñÑA£° º rð†r  àY‹¶@™Bz'ìyh'»Ðì± ”éUd÷ S 3à¥`*W° Öe£Ñ”IŠš&QjŠ»æo$ B¸öYÚD_/ /00¨ðSà›`]eúO¹ xÿZ¢o"‡:é5-0q¢ÞѤAuO„x_: º‚ZÔ¨MG8XT´¸¦™©ˆbj¢¨ mMz꧸ú§a¨ )iàŸ:º&Cy›q{ÀñŽè‘ªÉM›ð©aº ‰zÚ€ Ájµ$_á|ÅL`uNç$W£ÁS uÏ1uŠ‘¬Ñ4R0¸ ª1!Údœµät¿ ZzœÖ¯¶ô¯á¯ °ÞD°ì¨) Tè·W¢æEGõ›¶&‰á:®·ù€mÊÙV¥O¹ Ú™³Z 饡 ¯ ¯ ñqfˆRšŠù骗:Œ2kµU³3ÿ[6K³7K0»~%TïõCM0STs Úp ¶€WzÄk‘ªô¶k²WîX™dg  ú§\Û2P…f*jXËš ñhjVMºZÕ)2e.טCÙh­i K¬²‚´A…§·` ]ꬣÚ|µ´Û*Sÿð›`OJÛ°áºEñðdÿ S3eN¥ˆ¥!e­lՓ䊳‚MAÕQ¶prð§}ú§([0€J¨|%DÛÊIk˰‰X§QK|¹WKcÅ|ÎÈT¹I¶ ™’Ða6Gîä!¢úJU|K²_zº°Nð vðÎ+‚ËWØŠNAJU‚[»´ÿÊOcžÝô‹TVzŒ«! Û` %0–«Ðñ Ç·Ú¡ nœtºrPº¸*©;•Eg ¤;Š™ÀÛj Ü £Jëº ±ŽÜxL»XIÁ|Á|£ÌÁL¶Û¸äÔ¸Ú7S@ÄTÕH %(ÝÖcÞ¡¼µ·r¦ŸjNð $ðr`½3ð;»Ц0š´[»Œ;SkW#|jtWúŠÂ¯‘±¿x÷ç8J«¶ª [û¿‘º.𠀿0º3ð`›¨aŸåùQµ{¶Î„£ëˆ¦GÕ¤ õ‹‹â¨yBx ÁªÅQ êZM2ЧŸ:ªÛlA•Ã;,Ëÿ׫ ºª˜{NB«°]ôMZEÚ@Cy©N35­kÌÇT®<ÑN¡“ˆÓÁ£à¡©9LvÿÀ®\ë§ ÆA%Æv€q½êE›Z­£ñš¢Ö“ÜXDÎS´‡­]ô ¤qWp)â1£4ªÔ ‘$Á mðŸd(€ ž¯~m+È Ch>$ƒI¡ ÿa(¿"!‚ë á $º/¶hbÝ·¶$Ø¢ HÈ Ù—ªð‹`LÈÃHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:Ú1vÛ(È?ö(€ ÄðÇõÜÐÀDÚÂ6¤ž ÛP‚Ä·èâ mñm€˜ÿ¸ iAla­$N1K @°Ò•`’K S>$ˆ£÷BîqHX$AJðÌINµØ#* RÉéýc›°D¤-˜iÿM7R ÿè",· Ð8rz¶8"ÿ’°ú£„ÍüGBahE°{·D5 ʨ“žnPå£ÇÏ‘šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@Ñ6´Åý9³¡{üçi”ºA„© ³…TÐÐóƒËìh o„1^LyM+A.‰VÍüc~Éc_{QIÿ€£­¥*F¸ÝrmÀmÆ’ªZ‚lC€üìeü(D?NE®IáSýHYØÂ°tUlÇ"‘T§¢0»Ê­Œ?^ëÅ<®íã`i±êÊ=¶’»úÛ­ÿÛ1I·!ÉjfÊéBýMHý‡ü\ÞÈt™{”®}çéÝŒq×± âU7SÎûÑÏ€aEäAöx ßîÑ »H‡?ª±û2¹ú]nAÊÀ>òó½ÆÕìyå)ØÀ 1cxÍmBXY׶ᢓä­h©ª¿ö“Iímmk¬1ÈBxÅû4ðf@Üm¸!a%,þµRÀÎj«l[—btÕñ]SË™ ÏðÿšŒ\g4AìNØ7¬þ±@JÍåq¬jÈY{ šµöqÅ~,‘C¦_½6úÌž´Ì&\UgNõÉãó¬½`IõÓ µ¨GMêR Ž¦Î·a à–ø†:¿¡¾oèB)@\` ºÁæón2[`¸àØ((@ \Pë['@× pA íõÝ¢0ö±S lf§ÏÖ.x¶à‚lW[}·hB±í‚\/[Ø«ò4‹l­‚g7Üæö6ù,!@ /€òK àß u«òùLŠôDs(7 È­\»PMXømáÆJT€'²ƒ ü½ìƒ@ -ÿPTà˜J©ò,pe>Ùƒ4ø8wÈÍã –)¸ ×÷A\Ђ¤€âªú RL_¦­]=î>%[P„l°Ï^®WDN€[!)_ù×SåGšcS등­aùˆY¬íÎJ}ûAÐHºÝìXñyHm DèPAÑ›pnT× †>®¡!Óv'‘j ÿJ:} %ع@\Ú¬hžëhAèqåGº?UX—L%÷·v ÝuaVé\ä‚\÷Ë®´fRG –;„.Ï•Ò5¿á‡ZF¤¶­ª‡ïW‚$‡¸Ëˆ‡7@%ˆTÛ¦ÞbQ„È?n\Âjc½Lªÿ1ÔvÜÎI*íQ_ÄÒæ,ÁÏÕGïÊËOÄH%l¤:yòK”É—çq‹tA …?øsQs ÕTÛ—Þ‡^5nçHàgHöKÑaÜäG´Äg†~b‘C¸2@±Gö§z”7X%P¶UÛ¤Dãth†a4†L~Ô_%e W¸vÕIu]Üe I€Eh@½¤G½•y=ÖaþÄG88\¨çe—ø·GúEÀI’¥N‹´H´y’0†Ï4yÎD@L¶Aá´¿‡»p¤b| a‡˜ñ€»äv[¸ ãµb ¸AüCX2>ÔHkì´Cu (ÿf*àWJ¤R… áG×Ç\eªÕq]!rMP^'‚ÑrÇ–q¥"Q¦×Giæ!s@‰¤èDÑäÖw G*§$s1G–!o‹¦Gi‘q¢X @t¡ºâT·hprÂ!§'G‰‘᫘LAdi9"zß㡊¡áwÖÔ=ñwÄw8íè>è˜jÀSrñŽH—#çx¡ŠFß° ( g °vr‰£îf*ð Û HT§r Ðr ‹‰k”Ó¿  %€ÓHE@Sñ r0Š.0a—-—q^wl·Xþÿ˜pt˜8* ä‚Lñ MÔÆnptBGnê(.Nð”Àæ8ñ8,‰»ð €7•ÁnÇæ{N€á ‹³‹:ÁLyä¹¶käx.çmk¹Œ¨(r° £øp‚¹Ûrçg%`[ùw nƆŠŒ;±“x)æX.§”öö–U£˜$ñ˜:± RlR0`·”IZyRð lȘ‡C–9q £(ÑnIØ8t1•NàR ?Nàá#Ž qlTr»`†T;ÛP‘° Ûà{|'mæ¦Y‹S‹,ACš0r5)tÌÈo88mÀš.ÿ! ášÙ–‹¡™ !z68ßwDxÆIém̨r áê6tØ&ô{³ „'ÉÜwÝ ›á ºŒ !xÚ7߇O(´–ß° $ÌVšá¡‘# .ø ªû0ß` MÐA»¦ž§¨Öé4˜.Zvp $ –Pœ#qœy)ß0 ñ—6¡ ý&º°7.ð–K:*íè¸IPJ­È3˜©~œ:–(ÇŒw4â™%º) šx£/!.ÐuËæ¥@1©ã¦Êl‰yú4èQÊ`Ú4$JM,·hk¨;qr{ÿg7º3°tD… ˆ^y¨&:Y¦~‘0©*1Ç´&ö,Ù›½ù¨Gq‹gz22P-p Äu© q ¸Xß ¨rƒ*° ³z'ÊíÈwMq yÔ[J3c§ÀÙS° ›  —ð}úÈÞ¨r ËF%Ð:7Ì6‰ú©H§> 9`:IJ ¡£ª¢ñOßà‚w”Ëz*7ËkÏTQYÀÚx V°>6ü)z”ú=šç]›ú w°ŸÃòâÒ’7®é“T)ž&ÜÓ·!ìAì‹ñžOˆZ)º tÉH>)l 9±þÙèÖ>7eÚà×¾íÜ2ôŠ¢Í!ù ,òmÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀÏN¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ°‚€öÚÎ… €ÚlÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ_æpòTEõ @ÿ@psßýH‘8$!~þ#ûG‚6Èñ î'X %PìoƒìÀþ}$Èà@`‡6 …øKß DqØ Û‡I¤P C$ÿ `¿j0H*‰øï}•H–X¾Q´D P@¿Q}/@%H@ ¶o† L`ÿö÷EøÁ‚òk¢ ÛX?8æïŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF"d{üGúldO’ŽÌ¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°¬˜6bIËZÚò–¸Ì¥.wÉK mÃ’ˆ„$¢ø“¢±¤ÑlAI@Rþ`¦þLõEÓÔ<3YÍóI¢˜Ý$ˆ6$‘MÐ!Ã|fA¨)Éa²e·Àf8 b‹[Ó3¶ø_f)ÿHtP ä\ç-ž8‘m`Ò lÃÇ~9Íy„¡åÔŒ?ú‡MI ’´ÚÉàëôŸ-~yÑv @¡ÛP(%;Vψ*äàäŒEA*„B¡˜Ô"QMm”`¥ÿhCÿ‘„ÿýí9jHBš›Qh9#!€•D£ÃLÈ?J€„iZ´¡:Í*ÇxŠL¦öª™ùÇLrÀ¬J²œÊ4ˆ$Úp?HRó€IP(Ô¹±¥>ä©VÍÌDI0L7t§ jUç¹ þ]Ô®)€dKê1²>$ñìŒOBXˆUþ$ë<©9Ð þ Xé0¨Ô{6Ä©hõÌ?tÊOµÿî´¡£mgj%©P¶þ“cÚ°§YS—bÆI¸&øVööñç4-éOl’€µÓD 5Ñáv·3ý{j<+ @Ã|ªmÝðÆ€™þ4b()Tªz,žÆ5HK‡;™ÍN„½5•,¨QÄnµ’Ý«@$‰¿Ø÷cßÌï@Æ)aÉðu‰(cRaŽÁÖ˜Ú\*C3ÚÄ•eÒt¦@®ÙPømC¶fUµaÐ—ÏÆ½Ì±ŽwÌãûøÇ@²‡Lä"ùÈHž—13[^{Æo¶ß|è8ù©>LftÁ­Å…'sâƒtÙ!eMìÉþ[ƒ9°”Y2AÈ\Õ‚¼ÿ¦¶ ±›ƒ cÐÔÎ0ž¥œC&É;kµÍ•Ql ý;A*#8„½ÿ²Ñþ´|VkC¨ùÙÈÜ¢«‹ž¦GÉi ‚N° qŽó…á ãÏî4ÎØsY\°+IRy!}žLPK  däæ-rMjº– Üs€k'OÇ#ó–3ÌPɰ9¨Ã!sj‚ëÞ¦6žÅ43&w `þr¤ÐõØ9"é@ÛšØH]ðjÑ-—àËl À=Í;YŒ†lÜ#Föa‚Š¿­"uœ9à,ç{^¨PÌ©Þé[-ÊÑÈŠ ß“®tdüqîi²6Ýü¥]ýaX ã+^¬2ï§ï‡1sÙÿ”8d =gƒ*¼½ì”ö« ’Ôt R™g®Õ:›v«a•«Qyþ£ãëÔnAlºb®–ÜaWžtª-CÔ~ßÏ Ú*vë ÃfüºÓ¬í;uŠJŽ7 uiÁªÚû`…PåŠ)kÅ)ÎY%ˆÓ£díÀ¡YØcÒ*$,¼7æj†ÄÚ3/^vâ+òâ§—EauªÔÊó5û¼ÊjEsbÇÙ¸“ì·L\Ì>}/ô7=Ÿäö(@í½b}ëgOûÚËe¸t´½î¥–èÈï1ŠÖ#ìS°ûâ¿` @ˆÈG|†H^}N8xE–ïI? ‚ÇϾö·Ïýî{%¸Ìî7"‹¬ ‰”iBy¿O5Ù?îô¡<î€ÏþúÛÿþ/z> åÿèñ¿”Ô=É×1¡yí£˜€ ¸€ Ø€ø€*1~‚2€|„€lB8¸Šó|è…£á!¨2ø(‚ÆR‚³2,¸)ƒ€ƒ]4H'H1»@H“pƒ>øƒ@„B8„DX„Fx„HˆDÐ9˜„Nø„nRqîÓ{&IåxP¨5X˜…\Ø…^è[ø…rcåC6¨ÿ>a&†l8/TˆGg(}lAŒÖ†h³'xh‡|؇Z²†W<!ù ,òcÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸«ÈÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—ý f§-] ­öÛkR÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûÕÿüɽÐnôçŸþm·á†$mH‚AÜæ¾$Ø€Ihƒ-lѶ°»1 Â6–€€ï‹Ä B7D¢}ü#HI~HÄB‚¤0n ûH`@mØ¢ )a ¸À¦ï„‘¸ ÿ/è@ÔÂ>4IðÁ”ƒH Ÿ-ˆˆÁæÏ‚$È¢@$H¿"Ú I£$H?´±­‘#‹¨¿6"ƒnŒ£çضÑñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆLß?2²îùc ‹„¤@9I‚D!þh$öþÁIIÐP Ú $qÉ0 $ÐF$µq$¸PH¢ó8i $$ ‹ÜÆ)ÀÉ‚Üâ€$Ø'ýQ‚6hòƒÿØÆ#µJo‘7D`29ù²”¼ü‡6 ÊÜB³ÉÉ6“zÛhƒ$üFjö’”áä6‚¹HàƒÚpà"åiÿBl:o*,göÉÉÔ¢—–Ôf*÷9Å&ÿ° Ê0Jú†6š„n …%ç<…IÐFº þH`H¥§[à0“É€5I ÉdnSÂÌ©naEÔÒ+}ž;OºÏ¢­‰¹…QÐDI|0ЬÌdýÔYRS’ˆqèMfUÚØjAyÒutŒUM¤ñ4y¶Ä­j«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bë¥øã—¦ 'i.éφPveÚ”+³¹ mh~½”lA¼éÌöE”•ååE£Ë¯„¥=ˆEÒÙ[ÿà´¥›í4²[Ïücƒ÷H>R‚ÜÒ üsfì(°qc´ì?\»™ß‡<+«If5‰m%XK€FvÖ6d¥,/¶Hã*$¢¢ÍÌ?>)F p8)/:ÚšR¨½dVã›±Â5!1íÌ"‘ºÈ(Ž–¿iÝ@!^už%H­ÅhÑÙÊ–º˜¡j i ËJú”©˜-†ðP7P’š‘h¦†+v@ˆLWÁnˆ%VÑV^‚° Î'þÄKÎEôc5~ÈqÜÜ>7Ÿç,1Ïùð"³“àLë†mq`„$84Â,Á¹K`‹·‘óÕg2?©åŠõ–ÿ·¶(³eªìbQ¿Sî2XQ¼Oÿr2ÆÛ1Å¢ËÛ%w&ÇmëˆyéÀ fõÈå%r?8Eñr2–îüØ"ålIæúåfœå dƒÝˆ$²Üfö®Á¯ÆŒ†ÍûAc,´˜Œ5l<,[,³›•§gÝë>ÇB«qæ5c—ÍìfÛÅÁÎŽvæVè„|ãÚnü†.’‚´Á 8é.D¨¾H¦`§M0\Àîn·ÀôÓ¶ €&8À% €àM¿[´À`· RP€w»ïq°  'Ü»Øw±rn4¡ ´õW€ü árÜ….\x K¤ãïÿ³ƒ HPp´ !߸ €íóÍÁ Á½"‡å¶A’yùTN8@(7H @°}SˆH½%ž¾¢ àå ¿ ²õ©)û’ÊFé@”mQ_[eH_÷Ø:ëV€ @ÏN&‡)»ÛVïG=5ÿà¹ÓîÙ’úH$VÉÆâ¦eëG'ˆ‚u¨å–_µrgN[4³ÓYu’)ÀÍjq‘‹f~Ojéàr’˜Æ*fÞI~Óµ|Ï1Ü÷ú·ç÷’Î]0/³Úeeöš™¨g/!üµ ”_çŠ<¶U©ºt ÌZ¥!PMÿð•žê¬PV°ä¯ñ›Õ!«ñÇKwP†Ý:/ÿ ßð3 /0wée‚ °î È³DU¿u5ë©"»H¹'2àª&J¶Ù Åz*6ê\ñ wд6+¹º³Sp I›«J·$J4j!— %` w`¨¨’`iJs»:Ûú³k’;Z{Û· Ò¹®ò[=:ZÛ`O𱥫Qäõ\t¡Ð¶"»¤² ´QÁö~¿àµR:V³ÅÿE^š5F¢åMÍuµR«¡¢§šPÉDLÞcÊÊ‘E"J=æ K'…pz†f7Š\¶I°”¨²AV9¼Ü y SvæY\ë{¼ÔD£Z!¥¹´B¼mãZØ´í•b@E^ &«^ê!ð+ÄÔ\ôOo÷~þ‹f㔬Y a§¸RPš±½öv¬´@Þ4A±à rÀµ’RðgL ÑY½¢¾¦¡ðg@z6]´QÕy!0VÞŠ½’L÷è\@pd„K jI Lhè+Õ¾Q›ò vpôÆÂ’L‘ Æûé8\!&ˆ¦v,åi”¦¶¢ú“ÁÄÚS}’X`ÇçãCl´Ö@?ìø˜”ì8ˆ|=—)½ïÓg—©ôóHÔ¤(ð žL¢í£ _Y’ð—Ÿ|U‘˜®«¼-ÂIsù·rd²Qª#ÈÁËáË–”x<!ù ,íbÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÔI`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—m,¡möÚRÄöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯¾ßn¯ï>Fí¿/Dí—D‘$ÑF ó—І@nˆD“p¾ Ä€% ýø'€ûåO}H„-Üpð|Ipƒ-6È@‚ ¡ ‘à_üÄG‚Jâ‚ñŸ$ÐÁñ)° l¡@X(€š/1ÊͨF7ÊÑŽzô£ ©†&©oŠô¤äâç–Zð'_þã¥ÿÐÆ:% nC—ºTé,_º@(x¦Þ ¦¶ø"B‚Š„[z‰¤ùF`z !HƒXÄöµÚØL×9E &áÍ„©L“`À ZqM&LÿAÀ ¶á¡ ™kHÔ$àUz0õG úV‡ÀtH`ê_פ€0Íu°@%ªöñ˜FB±m‚ê—üñÒ$Uƒ|iT"Õ¤õ¥—ªQÙ¤Y.ÁÔ ŸÀK¿ñKÿXBr‚%.QZ„ Õ­Ï;lPÝ0Û]\A3(ˆ f`‡M ·i‚ZØ}þƒ²@åßKï …ä dyÁ ^ ÛÉÄ—ûmv›÷[@ÿøÆ2º.PoWÒèÔ·qiÀ` Ù6lW yÀxgpÛ¿tºPjñô €m|cY®œkµR—5·\lAdZ]Ù¾tƒ&Xzÿ‘Ú$Ä·Áß=ˆw0ñÎW¶&L= ÉžF@ J ÎB¾Tí»+Àv T[üc/ÈriÛá#«ö4‰Là=ëT_þoÓ]â?¶amôTáÄñ¾xÔmüƒÿ»1vˆ‚/áà—55’€$h „Ì~@ i –®å´×mq  ÿ¸‚¥<9ÐùY´“ùZaÔL×—I€4A íTä˜d^ç?›æ~IB¦f݆-¢eƒÌØ v‚& ²Á=ó85ô2Œ,%âµÐ…u ôG”z_Œ¶EO#« §Ê@ÆÁ¤ð ;8áÚ˵4¯o!m¿ú4,ôåeKLA¼ÞBÏÅr™ý%‹ †¨‘Ø…-꫻࿰ƒ@rÍaL Àö.k$ž=š`ƒ³ÓYgu‘½UDÂÍ·h¶¿=íW{Ò©ï šð üCßÿ®4GÍqˡęͧ’n‚¼ÛàëfL.Ú<3<_×ý‡$@Ðç—^a ™A®¿|ÎÏíð7þanÔ䙸r Åèbl£Ù…ô¬h+s¤¬6VH @„_º †äÚ™A}@r šåa5)“á-œ~&‘ž]ç`Q½öŠ·á‰ýã? Í?[L7Ñö¢ªÝ_pðâZé2øw_a ç÷¥-ûh¶áY`Ï^/º@¦[l_®Ó®žúªƒÊÙ1'}¹$/+(W ³FÇ ñÇ-têØ'å¿­š:]ºÎ©ÃYµF®Ògðo0U x5ò‰×k_ß žGþÿ¾jŸç÷ý¥+ˆÜçî„Þ}/ÈÞß¡ÌÊ÷…œú¤å@Áþ]}…}Ÿ7fm¶<0•X=v^cæm“&r¹·{»—_‘HÒeVØ^Î6S÷ òu303prðB…XT´A²`f“õRŽfhìµjeuvUö ðer°iöPµ7ƒj¦<†o:5vn&¶°gƒ•s^÷ZAõsÉcYÀUe8¶x;X »wS&&t±=ØdÖ‚Yba•XKhe=sEvå`^ÇYŇcÛ_ÿ[Ü7=<¥€Bå„:SFh f¦ õhÒ_µ2W=4\¢7WÅWmÿÓW„x\¨e}fEVò7fIEvçc×£VVew„Enjb¤ZEÈ=H%a?•]¢'V.¸B±dVw>sEn[å’ðj߇R{¡‰¤µEºP–`èPAŒ1§>²¤‹Ê¨.ø•>â·ŒbóˆÐ8®ñŒ aÔèG!ap€!ù ,^•ÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªU’$®jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçe@ŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,pN lðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜Y°@Yeîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„2’ W8˜ A$(AÒ9Ò$ mD$’ðBH†9I‚-ÿl1C$¸p†3¢Lb˜ÃZ$Á IT"K:G Á 9Œ"ç²9)²ä‰%¨!AzèE—HGHPá@H•H”ñ%ODH%Ç7š¤‹VÄâA’P[„ÑŽ-i’ÃH¸AŒ€L‰-€„¶Án€¡Ô˜È–” ·€ä +I’.âЇmhƒ CYN¶ <4å BIUºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbÞæÆÀ6 ‚Ì,Sþ؆?òÌX35Í,È43÷– ?Ü£ ÃÙ+2r‘ÖtÑÎ]Þ‚’Ð#oQmhÞêÜÆ?ÜðÿÂhn¶¸§]l2'ËšIJQªk4KÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖ6Œ£®­lgKÛÚÿÚö¶¸Íí0íÉÑH ‘³£kE„{¹ q‘ÕRü³H7B¤ Há±âm’ï¹óI) XÚ…«vË^š€—‡æ)ÀÍ 2÷UmîEÚdFÇØÝà‘NÎ}Ï_—ížùs•éô‚4!箎ÖuEO¶ãý2¶2CÞ¼ÆÇ+ÄÈÍq»BT òWmд–„è“„Îõ÷™I\æ2M– ¤”íìöt®«Ë3¤ò•Y³5¿6xÅÕE&TíëÃé´üW’à{C˜‹xÄ<¶¼•E¦Ny\d‘½&ÿèwæ‡ø3)Žq7wHû$¸ èa‚¡Ýè)?õ_ˆ£%b„tqûYáyÎTN Öb9%•æ×¥`G~ÍÄnIèG|¶Mœ÷]…ÖtÌe`ð%_ vH ¸Æ+€V}>y} bË'_m@qî‡iÊDv’SXQV&˜é—ÚxVEuhi¤Lì4‘ÔoŠã{ !O;ˆý·OdaÒ¡TOäPîçFÿPJ (iAf߆ÐßÁB}ÓW‚nùµ‡Õ9 U†GYÁuI@p,NÈLxn·zc ·°s™ô„‚5Däö[LjƒÿãS÷dØxŒ2cáˆZ’^Öt˜q|ò|ÐÒ‰ž8ФX-lhZÄeq}UЬLApr†²ØZQà¶h ²Uw³5~¢å¼ws{ØŠÂ8ŒÀ´IÄxŒÈ˜ŒÊ¸Œí3mõ<¼çºð ( ßàº(š0 @ç>r` N‚xO4mìã‹ w—¥§[׸Zs×u§uvëh?UtmrÌx>vZñؾdÏ…Zü8[]'ŠÆäS S S` Y¾èà?¤Ä‚¥õŠéZ–x»Ä{“pÑH’^]ð…e}¥C0)Oÿ8,9ƈ'ÒÿæfütmÛ¶m—T޾bá‘s’“Ýu“ѓۖRÉrv.ÐyX9x”db”.¥”@8Ô;”J™@i,k&ßà*×*ù%Ûd”‘Ûád”ÛàDJ¹Ècû …(— m &9ÙbÛi°Éç’ȀϑFgs *@r kb—…¦`HðoXé~ VÞÐ,‚éN ¾¨rMp‘1˜Vkûà’o¶m‘ ˜+hU.ÉV> -/àŒj"mš W'‹ßðñ˜MÂéCKI_ÑR“eÒœ%¦`œ(†–à—i – †Q•›öÒÿ2yiÒœ?¨`1ø »p0 3Ÿði›à¸yu\¦`eÉB¹‰€ ¨O— /  0/€ *íÈbMµi•f‚ò sÐЖØ*Ì)bÓÔ]Û¶ ßp1ñI¢ñÉžY˜Ú —]6(M  ø*¹éT Öÿp˜y` 3p /À ß¹i8‚´±Ÿºáš«‚•Û6r !Ÿ%*›°jW—`úÉIÑFqú”Ÿ>‡‹íy`w $z .pÙ”œWg˜@èJ.)R›) ¿À#J$ ¥Ú¢ÖTRµÀ€93¹3 +ÂId –£;*Š@ú£3ÿРºæLjJÇ•Ie¥$ð ‡ú¤% Ÿrà¨ÇEˆV¡Ú „}˜Ò™*ÇÕ\‹”I –ߤˆ:‰Z*¦3à j ©êLî—§ø<õ«É¡{ª2D”ÚRáÙÛ Q§$*/ð“ :B*ƪ\ÚŸ‘€¤ ô©¶ ° ÕÙÞv³*µêž!ÉùêSŠ­º:D¸¸ Õ©€•t¬”º€E¶ ™ú¥P Ÿº…ÿ œê¨üÚRÜê­¡a¤x£}ÇY` €£:*ìÚžŒz ïùsy Ëù Í´ø‚zÒpµ’§ÑžHðqZ›j¢2ðÿ+a>4hWg£- M€T£çI0kÛžë ¤2p³ dxºiUÔ³VƒœöyÍ©´ú¤YŸ6Û“¥$M÷™MV€…sÖ¡M`¶f‹YzMŠ¡™£S0«À¨sûH§”]ËxÖáI”m"\»0$` (·²‡LÕiTÖt ;:·ñé¸Ôú,º›ÒÔŸoê'¤M Ž´ÒŸVÊcÊi¨z´ê®Z‰³$Ë“ó¥'[*ý š1(bÛ`N 3ûuXiFÊPÒ'ùi•¢¤§bžÛ&Q¡û ¿pw`¢Ê» [J•O’` …xhÄf’·b¹ W×$±uÿ5a·P`¾jOæ%› ±|òŽ¸Òœ× –EVˉLötUMç~…EƒfV¼€òŽd»½à¹mØ%±yªOÞå]6aú[kJ(Ä*+Ò¦˜Ä™‘†`÷&û°H UW*æ˜~¢Š«›+-ÙLê‚o‰›þ¤xækMÔÅÀÀ˦…YÂ%ðŒã%»øªK·m(}ª*9éÄù¯Tʡ滭=é·sÒº‚𓇴m D!f”t¤”A¨'ñxÂ{+- _³©”ŒJXÔzZ9Ãb º)`ÆYܾ9él¡”bÉ”² ¾Xœk,v ïxºW$¬xrv’Ë‚eɹLÁSªŠÁ!f¹ÈŒÜÈŽüÈÉ’<É”\É–|ɽrn¤š›ŒÉžüɠʢ<ʤ\ʦ|ʨœÊª¼Ê¬ÜÊ®üʰ˲<Ë´\˶|˸œËº¼Ë¼Ü˾üËÀÌÂ<ÌÄ\ÌÆ|ÌȜ̡ÒÃÑ!ù ,éeÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-v\ Œm6p!PöÙl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þú쓊DH° IDâF$L$å—@B I„-@7´Á|ü#Ü À&A ,ßÛà†HDP ‘0_$Q$”`}¼ A 8¾&iƒ÷‚0|‘D ç' –Ï ùßãG¾ ê¯äáÿÉ—„ZÀ€$Úà¿óEB…°Eý€ôP€-D_ÚÀÄöyñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHG¾ic þXHðmüC ÿ$ ²ÇÓ’cÚHBˆC4RÈ?9@$r‚ÛÀ6"1Ä6dÒxÛÐF(mA‚$&ñ ‘ PI Zr‹ e&]Y¼L²% )E9À;dIÀá?*¹ Øâ›œÈ-‘©ÈãÒ ô¤&ÐÁDâÑF. LT~0”'܆?† ¿$ø’x·Ô†-8yGmFb‰–Ħ&‘ ‰@j³—þ ÿ¸)ÿÅRÊSxË $ÿ¹ z$‘H%5YÈ[ $‰ÿDg(køþ1‘¢%9 "óŒhðlAÁ' •¶X`A¸ÜB¥Ýh6-YÁ$f1xþ„$pÈÊ(&ñ¤ÑF=ùx‹ŸÎ”£Û°EMÏYG扴©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p+B>)ÆC¶…r½ÝM B×¼úõ¯€ ¬` +ýö°q3*b;¶!¶O±å{&™A?FV %øÇ7þ! $´Ô|t ù vþc¯×û§6äð@N2 ŸMŸ ðÿ¸ ¶êS5â„ññÐ `lèÆ©H—6á . È-ìšÚÓ&áºXß7¾‘„|ã &ŽùTêÉá¸PAo²[l³»×kÔë5æBf¶¶SñR€ð¡w!(xŸ†Wá2²þ °€LàlÝòƒ­"ùv¡[  ÚHA~ Lá  ¾ΰ†7Ìafí‚`t¬$&ÜáÇ}c(ÃtÿÄͦ |rCÚ KHâÁ–CbXùÀ.˜B ‚)Ì÷'E0H Ík‰o$× õ5HHzoðM.PA à„¾åŸ$A Æ{2+4 ÐÓ¬P°‹_ $ÿÊìHp2ü–Ƴ²r\2?Ù"Ìì}ñö㢙Ip2gLA³½DtÿÖh¢<ó¹ÞÀ‹Ré‡<“ýª$ñûÇÇò¯²Å–à]Äc’\—·oçµ#€‚0ô—¬šq^IÙî ’ƒ/äÞ³DÍo'ŒÀ.8zù°~r,ÇäÛøÆ6Æ~»9[%Ö³î‚&§ÈpwÖ·v¬ç|}@Ö­@¦^â¹·¡Nê±æ­¾×Hï|§-ÄI¾M–¼äƒyd"9@ .@aÑõq.9’½è€„e)¸*pA ò[@@4×!äKЄ6ØO…$} *ÿ# »`Èàv;Ÿ^HÈ&añTÆ£ CŸPËgyááûœˆÈ"HÞ“Ô|ôÛ{ÈÃVIRØÄÿ.6¡‰]`ÍÅfS_?N<Þû¾ ¨çŸZÐÈ“ÀéB¯þ¥ ‰!Ûbâ–&ÙGM‘j€ôzU ‘çY2p?QwX×€l w&Ä×Q‘`qR¶€"}E‘wñpQq]QIÈQ1oðahFóf ‘×|/¨…´mE‘uÈV8&h¶GÅyÂTÓu„ÓÅGóG…Ô¼‡.hz''1xK'‚&HV¶ ¶cNcº`~1hH0{ò N?Ø*h¶L4y~tKß° W 3 ‡|¸‡S° ›•|1„`zúñ MÀ† àU¨*Oÿ‡õ~m@Zš¥ / 30‰š8/0N° ËK.ä}²†à†i'g=˜*ØD}Üy-EZw œ¨‡™Ø‡zØd‚˜M‘…ªá^Iao¸*£P I`‡¶P[›øŒ˜‰Ðнˆ`€ù€²‹”…Üõ*7¡‹{XŽ}v‚d’y—™¤þòGÜ8„÷wKS â(¸›˜‰r`‡yÓ´xuMRQŒ¦"°¨ ³wK7€‹{8ä~xÑ}ø7Šu@60õz듨Y¶ ‘ñáÿ(Š\øKà«q@ÿÿÄtöRI¶p ¶ð“> ”‹—ŒnÐ`–PgчRð vðº8=ù“|å„ ÀôŠI…³’D?)@aù“Úà Iu s'ù8Ðèßð vŸø“²à€þ`– †HNøQCx•âQ0Yé?•Bù“›D„êd ©¶™‰i‘3Ðß@ÿ NЇŠ9•g•©1LZø“6©!N v%‰™˜w–Byžd w0w/©’où ¤'—›X—®9ˆT £ÁYÝgM Œù¢˜Êɘs˜þ` 9&樒|ø˜ y$°™O€j‰ÙS¨L¡)˜žÿÑy–”In¢×‰Ët ì¸YÐõžØü¨º y) —/°Tsò´•`Y¨ñ6Kÿu7ñ@‚ꉷ´~ò÷‹Ü$¹(™}x‘Gç· É‡M„èÇ×Y–Ä‚ýrŒ¯w†U©Yÿp0y›pzϦš"5‡ëÖÛ„M z&+&ºL%¹Œ´ R@Ž|ø*yÙ©O•…!©âù€) ÷d$+ 9’ËDˆ³ø › œØ›3𢢇:ˆ‰Þ° . £©w+šŽó×[éË™y¡÷™{Êô E•„ èñpX+qh˜¤ õ¸Y^ÿÚ¢›ø¢Ç‡Æ”˜¢tP¿˜Èy+£(IXÈŽ#Yj¨¦§!EZèR•ÚJìhS(êl¸r…†ég)Hšu‡›0W0WàV&EXO™DWz¹JÀ3§‘Œ{™¥ZÊG=9†t‡T’U ®úª›Ê‚YhLˆ¨Aˆ¡ô1GWÒŠZôA@ršz­Æy'yŒçߊL¾¤—Z˜©î1o-Ô_ Š*ÊQVVÞw \(’ÔRA)JÚy5Š޵y¼Òyê:(*›|´­“¯ðÚ`TiŠÈƒ€x}õÔ¯d ÙJ„ü1];vb@ç+xP%‹[d@8ô~’Ç€üÉ¡Mà?8›tÁ‹+U²1z»çNæl¸ŠÂòŠsú %Tw&zõÓ•÷d#‡eüv,ÜH|>) ö£S§j Zg,Y[† Ò£É"²#Y I ¡åóB!¨Øã€dEa †w·xK.p›=Opës ¤ HI>+—|Npkûê< E.T d°²Ýƒ„P‹Ëb¯ be½õ]JÀp>>aG{æ§i¦›1}逡º ‘ºÁº}i8TZJqMÀ³Q¨±!ù ,ñcÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸]ÈÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd‹LBÙhK€g§íöš½-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ! %DòýHIþ±_$a I ¡ñ[›î'7DÂ%HãG& ’ÀŸ@4ø>ûÙ‚mkk[膄€ù RBø¹¡ »9݇¿¶ ná IÐ6¾‡m¨Ÿÿq Âo„8,`$,8¾/¶X¢W¸@[´ éiÄA dž#Ô&*‘HyÎ;Ý—–´yüÕHäõ2ˆ¦ê§Z‹SÊS‡H€ª*çJ¡ à€¬ô6ñXg¬ªÑ6ˆKÛKb«SÓ‰ÿ¼c 5ÍÙ©šüö4ð¬Oìn쥇ñŽ]kÿ³Ô:<%pJûqvèùq"ÉÓ~»úæà̹b³l“ë†IX.Ë¥ê ºZž‘`±T›P¨p/ÿ8­E®ô¿"”În8Û>}ø¸Ïûþ¹Ð×LËmD\ ÜõØÔ/ѵkF•Ö%Œ·)ÙÓ~lË+ÅrÎ1äá`´ÐòN'žyž½þÒâžO%-E4…cÕ•Ñý‰HlâÖ»þõ°×mìg/·/‚1eÄqA,q9Ðþ÷Ôó½püâç Æ_]’¯:ä $nÌgí}· @?t•߈ïsÛ’“.Ó?$ÿë[‚üoDßjÂ?¿úﶬzéåÜu•ì{.ýb´¿ú F%¼¿qZô(CÅJþã@…§Lí“fS…U ¸?% ‰÷L·q X ˜uâ³*µÕe$‘ÐA4O ÐUïµ$ýD(³tS‘uL%zµ€XujÙ“JÚuoî÷‚“L0ÔUG¢ŠbƒD€Ue|5Œ6O%`_Ñcƒ2xf Ót„÷„UÜ—$›0(eEl5M{•J·Õ?>¨$@ø'1RóDr A…b8O4è<1ÕjfV1Eø4O˜dÞc˜þùì·ŸÛúîÇo¼ŸÂ?ýòç¯ÿþü÷ß#þŽÿ°©rfvL ©Àü4pŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ bÀÿÀ'" ñˆH¤Š“ÈÄ&:ñ‰PŒ¢§HÅ*ZÑ8K¼¢·ø;.zñ‹` c (Æ2šñŒ±Bo”;„Ôëz U×HÇüA¢!pÈ-2²GƒÌ±Ž(J CÔÆ…<ï$$„ ˆ‘¿)rC…ô£FÔøÈ!1R"”¬äƒHÆ„.Ô¤(ß–ÈQš’öÓÑå4Nžò•ãËc»èJXÚ’‚¥¼¥.wÉË^ª–bfQrùbúò˜w’%2…Å·e R‰¤3 &À^/”])Þ4q…Ímæb›C‚6“’aš¤ÞÌ‹ÒY¥OŽ%Œ1&;ß4ÎyvFžöÌ§ÕØÆÿ¯n®E™ú èH̹®•=°žM¨’ú|®M)c›ðŠe.¯cU¨FMCP!TšéAºÑ’6ˆ¢&M):š–ZÄ¥ÿS©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªRu1)µÆŸ@éT-Ó¥Z5VÙq(J:VMƒ8òªé#XÇ 4Ï)ä«dZÓJŸµ²U?ÍŠ[ßJ×5³‹uÍk´žºV*$pR©^û(”rE«„M¬bPÃ2ö±3«jN ÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖºöµíq,lgKÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p‡KÜâ÷¸ÈM®r—ËÜÄH¶¹†é*tO“ÉéZ÷ºØÍ®v·ËÝîº²Þ ¯xÇKÞòš÷¼èM¯z×ËÞöº÷½µ")|çK"ðÒ×,%xî}Ë€)ì~Ë¢¶ü¸5qh€`8¸¿$hƒ 9ù.Ø-ίX` $@õÂn¹]Ó–;°à¿²qXòD‚Ù!Àm(@‹õ«b¨ð¦p0Aäìè¸Ærq$$Ñb@‘À±@4 d» 9nM*Á¯7/•H¦\_ù.(Ȳ%R€‚K5˜Æ_nŠŒP Af¸ÿÈidü`ÿžy ö³RfÌd=×¥Ê HžýÌ”>Ú.ƒ>´¢»“èE;úÑŽ´¤©äƒTÚ —.H¦ ²étZ Ÿ@¨GméRcÚÔšFõ¤WÍêV»úհ޵¬gíê¹Òúָε®w] ³"dþˆÔ¥ÿ‘Kž†Ø¬­.¯{dkd÷ÖÙ¶Yç]Q» h{úʾ±kk냬S_Óöе±å/û+ã¹K+ÖOf:Ò 5AÜé:_K+{HºÏÍïÌlû×Ùö¾;3ð~|UáöJ§³îƒ³UÞ2é¶Ã'>š…S<*ÿˆX/ÎñŽ{üã_ü7ÈGNò’›üä(ÿOy{·Íò‹´\å0¹Ìgn¦‚Óüæ8ŸŽÈˆoN§â!uÎá›ñ¡[ÈæFwˆ½“¤ $Å¡-:ÓÑãtH·ˆSÿÐEýª#ÆëÝÝzÖÇNöÕ4ºìhç ØO»óÕpí¬mûGÒ ÷’н'éδØÓÎwþHÝŠr¿Z¶ûNøÂÞ<ÜûáÏx·¤ÛTTm¼ä¯âõÀO>!E H ¾!hWW —ÏwÀbùÐ/DÁy‚ÐM%q¬' ì ²ñØsdöYºí+‚΂qήûî!bá—¤ö)=µþ6gsþ!ºßV£.)æOFùpêýÀîš­çÝÓàuÿøÙ4{ˆQøe±xm\_Üç°Ó=‡ŒõG#:ˆ°?^Øç ²Ñl#ô»^ó'Š—ƒç$ÿ' DE€=î~QDoG' ¨*°C–÷.X$îw€{¸Bêz±=":`aa‚1Ä‚M¢}Æ—ƒQ€òòrƒ¡ƒÁƒ¤7z}#ê÷ƒúÆ%(=)ã5ô1!%“uS)ƒ%Q…VXÓ{L¨..ø¥—4Bƒ q/-`~Yx]yp 1„1!†«†z ±†]A?F‡Á„x%¨/rx44¨‡A†vHÜwng|Npˆÿá†àˆ¶Xãfƒ£ˆ7‚@ˆu˜6wvÉ•~X‹xÏGh•Øÿ)_è^ƒã†ž(‰I1m2ÒLæ]zÇ<áüB† Ñ´ˆ—6;””ŠŒ®‡ñ„á•‚±ŠGŒñmQ¹6{ÚX¢‡Lx`¸öŠs7¥‡‘h<šx"Ô8RɨuM{)à´h ~†† ް FAlx#øø1ŒÙ¥Fí¨ˆc!6!a~JæáŒÓåá‰q„E…. !Žä…‘í'Ux†a‘’Œ½H†8öhw m¥Ø82`uèÿ‰(Ñp$ñ Kfv@DÄ€%×@Òx(9Ù¢h!ëhO #ghÀt.±&™`¡}&InøO]©…DI2I‘;RŠü±@ûpu†dG¹m)myPrÄÆ{˜¹‡«hÞÕ–m9˜my 1±a Ià=%‰8X˜”ᆖ‰ÿ§‚B•8’ ‘—83Éx¸‚ñ “`ò‡8{®§‡ø(š½hrb˜Þ1˜&A›s´y;"¹$gé2¨ Á›'¡FHÇ›U9v5ä("ÓY¾I)™©„ˆ{ ¨“žKÿã™&¢–ïÈdè’î(~"‘nÏi.p…w‰Ê94æy,Ø(ž#–óÅ›î'Oä™uæä˜1n«è‘YXÈŸN’ˆ6¡kš¾rŒ !‰ò ÷Ù†J_¶0 )aaÛ)១„ê[°Wš‚™œQ|xº›¦ 1£‘Q ñžGœI%¢ 㣑žÖé<µYÂxJ¶QŸ.ºLè~hŒùY"<Š= “JAJ0¨ˆ££êÕ¡ q š ?9œá«h~%`¤¸åzhŠyz¡±{ª™m88Ú#·` ’ n ’  DÿZ2O§‚ Ÿ×™¥¡MJ¥bÚ 0¨?òžúžƒ0ª¤Zª% Š1Z6Z•ƒl9¢Á©ú3©#¹8"Ÿê©¶ ¥ú«£ZÑ3<){1¬.Q¬!*uŠ#» ª IIÐn@­¬HªN³pfZàˆ4ª8¹º!Á÷¬ÿ€o¥š’ ®Ÿº ½ê_£Jz16g‡‰8r‚{3ú1`'š(š~H*œ 1ti!£¶«GRªnàkðú©1Úíš?­*_ª´Ú©„"êº ¢:ªH€|%¨®¡ %@ªÊz0ŽÔ²2A©.1¨y §$ÿ¯# [ð*nÀ²2;/·˜%¡œ]:5a³éH®#‘€ú‰“B´‚²;ª¶àuÏ:’@ªR[1§S«_ñ‰©¦K˱yRz¶Aˆm³ â»*‘@ªpȳžJ·ZKª÷º0Ýz‘±ѶXÁ¢¸’µÚ@ª¹£uë³õj²c7y«J¢1“3Ú±!·’µ …€‰ !º°²¥;2_e¸}!«\¹¶P¯0é)º‚›²¤Š¬³o°ç¯"¼ðI¥4ƒž‹ˆ‹à*© œ©’Üy!6G·‘;²n€²ð Ú»½ A½ÿðn£ÿÚµs¼-!šƒJ¸lÊèË)°¾zi"‘» ¤ú©ßðõ»r N¿º°s‘£¤ª­ä’¹ƒq€x” ‡¶"º? I@¿ß° S 3 |Á20»p¨Kº[1þÿ»^:O‹zè¾ ’µÿ@ºïºÿ° ºàR0ð3Ã8üSà«sIžZm1»º„!Àm2°‚j§·g92AÀÚ±z>wjúö©Ô£ê©Ú{¬ž‘ÃÆ3` ßàJlÿ+¿£ŠÄä¢Â A¾X¾®kn\!ë©·0ªDP¿ß` / ^,8¼Ã3ðÇR°:¸›»©ÿ;ª¼K0P¼pìs<š–aº•Q·¼¾Ú‹ÈaÃÆ/ ƺ÷¿#›·Oä¾$PÇL†‰Qpu[¿[«³õ;€<^ü7\È¿02Àø‰l˜lu£jÊ|QN*h1JzÅù!AÛM:¼#ù‘,\ùzP¶¥,‘iÚüR<~%轞 Xìßð–aìÎ/àÚ+|ÈÒça >ÍØŒÝ¸Eü ;ÝÉ`œÃÜÎ6¬ÖæØ ³Gÿ@¯·ÐÈ€ÑÍ3Ùñ# ©ª<})FÍÔ ÁÒ,½ 0ª`ËAÖ¼mÑ™­ÙAÛ ãóÛÁÔ²½ÔÇ­ÜCŒÜË=UM)«m&ÆÝÜÇíÖœ­Òå6ª–À˜ÿLÁ|Á5ý«%€l,íÓ]M²¤Gb}&m1æ·Þ"Ý{as» Ãë:ª›ç’º-cMÈ8ŒÖäÌñKºÖ¨ÏHëÏýŒš þ‡ ¾Ï7‘ˆòM&ú»1Õ%‘—±ù‰ï«àPÁHp†âÄ\Ëb]Ù`ŒÙÀZÄÁ¶·ÈÙ}ßÌž©FÅ5~ãSŒãà¼ã4þï=ŠÍôíkè¹;«Ÿ2±E0ªm° 9ƒÜÛ2 à+;;­˜»U+¾ƒá ¼>Ýò¯D »àÝžÞ<Þ%` +»¨Y lžJz¤êÔ„Aç5‚tÚ××Aæ>Áçfëû6±¤[œ÷äQnÖÿ]ÞY½ºžså‘Bº22äaƒÁ„*²‹lÁĉÒi.¯~û cÙb,PÓþøæ_ê½Qµ1~1¨Ý­³~º Mªsð 30ƒÜË…<åßнµå]mq>æ¼}=ÃÂ-Œ·ßàÝ ¬ÓùÛ0Ú°G+ ªqnÏ«{0UGÂ>"éxáìª î¼ ›0W0w0›°ÁÕl·°·BÌíÙª,¾4ÜlÅȦ+‹ÅÂ*j°:ð1ª *½ מ³÷þ2·/ØKºL~$h\·ñlÚ™\+îÜ‚…À¹/3±Ë\k ¯®]-¿ºìó|˜˜àn2;´¿ÿš„ÓŠ¨mjDÞŒ 0p÷ã4¡é ô7©*Âï»Ú«¿êG¤H°ÌÓåQQëH!õG7±uJ¥ŠøŒ1Pß2û©]o‘ðæ ³v†3_O2J°(Ž1ù~0x#’ ¿xL<÷3‡tŸDõ¶Wé ⚆A¡—Õ€?K·t_uš…Rû ãóeçy[¶Ü!ô‹ïvïSx}ù¡å¶€aÝ4N¯/g8ZÉù¨Ÿ™otw]M-,·[«/Ÿ…¡¶oÞÝ»äŽñö/Bl]UЩÏãÐŒNJëAvŽ(îdGx_‚@ÂÁ‘AQÀXüI×FÏÿŸ¥ÿ¨ç¿)΋Ðo]¢ÎÁ¯|Ÿ½æxþ é:>‘ª–ºóÏõÏþøŸWŠk±ÏñMÀ@4ˆPáB† ÿÜÖPâDŠ-^ĘQãFŽ5FôRäH’%MžD™RåJ–-]¾„SæLš5mÞÄ™SçNž=}þTèP¢En|xTéR¦M>…UêTªU­^ÅšUëV®]½~VlÅ6cÍžE›VíZ¶mݾ…Wî\ºuíÞÅÛ¶ìÁHyýþXð`Â… FœXñbÆ?†YòdÊ•-_ÆœYófÎ=ZôhÒ¥MŸFZõjÖ­]¿†[ölÚµ›m߯[÷nÞ½}ÿ\øpâÅGž\ùræÍ?‡]útêÕ­_Çž]ûvîݽ^üxòåÍŸGdzöíÝ¿‡_þ|úõíßÇŸ_ÿ~þýýÿ0@$°@D0Ad°A„0B '¤°B /Ä0C 7ä°CwJJ¡;ñ ‘bèÄWd±E_„1FC[oF7 !ù , ­£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨Sç°„ê×°cËžM»¶íÛ¸ºÎÍ»·ïßÀƒ N<&âÈ“+êj¹óçÐgê:@ôëØ³Kl®½»÷ƒÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏu7ÿÿ(à€¶Â@¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶H—.Æ(ãŒ4Öhã8æ¨ãŽ<²UD@)äDiä‘H&©ä’L6éä“PF¹ŒRViå•XfI‘uZvéå—`nÅZ˜d–iæ™3N‡æšl¶éæ†j¾)çœtÖ‰_væ©çž|j8fŸ€ŽxK „B÷g¡ˆbX@¢Œ6ª•ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØÆe¶Üvë-„n.QÛ~Ûè¢æ¦«îºì¶ëî»ðÆ+/AqÌk¯]ƒÞ;ì¸ñKÔ¡#ù«ïÀß« u\ð 7ìðÃG ˜ÂE ,ñÅg¬ñÆwlŇ,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-  þrjWK­õÖYli¹\/œBØ0ÅùQ$'UmÍD^÷_ÛdC·Ë\*°´IÜ<ƒ÷ÞÂêÿ=VÕCYÂTÖ.àÎ÷TÙÐ…nbw,ž˜âFÌß’a.ù®ùn. ÙÍÑ*÷{®ºäš zU­·¶úì´ƒJñíQ^’š†Pûï“ꮚðÀo|‰§{GƈlŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€\ˆ‘£Fµ2ˆL¤"K"‡EÚ R9¤#—å^M’Iä$딺MÆF` C&erœæý¤ žtKS)$H’%Œ#+éÔÉYZF–¶Ì%Ð|˜ÿ`%¿Ô¥0]2JjýÉ”ÃL¦¾p©”×iD“º+¦2§yiRóš´&6·)!mÖÅ›§ÄÉÍršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑ>’³¢MÖEiÌŒzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦Ü(NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§ =^RU3h»*g:ªÕ®zõ«` «XÇJÖ¾•õ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷*®òõ¯€M”+—C¡@ V%¬bë³ÊÅ~Ó±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M­j‹¿ÕRÅ®­lgKÛÚÿÚö¶¸Í­naÛ±øc·wlpáõÛá÷¸ÈM.oz;ævǯÊUä?tÒØèZw/ν®OZk’ìj÷»à ¯x6Ýñš÷¼èM¯z×ËÞ!–· ï%H|'2_Ô·½øÍ¯~÷›œâò÷¿>Ì}ÛzßøÀvË6Ìà;øÁ”1pl á [øÂΰ†ë_‚t¸&Hˆ7Lâ›øÄ(N±ŠWÌâ»øš~±Œ)ã¤Æ6αŽw¬fòøÇ‰1…gì] Ù¤Eþ1w\š3™ÇC~²”§Lå*[ùÊXβ–·Ìå.{ùË`³˜ÇLæ2›ùÌhN³i¬æ6»ùÿÍæõ1œçÌ ÓùÎxÆ tóÌç>§RVÀX\ZB‹E¸~+ }­(3úÑêZ4“í–Z¢é½÷utÎ ýI¯‰Í"F¡¥!M¤mØB‘@µ$,×â¸ÚÕÛpC@ëZÛº‘Ðt†ýñêWßb° ³µ°i„$CŒÒ§‘³‰zýjm$V$HBÚ‰6$ÃNÂ’[¨l1ûÕ‘¶$áoO×Ô³¶uuÌìmücM¨5’`9s»z Ûhƒ­}1O?ÄßÞz5¯_½ $Ô Ûðoq™Ík‚h#Ý(¨ñkn¼Ö‘øÆ@4_fDß´~6=.ˆg•!ßÿ&ˆ$jÍï‘÷z ᦵ±Bò¬œÖ•¼ §­äêD 5žä‹òžÏ× µÖõzk.€Ð Ó›Nl—ß{ ·HzE^îðZÏܼLOwh~¨süûx5Aòrý<¾Ú u´AòoØýîö½ñ@Þ^mh‚w×0]¤ ®þÆ«wa 9ÈÁ Ž×…Ò ?ø’Óúä t€‘ïjƒ@¯þÆ/æ €˜^3@½ ¦°‹¨ËWí±EÕ%ˆLÁ«}º®®uèuñ)L`˜Áïƒÿ‚)8án©¼ÅÿÞ;ß*ð€‚ýÀý$>røý@NoúÔÏÀ®§<ÿìUBkV&ÆgX‚äñWËþðÿø†.^0 øø>ðepüä_ ·nçeoÿpsmðÈWz1¡zô7 ¨×z¯wuax˜×®f ·àd°Æj®¦ “Q¸÷ri÷1çÿ0¾·}ú7|3ð2 q*(·â7_'ø®& ®Q~kGxþàtíkís€!etÌvsq~݇zÜ'ô·’ È÷[F—w`„w#Ö…\ø…á…aØïvxÚp $`U؆'ÿ` i~ E€7çÿÀ€‘|ø‚20+1›0dÊ€:¨o V€ŸwcÿPIÿ° ÑFx‘è| u ¶‰š¨ÚpsI07á„Þ§zð!W€X§‰˜¸wé&ÛfèJ®CGy¶0‹n˜/ÑFujš( ¿˜‰qP^Púgză´Å(8²‰Ö [ÿ€m¬¡ _ï‰ö…‰k‘xu”È‹e²s>}{’‰˜ÈŽšhŠ´¶ R XzÜ÷„¥xkå厙¸wºçÿà”8‡„wmÉ'xÒp ƒx–èt¨ÈÖ,›8‘(sW ôׇùƒðXk%0]ùsž‚tájÞHxàØq×8„åUŽ ™Pª8‘ÛsIð SЀ£ÿ8Šù(lÙŽˆož·j:˜²ˆþG‹”'ð÷’U^ÌV‚eX}›`Ç(.øúƒß0l÷nïÖuñ($)ÿ o£ˆh’,9].Ù%š—-)p—nm° õØ„¿7Š/NçC¯¶fxÀÖþ‰%P <¸e õf”o'‡^R7޵B€ÃȘWpúׇ0ˆÎöy¨ñ•u2'oIw–H×[ji_÷f„`2jw¡Ž9B€ÿày%ð D9IŠø “nÖg Û‚áy-w~Æ æ¸·`~sB™=bnЉ´æߑɘ•1(I · ¶ÿàn6X^1ǘ¦yLY‡HØk7÷y»àª‡—Pø * Ϲrçn6‡q.ó–; B‘Bb›GƒÊ¸™úç–° ßp‹ŠY˜ñ~‡w`„µæßp R“R@zßP˜ ø ' ƒù_¶ét!· ›p3pS°h_Åi g(¶ày(:–™ò|Sqq”˜ˆow¤Å)Úp¢ ¤ÞB #¤Yûfææ’@¤pö"C€Ç£™…àÖ†ûf›ÿð™´f\YlÖž½V˜‘€h\‰BÙ=j*lún( njýèbö–e>JjÈ¥G楊ú¨©’zbŽ dŒ:©˜Z˜©œÚ©žj]Nú©FµX÷¤*¯h§úfë™$É)ªT!›°:«’ÕªHa«´š«evØ«ºZ>‰ú«ÈÅ¥ÂZ¬Æz¬Èš¬Êº¬ÌÚ¬Îú¬Ð­Ò:­ÔZ­Èê«Öš­Úº­ÜÚ­Þú­à®â:®l!†a®®K!ù ,MkÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë‹I^ÊœI³¦Í›8sêÜɳ§ÏŸ8 J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jè¡¢€è¢Œ6Z£¢ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf›&Úvëí·à†+ni’Œkî¹^‚î°ê®ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG½ERWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæì Åùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡G˜ª‘ð„€ W(H  mHBfX‚‚˜…,IB$ÜÐò0 $¨!ÿ_R‚H$ ) mD‚Üpˆ.!lÅ”P :tC'F¢Š*iC$na 78±é!QB‚$$A’°…€ î0†H\£I¤C1ˆˆ£$Œ¨Ç=¶Ay¬#ÕÞXƘ²$:" ‚ÅG¢änœ¤d8GK’Dˆ‘ˆ¡ ݰCOXŒÅèHS²$®<ÉcIËZÚ’6*¼¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉLûm#˜þø‡@¤9Íj„š Á¦/µHB›áæ@Ê…ˆs˜Û¨…-øpº ÏýQ/úƒ‡·f;ÿQÿ‚ojó}Ü9 ²6ÔðoÀ?$ÑI^î3í$ˆ? zÄ$ØBšˆ„4ÑhÎh£· A<1FOí³µˆè5åh IÄPšT,È:/jÎhccà QD‘àOƒÔ‚ ù¼¦ Ä”Š#Ýå6þñÌ~.U›IjL*€6$ªé£/™úEŠ|± ­ê6J*Ïø‘R &)Å膤 $¬)i;©8ÔfÚÕ 9MH^ïÊ×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊZö²^Ûg4™HUªRKM 6ɺ׃”VqûĦ-¨8QŒuµSe¦JâÕÿ^s¶«%k2gûÖ›„·Ú€«c¶Z…Ft¶ªq±y ßN“³iî3CNâ*÷´‚‹fAÈxí$¹’iHðͺèõhjÛ) ôúvŸ?zÑKÔÎnEmA›ßå„¿¹Æ€Ù¶á¬HBDÛ¹ùuŸ#µEQEJVm0Ñ…Œã-Q•‹Wm6÷1å&yýX‚ˆšq¤ÿ@BðÞœ6Ø àÔ¾ê¸8®V Y/v Ó-Ê׸DÀTcÚÞKÓÀXïUEú82®ÖÉ4.gy÷寸ˆ õ¦v¥9T+Ø,~îze¬ÑÔNT˃­š…[³yÿ1m(ð?ÀLÓ´¡@\j‘ÅœÚ<ë8 nÜ“a{‹*w8µ†f –™ª¨ãÆ·hôœÃ äiFº§!³älÜÒ–êöÐíü´cm܇VƯ š`¶™ÔàDcQûimp¸ÍŽí¨G,€ jW øÀ;ÝD Ƴ½égéºBœÈ•26™8=gyÊ™Ÿ·ÝgLv|8 s·Ã¯dÍ^ WÁJ2¥9úK‡[ב{(A$áÜç$¸®­ŒJ‰‹âÙöwÖ–œ¾iG…úW -E ¹A—Úï²vºµm8_uÌY[xV³Vf^CŽÙ’›üä(ÿO¹ÊWž!X²ü˜­|çÄíJåÏœ™æ%o;#¡^ÁîÓ ûD$uÛN™ï¼çDo'ÐÛéˆ$ °EGBÍ?*ê»þÜæ …'L7žb¬ý<ÿèHnÍ(âz¼\ Oø¡¾ñ7Ö<èNÿç«l«oºßü2wÏžáý7aêsEÂ-¼«ª³^´ê-]¸ffNÚk>¤êÃÙ;ƒ—žõ§²Tí¥â7æë»yÌ\¦Å-ÈYCä^´Í°%N;U¼Ï¯‡¤H¨³ªÈØy!ߢö”i/‹©)ÞÀX Ûð@noÝC|šE<*¶»q©ßˆÖ›ny£âÞSѦæi©x}È¿0@ÿˆ ÄoV¶ ®¬µÙ`¢R‘jüôæœé(œ½›íüÏwñÚ ¾ûœbk„§´—wŠ! $0H»·I:§|wöB(‘°€v¶{“& gFNõæMÁá|ðö @· M€F*àsf}x)åÒ}˜¦7µPà' xiÚQ€öt% u¥fUtö\â×Ve«WbùTѨ{¸)eö‘`[ž1b'O?˜`º5Hòe~N„íH/t Öm—ß  \Fõt¦Ò‚ acŸÑ^OµI.4~áHH7?h\Mnn\ïÑ”EPo.p…ø—€·ð ß *ÿyñ„ø–R(M€f ôf F[ 6`SèGŽMm$nóåm{W†á!mPm – *l¸nèpÈh›˜UIæoÐlÚ”ƒ>¸mÒD\ 5c¨ø IPßp H(…x)À*éw}ȵ„Q‰¨„MEfÔäÕ$^/Ø^ß|x^d·rÐQI td„1­"a×gaØèçZâuHrø€€ö„t~âuQÛDWCxöhÚ jÀ„h ájŠ*+Ø+˜‚‹¡XŠ"Ed%^!I|âSî¦(ïue Øû„EÏÈg)øˆ]öÿX“’ñL#çp¿EP³Fz»qRw‘Ëu‘¡’\›W€„"n 6TÜâô¨c¦bzj·Zj˜$·_¦õ:Ù¡Cÿ`‘áŒÈˆùh)‡Äµ‘†ò’ v3)ôÈ.à.ÐJ–’rchw{€ù&'ÕeyXùçvS)Kш±R˜³Ñ•µ±–%Ðß`¬8”=—` rD–/'(ð>òˆ’ÙJó™Î›C1‰…%›Ä3‹ Ñw` З‰NAYM Õ?.Л–™ŒXDl—bðFc‰1Ë)–áTÓ—A‘àH˜¦ÿ¹D`M‡gŽD9yŠbQÔœ×3KÑ™OMçOÞÐO‹IŒÁoÇTyse}y9-° ß™ÏYqì¸U'¨ ß\( Ú0žÁ—N BÑ–oгQ>9‘ Úÿôr€ü7Ó8“wyrp›š›Ðw:g›¬•ÿИ !ŸÀ—Ò´Ž sàQˆð¨ºtÌs˜›):jJWb]©/wð NÏÉ<’àiD¡%a”<¡tN'™¢ ”ѤWZUr?dJ¦;Áˆõ "Xr}%0€ï#a± 5‘Ž6¤f*&øN¡5¨ìã.œ-ÿÐ.6¡tÆ¥ +!—ÀŽ–p Ö ? à*° 8Qtðv Bš{)€¦ñC‘Œê¨*™± S€ S !¥á¥/0/  Ó¨(Ói>À©žj ,V9Eº !Ѭ¹J2ð  Ô>ŠÚª4!MR'©8ÁˆÒw¢ì³©ú©,AŸOŠˆ¥*¸:%H‚éÚ;ovM:.gV×´ º—`–8¡¨¿EE„ùV裪.A›9a„RР˜©¶C£áUº–5!Ÿóêyù ‰H|·S(!N N ¸YkNÀŽM`‚·S² ñŒŠ’ŠÚ.` p*«ÿG†#«?ÆØ~:°©ÅÚ¦e5ê—»€›«‰Ðê;¬Zþº7⩨4Ëy饶£¨º©X›°©›¯±‹I{„Ј;¬ZÞ¹h9 ³-à4KŸ!´QžI NgûE°:Z›Å*Ð@ëz›b+e *´¢+¡¨ÅêvЈ)€¥!ѵóY¯ß“¸\ë—Éé¬È¹NZ‰6#,»$o«Ñè¶I‘1[N+ 5|»¶ºGá ÇÖ–%‚·xÅ)›ª¶ë«KUqÀvdË#d4HnGBi)ŠÚ@3›»áüÿ*§K¶*) =˺©¥ ït_îÛjk$n™+ÅŠ¼½¹¸qQ¿0ÂqL‘ï뾿>²c¾;¹.š/³1‹£ñ ›wð“2eyNN4J;¤bï O“â àBs[¬ °®!¨(ì;(vî QçZv_Î6%i[Ú[ ìKë¼`— ¨B\ˆ+ (- h¥Øb1 |$ùnîù#Ñ[ ¬Ã$\ˆžÓk%@)€¸´[¸‡rd|ó%x¦e•™’éå$kY³ŒHÈÃxø³1«K?›sû´uᚢY%Æèµº·µYî4_ÅY$ß²qÿð±>±´ ÐÅZ¬ÈÙŽMr,¾pqŲÄHŒ~Á¡o5_|ŒÈÇYâ)·;¡£B\¹-`©ª¨x ³’¡ÈÊ4_ËÛ#ßÐxœN°´L»Çû˜ì¶»©p±¡:•ZÑ+c¶|Q j…<^€ $Vú˜â)¹=A»CLÇ*°êw›™JI! Uèå¹öjM¿UqÆì,$¾,ÇEŒ‘L»*‡ëÅr1E–€nÕºñÁ¡`fÍÏ™6_ý6$ÙlÊzÜ- <`†¸L’£ü#ÒÔËx¬Á . MT -dÅØä½I¹_)IÀ5òЧܙÜ̯û1ÿñÄ BÈ£u^ÆæÇ±Æk\ƉĂì#WjÏG!Ì€Ôt¡… ðLMíOLj¡)r vPµ@ N}È@ò®ÆA³Ë(¼¢Ðí4_8ý|3ÐÖ20oÝÖVª¸¦a F_I¢Ô¿ár„–ÐвpY·Olwrð303ð‹ÝØmM©u­ah Ø=²W÷Lf:¯M­GÈÍwj=ÁñÖq ×/`ÚW0ÙJÑ[îI¼z’ÙRq©¥{Äøˆ=íØŽ­–S0/ ÙáN$¹Ë!dÛT†^Èö =»Øo-¦ýNЈrðÖR@×8]ÇÍÁÿõQ¥õ‚™¦q²1]¾ÍaÒD¶M5Q ªÓ‘}–ЫŒíØ÷-Ü3 –FØÖ3P¥|VòÍÒgQPô¥u?i îvzÛPËYÈdå Û0ÄÓ½á¯F8†MÖøaÁëUËÈö ¼ ׌ ×&®™ËG¢oí  µYÜ^Êêxî,Û4.ãZã3¾µ ~é”`ÚtOË'ò6~7l°‘Ïþ<z­Íê”j –  » ÊÍvº§™º- ¾ÝÛ­–i<S`d'‡žœ$ RÒä‘®Åè'MVÅ“2†Ü¢ñ -  Îã¢f„–\ÐÌŒ·fâ¦}âß`È$—ÿ fBö‹ µÒ¶véé>é!é=ñhÔÔ`Z(þp{š.M­¥PöÇuÛÆÔÒi7¶Z 5_Ñ6ùÝÖŽ­Ø`nèmj º T4Uÿ0_óGñ„jØ4c9%ìûEj°1áàì¯ã|íÍN–\jæhl ·°®%~Ú§â÷•§¶—zátÐ:ˆ‘vzÊ÷{û%äQ± ûÜÏVl¾Ñ±` ¢è«e éWËX:ß^þÛ….Às[²ð_HÜVyaìÊçj¡ðñECžšª9<N° »€ñt} ƒÆçéçêv Ø!è‚þÜ.ðdtnÍÅÐט]êNP1ÿ?ð˜žZ{Y‚{‰Òýa®:¶THÜ›¹ ëíØm]ë YCûaÚ„Ñ|±~þ‰Áþæ'~Þ©Jñá2¢MÍbíâÖÙNèË'GÞ\é§2^¯íd¥‰·Ð\ûéòæMžÕò`aÙEqó‡»ÏçÒ ¹|ßÀï]¾øû}  í•æäéAÑ^m>~pNÆÞÉò†¯! ãiÆbøwýh¿¹$?èšù *Ðß°àcõ#ýµ¿©É¨^KõûϾ`œ O_tèè‹ôùMë°ïFÚ^PªZó5ß1RÖïoUš°ñðÿâáfÖɸ;Ú>oíà&?àfNãÈËß©½©*¤ê.†èUÝW ŒŸÚñbÆ¥]·þýÓ¶MÀ¶H"Q(@âDŠ-^ĘQãFŽ=~RäH’%MžDÉq› ( °LSæLš5mÞÄ™SçNž=}J<Tè?%(±ÐŽ3šJ™bi׿mÚlÙÚæo’£~VìX²¿MTࢴeݾ…Wî\ºuSšä(€6»¾]¹2ãÎ_ßþí£êO€¶$$޶‰hWòdÊ•O~ká"EÌ–=Zô蚊õ4õD7{$©%ïA’ÿ¸îDZ÷nÞ=Ï:P[ moâÅGÞsöA·ôº.ѦM$7m»Fª-ùvîÝW¶|é¢ûxòåÍ÷^ÔÖs±@rëü|úvÏJL»vx}þýýÿ¿i(Äb(©‰á¨$܈(2„Ц•ج"Ä0C #œ-µ ª²…ºH$©E¾ OD$7&N?ñR„1FyKoFoœè›oâà›_Xr &‡$²H#D2§]š(€šÈ­“¤²J+EúçJ-çCB€]Àc©…-Ç$³L3ÏÜî'\¼(4ß„3N9çÜéK—:›hJ:÷ä³O?ÿÜdM)ÿ$´PC½²ÿË/IQG…4Òï@M6-rSRM7å´ÓÊ*@¢6R A¤¸b‹/Ë&H bsoÅ8d‘Gžé9T( '€K _´H†9f™)úÆ &;féf@–ˆg¸9èÿLœ‹h¡u²e¢š@Ye˜Bu⣧¦ÚGàR'*€Iu›/ «;lwÛ»¨„¯ÅF;m}T»m·‰MX¢È²|»n»‹¥ûn½÷æ»o¿ÿ6O\À'Üи+Ê»pů/ !ù ,ïiÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@½Õ-BmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh‡7QÚl·í6ÌS½-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûÿüÅ-H ”ý%Ø/€$pCû’ÐIØB$( €$D¢ ùSÚ`‹[´Á Ü_úH@‚ýI‚™Š-J¾þ9PÄ $"x>  nX`‰þ©/ #úÑ|ÿß6ü± mÀ‡ä6°H4²|ÛhƒhÈ6àH Z$}Åñý‘ lÃ?þÁÅDòÚØ†-p@ñR¶H‚$F)ÉH¸Ae ·Aº’–‡?ËC¾r•¸d˜!¥£ËDâ”ÿØF4½(]Ú‚¶fø¬Iiž²šÉß+©ËmF“‹º,¤#(Bñ•ÕeBF© V–ó„)€68éÿËñ­œÅ`*iËF¢•ÔÞ7ÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’š´CÐ¥?nQ DBµ¸"剚ĦÁ©Ét© I2=]æùÊYA›¾ò-ß1“J£251£$ZAzZ[hêë|¤TRÎQ°š -Ù'õ¹ÕƒS¨Š!èȸ “n€\Åè?IˆQ Pé?XH™†Udådë<_)XÄü£“hå6€«&¡±ú´ÅUµqM ¤ Gôf$ÖºÈþ=R¬D*CŽYVÃhm¸ÅZ²YŲ“«§Lê›JOÔÿä–&;  øÙÁ.ò©ƒQçi[iÉF’Ò~º@ZJŸzó(¤š[¤²õ¯Ñea³Õ’Ò²(£?¼ €[,´s-o 7kI¹ö5eT´Åvûùf¸Õ,A]°ŽžQLl!ïúX׳¿¹¯$tj•Ú×0Ý )(X¬‡m,€a¹ÌØ"±.µí(? Üí6›£eocÈVÆ•«;İru¹PãvW€v•p ÐOÐ « ëUáv¾uûe\Í«Ë™ŠøµñiE9bŸ ž†m ³\üVó±/e,(yIB]>––o¥"ºyÙ4o–ÿÍ(#­Bœê˜";2‚SÈf:Êþ½ò±÷CÂg/(WA¯LÎf $%óÙS®œë¬p1½ÕG¬œµxêx\ KK†ÁFã©O1,]´¢¯ÉÖ}iQ݇ݓºúհ޵¬gMëZÛúָε®wÍë^l¥ò})‡©Ë¢VË*¨Ï=¤|ý#y‘UdöMUi‹M‡ÆØ’Î)a°ªEoxª³äöiÄ­ÏQd‘¥Ø¿m ²;3·˜J'ç ?»ne¡?‚he°|3— —C¥cnoCÉÞŒâ6ð`î÷ qÛÆf;¹_ÆŠÔN¦©DûnƒXu¬›¹±!×FpÞfÿíä?z9¦{+Æöª É­)ÓÜ指ü?†$Á²+8 UéÓWR÷‚4·J’ÿC]Ö0™/÷T¸“~Ð_Æ(Gji¬@ ’`®ËŰ|ṵ̂|SšßˆC ´›„„'}RSÈW?C´ß˜Æ1.ˆrSiÉH,²Ï_ÇáÛ©’„ñ2N/.ýa‹üYûS 6zC"!ZÏ´˜!ú­°?ºN¹¤‡ üä?´ñXOsE—’ÔîÌ=<ÅŽg á®7ˆ­n™ü»\í ÞïÚ@1þždI)Ó‘x\þ㙌ý¥$+m…¨Rù”Áz—ÌÚÑ&P ¼_d»RHPò%ÿ$¼±¿Ø‚õÆe›ŸÊ»ƒLÝG‹@ÎØ bŒ¥•}(߯›š+9$èEàuPÉ¢r sfyÅÄhh qdÙv?Š7kƒy#t~ø(ÞÆm’}³1d v¼§™„8*ÌçzH%‚" SAWÑKƒ–2jßö[Ù$yšÑ~s_'~9”‡äÞÐxL¦W¡r ”‡aŒ´l Wl¤ÔvÓ´vßðrp€7Hc8()Òl°´‚-‚t{Uÿð ßà)° ›]·€M†ÙóM[øEß  JÐ.PU’P–ðqvFÑSNTv…Çç-ÿ€aÄ6=º´Ef–{¨*]v@ÔÓLTö Ißp Pˆà‡À†l„ÃãUSÑNB.àဈ‹®<vo-àÈÁø-àqÈCJAa ‘‰Û$tÑß°OÏ´‹»sX!ñ Û KaÈ;Fõ VÁ(ÆØ¿°Orð ÈèˆXaR£b”8¶˜¡R°C%OM! ñ è9åÑÄDžHc(„]i@6ÐHøh#&xkèL[¸WËefMðû€6òäà)ãø¨¨ $ƒÞtƒ–0$à–p–Š—` ¿ÿðý†Ý6Ìh P»põ¥x[Øx–HÁ¨¶(M v ƒ„¸ ›X6¢Ô¦˜»ð (`‹ ^;áU(° ß M`’R0Y)kI–ÀŠ­ØÄ6£TMIµ)àº#f”gI p–¥(%yµèr “¶v§ôŽUÓvl•iY™’ñ‹ ޤ¸›¦†¦¨ØsðN€x£”uX™™àz©q–Lg‰†ôšáv° M x+’Y£Šf1Š¿© s`qð 54^´§;þx–$ ')np›ÚD5qÐ")kƒ™–3ÿAKŽ© ๿(Á¸–Sà‡R0¯56?ùøW¬i[A£t w)€q˜áŒ!ò¸3¬  xé ª oyQ‡©)Þ h…£$é*àÔ‘3‘’2ÐR°…@”„S Œ.ð–òôWr  5JJ€ß‡÷æšp ’d ¤ˆ|„›>ê-º Ú )P–0ý).ð›Óé)iÏi7 ª v ) Šñ  A˜‘’çéHXa}ó£êRà%Pq0¤¥á¥a9BÇ7„ù“'ÚP*§ ÑŽÁ†( 0ÕÉÿp }ÿÕ“uc¡*ЧN§a–P*§9Ѻ ƒh Cy8 Ú@) ¨bqŽŒ›‘ZM¤]¡™‰â‰ÄI8¨¸ |ê§.0ï)wð?D0õMò”?ß0¿:˜¦>‘MПˆè ·z7¬*©U ¤!§e© Š EŠ—e ™7¹Ú¤}Z¥±9e)£«(Ë´ cʆòú¥PŽºPëHcê7×*N`¡±i¡}Ñ*”¶· m©zY‹AY’ýZL釃©Co“ž0ŽéYú$Ù @º qPv° +²²&ê± ®H!¨6"³*r˜ÿ{¡*›¡)@ àÔ©—¬*›)`¡[Qv"4¦N¶$ Ä¥.’­Àh¦J’Gú‹.²)   +F;ÎZ%ɆHpI‹RK —^øƒ[3"°Y« :Û±Yªj¡zi´a+KÆHœÒäL$:#`€ Á¶8¤í³71ª¦{yµÀ¨ ‰Ú(¹$zy?é•D¶äE3˜^IðæA–di±ÉŒz™>{¡;°’†n¢‹b†Ķ”ªmX¥MQGšaº·VA§/Bcû–^mài`¨ qvæ!ßÐp”ä*à‡¼×§_+ÖK'ÿ˜"ÝØTÜk6‡o…TX¥W÷ ÅÉ¥)®.`X´›¿0Ú×/0×–h qEB·° Òô\š\Á-µàšï=”œ Í;WËËÀñØV½†- üë\²[àÔ!§Ú?Lé¹$×, ÿ†È† –° •‰áÈíÐÓ›¡’` ø3åÚ¥ÂÖÿ!½V›±¹»° »éx­ ‹ô-¶¿=GŸ³Ûôðs |Zµà‡à‰ÁßsôIKß>v ¦´ Œ¥õç#´¦àŒ¡s‹õäÓ—ˆUzâpÝìC;° ðò퓡ĸåçƒW/·îã‡Æ«¾¼÷ëÓÝ“T½žˆ‰‹ ¼ÕIëà3·£{ RЪÌ>mHªÂ븼zjƒ*­Š³’jøà#jê«èêø|ŠM Ôà³Ò*©tŸ>gžÔ ž%Yùóðø>þ”ëš¿¾¦;>?ýªSçÍ!ù ,édÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-vZmöq!ÂÙl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·j ‘´‘D $$±~¶Ø"@ ÙO>$(A$¡ ûñO¶ðŸøˆ7DBH(HþÁHð€ý‹ùø—„²¤äK‚$I(|ð;á@øç† ŠO… `Ù—„$LЃâ¡EøÀ6‡áÓ ÿè‡À1|@”„üh‹6D}Hð_Zˆ¾„tŸ·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNÂMždŒCIJ³m£”Žƒ! Qé¸Sä!q%+gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜©òÇa‰LÉY±™ÐŒ¦4§IÍà[Ì,H6«ÉÍnÒl›y¦¬”éÍrjL–æLg: Îv>¬[T<‰wÚóžøÌ§>×HÝÎGºpŸv{"@w¦Ÿ4&ß`Z=špÊ® ¡¼ÅìØI;Ü%¡ Yˆ‡Œ¢L ¢GG /ŠS $…˜I•·R»xn-ÅF 2Ï”Úô¦8Í©[\ Óžúô§×s(PåÂSxÍt‹W˜OLRÔ¡:u>B½Þ Ü7Õ‡Tµ<5}ªVÇ#eíCbYEßRÓÖõ%`«l»¦ÀPŠÖ¶ºÕH/ÏXßJ׺Úõ®x=[YËѼúõ¯€Ì šØÂÒJœ˜«a‰Ö‹.ö±mP#‹4ÂRö²˜½ (_!ù ,îcÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØdÓ€$”­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯¾‚g¯ŸP$I¸/P$Ôï†-h·¯~ $¸É-µ(J€¾³‘ þ»_Ò ´©¯ Iˆ„‚ÿ¡ï€’p AІôµa‚ é ùÜ Bƒ”  %”ŸúÁ´„LŸ BJ èÃß@X €€é[ ÿ"!‰¢IBÚP‚HØB‚‘àex¿ òo}H@á'€,ªP‹_ˆÃHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxtÝ6â‚üã}ü‡þøÇ‚òÚØcõzÃüC‡hƒ-‰Hîñþ! §g‹mhC‹·(ˆ'â†$\Rn@B>™D[$’•ÓÛ†-V‰mÀ/ 4¥¶±D N’zñkâA´‘â„ß'µ€- szÚ("-EMnƒø“„.mÑ¿ØrŠ ëcq¼¹IƒüñH¸…-è€vàÚh⯩Hç R ²,A'¢ÿHoj–¨€—(È(FïE,b$9L~‚‘¸äkÑPmFœÏ‹¦î·{‚Ðþ“Ä>ùG[è°¤’àhWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨Šº§!‘ÊTÃ)ÕŸ»Tê.µOxŽo8$ÝàE`ô{¨ÅKàÅ6@øs¥T½§?†uÅtd!ÃgV’rõ’J$,¿wϱBp£ùÇý(¾xºsˆ‡œaë=ðO‘là#÷:>[ ‘ÿ8 IY¾O6 ç BVHjµ|õD›iãG¾µ^Ò‘YkSgKÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p‡KÜâ÷¸È‰h"Û¥š¶Û[.Bæ¹Ëƒ˜–x’@"eÒ/¦V®×k B|vxIÈâw­»P˶A¶ìî½)€ ¶aÛèàv{' 6p¿áß=õ[QL€“ Î=–x‰¬ou² ”в ¬`M©Yö^7xÿ]È'é ò®‚åîB—Áõ$›üÀxÊ÷fVÁJ! b…0ó¼]²õ×C©zTÂÅk1CL, ä“T" dÊ¥ÎXx=Vˆ€B`~ªòËH\åÙa¶5·¹J™ ‹ òÉ$ƒÈ“çÈ•‰Fip2Í¥¼ñ˜"#Hr0v0V@:9•#u* ŽÀa ”W-É1Þ° ¤˜´‘q/0zNP‹Ó/ §÷\Éu-·§ohRˆ1åDXœÆ›æ³œÎš³nôŠÌa’ÏI0+Guüó–Îÿa›C›.ðƒ4Ùc7DWtSOIº(hˆ†r 1rxä‰>Òé>Õ¦0JÅ”×â¦0íyà /yv0vp ³ )Ur uÑÁo—I0»P›Ý±Ÿý²r›’¬YÖi.§¶¡Ïè¡Ê1€¯öGý©/—à8Ÿáa º}6ª¡5‰>ЍH2Jqå#ZçFtìæ0ÝÙ“Ç–J(?—À¡î3y3j€è#ZßФ @¹>FèŽMð”a¤¢ÔSOk– â#Nê>Sຉòv¤™—Ÿâ“¦QZ™wI=Ó§x@É™ä³r‚”™Qzw >n€gè>)  U~Úcx`ê=™ã£¡‡h¨}*d…6âi>«&èV…W¨~rZYT¥ — GX]©ÕS›°ª=kª¦(·˜æ#ŽYúzi4«ÐC‘¾Ê=Áj;!ù ,éZÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sê I`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—m6—=­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùJ€>B$” @H ¯~ $‰ë'ц‘HbKæCB$!€ûÙBm€ùj!€öÕ I(ܾ‰€ ”`õ7¾Hð IDüÂ'‰$¨ï  ßB@ð©'HÛ@¾$ ì û4X¿‰Db|ñ‹ßÿ'¿ޝ}¶8 ß'Ñ ÏW‚¶~îs¢ù¦Ø@ôY°‹ùâúÆHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽÛÛÆC¶áh/AláA¶ ú%á~Äžâç>&ò ·ø_™½+p,"ÿцCjOý»¢ ÒÇè’ óÇsþAÈ$h!›ì$*–IæØB!›<å,³÷Ä r²¬¥õZh aÄW$þ°§Ç¼2!Û°ÿÚÐ?<"¯™Ö̦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~’› h ýIЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’ÖɘÆ4©JWÊÒ–ºô¥"ÂAR ÓšR ‰äbA¾!kt/ ¡$ ¾ñ‹¸@߸ .AÔî!òM(6îà‚¨ ïSAŒ)‡ò¹à`ýÆ.¥gC8@ ÈQ ÐÈÁodW—×ËXâIHAR9¢ÊæÉ!iuAU32W2µ¨hÝRê€&´…•Aõ#Ví6‡¹üÃ%Ä7n‰‚¸…5Mø†8rVg ø»lY"…ªª@ plÜ.!‡ÁÿÆá¨ ÙÅ?ª(ÖÓ2E.ÞpkÓâ÷¸ÈM®r‘â)\ÂHÁ%ž)€¾6ä‘#ÔdA4¡“PRª4Õ› œ ‚ž4a”_A$1‰´ðfåýÆ|"…)°¾¸%Ñ;¤Dr œàâê„‚ƒ-šumbàŠ3»ipPôû9°nãÛØqq›V ÀÖh`E¾QX©ì¢³(° VÜ` N–¨â¤ Ü¥ðT ›•„$ Ъ*ÀpñP„ü3ÿª).˜B €_‚Ø¿) rõV,ü¸t²5Š”Ñ·eæµµ#¥È º ¼03ÄÈ 1óä(¨“´%¤ŽÁ_6j„+Gæ–dÙ qš—Ëç>ûùÏ€´ MèBúЈÞY¿·góÅ©ü% wið}cÅ)`뢵äàʉ†[£CMêR›úÔ¨NµªWÍêV»úհ޵¬gMëZÛúÖÒ¹ñ@Ôü=9$h• ’ñ9AŒG^_ Õhò!}h¶k컀!ù ,ÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Z‘Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ÛEQÎ<÷ì3ŒNý,ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×p…—´à¸ @BïзîÄ“PBIøý; ÌÀ¼r Ð·ñÆ d< –ä½³àüö$a Íó]ý@ØÑ†ïºãMQ¾ï}ð|ÞHHr>rD¿@íÓ^|'&Tb{åÛ[%R@„z|CÁ-‘Ïyò»[œR ö9…z%ØÛûâç<ûap „àßêǼß°{Ë`à`XÚŽj6¼¡wÈÃúð‡@ ¢¯‡HÄ"ñˆHL¢—ÈÄ&:ñ‰ZÓ§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”™ù*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^"¬0 !ù ,²ÄdÿIH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í”m[f€àí¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄ#äBÿ{‹-i³ ®Ú¸ •É6ÉÇjKÔ?T‚6Ù³ª ÷‘D!QB÷éc¿j$°Ÿ„$þ„_Ð6Û³O‚ö—:=AnŸC¶Ñùõ/TÛøŸp‹2DëH þá@NíC¨`Cüá†îMpTä€-4øIt/ $¼ü‰–°{’pᤴѽäyÙD:(4ÐSäC‚ýÿ˜Âã Äb§lA=Ê0"4ˆ7õ?þ¤€@á¦hH½}$‡!¢A¶Ñ-÷eЇJDÈ7ò‹8Ј !Ÿ 3E¾ä߸„%¤0;Xa¢>˜©îÕ¯ ߨÅf;lâ‰Ûè)¥ÃÜ‚zDèßä €<€ Œˆ p‰ì¥0‚S´T-¨§Å|ã2@H,ð0ò LáÿFˆ)   kȤðÉ‚¼€ /øÅfð)”²!X´£ ©gÅDÎR!NÀ£l)…G’°Ô“¦¥xhÃoXâ3˜B>é‚oà3 îBr>ÑPá[¡ާÿ̆4á˜à6g `± Ñ<(¥|©ÅaÓ Ç%@ðÎLá™ !/-u‹(NðR¥B^ðOþƒ“—PÈ?H@½kˆÐRÎkâ6t1>ŽTídß;å` æ!O’>µ©g‰[Ør "-H,K‚L0¨Í¤¡J©m¬0ÿ@gD’Sƒ<õ¥÷#Ÿð—©Hdv˜CH:Q¯þ㉢´WL=|mØ1 ’Tœ4 µ‚ÅVjJØÅ%by̓”´¶XŸ$l! µÿºö´"Ûaû'EÄ£Alƒ- Ámür‰í WÀ^Ö„„åN kЫöVº"ܚʬö›2³BÞ¸Á„øT±Â-z×Ë^ƨ·½ð¯|çKß÷¼·¾øÍ¯~÷Ëßþú÷¿°€LàøÀN°‚ÌàëU¨à5š % 7H‰• mh‹¦ 7l·¡ æbܨáßWfà ±Š'[Ç$šø¹:C¬ŠÙ7T ±SXÔ–8¥93"ˆÓ0ÑHöt)ñZâ›1´¡nx¢‘7¼D664 ï31Í´{åz2ÆcCs @ ÇÌ\æb2ËLeƒ$ÿˆ\$3“ ³'‹õ ffˆ E Ï6³LÈmì3˜²gÖâÙÏ"ÛǺfEO¹—âY½Ìæó¦ìÉ<´¥rÐ úîØRJy"`䢔O²/YÓ'6ˆ•jÏAƒŒ‰ª>È7ò,TG À×1.]šg‘Á9Óc í7–ÍìoÐÐÇ Žç“×\ëMìÃE®ö.t198ArØ„‹_\Q˹Ò(kh5—½‰)È`ïŽ7¼¯°‹]kÙ|¸žlµc=1€ö$È7lá)<`/˜ÁÁg0ƒ8aönò@âÈÔO‹¬|Öõï 0\/ Èb‡_ü8~ÿ¦&B wrjÏ-,ÈÀg`p…ÛÜ¿˜‚Aþâr1Ûè™_MMÀûèònÂ®å ƒ–F\ÃV:“çRC[ܼæû` W=)8GÂÙqöjžðƒ'Üß(À?>òÈaÃãö:±m½–ÆU¹6È]ãèZÝ6ÓRCß.äýñ£+Žÿ`:A¤ð hC;êgµ[МP’@Î; ÀE%¸ÃËîŒr6ÌÃ.€oèÂãOýÍ¿ÁEµ7üxÁ&jèâH>9¯z}Z$«Ã¥N´†%H‚qh¾O  Ö~Týâì Zbò޾çÄd̾ £8ìUwP„Ëÿ ;ùļê54?üp¹V~Ê~ %¯î Ôs\õhq Ö>)È"û’~ ETa ØARWñc[„cx6|q|îW(µp a NPx„7}¬§‰'S }dR;6OV§}âGVç]ev|ˆG—rA"ö–0r z:(ùbû7vôHôdnÀNÙ—}âEÀ@çÆ€tT˜’o%d L‡tH÷Ôçƒ~•‚‚”?xÇuG~âGX ƒ¹§~4$)¾¦hOÖBß  ·p6Çp=GûWC»6n³•qñ„hn!YÎ%C@ç„=e†.å(*ÕPý#I„ÿg…‡W¶G’`*Ð—à ¡u?\$[ˆ»@ÆUµWŸ$YT†œwˆx4†òdŸ$vS ƒ«·r CIð MàßDÎ@x—‡ÑtTg DGXZ4t\†|®X(ù¶d»àÑgx˦-ð % —  Oge³´iÅFw•ˆ¤vg¬õ ›@‡ø÷ *à*@…PÛà‹UÇh:´oÏ(~O8AžbgjdîÖq÷.ð.ð'ÿ ‰v·E ¥Dy4Ž-Cq0EìH‹ fç[[—D4¸c`U[÷2ˆŒ¥7"(o"(s‚î“f•õhZ63v“v|» ›° Wp3pS° õ6DˆeVfØsÉ÷2ê(bµaÑæ’ðaŒM=v’6s 9gIÐÖ.gÎ¥”<“d+ÖPŽ¥”ýxk- ¹bIP„´×s4od  ’P ^vr ˜‚9˜„Y˜†y˜ˆ™˜Š¹˜ŒÙ˜Žù˜"ƒ{~¦¦K!™{!ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«NJb!ˆÕ°cËžM»¶íÛ¸sO% »·ïßÀƒ N¼8ÎÖÆ“+_NÕ‘Ü6Ì£KŸÎùRÞ¨kßÎÝb«îàËÿ'í|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ¹¼ý'à€hàwYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹g­dŒ-•ã8æ¨ã޲-Èã@)äAä‘HŽtK’L6éä“PF)å”ÊÑHå•Xf©å–¹eÇå—`†)æ˜/yIæ™h¦©æ[¯ÁåãšpÆ)眿½Içxæ©g‹vºe枀*è †5B衈åJ¢Œ²×'N²4*){Ûø餘Jf¥]†fê©d6~*ꨄýIê©°-Šêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ð®hj¼ôÖk¯ˆón•/Q!ÜKk€þ,ðÀlðÁ'¬0Nr,ì0`¶ŠqˆHL¢UލÄ&:ñ‰PŒ¢§HÅ*ZñŠÊa"·ÈÅ„h±‹` £Ç@’ñŒhLã­Ü Fõ!R ÛHGB‚u \÷HÃ7.„tsäc’–t@AòÈ ¤!™´¤EžÈŒ_¼‹IÉJZò’%‹$&7)BMrò“  ¥(GIÊRÆI‘cñ¤PTVšò•yr%,]¸Y RA¤- F@¦n’]AÞ.uÌaÞÆmŸC‚0“’T¢¤Ƽ £I¥$”%Œ‘%5å´ÌmnF›Þ çÕr°bö¤›âL§Tœ¯—±Sð|8Ñ2Ïš´ÆTètˆö&²ÿ)äñ†Ffªg<º—wÞ(gõlA ÊPøì³¡ÒBó2Q‹T4€ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªšªÔ¦žì¢:¨S§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊV²2µ­p«\çJ׺Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆ­*T˜^2V4Hx¬d'KÙÊZö²˜Í¬Ö¤ªÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖ¾³®m|HÐ7ÿH¢ Ö,Èbe‹·%Á·MBl1˜“·qùmnh‹ì¹S‰ÄrB7DºsÉW@IÜ»n"$1]w¼‘pnÁë¦ßjÃŽín ˆKÜò²÷,ƒûn$i\ã ¤¶°ï}׀뤻 Šì€åÒÜþD¸ žËpKä(7Âq •-Ü„K"À†ËôP‚H|ø¶Ç ±ŠëóÜ»øÅ0vØ[cLãÛøÆ8αŽwÌãûøÇ@²‡¼*=Ù+µ<²’—Ìä&§¥ñÇ?0eøC!ÿД\”æZs¸ ù‡?8\‚ñrù(Û6Ô»e‚×ÿZÝ™qÒfƒüãÎÛ á¦×ÈsJ–“€„ßZù Ú¬[â@¸IpC• b‹êþ#Ï)VW’Ã2éq5R ¦ÒF‰ñL‚:;z&rN  Òç6\:™~L¬Ãºç‡!äUï¬Ç–êr.ËYõ@î \7ØÂÔ§N¶`-I3[ÙЦۦÃ2ííì:Ú*­õM„ínC¦ÚÞN ·Eòép›ûÜèN7Ÿ­îv»ûÝðö àŒ<ï‚Ô;ÞNé5¾÷M³:ûû"ÿæ·ÀNð‚‡¨ÓO¸ÂaÃîúãÀ5qĤ|gŠS92ÚHÆí<ìƒ ¼ÙaÕ†$´ÜìJ¼ÙwÿþøÂCb‹r§\ ?àËW.’m— w.È͇­ò¼Óx&nÎqžrâ2å—îùU[Nôƒ@¼é‘Ù†u ,æéêQÌÿ¬Yt«ÓVzØ£YÑYStÿh$Qå?U|ë·óÖï ã¦êÓy®j—+=0å­…<&õÜ’ ·ÿŽžx|Ú¹Y@n±ö«‚{H:Ÿéûáˆ}ý0Ð)dH€ðÔ½ÖwNôÅ é‹ãÝ«’ øÌ7.Cœ¸åfLJ0iè]Pp³¥|]$´Á¿)÷Ç6ÖþwÀ4‡lÏüBLß;¦I˜4o^¿ÿà °ûÿÖ1ŸrÑå}ªÑ—~B:ßò›çæy¿äùÓß'»ïýÅâ$8¾ w¦xl”eWeËÇvZ58ä‡t asÄÕy1e¡7£7e•âIvt£'äg j‰f Ï×T{‡r}uŽ1¶|ˆW7|˜rà‡yq€_5v¸€’aM&fM{¦vk' &¦ Y—E˜~¼W~ƒ÷ULÇwQ‚T6‚>‡Ù1_Ô%á·…lçÑ×\[˜²wi•ç„Wçlƒw†ˆ¡r“f †xv@2G…Uesq§qUæÖ7…tl8X"GrTfrrÆ€4gqfe™×‡‡ÿ8 G‘øˆ”X‰–x‰˜˜‰õyšØ‰a1‰žxŠ#!g HŠ¡r´‡Š¬øh­øÕv~¯8‹´h§X‹¡oPäˆCUe÷W´÷‡ü×q±Š>õ‹¦aŒ•Á‰¸h²8޵C…G¡m¼¨ƒI2iÂw/·H6טCݸ·æŽxmR„Œ\2e¦70ψt8‰áH$v"ŒçB‡ß“¦Œ32Š´ØŽyâR7âÁ&|¢f^ÁmüØ=ôÈSæ% §‹1Ž\’7÷˜-YæˆÍ+$á’a“7"Ù-Üv‘£qÙ$¨/ 6h˜0‚w6»çHP’Lÿ±1V)irÓ´°±â‚’X£“ÃÈqX¡>f”™b”/&”Ð)ª6iT¹U&• fMßð 5¨8)PÐÔ @*ÐŒsh\±q̘ZÑ8ß  JÐ*°–M)àzioOiд) –p ‡i YÁ•*&||Ó) M .à*àN0oy­”¼¥rq %ÐN@ ‘™ƒ) ”l9öÃc•)~‰? `að¯éEÀ¶™Á”‰µ»éÄ)ŸIµ9•™•É©7N¹"´ç«)½©z™E!?@wŒÿ9ZS ñ›S!lYZ–0rP Rð» (°™ßðëù¸Te™Öå)…)Ó)Ë™YX7˜I™è‰žá—Ià«C”2Á˜ÈáÀ¡YYŒ™ †5  Á¡a¢Õùrf&À7K Žû6€0c Á8d¡’¢,ñ'6Š9Y°•$š£,¡¼“i¢Y²’µÁ£b•Q™½Ùè™Û .ðš½É¤<‘¥±/Ïi›1˜`êb*ðiÚ¡µ4ž"p— ™ñ;kú“ÉZ^Z:gêš±§ aœEã¦Gò¡ q (a¤ ñlKÿª— ¨Ñ·i„šXcê3¦á–Ÿ)}m(Ž£ 1›‘q«s7½ù‚Ù­I­ù—X*—´z 7IiÀZwj – (0_ÂÖi8i»ª?Ê}*’` £'Š©sT2“IÉzyú§±:øÿYÿ§¡©¸¤–‡¥©6‘Ÿ%Ðßð¬q­¨|j™ a¨wÕ|âj¯A¢°¯á¢°¦¯º¤ ´MûÚª ‘i‘‰¤âU¹ªZ R¬Z™âj™7Ÿ+ë§1‘O}µ —@N° ˆª®ü*º;J¦æ9èÙ0èZ%Þ¦-Æ.S@\Þ°…zØ~¸ç~:çïzdNWðQhðAðOi!£’VƒÌ7ZÖx4Xh(G[!‚à qÎd!îH^"Þú)æc B+w ËÝÜ0j0åUÿNRg§œ6Ç~:Oi;¿!8i†pÛ x4(y(Wf%²gvLÙýÈÁÝ ?I®¥ŸÝy†Ê´g Nè/ /ðÓ³…óÞâ1ø~lI¯ ·'ðïçö}Ayû_æE?MwV“mÓ¡QõMõ,[ñ;òÝ¡ew·xÚ0 ±ò.ßõßà%@á'óaá¶°ïá÷^Õ·ùglœÏ??Ao³ØþtgØ—"z®2q×Ñ•Rn–Ðâ(þõWHbÿ0×¿Ýø^ãŠæ€O_Á–†ÿ®æfñˆwgÊ‹7eH°£`¿à,â÷°1õ’h ð5(—'þà]ÿ¿|%@ÁÎjÛ.À±Sð ·pý ‹ rÏÎãyá\4¨vÕ^uGƒþ1Eø¸-’Ø"Aî!À‚ ,èâàB† >\¨âDŠ lQ#ÁŒ=~RäH’%MžDY Eú+øo›Œ2^ØPâÛœHPpñÀ œo+$ñ÷OiR¥MÿÁŒ¹ô_JªU­~´uôVm¦– ¡” $Û¦j @ÂV$H®¾…Ûj\ºuíš”C±ãÕ%:T REÁÀW ßEü°obÆ?†lðKn~0eÊ‹71«hòo¥¤+6;_ÙåÚš p6A§‘ÿmße @@³VŠ@6)A[%t#¹u[9ùË?‡ò"ÈÅ œl]ûvîݽ“tÄ€¤æv9¡)ãÁ7A-Íɹ©ý9»rˆ[?pÚµ¿ÿèþ*ÚF—Û¦¼,iª“ªc0B!”°B #K%,Ãl~Ù„³›\pÂTø§„¥xáŽMì/‰ýô› 6Ù.¼ÐÇtıG›KA záGÆþ2¥½’d²É‘ü1Ž%Ë€ê;¦Hïš\¸â+°ä®44ë)ÙžªÑF¦œd³M7ß|ð¡%; NŠê´3O=¹‹€ 3_˜BËfhÿ4'v¹%C–’(sÆþl¼qOK/Å4Ó=›Ð´SOßô' ñºâQ€mæb )žB KnÑÆ2ñ˜±V?Å5W]«r0PÂrhÎ]‡%¶ØíT5 [<ÄlÙåID5(?Jm•ÔXm·]°×Èúra1$wÛ½„å6]”¶1Š¥üLÂ6äM‚„QuKÂ5ÿ¼½V*~Õ8`M ˜BF8%kú¼·áGmÁ6â„'¦¸b‹/ÆøÒm"Õa–pÐ~#~-c“OþÏà†øe&ñt9f† ”Ä7"©99Ú"¹äe:è«~6ÝmËuó/¤?ZZh§û3Ó¿§§¦úÿªFººjƒ`Öºk¯¿;ì9»l³ÏF›â¬J!mÅdÙm¹ç¦;])4š“„`¹mºn¿ÿyå—§‹ÔÒ|¢Î™§¾zë¯Çþ#£³ç¾û§£'h à½7Ir†À'?}õf}}÷߇ÿdÍq7ˆþøïßÓü÷‡Ì…íù`h'] €õ`¸ÀOý„`“Ô¾‚M‚Ä`Ó kÿ!¨ÓàÛB(8ÒÐG«“ýL¸B¶Ð.„œ eè&Y¥†’™¡¶p< Ä|9âßJD' w™^A@ ˆO„¢ûÐw½}爹"DŽx˜,¤‹(ùbÅ8FŒgD£{UÂ4¶Ñäc#'ò39Þ¦ŽŽ’òøF>öÑäÓîHB2t˜©"2H­1&,]šNÒ«!v¯’†Äd&5¹IN~„‘e(E9JR–r$m0e*U¹JV¶Ò•J‚A$ñJZÖÒ–·Äe.u¹K^öÒ—¿f0…9LbÓ˜ÇDf2•¹Lf6әτf4¥9MjVÓš×ZÄf6µ¹MnvÓ›ßg8Å9Nr–ÓœçDg:ÕIÆK®Óï„g<å9OzÖÓž÷Äg>õ¹O~öÓŸÿh@:P‚Ô EhBºP†6Ô¡u#M"Ñ1䓽 !ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«N `!‰Õ°cËžM»¶íÛ¸sO}­»·ïßÀƒ N¼øMÆ“+_^ÕóçУGÎôu騳k·è|»÷ïàGwÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_.ïþ(à€h!hà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èb\­¹ôß‹4Öhã8æ¨ãŽ<öèãäDiä‘H&©ä’L6éä“PF)å”Tb5c•Xf©å–\zt]—`†)æ˜fÅHæ™h¦©æÔ­éæ›pÆib›rÖiçxØFž|öéçŸ%š è (ÞBè¡Û Šè¢Àè£þue¤”Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶I~Éí·à†Ëá¤[‘K”·âbêhºì¶ëî»ðÆ+ï¼ôÖRöæË—¡ú2kîFÿ¥¨H÷kðÁ#¤Mu œðÃG,ñÄWü˜ÃDlñÆwìñÇ ‡\¦È$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWúŸ‚?aœšÖUwíuHcŠî×§@¶Mt~ÉIX[3QØ\Á žÜgk·Ë\*°´IÝCÿÍ÷ßÐú=ÖCYÂ×!.á)xVÙеnbw<~ñT 3$¸d›[>,¿ž3˜¶@fs„ ™ŽÓMää¡·îºA 6zU±»öúí¸§êðî9nR›†ûðŸú¾šñÄ'¯|‹ª'ã\!¿üôÔWoýõ»JýöÜצ}÷à‡Þ|œßCW~øè§¯þúì×x¾@I´_,èòkV{ýøçOÜûöñ¯ÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0„Õø02ÃÚð†W¹wÈÃúð‡pY ÿ‡HÄ"ñˆSÑ!—ÈÄ·5ñ‰PŒ¢è¿)ZñŠXÌ¢k¨Å.Æ^ £«(Æ2¦‹fL#É%ªñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úQ'lTÕ2È?òˆœ‰Ù#$H¥Œ”–Z¨5H²&’¦b&mS°¡ 5Aô~Ò„MÎE¦T’#É’Ƹ1•}Ò$,7óÊYÚriBLÈ,‰PÞò—½‹˜™F ^ó˜Ëª¥RfÇf„ÐD¦4EãËiZ„Õ¼¦6A”ͼtÓ"ßäQ8·IÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JP_ѯ M¨BÊІ:ô¡¨D'JÑŠfkœÍèE»bLzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦ÓÄ(NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§ªÅ\Rõ3k»jh:ªÕ®zõ«` «XÇJÖy)³¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®x­ÚYóÊW• IˆDÚ`Õ¾²¥`%Ø“Ü Æ*Ö°w) þ*DÀ ²uA‚$l1IƒÄ/~˜u o’à[˜¶°l$VÂÕÐ.EP$`¬$V9ÉÿÆ ¨umY¾4Ù6Lµ¸€du›T D²¿=cÝ@[âže—mDþÓšHB‚­sÙÒX„˜6«ÛUKk X‚”À‘„ ï[À‹7´A êmË@»6Á67¾øÍ¯~÷Ëßþú÷¿°€LàøÀN°‚Ìà;˜2}pVl!á [øÂΰ†7Ìá{X-‹?>lHí’Ø^#>±ŠWÌâŸ'ÄcñvZëâ[þC'Æ­±Ž#ã%Â%鱇Lä"yy7>²’—Ìä&;ùÉPŽd’ 2e‚Ty"WH–£Ìå.{ùËòI1˜ÇLæÌl¹ÌhN³š×Ìæ6»ùÿÍÌÚœçLç:ÛùÎxγž÷Ìç>ûùÏ€´ MèBÏõ̆N´G­è„0ºÑŽ´¤'Mé°øƒ@„B8„DX„Fx„H˜„J¸„LØ„Á‚N…R¨46…Vx…"ÒA¨‘æ¥4.€aˆ…h6D˜7 …=ãdX/=gek8#K¡…@È…Ñ¢‚c¹‡7Æ1†`ˆa’dÛP Ø•ˆ™cjþ°tÿ!fž—8“¨^ÛÀ\¡—‰šHpK÷‰2C‡}a‡[r Þ¶‰šèYÎö‰ŽØBh˜%y·‰-×m]B¤‰Ià‰¬ˆ^´W  ‰š5bø‰‡˜ošˆJ»ØˆeD€"˜‰$ðX»lý–‰Úµ‹sÖm™ˆ¢¦‹œX€¬F `"Üz‘ð ¸(÷€TÖŠICŠÇ2bÈx€ž' ¡m¡gbKÇŒkÆu¡×cíèühtñhj@#ˆÐÂ|¡çvÀÇ‹ ñŽ?'nú8f×tóv‘° ‘‘»Ç‘^¦r¡·‘­¨†Ë—‰Ɉe†Œ‘q¨%’ݘ‰àÿW¡vÉl fï’?)iEY¢†Œë˜(Id§Xnòø R9•ß0ƒ>ù‰µÐs'‘Q–‰ô6e»` r N0–º`’嘉hÉ•5c“\á–T¢v“²tßð W 3€—z™—Wp7Õhji4 A¥“%#'|÷ß  / 30™’ùSà› iûPÈ•CÉeüø’Šù w—™—/ “ /ð˜2 –ð ŃK÷Ž|'nÅ8•ø4M š‹¹š‘œ2P•yœ`™) GzeŸ)kŸ@š{) \ ­91»ð »H›C9˜‹ÿAml¹|¨'g}¸Püø…V6Rœ¥ùaŽ’—1ràù×è(žˆá±œHémAÆ¥ŽzØ!{ôh+µz´eˆxÉš¥I Éÿ0pš3 —ù‰þ€ŒçölJ)&Y –o·peý& ÛyÈ6rIj2J#„Èxø;Š$ù7¶˜ Ÿ‘ù­™‰ðö™—!ŠnšF©NZžˆá~¯m€XjjÊŸ1¢išPLW’a Ø)Òùcú€ß°H¤‰jÔF€™Èp­¶x×–ƒÑoË–´7e#g(­·o¤Á¸ '“£ Rp¡'×ÿà6p rP¤’93ð.°¦¡Wß «i Ö` ¦Õkýhl¦µY¥Új1]7 ðl\grÆæqÁ‡cjk—µ² ™bf S0ú˜ú€µ‡—wjZbz¹Vu}w¬x*c—d’7ew‚ç#W­6l‘›0j¡œ&J¤“9œ¨HŸÿàž¦jZû –¨æwñ*Óµlý¶ª±9rÚÐzPÚ\ç­5¢‰ifº—Jcp}šSp§· ïˆßà¬vú¬‚¡§I†[Ϧr-¨žˆw«Z…å„iÙuð »@©ð9¤.𠜨 %n` )ÿÐ.p Þé×Qú—“¡mËÉ|°:¢§jP €—…lÛ0Yb:§˜KÛP¡hŠ¡%ð sŒ$ðaØ» iˆÁr"z¢ˆ‘o›ps.Çum`Šþ&þ rö‡J([%=ÚˆÊy;!Öà³Xš²0S™”ºšFZ•*Ðÿo‘pRŸ¯¶6¡×¯@KÛpægv “¥x{'n„lj[%¢h}+*i\»ðÀJß .ðfʉ›à–û¯ªt—kÀ¦s»kqø)¸ê)I¸¨ô ›0¤• ™2àR`¤* ¨ß` žx˜ºXŽ£±›±²·€ÿ’‘Fwc¾JµÔ©—òyRio(¹W¶f1ÎTà»$â[Ú ¼Àé¼’j©) ·ð ×Û˽ovXº ,îéžéžsjÚpýø—Þ eU záš–Л° wðÁ¿ •Òµ‰ëØ»Ã"°Q¿„’Žšx^ËEsI‹‹¹ Žr‹?©K9ü'☮ªhÁ¦«ŒŠíUì2çh1¹½& ²umû¿ÄÂkñ 'FÅ)Åm¸Åo¥Åáå…;,cÌÅoÆ=èÅÅaÅfÜÆn¬cÅ˃eüÆtŒ®g0nyºu¼Ç|¼`qL2¹©Â‹!È}\WxŠƒ{øˆs<¥+…\%NPÈDA‡z\•,ɘ¬c|›œÉžüPUi¡œ£<ÊÐÑÉŸÜ@†šÊi¬üʰ˲<Ë´\˶|˸œËº¼Ë¼Ü˾üËÀü+¨ÌÄ\ÌÆ|ÌÈœÌʼÌÌÜÌÎŒ)|ÑlÓü$!ù ,,cÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥È$.cÊœI³¦Í›8sêÜɳ§O’~ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öéçŸ=è „:¡ †&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐjB´ÔVkíµØf –$Úvëm|—|»j¸â–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDm4U­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ“7­@7.¹™IOnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì ¸¥ÁB¥‘hƒJ@‚ Áƒ%I‚-l1Â6H¢ 0AaH\h‹$ ¡aá ÀAZ¤„'Œ„$ÿv86ˆÐ‡!à†H  8œH yˆDŒà0 •#« C @AH DIL‘‹¹âAHøD4B„ƒH‚Æ(²0‹nÔLÚà<æ"ܪ…(?þ1"7$ _xH+ †mXa¶ØH‰ Á†ã+)1‡Qä¤(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥¹þ!^ĽÜA|)_þcþ@f%` bĆ$І/k' `mðä5ÿh‹þÙ¸…-$A‚m|Ó%hÃ6´!'j# ‘P&8eHÌHâ›ÑF¤ùÿ[àÇ„â#cÈÎ?òòž9f9} Âhƒþ„aRÐŒó@ÿ(A3çéÐhòò¶ !õMa à’›g€¶„{ªt ýæ?’é>ÊÔ—n@‚J}hOsÓ—úÔ†9{ÙË[`ŽÁ6‰ÄcF¢í,H?Ÿš4a¾Ð SÔFœ˜„$T´Šÿ@êSMj­rKÚh¢$üÁËmØbŽ’¦. z²³®sÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙ¯øãµ¨$XÈV¶Ê43%ªATZ‚”6¡tÓF\MzLĵ˜ŸU¥-nZ|ÿ DœÃ´­)W8Ø·½Ý©c>zLÕ²Ÿ·ª6’ÛKpn–¬ø\®r…)\³Í6·±ÅWu+™Âà ç1ÁK^A¹”—‘(¯djÔò€ŸÕ%ÛY{›ù“27U" ÙI @»¶hÃ{ej‹85 piW¨ íú4¾b.lrÝàNF¦Ú€ñ©áØft‡ßDð'IpPàó¦ÜE ì[ƒ¸u³+´ocŒ)I0³¹<áP]{ãæÞp 0%j$H¼Y¢¶8mç=²A`<[ÞV&Ã"üfzaÂÖ:ÆÐ³JYÁ З[J>[$P_&¯…•ù‚#1NðâPÿ¦6.(—¸Y3ó"äÖCïœb´­Å ‰h“WhÔ4³”¼‘HgsýoÆ6¤à%ÁÍ)N|úmóÙXÜg óÌ2îî4y €9~Ó 7öm[“™^¢>¸%ÐtÙ˜ka„,»•ñ<›+`i&S‘Í%æ’ášp¦3Å´¬Ë&cá6û2jÖ°-œ˜i)ø›&jWX‚Z;’h§ÏVá DÂ8¶Ì1‘@ÞjÏ´ÑÁf¡‚ÅlÔÚ‘6ê²ËædsÿÍÄå š]W‚(³Ö·°«Ü* èpÚ‚µã^Íi÷f\ÖZUÎûåeÇ)DÎ’¹²~0ÈGNò’›üä(ÿO¹ÊWÎò–»üå0¹Ì}UèHÉtãše³P_‰á×z×­ýNågÚ*ÿ7Ôªù}}6|ת…MÅ2ðÜ®SáaszÍ:Í­§æ»‚*çAšãÜz}lŸEºTÛúpÖ°ûáü]ò“)B€¯¼ë%r¿Š™Þ–朗Z;ŒíDÄ÷Eê7\à1ë=‡XGmWcã^3Ž!g¡Ù9_(o#ÁJo SIê‰s]Ê«òœ)©ë8fS§‡'1;­9¶«}´÷ŒI«9N†R Ø,o|iã{ “ìbkòí׎úÕ¼‰Žò@Þ>SæWî0ÙÎÜv†Ütù¡¹)ÿ@?üVÄSN  h´óR»Þ÷¥[%ÞN™2¾ ˜/&ÄØÍ“Ú°‡b]U×w@5€§`›Emô_™”Iã$`ŽwSäz¤a€§ÒV´—Âfz¥qhðE¾$B•47€³ñ ªât€‡kð÷g·vH£1˜*,H€·ec9Q9(È*i×v?åtÝ4ØN   AAà*@N 3à*çt ‘\7·NEÖ&º )M .@B*@…-)à.+%UP’P‡å†&ß`R¿p -P‡À„-‡Pˆ†qhJrÐ@k¨ ÿNà.à‡ à ЇMP‰§d. …pØð‡pX†ƒØ…‡ßŠ*˜G«8sà@’èˆf(‰”ø‰n(‰r` »~tZœè‰.Š¢è‚8Œ§‡ÊØ­èFˆâ“H’艓X•H†`Šp(³ØŒU´uP…à@Œp˜樌ÀŒnô M@n‹³˜¡qˆ!‰ß(rPEºð{@ŽéHp* ÊèñèF’ò¨ˆ$ ‰‰‘Û(’X‰.Ž>ĉ$ FæØ‡S ˆ)0•„5AIKÇù;¯˜RÿØ’‹!‰89…‘g )UᑳÉŠXŽú8’ é€'7Á ¡¸s. 0…ø¨‘±‘ëh·  ± Ú° (àU» ­]»Ã‰}¨”‰’q^ kIß`‰ð†í¸•px–P-p Ú°Š0‰:S•[i‘Єh1p–ÐGN` p˜‹ŒÉ•Y)…•ù;Hù˜IM™ÒÄDDuF?ñ»°—L˜p˜å(t)på(S€›r@.Q²ƒ•á])é»Qc–˜(¡pNfèNØh‰ùˆ©Œ*`¹ƒšw)í¸æH¾ÿ4|Û ˆQ“1”´9Sð NÀ–¿cHa—±”;±N0± dùÙXfX~ÚÓE “5¡ .@åXœ1Œ~èÿ(Þ`”³CŸ/A_:A‘a—ö蕉Ea˜:ð1›q˜4Ú—ÐOð5«˜Š›`¡ qˆ'9š.ð(¡‰:UH2ú˜ *° Ç(q q@BN €ˆ:y'z“H ½3šQ˜gôy'jŸ ¦ë9¥:Â%¦¡¦y»à W'Z5á¥Vjljï)M(« y C• 1Œ(qeqQÃæºvJ€ßÿð¢4 9ˆÇÈ€7èüƒÜ[+$ ,ă>bLRVpªQ M|&ÉÈ â$ÍAÂKËCxª<$° –ÀÃ<¬*…CO׉ …žÞ¡‚é´œÌÐÌ3È-â $R™.° —` –¿ïqdlÆL”hEEŸ&nF²ÅÜA£ëhÄÞQ‘+ÉáÏÑÁ;WÀ2Ūâá¥ïáOù ,Ë\ù ÿùpÇTÏ(‚b5ì,`[Ë qËLìËC²¥ÜQÁï(‡ ÒÑÔþfÇ›«äÑ­T­ía³¿{/ðµlÕ‚B2¿8}ç:µò± wàÔɼ»àVd R‰:Íh.Û.¥:¾FVü ÕDí-y,¿ð ©8®4BLž5¿ \ÉÑçÁÆ Ïa TÌÚ/¦Çå Ä%~å&DÙ TÎx´§}g¨YäÛ,gq)fn¹“¸©Ðýá?¨G}+shàó*ÏÝÎüó¹ z~ï®?MßádŠI@“¶íà ùÃü9Ó%(îv£–H€t?oAR i» ããmš?®]H¯’ò·7{èÒ€Òpå6/¡ÁÒ„p'ÄÊ>—³Ì‹Fô³Ró Ú(4^¤M€Lù!±öÜ0Û¤õ†¶ ä` ê¯7j?k[þi¼– Pÿ´°÷‹¾ ʿޚP?è¸!—óÍGìˆè}c!nÂ6 N€P;!rGæ‡~íÔW}'ø¦–&rfg.~ÐqVç~çï·rÇs.@€Ó3óFgq&Pr6e*@ÑCWçwÑaÛCsQæsá§€ ¡è€.~.=– áöAø=¸{º3%8k“„ZÎc L=8-ð ! ¸‘…áì—NÿNÐmàå$Fh4û wH–ð óV|“J‘`ž(Ñ·p–t¹EHöÙÅ9’©–›±˜=³ Né›0,a‡9؉I‡ºIj–9‘G€‚È¡2!ƒÄD=$ʇHáwAH3™.€¢8Š’! jØD`jßI{g ¤eÄXf£úvtXÿԟשsæAu˜vC¤*ÚŸŸeº c¹T-ú9è 9‹ J†…£ß€YwªʇYœtŠ[(”¹f”{sgS†¢)0¡Þ™x ÿñ\»@Xd]×uz~tb9š7N` H:NZå.ÅP[Ú“Ýô ]ZÔ‡€Xè7%ˆ¢§XPg ¾4H»@X8rdNpª—éý×Ty3º¿ØŸ‹„Y^ôS`vŠ@žN!F)kœ·¦1#¥>1[þ‰z@ôS²úK8&CßàšØãw¾t§ÿ `5WÛô©xú§`ñž)³¨Báš° ›@ 1x%  ÿ`¯õ¬bñ¢.ÓŸð:HoŒ•¬ÿðcKÛ2¹9H[)Ô·¯8±Om5C°;Aˆ¹Œn$  ²^¡±#3H‘ôS‚y’)¦›£M2ô*ÿÛáW©oÑq4ª2úd­>Á™q³Má¡ì©2Š„::K›j (0NÔš6κ¤H‚¦8§óO«é”)®sW`+Dë:6¬ ƒ¶®Ñ³&sZZ;l»³,ã¶M0¨Å±©%€“0µcH‡r=9¶ÂÁqSÑ; 2tK‚ÆzR2/7HáúB‰ûj›/5¸‘Û»° º° ø·µx:¶(»¼øcî'¸Ó“*¶ 6Y¶¬Ñqæ˜ã:ÖRŠ£˜1@Û/¨+V¹ø"¼×I·Ï!¢›»¹# F‹NÀ°¨k04EvÒqg/0‡®«/Bæ’Í‘»ÿLH0nîš>ùmkE¼¿H†¶0ÙºHÞ°”ÔqeæÇ0ƒJôÕòÇ‹î‹|qP{ø>¿H²¿(U›M 0ÙJHü ì/n TK[>Þ)¿ãC¡=¹¢á|ár¯dVÌ=£ «ÿô¼ä3v¬U+e>[u¿I¿äƒaƒ¤D€YÿÀL»½ÊƒYNKº(p ¥…¼"œ¢ý–ÓHÁƒÔÛ€»ì3Ã(ð|›>ÛÃ@ÉC‚$«@ÔVæ³K˜%«!l>ìZAa\>¿4Hr¹>iàv3ä>ìú =DˆØƒaõ9H,¹Ëcë=˜uAR¬ ›ÔnTŒYwÌ«1$$AàŸ-$ц°¯ˆÿ’P$ÈÏ|÷‹DàÀ äéÓ BX¿óI" <ˆÍ·A… }ý»_AJÐõµÐ Ipà ǗÂHÈσú›H$ÿÒW¿úµA¬ß Ñ?[,„óã ú0À  †í£!K?À}XŒàû"CŽñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ˆ¼d Ù†?  @~Oó+Á² |n@Â6´ICDIˆ„ ·áGïµ! ÿØÆ ym|’Úèd÷n‘ú%€ñ‡$HÁTzÏ%Xà'òP `T¥öü‘Ë^Þ ·@H/;Iaf¯‘n¥-’@ÊR²„Ý“¥¯˜m´aˆ­ß?$! 7ØÂ’Ù†-úÇÇvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨¬œ©Ð†F–¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒƒ R ªDÑÉ>$Á ßøwñ ô!¡“XÜEJ@€4}¼E @85h Ô§ $ MP€ @­žo‡g«¦*€-™bÕK'[xT„|ã2Íéû”€Â$¨ ­€ûbWìàÀ©0@ûæ°U8€¬Q€@Zà4†*ƬSÅ«Bë½+ ¶¥£KÁC4ËØ½9–.—=cO¯VMÊXâ§µÄhÕ×V8A.P‚õ^zÿ8`±ì möøÚ„üU·è›ƒP ÷!*p£m1;ºä ä¶c„.s§KÝêÚK•D£>{‘վϿøFx½Kooµûèˆ œà‚&¨ÀI+ñþñ M8’ØDm¥;㢀¼Êû†?T¬ÂV#. ` øºÏ-(®â0Ú»9®E€»8 ߤÒ‰~Aáðz8o–ìé‰M"Ù‚´¸$ëå¢ ä €÷§(ˆfO/x“Ñš‘$ºµ†A ª79X¢¤iLva‹à×R˜ªYa×ÙœlÂ$€Sm;Uÿø$š5ÜT,“®ÊĵMH¡|c§_—7ÿ!‘óâ™4ò—w`HXÂc¯Õ#S}sL&ÑÛ¦^–Ãå+îŸWå„:VÉij±Qd*€<;dÑ®ãä2U"CA+޾9þW2eÀ—ÐÄ%Jk;IX‚†sÂL^ë„–DÖ 4òþ¬ÊN:¢|˜6È­+¹Q¤×èñ@Äjaò)V½le/@æò©ö)HÂ7¦]aô9A÷@lÞ1ŽV˜o†`ú:ÉêõIb™É¿ŸàÔ !ù ,õbÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØdÏIBÙhS€g§ív›½-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ_n mËO‘°vý Büô J‡$Øm x69 À~ @ÈK¼/nÀ_1ˆ?;°ú“Ÿ‚;´¡tE À6àO rˆE@X¿ö!A#$€"ÁBÐ~ˆÛÿÒ„J`pò«D PÄ‚¤0~(P¢%R€‚µ „ñC¡*Á¶F°ñ[a B, ä…ðûâ8C†°†œ`‚Æ9Ú1!u¼£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ$õ$ñ1\§’@2ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVº²o¶x¥,gIËZÚò–¸Ì¥.w9 ü÷À¤(y Kºæ>û‡6$¡ sËl&ü|)€bä·ˆåûþa m ™Á¦73ãËmØ‚’Î,È-´±pþC¶h'A ™N“!ó á¦41óÿKf¶ø%ï·Igþß Äç7·M‚³d¾DçB"ª™ƒÀ ÿ`(¶ñP,ó¢ùG$ hÒ£8þ¨ QŒS!ÜT¨e|Ifþ i`Le  Êtƒ6þQS  ,%Y7åÙ¦Îôˆ„AÐÐj#ª‘ÄF£ÙÎvj³¦IÙ9!òN~u þ؆J bɳ=t¤mX+ dêËŸvT¬R}HYù×$œÓ…u¦-@J$¬šì7‰š„°ŠìœÆlˆ?$úT7œÑ€¥&O W¤"s°ã\›cëÔ…”–ŸÍüG lzÕ¼f•¤ÔT«eÁ Ö»ÿ† ™ûœh5ÍÚË~s°”¤¦b RP—”¥vµ-È(šÏ½ò§ÚpùIØŒÖô›qD,AÈQ_2v´·Ý­n_Z_úº‹Àf¿yU$x·¸H§wª\‘q“¼§g yÚpÄ›­oKzWqö·4‘͔ͯÉÌv>3šüe6b kÚñÀ¼Ì°†7Ìá{øÃ ±ˆGLâ›øÄ(N±æ0Ü•NÀ1òX|à"$£c}(µ±Nïgs­B"aŹD¦ÈHBè¹á…”Eˆ?pjRô·i+: ª [tÙ,.îšl‚ß‚XVž±²KhÀ´!ÿ§¿”Þ-HÊ$ t‚9È6üá]¨´m0ç-À»¼Ö2ä§)AUCÚç'+t€*@r+–) Da›s”BXl# $èhwßi×3’@Üt¡ôšYæDçYÑßdt5qê]—ŽzÎÚ”ñð€[ç;³-ϱž3Yê`᪙y†^ˆe*U5ßËé•-5µŠäæiº!h¤ê]·áÂHHâÛž€…ÚÅU´!¶h| 2Òl‹ö )ÁPÉ'cðòWÅŒóqEt=}ã»"Nø÷íðL üàO¸ÂÎð†çŽœä·ü¾ápÍ% âϸÆAEñ™7ާpó,ÈÇÊDÿO¹ÊÙ䂎„|å09´^>•Èüæ8ϹÎw^†lÚKaTOûÌgdL)0TŸ—Ît‰¯éP_zú¢Nu©)ètòeÑû|ã­s]|M×+ÓÃöˆ”{g—ˆÕµgô_Ú¿16h­Í”ô6­=#w·^ÞñþõëíïožÛçë¸×SX_,á©×÷4¾B4—Õß72ùE^ò‹WHǰù3:ó‚}O·Îg…}ëÕýçÇNÖÇ;ÏõŠÿÇ7fOûÙÞ·G^ßÁ¹ôKÈÁ ¿—ƒtÁÑÃïãÆªP¼!,ï&Ø»³¿ƒ@f0 Háv¸Ãì|M­Oo÷Þ݆ÿ$¨_¸`övÃö'šüå_öW@È šð ÷Êa G~îçÝã d²g / äGæ÷ 8õ v€j‘«'=^'w¿`i€N@qÚ&»À~ûg<\×gw hx~—õ (Sí§<ÝÔMÙä‚Ó7(@Læ^`AÕæ‚-8=-HIÝO3X}Óg‚7È`9¨ ²@f.„>Xa-ø‚!$hƒ÷ƒƒ$7/… rq¾Ò‚`ØM1€a„÷ÓX)Ha`X=aè‚R ó‡(Rjȃ±Ôjº'w hi@†x~8e †µf²ÀN±VyËY¤÷ä¨ô‡ß` s%€M ¦uN§L}W0€8{° ßP|ÝÄN¬÷tU÷qæiº¨ u,›×vP÷ }7j£¶ŠŒGtM׈šxW‰Çvç˜vS÷Ê>u…w<— Y>·ù‘9‘¤äoy‘™‘¹M°‘i¢\öè‘”ÑrÍ!ù ,ñdÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜyÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ‚0Úh·!EnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·?Ûîǯ‘Oò×ýІ’´‘„@˜ˆ°¾$Ø¢Ihƒ-l‘¿¤/€1àÿ¢ÀÀ­}‘˜ AHà†H¨‚aþ@‚þµ ’Р@HPF þK ¨ [´ $,Á¨Bó™0·X¡ÿ(€ZØ¢‡ã» <(€’ð‚@Bül1D(&P~$"ÁøÑnH‚%qÄøQ„€%ˆûGDû¹Ñ P|£çHÇŒ°ŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"÷‚4²‘ÛÈ?éóMòI¸à?$! àþ£@8I>P†Ñ€”D ° m|2… €+KÙ¿#JâÛ@B^h‹H @ƒ±$[IpЃÔFC0qa•œÎ6’pËirrH.%á@[pP ‘hãÂ)àœç”„?pCÜ‚­L£@¶Oòi£•)¼%&'HÿÊ_¶3œ¥¼¤+m1É[HœðG Кo’‘ â'oÁÉXN2˜¾\¤F7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Íé…2ªÓص³§@ ªPM†D9þt¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®ò…œ{œd2Áʾ} ô“›LÂ6ÈjI‚|ãNÀ.6Ѷh&&QÁ›@ÈQ¯ñ«ÿa )NRŽ„ÕáaÉ÷] ¡¿¸CCðj>9ðUz,BZ €Ë‚-’GŒ`Ç7…=âO!.Xg!âÙÁÝñ.£][KVžÿÚï­o]¬üV+KôVI›íHlË—Ôzõ¸Qlkc‹Üæ:͸ήt§KÝ_¡À~Âu£.¾ñÈì¶O»Ø…6nñƒTµ™ƒÜ@ïªO°vøFCuk¿È!èí@¼Q]Î@ r(¯¸›<÷ŽÄ »h nÉÖʺy­@,Á>Ïž¶‰tœ¥sG\0×%ßПÉ;MàD°«ÅÝ#oøKЄ~~ýoÔ ¬³Ä®Ù…&ôz ;än”°‡gÖ:y ÎÊ‘ âàÐ%y)”Å£8'·‰KÀ ›˜‚설@.xòUJ+€(7ïÉ8e×Ìæm‰Yÿ’.á,?Ha r(ä  G²Ï¯.p‚ þÛÚËœ4Ž_šÝ(à9¶ÁnU·h¡€Ù-Hí†ë,H¡ÍP“Äy‹òfÔ5®xM@©eòá!×® ³W“-Ǭ”uÚêV*Ñaòµ…Í:ü*ÔÈFQ¥'td3ÿ Ø"Zö¯¤ìäÄY±”Á@´ý¡"OÐ M@>]í¸pöÚý™€¾ íóay®sµ ãÚdú¨;_¶.·¾÷-Ÿ"p«Þ2¶©Í¾FÓ1Ì)(€¬½Cìƒ5Ò.(¬S+p~'ÎÐntƒÅ/Gðø\~Dè£ÆéÙ&Àê*}ã&LNÄuã0¹ÌgNóš3DÀ“¶¹ÎwÎóžûÜ(__0é˜óé!ù ,MÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Z‘Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬ó„ äÔÎ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´Ÿôsí\ߎ»Ö·—D‘ÐF —І@nD’|yPP $øN¼¿GÂüÞHHb‹1}Ý?'á†-äO/@ømDB¼ît“¼$ß =óH˜¾ñÜÛ/Pý’@7ôù;HòÜ€„½µ~ì+ö"цøÝMy!_ðö¼ß™¯žz¶· nhƒw½àY¯€»“šóRȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ âMÿþ!Ä—¡0!þø`—((m0quI|¢§8ªmPñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘&’át·ÂÁ) q.€¤&7ÉÉNFí¨¤'GIÊR†± ¦L¥*WÉÊVºò•°Œ¥ËŽ(ËZÚò–ž‹"Þ€Ë^úò—À ¦0E‚Êaó˜‘i2—ÉÌÕdòpÏl¦4§é^".š•Òåz.)lBÊŠV,œÎÁY‘xàœ€Nmúíd'9çù·u@žÛpçÞ¬xÿÏ{¢pöìg;ácÍC}c ðìç=£7Ïræ-  ÕÞÊOvÊ“ ÅÛ:K @ÚÐ^>ñFDÀ“xä@µ‘ν“|€-FªO»YÑÚÀ©$ðé7olƒ¥Ú8iÏÆ¹7[dädiR3j·ÈÀ©Wˆ?~z [À“o˜Á ¦ "¦“©v{ê œ:ƒ’ªÆ¬ÒzÁ ²:ƒ¨’¦¦I³ÆêÔ ŒU ›˜•Õ¬Ú5«.ØZ÷FÖ§v0ªQ=3Ø„ìµYcõëZgÓÄ.o8ìXŸjÕÄîí¯“íë ,A>[X‚ob-,eÉwU>=–? ¥ëþA[ÚZv³d•Â.ð4¶©’Íê¾AÄâ¢6·S¨­mûÙLá¼5®h$j-)t5ŠËÕÛ rPåþ¶oÊ Íw¿SPøT!f¯eÎ;oöG½˜a/5£%_¤!ù ,/IÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃGŒÿ‚W¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ;@âÜ–€ÄD%´‘Ä@©œD’D’ÄãHòr¶HÒ†H8>º*“¹$µL^Ðè(“@n`;U.î&Ož„î!á9Ê‹K‚ÄâÉ.@$–'T ’¸.2ïÑÞõ%Q‚$Ï«Üça‰ÀŸlKîáÛ‚:EÈŸ¬DA%Dr‹úà—Œý袷yú»ŒÄæ:kãHÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ#·a²ÄŽù†¿ñ =ðÇÉt198ArØDË~qÌÀ‘Ž”Âdp?zlù†¦ …Ìà“ždä ©I“ýb Ÿtd* CÊ` (åÈîÐɼ`ž|€ „_Øa”–0$IL°3¤~2:~Cø$.gM] èå/¹ÈÊ“”¦*yLl&S  ¦@î ‡\NÓ“/Ø%6±©ÍáÌO¦>Ë9ÿO$dìôd5¥ù\sž Èæ?´±–&ÄÊr§Dù9Odþ³cߨ(ßiKy"S¡ÿ¤ãÇôYÌc¦à(ÀÝül¡ ‘FL–ÑäP9Í[Z ß°„$P°Ô¥ûFD‰¹J=&@ÿHlám2dzœÁÜÏo4Á»´2:²KH’/pÁ œ0‡ó!w\õ˜3° Ns wØÅ7œ*§¦•dO d ·a‹ŸÆŒŽvUÙE_fÇÁä®#ãaYVX4–°Ž-ìbQ&ÙÆN¶d••¬Ë2ûXÆFö ÕìɉÉКֱ¨-Y^%ëÓ^6d–=íûY×H†–¶™ljQöTÐF¶µmmoûZغV·Åí:u!Ê~6fÇ•™e¥+ÇêZ÷ºØÍîº^ Ý4Á´»àÕá Ô± !ù ,~#ÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,ó˜$Ìl³RPóÍ<7QÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûìsp8I IDâFìlûÞ%PB’Ø¢³müÍ»É7Ÿ»Óï{nDRözÛŽ| H” ¸ø 1¯wîÀ#ÔFõy³oPózK’ÄÎؾ»‘¸·߆$}ÓÞÎJÐ<$ü- µHBø@I´¡x~‹Äú` /g;^òô×=‚$¡ ¤GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈCù£‡@ ¢ćHÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&•öÇýP ܤ([ô€Ç…òo¥4È7÷Ĺ` «¼Í+G9"YÐ2ZÃÛnÉË·  —Óêd€ILÍ`ñF1—ÉL·ìc,!ù , ±£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^Hb!ˆÕ°cËžM»¶íÛ¸s/% »·ïßÀƒ N¼8ÌÖÆ“+_Õ‘Ü6Ì£KŸŽùn¨kßÎ]b«îàËÿí|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ­¼ý'à€hàoYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹?egS 0Öhã8æhšŒ:öèã@) BiäGÛ©ä’L6éä“PF©RViå•Xf•Zvéå—`†)—b–iæ™h’õ\d¦éæ›pÆIÛ‚rÖiçxžH'\{æé矀ºW#‚j(O²ª(z}æ$É¢¢—dOFj©c+åUÞ¥œ6Fc§ † X›¢–ZÚ¦¦¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëîf¤¾+ï¼ô^/V÷B½®Èï¿,ðÀlðÁ‹$G óeKÃàækV£I ñÅglÐÃKјéTk,òÈ$—lòÉ(ûòQk¦ìòË0Ç,óÌ4'XóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ¢úk1M£Ö2ÚpÇ]’¿¶®-wà ÜÍöH•–ÿdÇ{ÙžàzS·É\.°¤IáVÎøãÕ:~•ä~½ýQÛCQ>å{¥ ]Ÿ&6Gç­ì”. iNÒá^©Núë°ŸÕfèµæ/Ý q^%î±÷Þ»ëta•æ¼ûnüñ¶ö©üAŸd]v¦#/½ªÑÛVýôØg#ðÑ5O÷Õi/þøä—o>·ÞŸ¯þú¶¥Ïþû±ªûÚÑÿýøç¯ÿþ5Ú_tü»Ö¤˜Úð€\Žÿö³À:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡®_Dÿ„Ä"Ñ)D<¢—ÈÄ&:ñ‰PŒ¢§HÅÕ$±ŠXÌ"v´ÈÅ.zñ‹l ÇHÆ2šÑŒºCÉòÎÈF Bâ&€#ÈõÚ$Ò‘Cỉïh£[ðqCy Éÿ¤$ÒAƒ ‰ÝbÀC:rls|¤$Wˆ$0„G˜œ¤&K½•\q“  `"CIÊRšò”¯år>)V¢ò•°ŒåMú&Ë¡@*¬¥ÀiÃë5²+ÅÓ¥­~)ÌÚä‹sHfR²£J”´ ˜uq4£dH²dƒ1®œ&œ”©ÍÌd³›à”æüE̵D2œèìH3ßÕ²=r3ðØ7qâ¿æs!÷TH>ãÉÿO̬³Ÿíe@ê¤îÅ AhJІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’F sÏÀ>uRMŽÍÓ¤0UUkVUó ~Œ©c¨Óžâ,ŽùœOû¸œ•>F=ª~òõRšÐR©Pý)>£JUfAo'™THúTÕ®‚ª©GÙ—WÇú&°’õ¬…¢)NÔŠÖ¶‹¡Y \ bV·ÚÕT弫^ fÉÌu¯€ ¬` –Hö°ÿ’+b;¯¿2ö±¬d'KÙÊZö²`q,f7k0¶rö³  ­hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚÿÚö¶¸Œfs;^ò¶4}ý­p‡KÜâ÷¸ÈMîùêªÜæ:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz—¶$ Q|û]Á ¼„a ÂÜò2…TH¯$l! $äÕ½yŽ"¡Þ$á¾ø Þ~“€IØ‘¼¶KkF‚•|ê¦ Æ‹u¤‰úF˜/Õ[ï…ëT„PxÃvI‚ÚÀ£Ö|ª ñ[ Ó'$¸Â*fÓ@h‡EÀ1VˈK@‚‹80Îq\ ébúFbÀÀ±Õ [ù¿K¾ËJ’`‹6  Ž2^’d-{ù˳j/˜ÇLæ2›ùÌhN³š×Ìæ6»ùÿÍp޳œ×Õá9‡å©ú‡÷Ìç6ò´ÏPñÇC?úдérA^Œè¡º!zFHŠ}”à.ÄÆ”~JR“,:ÿ Ï^‰t·v›i—ˆz!§.¨+£äÉ:!¯ÖžPÑ5À‡}˜ n°EªKÍëÐ<!¿îµ°Ñ¶ê®[:­¶HcmO+ûÙœ96´—âl‘lzÚØÎ¶¶·­Ã`sûÛà·¸‰ó°M—» ç7Uª­îvçìÑð¾H¼ÝMïzÛûÞGÚ5¾÷Íoáx{†€«EP˜-‚GÄà‡Â/²pè› ïwŒ#.q–\û&ó®HÆ)²ñ‰ü›"¿ì¬—ÃîŠ[ä¦9ÿ¹Ékºr—øVÔ4´ 9ò–cDß5çLÎ[»sÞÖùçºE„Ž^*Úæ-9:Òark†ô|éP¯Ê©=õ‡HW@B¾!Ã’ß¾)VÏ×G_ôÐòo)ýrœ ùƒ¨ öá} ÿýaä‹…ó =A^€íÛ0Ù¿o¸ÿŽæà„Õgda/lý—¬ãý‚´ßï ¾Þï~ƒHÿ`²‹úEB|‡W)d`~°¦B¿''ïDòWÖ‡-ØG¨ È ñ~žç.È7@($P0ÍG‘z  ÆG‚1‚*(w@M {Á‚Ž7 (2(Ê7.÷4í‡94Ø‚S°º‚¸¦W؂ʑ7Ž}9()¨„ó„T—w°@O˜^tg1‚ô7¼—Á'…á/_¨–p°×o„æ· FØ…"h„_Ø„V!?kvƒ‘…H!M÷÷æˆÛµ„NAˆ‰ó)&x4ÿg]!wˆja~Q¨»€ý'\„8ñLâ8UHiHèGAxKd9Ø´µ –Ô‰ !€g‡‘7 ‘8¶TÔå#±†5c-€‹š÷1)HƒYx‰åÕ|¢ø.ðŒQ X=Úç}!ø¡aÇŠ?’p(j˜30‰¡{™è3±†~¨HÁµ‰`&A‹¦"3 W 5|ˆƒdáJÀ(½è#÷Gñ3À}WÓ.Љ3Ša:u(Ѩ°È¡§t³zûh_ˆ‹Ð|ÜdÞ(i#;7(ip1Ž9ó‘lÑŽP(Y»ÿ¦JNà‘!xJò1@”Yy@3’õW†H¬cæØ)©¹š3` À™2|é/ ”ÿAÞ§‹‘s‰$ž"ØÙï¹Âh"¼™™¶@™DŒ š-ñž¤V éxiñ »ÀC#£H›1‚YæøY¼±‘ç4Ÿ)*Hðþð ;)ÀžÂ)¸‰û¨ až a:ÐÇŒN÷!©&jiz¡0x!ê2ÒùÚçÐ'Ž!é–íé ªÝ—,¨ž9Â}3J£:5ü¹ÎI¤™ØÌø)¡C†Ô”"òš5Ê¡0G6&:¥ !Tö !“¦ñž7¨¤5‚›`в¶° µ` Úॠ#j7ŠpšO¥—!jži„ñÿ Æ×–/¢o­¹ ƒ§ ’4â§FCƒ9ªäI¨9ÿÀ‡„¤‘uAh›ñ©oÚžFZŸ#¤0r Á_ÿ ¦’à’gó„–‰”‘Š Q¨0Á¢G²ú Üù9¶²:4 ú¬ÁjºX¥q ¥§H*•0Xš#Ûð§ú° Sc¨q“Šˆê·¦œÙš–P))8Äê#IR¯åê z¶ þ`®Uc¢Qx'G‡ø‰¹–!¬°‘Úûš¬úZ8hÊŸ@‰#*º¥"ᯂ( =R¯û:A °²)f0•®@¡–Ž£°+dB“¹T#üÊw ²ÿ«K¤ j¶É˜Åø&Ê#JÙ¬òjF{@†„­39,ëÄ©P4(rˆ••àhúªAÑ´Ñ­Ñ«{u–@§H¡ª"!6^ûT3Û ƒ:2ºêAè…;¡–\K¢žÚi!GK5r·9áµ ¸,Á¢fkxÈ Ôšm„KïÉž¢õ‚‹|˜³T¢²²¸›jš©hz¸;›ΩµCÚ×xíG¡¢oâ?–›[º1¹N {i»],¸»­jµ‹·Óx#È…¡˜•š³kóZ³E;o ´ÄûÁ»Ÿ ! ½Ñuq+9X½‚ÿòšRã»)q½1¹ª¶ŽÁ™qêhÚK œ{z AQ8¿HÑuñÛ÷8Á¾ª¡~³¿úÑs˜[,j¢šg·lq4˜‰ÈË>Ê Ç™îKüFµ+B¾T¾›Ìw!B©%Œ¼4)§¾‚¿,Âh¹©ëuVŠ|Á¦„aTÝé&¥ç0éÁSÄ31‰hª¹ZAÀw£ÁÁ•!j¾õ(û¾~¢ÄAƒgÊ´3Üè Q`!l°K‘Ö½cÅžáŒ0¬Ë«n'l<ÅÂ"Ä‘’Á_œÁDC²ºaÇGÄzqzy —уåzˆÿ¼ÈŠÜÈÁÈìÈC¡g­Èr¥O±ÆN!›^¸Àš¬I6l‚*.Œd|$Ÿœ« ÛÊèá–³œµl˜ ¨+æ{(_ 4¥¬° (÷·k¿¼·œ1A‡ÃL©4¤«mlÓü$BÇD“Ì-gĦ&Ú<ú–®Š †ìòÍüa„~œæœ0[üÍ ïÌQ,lw¥ì™&‹.ã< =ó(¼—ΫÁÌáñü\Õ܇5QЭYm»Ñâ~W• ]è&vGã‹1n .™æ”÷šoçž-Ùø'ãr 9謳ι`¢Wõzk­×nû¨ç~å%©y`·)ïª/üñÈ£˜zwÆ¥8WÍ'/ýôÔWoý«Ñ_¯ýö¯eÏý÷s/ÿ¦÷Αþù觯þú'šŸûÀ~ÿe³ÏoÿýÀ™_Ÿþø÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺ0LâÃH _HÃN¥~6Ì¡wÈâe%> ¢ÿ‡HÄ".‡FL¢2Ã%:ñ‰PŒ"÷ø'Å*ZñŠXtb³ÈE¢‹`ô!ÃHFn±Œhlà!ƒÄ4ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>zdÉ9cZéÇBò)‘"q„©r‘Ìr ±öH¤’zZ&g#°…¡à’39Îó~Ò„MÂE¦,R#É’Æ´1•vÒ$,1óÊYÚ’h@Lˆ*yPÞò–¾¤ÖŸF ^þò˜Äª¥RbÇfÄ|ÐD¦4=ÌiZ3ƒÕ¼¦63”M»tsqdúæ6ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'zqRô¢Ï²¨MŒ‰ÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJSÛh´¦8]ÖMsÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕ沪œIV=ÃÑ­zõ«` «XÇJÖ²BK™fM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^AX$a•{ÍËnHàI¤«M˜AvㆴÙâ}‰µ  +7ØBm@kdÃÒÈZ€%¨…’P$\u³o‰eÐH¿â鳨e˘VKÚÿÆÖ-;½-SP¹Þêv-\-k¸¤Úß²¥¸±­q×RÚÏv¹miädÛ Óºk­-.›„× D³Øµ $a Ib6¼m)uÛÐוä½Aa/bá«úÚ·=཯~÷ËßþúDÿ8H€ 2à‚˜ H‚²`4øÁŽ0%üß [øÂΰ†7Ìá{T~±¼ü!â›øÄ(N±ŠWLOÕdq1‹÷¨ÜÇKÆ6αŽwÌcõÀ˜,?öÎ|{œÊÏÄ·DNrb‚¬d£€Ø$Ln²”§Lå*oÏÈVβ–·Ìå.{ù˦„ð„-"f0›ùÌhNó~p¬æ6»Yÿ3XÖ`œ‡RfŠÔy"w~³ž÷쓞7]‹>ù°þð£³{äŒî÷ÊgŽgÖ²û´ˆúÕR·†Ü¢ÞÐ7Ÿ-îÝŽpüº‡ÞF»ê x!þh7×ç—ì@YÝã ™C´säi'ˆÓ52ô•3zî‘Á ’wv‹fÈúÔ»#·ø„¼`ò§&9ÚÑ­fq³ -GÈ ¤0Ƀ~!Ú°x%Hæ[4¾ ÞA¤ _ÜᯗڷQsHbäºçY³“ez`¼ ‚GÈ ,‡'Hž!gw$R3pÅ×^²=ÿ»Ý€9ÂMn!Hø…€ÏusÉßø•ÕüçG„ÿ¨þõ¢âG¢ì…&vïÓy ‘~vð{gÅWto&w0Cø' Ûgˆ‡uz¶híV¨Hð ß°hûpHܧf$¦u¼åb(`(ð$Ö`µÀn€×f—N·‚Á§'QW—tA³|ô×nòÆu2Ђ cy§÷NX%Ø}ÏÂv ñ2ð4¨ç`OXÅv=3É2`KÇnØ~ C‚ý ·pnÚðpÚ`p‰çhˆY:n€ƒ0t%ð¶‡xp—hšÇnm—N¸]ÿrÿh'…‘fuÆÇs1Úðˆ@wsÑx`XÇ<¬¢s2‡ávŠÚðõv`ž˜{w*'„±h‹v ©8`‹‰b˜FùÅ üfsS(q‡á†xP¯ÈhÛ rηw°–‰ÅGƒIC„Ó t0^18‹ëæn’ c8ÇgÚ`ŒíæZÕìuoH@{Âã²r Zwoò¸rj·iþ0ZóøuÛgkÛP ’ ÿx|Ü6™1Ô¸1áX y/NàŽá ‘9‘¾2}ÉsiÞ—‘‰$¸ö‘’!’A’a’’QÉB†Ž‘.™@ÉÙ‘6Y+~ê–“¡Ç`;é`=©“ßf,)/@i`?y”AixIÉ“Ké“År7”Q“c%K!•7Il1)éeCy•^™N3Yù•xE:dy–/1–hÙ]¹–n _jù–dUƒrY—!—d±•«f•vÙ—R†—¼Æ—~9˜ÎÁ€„y˜ˆ™˜•–ŠÙ˜ æ˜¯B•T‰“ ™–¹a ™™y™œ)O¨ƒ‘ƒØ±™Ù?ÁXš^&‹¨¹š¬Ùš®ùš°›²9›´Y›¶y›¸™›º¹›¼ ¤Ù›ÀœÂ9œÄYœÆyœÈ™œÊé1ǘÑœN!ù ,MTÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë‹I^ÊœI³¦Í›8sêÜɳ§ÏŸ8 J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jè¡¢€è¢Œ6Z£¢ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf›&Úvëí·à†+ni’Œkî¹^‚î°ê®ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG½ERWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜ËË­@›gî9¥T.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýö#vÎý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ ‘€ú¤¡sáMÕB †ñž ]Ã’ qˆÉÿgrC1F€P0D™üð‡ù! ,ÑÄ•… H¼¢;°àˆ€TSÅ Àm(ÀLj¡À†1”C„€$²%HD ‡H¼Q 0¼cã`C4¡Z£ QR‰àYã"KÒB4Ò)@‘ÃIŠD¨„ ùÄx²$n´¡&IPGNž’Œ> ä+OBG#Þ°³TI'sù1òò—Uñ%0‡IÌbó˜]ùÇA”‰Ìf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›Êò8!ÂÌqšóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©Jsw‹•ºô¥0©Lgš 6Ðô¦8Í©NwÊÓž¾t> ªPWN‚užâªR—ÊÔ¦:õ©7"ä@„ Õªï¨Þ,'VÏùed«ßü†XÇÚU$õœ»°…äà„µêb_ýæ?¾ñ‰+È`x½«^§°‹² ¬Óü†.^ …ÌÀ°ˆÁ fà„Møu›ß¸Ã îšÉÎÀß8+6»Ø Ì@ /È`X¼6V @µ¦8?aÙLÀµÉë ¶ñXkÿN¡°Ÿ]Hbå ÍmÜ5· ¹«6AMSÄx-B€+Û–^%BÙ…Ôb˜mðï þÖ!†],t§P]07!”mi5¹;]„Ö!3˜‚,R.`ZB”ýnC^ ƒ)XS™‚MîCJ»‡lúö¼ ‘ä×kv5¹í]È/ì0±^S™» /‚Bm˜µšåüÅ& ,À:S™–ÐpyBÍv "&±Að×mºx“‚Š•+õfu ]ÝÄ&¦p…H¡Æîtñ@êKÍo0ÈI­@øµìá-™IKpǺrƒÿØgÀO$¬“PJlHFs €@pˆÜFGyéËXjðnˆ¡$/ˆÉP…/]â5wÉÁ[œ’ˆì«! ‰P<d–‹bà!ÍÇœÑ dHQPUúÏ |Úÿ:øÔN-}’¢-œ¸Ôòyõ«` «XÇJÖ²šõ¬hM«Z9ÕÕµºª€þ@á@$±Â¨> ƒ ì_±:ǧ­²®9_S%#Á¶Nİu*à ò¹b¦€žD_ûJv&ÄBd!*¨&U©M¼Ì?´1D?pÄ4¦Mýç@(„‰¼ba‹Ø7ÿÅï¢Æüé?p™b2µ»­¢¡Æ”’€‚,H,Û@A•6“NŒåY2v±“)à!©¨¶!õjÿÜÀCh¤ð%%G€dº6PŠE¢F­ ™ÆÓ‘ñ3íK¿Þb§éé Û`âq™‚ro»àúþ’™P ï¿ò¦“‡µ ˆ?ˆ9?ÌF½, ”þ"²[Ñþ¿ºôŸ}¿ÿ&·}ÈÍ-UûÃ6XP Žf/³J¸›Öüc#×[aY⯼$Ü0û¸?2´¶mB |“øØ_«ïÜ \`àêTƒÛ0è\}IÝR–±^´L<™IPnöÿ¢<ÔrýЋÇKÞ“Žë-sšbf7Å’@%;ØØß“‡I ‡§xJÇpÊ| ù H÷ö>&!OKa›p“) ±h™C nCÐ8 sgû Zújf´–dd’ÎUoÍ®Fš(ã+n¶5–f)c %én0®œÚ^)›W·þÊÒÁv¶´§Ý½;j’Ìö!( 7D‚®¹Z¶³Å òܨDy‡6nIjã›A7ºý3¶Û§>÷@–é†6ô›Ÿó>óÍÚA7ܘïk÷\{‰ÊI|Üôc81å«ðh#¥éÆÄ bnz4!ûÀcÈñ· †#²föÿö)ý:7ðy¥" a;3m“ð‹¨lðAl~@Tê÷e<3 !)€oýè;‡¹43žÇŠ5þÇ7þ± ÈAR¸úûbj`•/}”/[¥× (èŽJ}S È Ö.ƒÈà »øÆÇ>²ÿÜdA-*µñ [¸@ /À?ƒ Ìà3pÂ&äÞõZoù¦áö˜Ò7ØË6|ã™AÚÎùØáàt¼0Ž–9}Š0$À.t1) DóyÀÚg {Ň¾€û@ßÞO6ùf±”¿x‚ÚÂv·Ï îôSúùzér®wÆá~êý?:n‹;¸ž!²—ý ¦ ÆO^è¥ÍÿÏ#ŸX¯ã•ÛHûB4ßù¶Ka?Ȇ{ø™æŸ¯ô¿“ÒñÈC³¾!k'{†çðQ¢wSž”{œ¡G•å'úƒB¸ä>Ú Àikwšx×>î!D=m•Áa7çLw¢?(øT·ðBàºy²W7x¿pÚ'– –` ²0b•%s 4²°p´Wô§'+”‚þóA³özmw±W@ràmÇJhqWiž‘R‰fMG˜'à†@¸DWÃÔ‚/X‡G{R(/ ß¿`Û'„úCWèó{ëÆqtSIð]|ò€îÃTcU§†Åwà†¿„ÿÿ€uXèqq?$‚ÙUBýsH}²ŠC)ð °GxÙdžñ†Ÿ¸ #ô}„ŸÑÅä?-·‰cg„dd@Æ×~n7x¨$á%vÑqù§äeM iœusñCÿ ~¯€kˆxoøK¨”¡§€•…J¹‡›ñ^eg?pIÿPv¶ð VøŒÆW|2ðÔ˜q\å@±ÔQ¼W‹–L¿° gx£˜}í(ïès{å@½} tM´wÿ` i—‹ÙŽÙ‹öf"µH¦çS$×K9”Pxloø 0$h¥·RòEU„àh&áõ}óÈ_¤ X7º(SðK°öÕh·P [¥j‡Jä×1¬Øqˆ$uÿ° hw3pS€”q‡¤R=iwwx÷}ýçeQ ăÊ4YUÇ_@gsóó{,F@#'rµUrur†³3YvM+%fN„oû#hSD,˜J2³qTv²ôRDrSRøÖЍoƒI˜ù6’«Hp:DA=ùniWtYqOÔ‹Ìd€’Ô?av 2L:3nÀˆ–À”Y)÷t¶ qs™š–©™¨ôZØ‘‹çsO¸3–ÙXáoòæsAùpwq²‰n%À…º&v0GAYåm·FmÖyq±’Ã!ù ,õbÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØdÏIBÙhS€g§ív›½-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþª ¼/¿Hq/Àüø+Ô¶õ“І’hC ²?÷%ÁLBla ¶•  AX‚¾/$ Ü ÷YP ÷! @‚Î ’È @HPF l ¨ [´ $,¨Bõ™0·Xaÿ(€ZØ¢‡çÛ :8 ù³Å ¨Àü €‚$È¢@"˜?"Ú I£$Ž˜¿³­­‘c‰hÅ6êÏpŒ£K²¶9ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆü‡ùüaE*dp¤#2IJrŠ”üÇ?ܰAƒ1‹Úp¤?$ØHFòÚ`[%³§I[ ! ‘Xå-H‚m8Ò Hb5© `•Ó3e$pĺ˜¨ @(°þc’x &"‰roID/ÂÈL*²–ŠL¥-4y‹Zú#€Û¨Å/»÷¿g à˜Ñ$*I°L¶50™Y ª ÿLƒuó8þ(H$áŸò„¤-§Ù@bFÒ(hA÷¹½m@²† ô‡0‡)e3†ÐÆ6´ál{òD¥bÏ[¼ðl‘8©COùuöÓz @ BÒH´!Iå@4¹ &"²yý”)GrÓ£:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hí“<ý‘ÒÚ"i¬Å-þI™¦MžÃ\¥0GªÍôá• þ` M âY¢ošék&bØÇŒ’)cAˆªMa¦”¨3ê3K2Ĥ±še¬PSNŒ“­‘ˆ(H0W¢BQ¢ M©?ÜBÿÜ0’£”h ²¿d¶8©o "‰Æ”t¢šô‡AGZÁS¶Á´#Í¢)åYÍHnã¹ãüGPÜҊ̳ÑÆN'ÛO[Œ1Û€´–nw¡¶h¯&KpCMF£ÍgØ Â$h²“ÔÀy=¶Ã12°¸¹lNÓÀ[pW“Hæý{ʼ—™)©-CjÚ¶æÓšÛá,èÒ„(˜­ÿ@0bþÉÞÓÚ–¦-\«$0È݃$Jx.þÁHû¦°½"Û¡hbkRÅ‹‰¯$ž©Þ”Þ8¥¯-A~r]‰T’ÿ¨ Ayb!ب4ò9ÃÞXþ#mHiŒ'ùL$à·ÿ Ûå²ÛK“ùÀ.²‚•ŠW»f…5ë`ÚõŠTÖ®IŸ‰×2SÙcàˆyiˆ—Ì~§€,_GóÈÝü‡A‡a>X‘é5ôdžËÌà’·ŸHNò©E]ÂøP“ÛDI°éçÞâÏ=`,®W¼žrÇ* ÚŤً)³<XP$@V“7,(k±_Er² 0jn *åÎS±~6—!ƒW™N“Ï€FbQxC˜‚­´N×]׊Ðu!ÿ^©×ßjÝ~5rHgÌpó\|IM«Ä'NñŠ[üâϸÆ7ÎñŽ{üãA"ÈÇFƒáU#ÿ}ëŒm!ÒËÖ¨´Ú!%m)sÃH“´•g$¤lWP“·¾%ò`.¢š›þˆÑÍò[4AÊ·ÐEP ]¨ Ý•>xh3óX‚@³å<õ«»>T™ÃÅ ¯­¾‰9ÞµC¦šÝf¦›2N*»ù~¬ ³;€ITå ‚öVײ qµ%-³],úŠÜ…¤@7Œ]æZ0¥7œ!%ºd[°Ð.KïÔ¥[ŒÖíŒAöŒ»eÿ†S¾ÅNó4ßi#P&€ê¥lc—mèŽû1•1Ýxa‰lÙ“–0ûX 𖱕¡N”*P—IÙfyR(¹Jÿ(PäÖ QW)p R°‹QŽaè— |Ùh—/"O¼VP·òt\€‡P" *Pͨ'QVRB` ‚#òtˆÔgÔ51’™Bы߰ Q“Q™Ná .¢s%Ž”‹ºÈ™š•bÕ” ²%!5q rPANð–. šÿÉ[©—,òÍ©Iûð¹x – ràvp º(s9ÏUP®y ñ(P™ÑM«È &Rð Èi•*ÒcšTÕ&Oß° W0302P¡3`$©g7¢\á—ä—+2m°%Ow ñÀ¢0/úRp™ öie–,J}w zýÖP $"Oww~ßp1p¡L:¡5 l8#»e²G)k%Q(™Á¢Q¡1:£Oš^«µŸÒŸÿ¹:êü5Zº0 &²›Wœ ¡¤Z¡#ù¤‡f†Ác7Y´S¡¦Q©4Ž`¡šñ£0¥ôÿ•‘,Q?+ñ£ÏØuÔr›Kö ‚9 ñ¢ :.€¤”¶ƒ€—ÀB3‰€—›ØÖQ†*ØÙU§<&QÞðŸpâiLj¡3° q™P…6h[À5jñ¤~…Åk‘t‘EŽjØÄL¤:™”&"òä`«õ ÿpZª/Т300:4:l)OЉ£~¡I$DIÏUOÌä?”TMãԬůÓz•d©Á©M.À—¾)%æµ°è æ©1â)0®¿*ëJw³„Mõ§€¡I<(oé…dt¥ÏºEÒª–†q˜,Q›þ9¬‰%;ä€Èj 3ÿ0®Á¥æú¿02ªN°¡˜È@þŸöWS[¢Æ§’FÔ‡Xmÿ*=*³²x_eÉe½JÀêà*{™çµCUÆ]ðÊǺS +Äw‰x›HxU›÷™ŠJ%FR\å ±®/zðú¢AëI”‡{‹´-–IE8u6‹O«Lœ«ø 8»BŠt)1b²°Ešâ%åzú³^ x)&/€±ž´±F{¶{²†Æ{\Æ ¶g}ò6¹^ᔚ@™m:Ä&rÚà*®ªYPÑx³‹€Š–›„q‡U¯•ÔdQhP+µ”»ÿk”û¨¡ Ú¸(èYšÿг ¬¼(Qä±Þô™dzS˜}Ï%{Í¥hn°k¬‡kKÕå³0AÙ5µ1i¢žô»¾v@.*€+ª-(QѨPìJS¢›+Ð$€õ5‚¿„kmÃF˜ú½{§!S S`u A¦I‚b‡˜]»Ð«¥Û¥…ëµ,ù@îæ§Õ¶îôŽŠäU%øŒÖiÄœsúNʵ̋’ð‹aÎ¥!{# ‹¾D%Qt˜±J*ÁÊ‹¹˜HSìu£B2·|®óšà ®S±éêÀwª^ÇL˜ª¬2â›-£Ä¹Ä5(&:P¡”Pvÿ ÀK ¬È xÐZ\c´òöÅõk:r·ÒÇ®¿ð Wp303¢YÖtñµcâ5ox…Æ9RŽ–®I°cŒ'ÄZPª–Ä!¥Hc}P ”LSùI{<’aäYn¬'£Y씌Ær,WM@LSñ5€EbT(L'}Ü{¯fi#DµËö%QÃ[$*›'j&Q¡Oñ4RN¹PX»\I’Íu²VŠ ÉE6o³4WV(Qµôô<ù§„‰âdVVJÛJTµM…I íô™‹ÂéÅ)Æ’´Q)upP9PLK$)NŸuY΄’PäÏ7äS´?ð+»úq•- •/+šÿ¬( Ùäì…ò M• à<- µs4j %5 Ñh›  ޹ ©Ô+Y!ÿ(Éi\çÌ+~Y”Íè²-cž<1«”»ÓÅ.aÖ‘Ôo!ÖòÐC¢ÖnÅ8p ;A?Y?ŠŽ®ÓOu;?Çž€Öïs ¶` ¶p­nô -   „>aé«ÈåøÓ|­‘ÝFoqt° ½Ùìã. .@ÚptÚ áÖÚs×zÐ)G*àŒAÉÖ ÃÚ™-:¹ˆœõ G!$ÒsahÛm´×w$°¹}:¹,Gë¼ÜÐ6ûÃÛs´ º(`Ør´ ”-¿=8G…gÚÑ=º0Ï=ÞèÞê½Þì $“Ô‚-`pÕQçžrd¡-Úë3|XÚzćòíFúý>å­<!ù ,ñfÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜyÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ‚0Úh·!EnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·?Üîǯüò×ÿ TBID’D%°ŸJи!LBýJ@‚ýPüóŸû [¸á Tàú’à[xðAB"@ú™”„'B@I „çk`.C¼p€&,ixº íkƒ ÿMX‚ F¢ +TâÁH¸¯üa €@à¯}N´¡Ú ĉþK¢Ç8+’ñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>šîäC¶QB {Úˆb$a¸! ´…@þÁH á‚H¤Û@HìmCŸtá- " ÜB$ä-HÀÈO À?<åÿ´÷lÃIÐA¶ÁÁZÚ¢Úøÿ$ÑABòR¾$?°WË$ÜP‡ÔF lQË[$ÁËD¡ÿÚðiRÓ–¦dØ2‘SKm02—»DÂ7HÍ à–"4ÿ]2ìÄ©¥>·AÿÁCú£‘¨¦:XÀw @–µ¨¥1¯WKhÞršA¢-UJ.ó—i7·QÅëùCB, ' ²ÉI¾“É".·QDJ‚˜-È?nAL[tò ‘ä@lQS?:Ÿ> ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊUóµ«` «XÇJÖÀar|b,«Z×ÊÖ¶ºU=_}«\óvÓ¹Úõ®xÍ«^?wVáŽ>È7Ö÷J~ƒHâ· I¤ n°D |€4A û`ß.\‚´À-PJðYÆ:¡P€@€¸Àƒ] °ÙÎÿ~6´PÁkwÁÛ]h#¶çÛÄi  ¨ hBq]à4Á àóç@fû Î൸խ°ë‚&W|ÀÝÅiS‹ÝÖn÷¼Æ­#ÌW[Ï‚V´º}­|½û½ï¾3ÙE @\( ­ ¶»\ûĞػE @ùÚö½¹0wéÛ·qšåºPA’»]Ô.¹)@ïvUÛ¾ZÍ‚¹¬\ Ä¿–/vAHIX|U€Là×ÚÁ %H$êZ·ÄžåÆÉ®„A»]Ð .@pÒŒ¼˜ „ʼnuñ‹AÜcôª p‘«WK ÎT!J–±|[ðä(kïÿÂL†¢b‚ü7ÀÅí²qŸì„]Ð2Îgn‹åÛd6CYÊS‹k^àÌ¿9DË 1gÁ,æ?#!ßPpBXüb5Úͱ²ô¾a Ÿ@*P€í_ ¹}ÖF‚?3*¤Ðn3¢«WP‡´ÀÎÞngÃ<æô¡wͺ6H¨—Ã…üºÅ­1c-$_JÑÃÁvWj¹Ln$Y²Œ; e)¼@ SÂ&ž§O$$ásh•!‚ÞâNÖNè± üüÓZðvxȳ‚Ý6˸ —`·-ù÷)@ä×gõ«gã®»ßÿäfÀ1òë×’´œ=nÂûýw7\ÿhöC„Méí¶Vož>KЀo¤àP~-,›ðý1¯–¥@8iú¸/ùÏ-ÑìW$×9wÀÎ[0r‚hÛwߨ3Ak{ß.w­Ò—'Ì…@"8—ïÔ¾ìŸW!©–ˆÑ)³ûqÀ_ J+Dü!iÿìÔï €`Z (ŽI·K`ayÊ”Ÿ’ðG-‹ÀM[Z‚М›BMîpp½",{Ý]ë'” BlN Ôx£ˆúüß>M>Xk©×*¶C‹‘&ï¼àp%lO3ÿã—ß„üÌ+ïoæë&~¥Õ®Þ =ËöÛirHCêÔ—×,'ÿ@ÛýîØ;_ŸJ¢>„$ÿoüÊ ÈßW.¢ø÷Øoƒ‡¯ö—r¾4Mÿ` w@N` —` …w šð íw~ åD ~R{ï65Tt£gtM ;¡O’Lpf êH*æ\t¦rPJ%` »ð|µ@ Õ5Ëgs!i+æ¿×]ü%|ÄÇ‚$‚H° ß —ÕçèÖ„—ðM€è'}YC~ð]%q}Å5qÛ73X„ø[u†…¼'h vð4H9¢€’ÛPII Áƒt¶- uÁçƒû7X¢&3ÈxºWó¶i¡„ßà$`„ßàD’ÿw:5ŽwˆÕ×aç hµôHßà …¨œ&jnàH`¸8:·‡l|üCøßp MPš€Ÿh† LÇW‹W“V ¡…¯¥}11ƒå‹@Çõtñ\އlX"Aˆ!@ dkÁw‘‡øç_P6|ß`eµgR&ˆµ¤ D§ƒQZe8V†n‰ä-Ï8ñx¹$‡DG)ç—Øjò%ŠXnÐ…"qSpÖHg°w¡u ¡áß M)5Æ×~5g÷hjVh¨„*ñ ß@ 9vBø$ä €$ MÃzev‰Ž¿lòõj8ƒˆ€ÿ¤†Ðt DÝ•jD§…áRg?€ÚbwqƒïGpát+Vh©Š±5N™(Ò5IÍ$…$špd Çt‘X"‰'g)o+¡gs—•"¡P±ø—@”3Ñ]¡tX͇ƒ qv¡fÈÖ‡"1[3•‰rЗ!h (p 5¸4V8xiWq4)—ÁzÁ8!ÇWº0Ü‚{[áüM ™ÞpžY±XcK–Š™y ™Ñ’p 󷯈—=ão‘PXJðyQ† A^=6qšIœ Ñ|ß € Àœ?IÐE&BšbK(àGÿàZבRÀ€ Èo± ›@)° K˜¼w]-â¡› ²íwœ¨P\˜É_M_Í¥Ÿá€ é8|ñ›r“ ‚š—4žž—àÖiy|L†]7[é“Bñ\e4‰$2bœªBÉjs'btÈHiùß A½¦r9cK*ªZVp ¦fó ®’ ɘP¡K(Zœýy„/ ˆ™Jqà\Ýå "Z¾X!øù *žZZ6pƒædÁס § Ðu º +Fæb/_š2,:¦-±…Ó&i:–\D¹–`€ãw§(ãbj¯¥„ÿ Z æ\Ñèzº’á™<“§61¥¶\ö\ƒÕ¤ Ù.ö‡„zœ†z2aÚ¢1ñ›æùZ‹UžNð`¡Õ_$ê9šºž…^eØZ àœÆ•oÙQª3ˆÊª9ñªªX§f}7:§ª¬7a^þÕ¬Aü% jLù2[éP=ú&ZTö_îU¹º. £5³«:‘M€^“åy–¬Å­ú UJ3å~–*žEJÅŠ?Ú299S‹ôNÐø£«53âGM¯5[‡/f¹e ßðO5·L´2¾ÔOKÈTrå'*S±€t²2q°w1|í'g˜ÿЧ ‹L0ûøho!©Š˜›‘§ã²q*2û– Q¬R ¿Y£#S²:[Øjùv´0#~ %F±³t±Š7K2à7µÁÑÈäLp†³ÞôÃט[©Ú0R˶ÃárÀ@¨¶ȵõ“°ÖD¶É1·sHÞ0ì×Mˆµ¿Ñ´ó$ƒ#ƒÇg²-fiø|SM‘€ö‚ßà·Æñv0£ë†‘ûK¿å?ð)ëÊö×\,»1þgJ‰(Ø™¿†_3d¨›u—7UKN¸©1‘ Jí'QgÊ»1×D‚Q™Çá›` ¶` ºÀ¼¥™ áµ½1pµÿSA$سòy¢ô Ç’û0öšb$ú|ië0ß t´ ½Êá¸ùÕ[¼U1îë»Êα*è0µäˆ@‡·@´ H¤€ÿûšç£O'¹ Rw »> ›JÔ׺ÝCÁ‚¸uáÁ´4OI©hÁ;>Œô’GB¨‰rñsV›‡à«Á\–çEüyÂõS@ÏçÂJ>_Áͨ”V&¡$l=7,yvp ÔÄQ°IL=3 €©Æ@é+)\=i©AŽA\>™UmjXŠñH :EÑ—>_?îºWžÃÀës (ð­ìs VÇtù)Ä Q¿ÿ$ð~†·Û=7vA’f»4x— ±ÅÜ#ƒÛ Y½iÑERÁŸµDjµ*MÀ½ÒCGФ Çœ[j>®ˆ5‡„XzY‡> ÅMß° ƒÕ»Ð¯qÊÚÞ` vœºp èl<=¢*ǯs½×!ù ,õcÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£j$!µªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚ70UlÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿü~–I”@B HwüI°…-ò×Ià~´EP °îÛ_ÿ"! ä€í# à†H  |[â6ö50 ÿ#߀$T°„o#A$1B÷ð úû ú`(€$¸!ûS` ÿÙ× d„mpÃÙ' hðˆ’  øá$ éwÁ$´A€E ¡ü°Àºƒó¢¹ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ ߨ ‡ücÚûárHD:ò]…|¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,½ólc€M¤ 6¶šF­– ?x)p€í«¥1‘Y`ÚÂì«¥$"‰h£‰˜¹…ˆIZþã‘ä&AÀ¹pjœèlY-oÁLFÚB›ŽÙFÿ0ø †ðæ?FÈÿÃ`S hà6C‚þeÎgBn©PÄHn5Ü'$á7LT Þ”AóÙÌ6@¶8g$CRR¡ÿx§!pRÄü#‹þÀyyÀz­–ÛÈ¢G}‰Ñ2b´‘Àÿxz2t!AuÌKkh P³©Ôl I¢î3 þhbRý €v¢L€|È?š_BÿÐ(7oÑUºíRÅ¡6J‚[˜u©Ð\™Q!’ÖÇ,5Ÿ‘à¡6Ú:E`.ñ¥Á,'HÀͱ²”¨EµYRËÉ.æ2ˆZÒTmn®°jIóÙTfÆ Þd™-(jȼ*5‹n¥f`ý€6ÿxñ„íÜ*/xH‹Ú"µ=Y-ϹҖ*æ3í!Fs¸O2&…@ÂoâÚr¶«Þ„í?üÙ’%´! õ+lbQü%°úÜgU·©]©FB€NäåXß \•­Ó«9$<•šYŒ¶*$PäOkéQh£…=(¸ ÔÖweÒ4n7¯©ãÊ7¸ÍÄè~»¹Uufu€®È!Z™‹õÄ/sæ3‰¹Lü®§ È{w™ÌüÎòÆ8αŽwÌãûøÇìjhS0¿MDGŒ_ÿ~±G|ÖÑ¢êîö‘¹Kþ`'6ßÉÝ'!9Tפñ@Â,eô PÊ·¨…wãË6‹øÿcgVHœA³Ýf pÃ=æAÊ ÎâY VK ,ò ÈaS,ó@´©èÊÀuŠùÔ†KÉ”’ÐÉ´%¨Û¬Ì*ÑÄ‚±„¦$Ña„ºÑ’¹EÿHP—’à·¶ØF• ׋ޤ Õh$¶1Pé À¢V ‘7Åh‡Ô–+¥¡;L[ÿâ¼ì¬@ ‰éCW¹ÜŒ"ªï2lMÙbÍ{žîf, ZŒrzç7sZí|~Š$cJ¿ý`Œ‘"’p1fÔ›çpP†¹­,a9¼ÏäU¦%ÐtJý—djµÛæ,ÿ»Í´؉ÿôfSÑ8àÁFâ­­]ñ׆ˆ×¥Û™ÿº÷Còý\›­I(¤6Î+Φº»™‡¤ù!« }ŽÐärQ€@(âMÛ Û`¹gÊ=_nz|Ì÷ÜÆV½ÉV7è“Õî~4з²õQ…4â ízcøVÀ3¥®¿¥>u`Üç`ñPÛ‚rW2â‰þ ºKÈK4ñ¡%,$¼ ‰ÂoS¹,€ƒ:X$ä{„$¾XÒn•/ýÚÖ´gÌ5[ÐÅ&~„.¿©/m!ÆÈc¬Ø ¹{jÄœaŒˆÝa_WHØÝ×Ä5_“ò¥éîëã"t[ÝBàlä9#q d·èм*ç–Yzô+;ÿùi™9ÎFмQßôk7ô{ç‚í»dƒ+Àý×b|ï÷lüi¡²ù׿¶î³_t&ÖþûY×ÏùÛ_På‡NÑ býûŸÎýº3h3¡ ñ3q M`&8PæQw¿€Ä+! (X9–àiCÇè€"ˆ/èÇè8B'#8I 8*x/ù·‚ã 4¸31H?B‚7؃>H/½G9øƒ ±{à“ƒÔG„JˆƒKØ„Nø„Px#û'G%…Ã2ƒV˜…Z-F´…^ø…`†b8†dX†fx†h˜†j¸†l؆nø†pø„F8è0i‡x8s8>wxGØ—}qÔ|{87‡Th…(7ˆˆ=!ù ,ímÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØð‚@öÙÆ… €Ùh·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ï>FH$Äû@B‘¸‘ Àú%H‚$lḡ}÷sÃÛ 6DBý;ŸÛà†Ä‚æû_$!€ùAp ¤_AB(A„”€„åKÂB8˜A$pð €@0x¾„%€$Òð„m@Âÿsˆ¾$ÔB…” 38¶! m°…$ÚPÈ}`"˜¾+ Š(¡ÇHFÀ°ŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£çüÃÛ(H ÿ!> âc¡IÅr‘¨bþAHïÙB‡‡Ô!Ý`‹mØ¢ôÇ-lEJ‚ Ü!)ùm@Q¬|"+¿gÀH@q”üä%ýAI7´a–ÞË¡'  XþCøÃå?žhLï½ò˜<æ+YIÉRš’{„,A/ Kd2Д”܆,+é=ÒU¬ 'A˜ÎóA²‚ˆ7µQA²pøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–2Š‹t$gùtA¿]„NààD¸ø óýB(0ˆ "…'8Árèéù\08@*pTU TGx/¨ ‘ªT›p>¤q€ à‚¡†¦w”ƒK×*5±îBÃ. Y7ºÚÅ ) @œ€HöIµH€ ŠÙ>±ª `*[ËØÆ:ö±ý‰L«g×ËhbßøÅ6”Ú>4ANPMݧU´àÐóêGÈjØMpê‘1JG\ VÓÿ¢Öys0‰k#Ë9ÅÒ¶iô­Á*€"ð–rÄMPYNM–GÂ5ë©¶AØx ÀÜÌÑSà‚)X¢)¸Du I"B¯Èš×4ážš:¦y$!» §@æË]ж  € ,ÁÙ¡4÷I­4§ÿ(_nÑŒfL‚z4'İWòܧtxGÿpÛüwß¾„’’X®ÿ–h |ã%hÂ7ì`°«±pAôQ#,m0qBŽiCÿ)¸@Ô½E R )Äå)p(ID”`Â2‡·áAôjAÉuË7v‚¤ `´IB§mxà6û1ÿ„üCä T´¢E’p¯¢°¤ ð­È?¸i_?Iw!𸆢-€ Þè,ôFþaA°8@Â¥‹3M8Á rp‚%rÔʉ–Í,jû*åWËý1îY&»aÌ¡’ÀŒÑ?ægåìšÄB ôJ2ìØaM¸ò—YtL3j£Õ)µÿð #)ÜAàoL\ÌÀ1«ÄgµCägÿ…‘#!6òŒ´zX÷ {%»°D ʬV+µò¦Ë~H‡÷QÌúæ[E.x€;êB ¤ÞIñívþ8”€ÑÌ~`¡ERnÙEO%« 2 j™4A)Qªê‹ÆõÿwG ­n‘°Ö+aêÂm2óÔ¼F׀ɣ î9ïGÇ,yÍßÍ’›„Ó+jv¯5ÂÙÉþ*§Ñ{2uЍ˜‡ªEzKXðKF=C¶ÐÆ%í›ïÌ` g— ²v…ØÂÇÓÞy” mô˜8œÆ-nñÂ_:ä3øÐöÛDâÖ/ a½"®{$t± RðÝÞÇ92‡n¡ µYîÁÚÿj¢Þ!!a? ¥AO­·è$±^Ýß2^ïôŸ|^ÈàH†ø° >¹$@ÀÉ>DKß  %` Å©|2°àš¹‚Y¹rœØ¹9óxeœßã™Ü¬9ž#£|’@·@ƒè³ –pe» žç#à룞äyŸøÙ+Ï¥”êã hžÞ£h‡€ì£@ Ùqù™7ç– “s Z8öYDlô˜çSj0>æ™»ù pƒ×INÚ#øM.æb{™=ǧV`u×ÓWW¶kMàb8ª>)0jIp –`aÀŸã£Za^Ê¡zÓt¡ŽH8Ú¤z³¡¾8<!ù ,îTÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡½, b—Í\möÚeNÄöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þú©Íþû¡ ?B$” vHÌ/$@ ‘pCA°>$¡ ˆ„$l¡?$$An -$Ñù­ n¨EÈV 7$¡H(A“‰ ¢ „9 þ ’Iäo…‰ "Àô‘­†!à@Ⱦ $ LŸÿEˆÂÿ‘M†tCþÚ €0‚|_ l1ÁBq îCA´A„ó+¿X¿þ­‡3Ì"gÈF‚X°pŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆä“?ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºÒ-ÿ؆Ady‹‚lC·Ð†@di ‰ÿð¥-™÷f‡%Ð¥@€f Ù†ûH°4q–È»EþÌ(&"°‰Qtbri mð’ ÌÀ6l.r ¶x 0÷EmøPÿ¨ß@Üÿ^’À Á ¦Aü$ ÑFAwN/’­š ˆ.(Øb·æ<«ÉÑØ…ÔdÞ=k)‰wúR€Û@ š©Òw$ þ`'ñ™RIÌ3y)ŠO/ @¡ ©J{)Ðú t‡=©ÚdyMuBP<ý?ŠÏXÖOGýéB›—ú2¼œ(Múv*“ Û`&V³j?ª&ïžÿá;§*vÚ"˜þhnŠÏ꯹fº¼œêT ù' mè5œ»\b%ÑTy>ïžÝÜ_\ª•6s³ uæþ K]zT•å9}yK·:U |}¥lgKÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p‡KÜâ7w.mD\ŠåïµDk]ÒÚƒørÕܨ6ëÜâu×”j Ý#òµ¡Ô¨4u˜Þäýà•¸ ½R”ŸŒÍêA-*Kþ”læd' º <‚޼ø¬ IëT7(4Y}0<ü`aF‚´É»¥VïkQ|겇¬Mç)_žÊ2Šj &f•WSøcƒÀ % €ZD¸~¡-ÈFFž*O¡wU' 8_[‚—¯]Ä+*²V´™$òòjªâãœ.þiD ÂÌf~ºLÂ6ü‘V /È=Eã?ºÊKè"8ÿ!±¬ûM9OÁ¾ g\åL äÅ2 æ…8ha²ó´Çû‡X‹Yd[ ±,+ƒÉÌ*/°¢E+1!ókùÊ Ù…¨ô¬ÞStµùņp€°Îöi†¦Î2ž È!a­§bucÎõÍ!h±—VÍÚú¥ùFA Æ¡²»Þ ôCæéú›zkÞŸ+bMÍ"‰[Mj¾~Í7COÑû;í.l!ÈAšØ…CÄ›¶{«)\ÿJ¸ŒñùO\A 2(ˆ ¦ð }/Ä"\ùóœ\r|C/‚Bœ° †`¼¢ïV^\+ ÐoÜÁ!3°Ä/RÌŠV;yû%úùóÀë™ÁA&0¢S}é¦31(ã|""2˜Á6lÞÜF\éù;ò¤ v‡<`Wˆ“®¼wà¼VˆŠïý³–üû†ûž° `Œ‡sΓN¼‹2p¾¿ºBúóÌ î ¹hÞ›¼r6±»‘äÝú ÿf¡Ïoÿýʵ¿Ÿþø÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺ0NÏ£H _HÃÆÎ†8Ì¡wÈÃúð‡@ ¢ÿ—3Ã!ñˆ)"—ÈÄ&:ñzü{¢§HÅ*NñtVÌâ!¡Å.ú‹^ £Á(Æ2r0Š•©Ÿ×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£e‚Fé(Ñ,Ü£ IÈ”¨­:BTȈÈp½…ÆScWh×ÈNI²’²[â@ɤd§-i&åâ†Q") eÉciÊ3u²•–a%,g¹³Â©ë’k1-w™Pz+ch|%/‡©-Yò¤}¼ÓeC”Éfó™”ñ%4§ùAgRóš3’¦_´¹n É›Ø §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:tZŒ|¨DeÍs¢…8%r®ˆnä¢ 韜¹Q‘šôU òèIWÊÒ–ºt)±x©LŸ••Îô¦½BNwÊÓžúô§@ ªP‡JÔ¢&­¢FMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` +5K*VÁ<²¬ Ñ)Z×ÊÖ¶ºõ­p«\_Ò¹Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KXyI˜…Ml…êªX´”€¬ Hp1›F–\ y¬fIP‚84á²y¡, F€Ñ @ŠbAkÎrV œe%X+—Òÿ•öjI° &‹TÚveN¯ìІ¸Ö·oáM`ÚÈ!Øi.rÓÒ6 AÁ%€"±\%û8Hæ/‘È»Øðœ=S¼!z‘”G¡+»A,zµDR漤_ú„øÜ v¸Cî-¡‚ÚO¤P`ž-oä'¨ øßH|ÏÔ.ÄÐÀg™‘]Än±›à€‚ôúÑ©ÿõ"JðOdÓˆRÐÝ‚8!ùæ‡1èÅç´ÿ Ñ/ˆà}5ù¥íÿ ßWzE0Ý'.ðMP ठ§Z á.  èãGú%*´'&yö Ûà$° tã|Ï'J àSöÄÂxу;Â8) ½çHðC,x(}}Q~Q€di‡w႞ákð77ˆ¢”~ÜW xQ(A­1p±‡"O—=˜F˜c2vejS±…”pN¸·×ÿ„ö÷HÈLAIwm±‡Ê‘ejuƒõ.?˜H‡èe~=ÿhyH„ÈR cÓ(H—˜‡!S / ™ãz”ge2²†Q… ¡Ð7™c=(ÈqpV–ˆRBYá/.P€Fحؗ€,“g‹“‘ìãPƒ¡‰G¸‹Ð÷еˆÑQƒv#‰ ˆ¾"HÃz ±}Î’hV‹ªpNòJ+q¾¸ŒE¸-Ú¨3…˜°‰˜’hW¸—XyV¨̘,Äx35gÏÇ‹!ƒ6wxبøOí(ÿx}ð 5è†z‡NðŽÁŠ"Xmð¾‘˘€à–ð âx,Ù1¾¦!’9XÐ÷R{.™"ÿI„.ðY`’¹- 2sX )…ýØ.°\É.ØH2ß ^!’/©)I&xW XŸ” á Q“Ôò”Ø2Yxñ)—††riI †û˜?¹®Gu‘|Ÿµ•\‚v,ó(YMðv€}»˜\!Šˆ’)Ð(Y—¡˜NRs—Æf|Y1—` ØU–`7 F`él6[С™%– ¤ ^~èˆi÷w“­9I™WïèT)IÑm.¹–—O¢ Kv™fVèÖ›8Âù|.Ð2é“NG¢fbY6ÁŒY™n· ™Kÿ2q‘“àb9C QØH j¯‰Ñ)m¹%2 :Ð÷Y%y’4œh’nù‰{;³›‘‡ê‰´C„ÝÒ” á L’eãBž1‘eÆ-íIŸ³# ©èÓ© ÙYy¡)ÜÉ q›Ö( Á&qø#º+‰S’:)Š;z–ù€Ïy‡á=Êv 4òQ£‘³“BÊš})6£.âkú3w@ËY’˜ ±y!g—ÀŸ½‡ŠÖ¨Œ¡‰HZ#/pLš¥S€e¡avdi#f¦’¥Fê]SŠYvzº#SŸEh¨ Z(Ð]ßÿð ζ Éw ( uC2 YêVšÄÉ$sR¤Eñ÷™³)’` I@rP]É%mSj”©%ƒ¨ Á‰œ([ú|Y”U©²ð#º£ a©Ì¶¡J%ú¬}*°žÁ¬á©­±ZG§ñ¦¡¤qW°7*]V¢C²blV¬È¥ù¸–ºªŽ‘h( †'›j[ø­&b}JL*4Ô:аZ¡ ¬ì‰$ØšY@zòã›;"f%xvPl¢ôÈ€ù®ßp ²ú'ú$ùj %‘†ry¬;¡zazQ˜™sP“Òj+ªÍÔ”5ÿ˜kø…2'û:Úºm*A«#€ù‚ù ûö˜©Äéyø—¨zúК±®Gb©+y$c N #q0³1¯xX|ìçhk:X+d;æ)bŠ#=;3q{›!¶JÙP’ég ‘‡¼cxë;% ®6²µ*·Cá{íÓ¶q“Qˆd˸ÙEɰ0“®á‹FX³¥ ui‚¼ˆ}é(œ¨+«VË¡º9©gH#@· “ —ª›º2| )º&Ù(àüF¹_‰¢­Â¹$Ó»Ñ}‚ë5˜‚rà R@„ÇdžSk|:¢ {$Bÿg¯U#Щ¢”¬x„Q¸J¹-B{)9´íÒ]ƒ‹ÌKHX¿<úK%:ë-ú+­1‘ýëÝÒ¯†ë#ò+/î ÷ëvËþâœÌ°+B©ÓÀiK¨()¬eó¿b‹ ü0xk7¬k¯¬ûÁaV"žw:"ßWÂAS”")¹³‹<¬~!]aÁ#R¬}ãÂ.¡º q‰Æ[T üº<¡Ã'±Â±dKöÄ,åÛÐnßà¬/ñù+œeȧQ¢R;„ø—”ói­ jŸ%¾$BÄüâ°‘ðÅ>œg<¼a²KesªI+yÁBaÈÁÄRÿEÅ=ñ¸ðÃh¬ÒZˆÒš6üOiƒKÁé(ƒKÂI¹e,¢+rÉ!É<šÿˆÊTK”1¯=º£-¥M°}VJ*æÍ …¡ÅF…tþåá—ÓAän~Dm¾çÍmÄ~è‡qV!+è†~èˆ9žèоèŒÞèŽþèé’>é”^é–®)z~éš¾éœÞéžþé ê¢>ê¤^êjçåI‡êƒzjP!ù , ­£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨Sç°„ê×°cËžM»¶íÛ¸ºÎÍ»·ïßÀƒ N<&âÈ“+êj¹óçÐgê:@ôëØ³Kl®½»÷ƒÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏu7ÿÿ(à€¶Â@¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶H—.Æ(ãŒ4Öhã8æ¨ãŽ<²UD@)äDiä‘H&©ä’L6éä“PF¹ŒRViå•XfI‘uZvéå—`nÅZ˜d–iæ™3N‡æšl¶éæ†j¾)çœtÖ‰_væ©çž|j8fŸ€ŽxK „B÷g¡ˆbX@¢Œ6ª•ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØÆe¶Üvë-„n.QÛ~Ûè¢æ¦«îºì¶ëî»ðÆ+/AqÌk¯]ƒÞ;ì¸ñKÔ¡#ù«ïÀß« u\ð 7ìðÃG ˜ÂE ,ñÅg¬ñÆwlŇ,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-  þrjWK­õÖYli¹\/œBØ0ÅùQ$'UmÍD^÷_ÛdC·Ë\*°´IÜ<ƒ÷ÞÂêÿ=VÕCYÂTÖ.àÎ÷TÙÐ…nbw,ž˜âFÌß’a.ù®ùn. ÙÍÑ*÷{®ºäš zU­·¶úì´ƒJñíQ^’š†Pûï“ꮚðÀo|‰§{G³ÆSÒ “®´L+cIK ù0!þ™$V÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡Å'8#JÑfMÔ&Ĭ¨F7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgºÃ‹Òô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©¼%T7ƒ¶©v&£VͪV·ÊÕ®zõ«`]2ÃJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®x5VóÊ×¾:*•~•Ë¡P ©ö°÷1%bïbÓÅ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨ÅüR[[°öµ°­lgKÛÚÿêi¶Ím];è–Žíû­¼|+Üâ÷¸ÈEoDzÜîì5¹‰ü‡N ÝꦹÖÊjM‚Ýìz÷»à oܤ+Þòš÷¼èM¯z×»EòĽïDä+ú²÷¾øÍ¯~µCÜýú÷¿±ïO àX0¸=°‚Ìàë‡ÀI°ƒ'Lá [øÂΰ†7\ËqøÃ ±ˆGLâ› >±B¾¡b‰(¡Åy1Œâ€ÛøÆ,qŽwÌã¤n>òO»ëãí>–".@ „Ü‘WÂ41,“§Lå*[ùÊ©±•€å.{ùË`³˜ÇLæ2›ùÌhN³š×Ìæ6»ÙÿAý}³œçLç:ÛùÎ{Ò1ž÷Ìg5ëYZ¶Ó 8VÎ.y+î3™¤\³DÄÑo)´¢m„äI[ÚX¾´‰­ió¶ Ó uNDmZ.w:&¤>µª}jêˆzÕh©ôV[-bNCÄְε®w ÔWóú×À¶°‡ýO\‡ú̾frª‰ÍìŽÒºÙ·"²´2mƒT» ×&H¶²mtÚà~JœÃMîr‡$ÙY6k}‘gÈù3ºÍí]u³ÖØÁÁ7½÷Íï¡»ßq7ÀÞV}ÿÆà8ž7ÁÎV…‹Tà 8YÞŠKüâsMÀ@í]ŽÛâ¹^¨Ë1‡Äâ"gO¹ÊW®£³üåKur”‚ sžÈºæ8'ªÌ¡²óœû<“,HУÓóŸ¯ÊFOmU“Îô¦;ýéPºÔ§Nõª[ýêXϺַÎõ¦½ë`»ØÇNö²›ýìhOûe]îrˆ°ý"owR@!ù ,cAÿH° Áƒ*\Èp ‰†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\™d¥Ë—0cÊœI³¦Í›8sêÜy’ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖ9 væ©çžçáÉ矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Ä¾B±È&«ì²Ì6k$ÎF+mp—LÛhµÖf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ>„óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þÿ+ß|N£Î‚nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ áçþc†8Ì¡wÈÃúð‡@ ¢ÇHÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠUª!·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ kÒ†AòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2˨ Âa0 !ù ,\®ZÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê”&‰¦P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7½-=åôÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýø—§Mþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì +â[Øb ¶¸iþ1T„„Aaºþ¡ Iì/…Ûhá M÷Šð ÿðàéþa‹n‡<üàeÿ|XÞP*$È6>˜Dƒüð\$¢B¢è˜[<…‰ÐF "  àP#È ’„0 À$üG$ B‚&†«†’h㨠Ž) l¡$œQ ¶€‘X6À $DB‘Ø©eqã"á§øÅÅlãÀ ‰; DH ;éF‚@”¹¤„UÖ°”Ö‚$ Ïh‹'6Ä–Œ#Û@H´!$\#µË  *HX‚6,è²E#â<2F‚HÚ87Ò ŽädI°ÅTfR äÔ ËpIS"ÿ°æb‰G$”@…q4!/#ÿÃ-BÒIha&ÃH‚‡$0#¹Þ‘x:››Ü¦ ½iÃ^úã˜M¬£:“ІrÖò•lç·zhËbä&MŒ."L2Þó §t# ·ñ¬ò‡¯Ì¤<ÅEE9V²1ØÄ#=%‰Qè…€ÐDÖž¸¤SϘÍrÍ‘!WmÌJóhP£’à‰qlCŸ"BC–õ˜Úç=IXF7´á$ ˜žU“é#ÔöHH„‘74äþþáMmj£†J-£:K°TsqŠ=Ä NâR’0†)ÅìºPúÓ–0²eHDëX¦¥¦UÝ?:(DI„°±Œ­lgKÛÚÿÚö¶¸Í­nwËÛÞúö·À ®p#CZ¥–p Å@ BZØ ¤ƒ¤+âüèJy&¡¤ŠäåI7©S2š«<œU£î/¬‘ÄSN9'~—þ(nˆ?òÑÎ\M‘° (¥U€=‘xJ@»È­c^°FØÖ0¿€ã!!µ+B<’ÁïimùA<ÞQ†ˆU[S¨àŽ~• ÿ8ðIC,à˜ð¢…ZJ wár×¼æü{W\C^BŒ% f 5|8»Á„kÔnàÙc¸„jdpˆ»øJøŠ˜©\%H¨c"į‘ÈiNÓûÇĸÅKõë kŒbÿ‰ˆýg/Çæ8úsŠDîŽ×¸¿ÞQš®Eç—™š\¿„¹.Š›):ŠPÁ1ö2¡'WhæŠV¤Ã=Y¥W·éL{úÓ µ¨ÕéÓŰ !LJ#!i(Ó­£ãa«^L[¥y6f r݆m2Yד¼a Rë”ÂQÞÌÜ?Â{ÌŸ4­ÆÌ5åjXNY ßX s¸Je:Ûp¥¶«|\ˆÔp“Êœö*»Š grÖfö°5YŒílg{Šè¾1ãr8îöþã߸ƒ%¤ 'XÂ÷Æ÷@ƒmfE‚ÎÿÞÄ2ÌàâVØ„AÂíðr–ZoVça_y)¼  ÿ˜Áfð)\bŠ7 °ˆýøæœ 38ˆ f ƒ‰#¿ÃN÷â8›IšÒ´ä©8AV>ƒ)¼!«u5„ óíyUvàµù.d œ[œç‡ºÃw:”~4!Úàã¶AHöHnQßø·%”¾`å/¸CÂOLJF¾Ú¤wTˈNhRÕŽOæ©«áü‰‰ì|çÛØ;r½¨ÐÁÔÑ…—o¢!ù©E\j‡Ý¼U÷€\ tgHÊWþt>e¾…Q% šÄ„9½8l GÞerÝB ÞN5Cf …)àâعZOßÓ¼UÏKHQ¨fѲ˜5Tñ¸zˆõ&øãà^OÈÿdð‹;ï2pÂÓeAZòòÄ©#M)H7JBe<èIëhkmñ±ïqðL !'÷rð¡|ÌWI|äMš}xaH!Qn„P“†ÇE˜´P·€unZ'Gqww2ðHð v°r+çšpµä ·£óÇIõ‡·PF•B~ç{ÀçL!$87„2ðÿPPø¸|ñ{ÈO„1}¶ƒy¥BR…B@öqÕr¢TCW „ ñ%˜I'˜‚NWWï×v~!{$W!†Rš„TwdCä$x<õCHXC¿`| Q„(„„7Cöv1èuä¶PFÐô&d‘ÿ Bòet  ’@‰ú.ˆP£‡v~tWqã—L'h ?´ñD'fÛ$$€H\õCÛ`HPƒÐHêdG•÷Fc÷J»†Ç7‚~Hlma\¨‡Eε Tø.A‡LÿöWÀ‡!†’§L—Å\4w‰…ÃB®6XÿÆ|^ÇsFhHè`ODƒûFs¼dsÐø‹"ø.@BÊ$tž…bïWNCsó÷JÛ`|Èux„_åˆFDLÈõB2'bE ‰®$q÷ åw3p3`&ÈBtO|dNHôvð¶ ”I‰wR“…FòåB¸4lE·oñ q¤‰ì§5U$mHäa…±9Ëæjjh\í…F …R&äPïF9ÛÐmÚ8g„4X©¤’ÖV9¸æjüEYõøEû£E®ÆX”Ö^ÌÖáÆ\€„`=(l7¦LÓÄ\ÛÀjÄÖ“”†•ÂÈQ ÖUÊ$]š“C6©µkþà³FNPˆ:(U xD‰…8jˆ™˜Š¹˜ŒÙ˜Žù˜™’9™”Y™–y™˜™™š¹™œÙ™žù™ š¢9š¤Yš¦yš¨™šÀÓµ!ù ,Tµ\ÿH° Áƒ*\Ȱá@#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL÷BÓP‚OGmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oóÛ¨îÏ6ÚäÿÈAþA@€<`æl$” IH ä’2HÀmØ‚$° æ>¸ýý¯ ·°…$H°®PÚà-˜„$”@„ @$Ü` D¨ ÿ‘„öp m„˜9Ü¢ ˆ„ÚàCnƒ…" ܉" DTŒÄ 7@Ø¢ý+È?´AA nIà`‹6Üân€ˆæÈÇm Á8È[hA´€·`a$ÀHF’à™¡шC1†L%QÄPy¬båÀF” Ì£)ÿq ¶Á‹|´à5§ IìЀ‰D"ÁÁ¨Žù‹¥-˜x?³r 8e2‹ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒç›Ò(ÏzÚóž^$>¡†ÿ݉2w'ÜgÒÚÐI¤À ·+€@€|—«#BC\à‚¸  ­T@Q¨€·s(ÚÀNÈH “ÚÎqÁí`*–Ä´“)ìJ  QÁ.8醒‚iÁH]‚$ÀôœÝHUP¸àŸ—+èE**¨r# Pð_LT§P+Sx‰& ñÅ^Pß"# MŸohÛ$nHBþL­“þŠÿ§‘ºxä8º[/Âf0óšÏà3pBggˆqO3’à"Z&Hz«‚\b²ÑGºõÍÇþ’Öw0È &>õª[¬Ì6ˆ$L¢¶!Éý«G`ª‚üè1 ´;ØÈ~æ2xAh>ƒ Ð=â.èìÊ ÒHú|\$-&È.¤àQÂwD´25€@þ½t„|¥&à'"©K<âU߯7PŽXÉmq"1'R@Ð&Ã$‰ÒÞéXni ऀ›?@6GiÖ âô¼hcµh7c“¼ìh²Î…A8º­ÄìXÙ ÿÀ÷B .…oØÁ ÔßÄî;Ìȿǥ€ÿ&«H‚ Ó@*‘åOåÛð†b-ýþ%!»ØFÔ»”õX†Y‡µ6 aw.ð ¿`37z§oá%ÿ ¦‡Ä`ýöC0Lr<G˜´5•UQ·õwî'¶p‚)„'ØCÏ7xs'€qMð dEo·‚)X!Ö}PP4\þ~’f!&~f#5U´‡(+¸‚tt‚µDb»ðotG6W€øS ¶` P8’prÝ÷ls‘!„DU\~”Æ@¤†%EQÓV(¶‚'hF)äAŒ”¿Ð„PuG2ø Žôô¶‡Žÿˆ†ÛÐ_0tåGRThWä€ôT‰'aS @ˆ…†'†_$…·ÀHDP… kv7s0(8§… (p€¤¨B( ‡uA‡ 6zñA!D^ D"¶8ÆxQ‡j‚ƒ}…{èôZyq0‰h^dEÀÈgŒ$h!E@8K‘A¤E¤† ä}VÁRÚe(ýK¤’° h{WHwZh^f·?)Glzr‘ACö{Á&_@Oµ‘ST5ôiåfgƒ’|ôq´T7’/0ƒõBgý•fw¡†~ù“?qtEµHk¨`ƒÿ†ŽS! e ²F(LK Ûp·…y3÷Š77´x_“Ÿ§CX$Ø’â×`¤`Â("tH8V"Õ °QPŒ:Ù&cÅcûèß@{ÜhwSŽ3`’Zµ}Sˆ}-Ñtq4=QtÐL(ÍÇs¾ÔH›àt3§…FjOhTñ{g[¹X%0ƒ«FÉ'êÆ•Hö–0ÝhˆU7ƒ¡B ÉJýs]AVeµeMpa6q ”LÇsš©C¿° 8‹‘)E/Éet@ÿ~ÁÑŒ1!– –›`;÷'1–oT ÿ4 R šU'wYk8L,t]¯Çľ¹5W%(»·v™ÔH¶€i›° Sp3`”›p Û€oüc|VD†è•¼y ñ t²w±†4CŒùbûð?û#D)ÿ—Iˆ¶*'R¦ƒšwänÔ€$›¶ðIµ™jò ¿€pIB¡a¡PTH¨ŸcúD¾ˆ# &‘5r°Z’¢Ae( l©Ÿ4_æµE½˜>&¥™9a9–m `!§Z÷奫¡¦_ ¦f$¦ŒÄwç•=89–’QK¤VæUDlª8?¨û¥B;$ 0ô§±ÑO×"¨Œºš–·qL'Ú,ê£2LÇÔQúx=W[_@H—ÐhŽ:.d þ µa ÑFk1‚¨°‘lqY&U’žè£ /NPR»™˜¯Á«ý2Ÿ­Q¢û©¹1ª¦£·Ã£œº¬Í"¬ÌŠ4SlÆÊ9÷XoõªÏš­Úº­ÜÚ­Þú­à®¹£Vg;D²S§³£†âÚ®îú®ð¯òŠ/´öZeV¶Ó¤ºjP±#QóÊ3Äú:}Uv¸¬­!ù ,òYÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØó‘@öÙÐ €Ùh·&EnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·?ÛîÇ/ÿü)•D‘$ÑF ÁÏ~’hƒ"1À$€ñãŸýx¿üùÏåC‚$l¡ƒIPÛ’à[x!AІHð‚ç $0šƒ,Ô J Àý $DB lB °…%8 ÿ膮4 ph¶L0mÈ`ûèB‚$Áƒ‘ˆ“D” úã؇@Þ nhCã7Fµ• ’€cþŒH¿:ZÐŽxÌ£C¢¶=úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IIÇýc m¨¤Åü¡ÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉKæüã—Àü‡6âHLmlã’Œá¤B”)dF„™/ æ@³šCBG?~cÿÍp޳œûÕfD@…tÁœ÷Ü7DÊ|V R €DÏ~Dt £gf@ùC¡ÄÀ-&›fò SP½t–ISišyðÉô…é?Sé3Ó™WvË£]õéå¤ÕvåÌ6Œ‰M£JÚ¨mu<Ë\Õ{"ùš†Ø‰]}ú›3ÿèkRµJR( ¬r¼Ôµø±Å‚\in{æ¼ l=m]ÔŸz± Eåõ€o‘Óœæ÷(ÅìÄ®ë€B´Þ•©p—Õ SõÂïeèþ´aÀü6ÆÅ•Mñ­Ïêv:2´Nìa»YÚ S§ m«‰‚Tq:µ —ÝödÒ䇶Ú3lÿ¥+[ñúì‘–@ã)8m3ø^mSÌ¢J~õ[CSaj_²¹—tê“ýì„™},~+†óù"D™Ø¥êf.™ò•&vÒxµ?$¾Îf*ѯA—1Ã& ‚VzØý2g*<ñŠs›öŒ1ÌÕŠÔ’ŒQ|v~°rû îüûfªŽ[Lÿ2ÆàDl³éúu[€ññ8%kÄl-x·uìùV¬Ztqâ4‰mni;¿Tœ3Åò–Ø6 ;vábž2)€¿WŠÌ‰Ž”æBß,¸Iðna á ¿|•)ÿzddÖÁ^ßæ÷XùÛóñß_üË@f·ˆ?¡š}¬W6©ÖØÿ¬ã Ncnzѱ»>ú×Ïþö»ÿýðŸPâO …¿sê¿Ô>.”ÿ‘¼ùS¥v$jWVbÿÇ>Îô Ûp – R` —p€¡Ò'²]ÿð »p11w° È)8$¿trÀ1ñð¨>x ‚ 8‚áS‚R@*(/0*ø3Ѐ@B„VQH‚¸20R‚‘‚gLò –@ƒ a…/ ƒäóŸO 20Û€ƒ;B†GágLrLw°ƒñƒ>x/p—ð$÷§†f&F5!s¸=²Ð`VøBè–0€Ös Þ$uñ|ÿ(†=Ø?3ˆ C„(Ö’÷€&_‰bTlD –`„Až¡h—òw ‡‘ß Šz‘|Dó N`uV=û×Níô và%MPu(¾Vƒ±‹à£RW0ŠôChÖ‡MX‹ð À‡$´ø'³¸†‚ßÐn@$h*÷dN0ŠÓ(qЇLŠ—ò ¿pZ8Wp»pRq‡–b‹SâƒÒ‹AGΘ ¹ Ù™8Åø9(*efˆ2°8ð˜é1Ö¸ÈG™G#Y9‘(™’*¹’,Ù’.ù’삈09“4Y“6y“8"™“:¹“<Ù“>ù“@”B9”DY”F(t”JÉ0åh;!ù ,kÿH° Áƒ*\Ȱ¡Ã‡#’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í“nêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ›0Î8÷\ÙD>-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûÄ !@m ´ß$¸!P’´!<ßIoK!QÂ@mè¾wï·ô.8 $$áFñÒû.@-w¸a½A’ì€@H¬OöD‚¼-1/ ù{ð%ü8ésC÷ú6ñ ÀŒžûô>ë%ámHÂùæ[˜Oþ ÜoÇÁzðƒ ¡GHšð„(L¡ WȺð…0ŒáI¶ñ¼†ðÇ@lèć6Ä¡ÿiD1lýð§@>$È?¦h?Ø¢Iè¡¶‰$¡mÀa×n[øcZÜÅúà ¤ŸnaAÝ q‹ÚˆŸ×þ¡ 0no6œâ?JŃoyéÀ¯¨(N‘†úã%‰ Dllãu×D9NQH¤"ÿQÉ%æ‘a:| ·‘ÇDÚ°‘˜"A¶‘(Þ¢–£üÇò9J5 $‘ Ó$U2I+à˜ÇLß'“HA R€Âì! BHQ„•¿Äå*YÄl£ Ïóš{Æ-F ¼¤ óh Fm Ÿ6܉âðk§4â%…×ÿ†sŠQÞ´ç‰~¦OÛ“„6þ)Ç1TŸc4¥ØÐŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦#tN%&Æ[@øÆ@„ª7¡~ãNhAà‚|îíº°„..á„ÀN !Që&G¸à«_u€R™êT½9À pÁYUP€8aÙû"×±m >ÀW[pVŒ¬2xA.‘·³Ö)(Vë‚MÐ-¯^ë^—*Y¿6œoÛª ÏšÖµ¶Õ u «¶tõ)ê7\ð¾~5±LmX[@X¹ÿÉ¡ hƒäpØ´²«iMkcçÖ„`}•ý* @€Èv¯„-BÛ€iƦV (€ZEKÚ¼©õ¸€  +€ëÒ-'p€@Œ;4a­›ØªÚ|ÈË„(¼Ð.X§`‰¤àºïØ–iMæįî#Ah…ÛÖ&PWl™bë;à^}A ۾ʶ¸p%,¶O†R˜êÈY­ªÝÃz¶MêÙ$\ d²LM.ˆELâ°ø HÈ‹A V»¨=ŽZ*Bc3ĵaÝñˆgüPx AFˆ‹EÛ` R$e'Šä¦°4d·&¿QÞïÿÊ ­ Tô¦6ÉL[2B–,='à"’½ï@rBf¬M±wÿ€+f!ÂÙ¯&  –Ûó¦M¸Z$Ð 0 @.qÔ£ZMzŽö»—ÝÂ$ÙòYƒî€ºûîÿX³H*ëuíŠ]j·0¼.Lw]ŽZ(ù½“dèaü奶<¼o¾$P_<O5K8/ò"‘¸^%[yÂK­Æ,;ÏÖo{ž wšKÐNÒK>$¨<Ø/ÅJż#û뉿堻@ ŠÿÑí5ÅÛ?$Éýê×uþ–Ü!mŒä½üí¤ós‡zÓ?"Œè^¨¥6~ñ²dHyº7yçëçaÐí·Û@Z4iŠt0Úg±w|[¶,EÊä„$HIÐUçCi@0T4jç‡~ˆ·{ëçW0è€1áCíäM( ‚FΤƒ²Ä/¥y(‘e w æhÚÅ+±HeôH°„Ii H´”UÇ/4Hmð=”)€{+¡~-†V½ÖWq€}KWÔNÞp쵬[÷Ð;Ø~¬[%±; Ú¢ Ô¢—ýùMx!ŸíVȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ø‡HÄðh£ˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2®ÈfL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNz2Aþû¤(GIÊRšò”¨L¥*WÉÊVº26Æ#Ü6'‹WÚò–mÙ.M‰‚]úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<Ç8Ë«!ù ,ÕÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXgÝ4Zw­ZpíõØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡z$IT?Q$@‚¶$ABL$} ëGrK-% !=ñ'áF$ìsŸ"¿éµ! þW>ç‘€ID ‚„6H¯ nPHç†6ðÏ %hƒŇ< A‚áüä'= „ùC!ôlA þ»¡ôÈ7‘HHƒÑû`é’ІDÂŒý^ØBöIp‰æ[ $Ê¿ìé„XdÞ³ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉ@ú£’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌfì¦3§IÍ1¡šØÌ¦6·ÉÍnzó›à §8ÇIÎr&GÝ»Æl!ù ,ÕÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕN’€õÖ® €Ö\‡}äDb—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïýÙ`/~ö$” @Hh $Dâ†\ŸDnD"‰-Ô{-mH"€û¶DôG½Z|­µpCJ€óA/~ÿK‚¼ÆÀ¯Í€Ï‹„"‰ôEO<ˆ£BNï},H "A½$ „žþ"a¾ ²Ok,”^úÒ׿¦o„Ó+Ÿ-õ8?¸0zH¸ßÿÐì• m(Aù´×D„¯zW÷0¨Å.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:~ÇvÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜¬É?2ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZó2›¼¦6Á•M|Ã{xܦ8ÇIÎršóœèL§:×ÉÎvºóð´¤ P!ù , µ£ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«NJb!ˆÕ°cËžM»¶íÛ¸sO% »·ïßÀƒ N¼8ÎÖÆ“+_NÕ‘Ü6Ì£KŸÎùRÞ¨kßÎÝb«îàËÿ'í|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ¹¼ý'à€hàwYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹•ãŒ4Öhã8æ¨ãŽ<öè£`Dü(äDiä‘H&©ä’L6éä“PF)å”XeGå•Xf©å–!YÉå—`†)fY¯iæ™h¦ùã‚j¶éæ›p–ÈfœtÖiç6‚çž|ö駉sþ)¨‰Û jhw+ªhˆ2.êè£~y 餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«­’’nëí·ànØ-WãB¸šˆîºì¶ëî»ðÆ+ï¼ô‚$G½øòeK¾Ì–«V  ùËïÀ¬Ð¾KɘèT ìðÃG,ñÄûÔðQeV¬ñÆwìñÇ ¿pÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTª®ÀÇÕ–qÕ\w}’º bíuÁ ŒmÓÈIr’uï%öyo›Þ&s¹À’&rwÞ|ÿ»÷V ¶õGhøAƒ÷ –6t5šØŠ?v±Sº4t8Jt{uyäœwÞV¹ŽkÔšº`'”x“¥{®úêlŽWáP¹.@ê¬×nû§æ~ìk”Ýä·o)ð¶/üñÈÓ(;u¼µüRÍ'/ýôÔWo½­Ñ_¯ýö´eÏý÷¹¨÷̃oþù觯>‘äÝú ÿf¡Ïoÿýʵ¿Ÿþø÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺ0NÏ£H _HÃÆÎ†8Ì¡wÈÃúð‡@ ¢ÿ—3Ã!ñˆ)"—ÈÄ&:ñzü{¢§HÅ*NñtVÌâ!¡Å.ú‹^ £Á(Æ2r0Š•©Ÿ×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£e‚Fé(Ñ,Ü£ IÈ”¨­:BTȈÈp½…ÆScWh×ÈNI²’²[â@ɤd§-i&åâ†Q") eÉciÊ3u²•–a%,g¹³Â©ë’k1-w™Pz+ch|%/‡©-Yò¤}¼ÓeC”Éfó™”ñ%4§ùAgRóš3’¦_´¹n É›Ø §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡(I¬)ÑŠÒ œ>1¦E7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓ!R´¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©Pe!F£ ˜GRµ3H¸ªV·ÊÕ®zõ«` ëÃ4*Ö²šõ¬hM«Z×ÊÖ¶ºõ­p«\çª/ “®xÍ+¬J0U½~$¸#ýÚ•¸ñõ°$(Aš@X»– d Eä®Kb+IJÀ™}Ké${µ$Ø€ íZæÄÙ Àm(ÀfUËÞÿ@“ˆâ€ÜÒÖ,m$ÑZÈ!·_[Û8à¶5M¨„º"ËܶT"ˆnAf[ݵ àº–H &Ù¾v)²@%p»ÜÍâò¼`±ís% Øòú¾iq/wñ«–ÞR·5då/ô —øÀÉ10‚Ìà;øÁް„'Lá [øÂΰ†!Ü g屈-üS¥Ä%@ŠâƒøC~&ޱŒéãߥÅ6îI-*â°¬W¨Hâ=óæ˜!‘Ȳä!{æ½'ýÇ’U<C¤”fc\¼¦|ä.Ó…Ë\v²—Ç<¶‡ÅÌÛ2™Ûiå›txÿÍp^ šã\”7—ätγž÷Ìçù‰¹Ï€´ MèBúšbNôE}èF;úÑn—#MéJwæÏ9܆³b0o¤Í–µ¨Ûâiƒ Ϧ)ÂèQ£R Hô¨‹j‚hy Yu°7Ý•0Ï%©VòAdbÿ¾Æ>öCV]f7)Ù"´ª²§½®}ìÚiJ1¶¸âZÄÛ‡J.µ9‚gŽñšgÎ.Xºwf7†¤`ÜQÀC¾ïz …Þö&I Òî|—ĸ¿="ʇDÞ(›@<í‚3dßxP>KHüâ6é·ÚýŒ{|(ÿ¸E(oc‹Ï!ÿ¹Æ²íQïâ $À»à‘«Ù"÷ø½ "n(ÀÝšt® Ýr¸àÝ+yÌr÷jǰ±2¸Òíl{êGêyB.š+dÎûrV~²'ôÜ£ùqÎ2óŒì|ƒ?ú²‰´b¹oÐív*úA¼>A±#ðHI2|ïD¬SiÒRÁ×m¤C¼pMWß èxª3~L\§¹@ônó ñáY{‘äŽeX!›WéCý[Xɶ°;AÚþ‘Ïú¶å"^æ+âûq~!¡9D[vxv"±×ê‘æ Ü”#~'`竌&| àåa>ÿBBïõÙ+¿ù¡¸Æ£è[› ·›¸y¯ä³_ÔÁŽÈð@qóï_Ô’çÉ7ÇW1€†E} áâ·wQ9Ð"eX,£{0á}XØ:óøâø"Ø%X|ò"m a~Hø÷g,#8ƒ42û²€ƒ7ë—(ƒ3ˆ5h2:E(˜,#èAH2÷‚F§ÓWª÷&Rv‚UÇdXˆ‚ð’„Á‚ã·ƒÎÂáBó€a Ay²B†á†N6¨ûVb*h…ÈrL˜‡ì&û×nP(VÆ…RB‚ÈXX2`H^ˆÐÿ±bU¨&|¸“Ø3hˆÃe(pH¸m›1èdW6„‡YB†‘(u(humR‰*6„{(e+Óáñv¡‚ºÔ…rIÞ†„Ø#nØbø ȘŒÈx…SjÌ8Œ7£u³ôÖ¨x÷ÕYÓHu q‡PR‰x ràã(r  Û@‹LvˆQ#y×7ˆi`Û÷lì‹Èx!qÈHe,wãGØ1Ç{Ïw¨p áfWS‡ßðÛ` 3 i3pr0‘ëd’a²t8ÃW’#1d÷näc7s&hŒRö W ‘±ÿ8ˆÜ§déõH$ÒÈ€ÁpÁê’\ôÇò¦/&y8“¶€“ ñS0 É‹SSn{á\PÉŽRö S/ð’ )Ÿ ŽBØ“C”7q|lÈÙo¼GA}ýÖz\B†RvR0ñ20‘3À0›Pj±—‘ŠH‚’ 1|f—wüVRG:È‚³G72² ÁÈ•Jr ¸g ¦)¨¹gYh©–{ aš¸—šx!’W²ˆ¸ºÉ°ƒp¦èv³\R€%§yœªi / ˜Ñqp˜àšSPœÉ™}qœ§Ù2é‡Û˜xÃ!o7ÿ7ÎÈ$û‚œ²9T)ðÙáši9²‰g†SX1½‰¡hÌ·q‰ !™9rH¶ §©6é™Ð9;Ò)ªšA Š{¦'Kæ8R|Îi”)s¼Ùl'Wk°VŒEIùÉŸ ”q H@šJrš©¹šq‘/à^ŸµÀk´)£€ñ“Y"—Ñ”±Ÿ»is·Ea”bRvJ:·œîI®Y(ïgZ z&Ó™Á шzbú¯'˜$Nú¿¥ÑžÝr¥ ±¥wÁ¤›²v›7ž'A<·v$?6‚¿`qRJ2P¥A§©ö‰yÿ0.êu©#'—Irþ™™Ê½i‚â¤"heI4Z¥%ÆÆŒL3©¡ªÚh1X:K)?È›!˜ÿð w°žTÚPª’  js nù˜ÃÊ2E¨q¢œ‰iz±€kH•Rf pÚž®iš€µW(Ãj§&ê/ÁwÌùïX*0i´:"È­nú wP“°œéh ÿ` ÜZŒ:‘Ê#-§›”ˆàZ™ Ñ›ò·‚ë¸$‰H¬¸ þ` Ú° ÀÆÈ‰'H>3BÊo¡¬ápͪ$¸®µ±µ÷¥J‚œè­s© ¦ §@Úsÿ2©eê&ûŠ„<+±TÆ88f†ýp3÷”Az¢tt]lj€ŠH¤¡ û"¬Kh4ÛY®˜Ú€Ñ|I™§¢ ¡ \Ö¥7²…Äæ³¹°;ã™av5{%f%ãB¶."‹ZšŽ;92ÛxJ!4¸yë0Fk±Çª0;z;¡p„w¦IDw‚‹·ƒë2vÃ&9ëª0x‹[»:x„š¡h¶†è1/ùGº]aZ¤W¸|zûB\Lb·P3©Žk} sbˆ»¢ˆ˜®@•¸q» Q»ñ¶Ñvz— Ìë»CEv'¼è½é_»Æ;K×bó(t«R§ÿ»u1¾aØ­»±W¡8¼q¹3¬^Yî›Y¬  K¡wÞcÞç¼µ*7ìk{û˜ œj—šw¥³ohÈ¿nE¾·ªáÀ3ö¿šš`KÒ;a\ )o—½’ÆKxI¥ ÌSЋÁ±ÁS‘±½'ѱ2ü\ä»”Õ¿0ad\öûR5,8L \S\뇌~,œY›.°t'ì(Ql-Aü“j¿dW¸Ú Wý–Ä8},\’^ì *e|ÆÆ¡ÆÁÆáÆÇQÆÚSĺå"»vyl{\}|zÈ|,È~LÈÔÒnÉ™UÿaÇ qÄô§"ÂÂZësB1ÅL%ÉçGŒ³ÆSÒ “®´L+cIK ù0!þ™$V÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡Å'8#JÑfMÔ&Ĭ¨F7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgºÃ‹Òô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©¼%T7ƒ¶©v&£VͪV·ÊÕ®zõ«`]2ÃJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®x5VóÊ×¾:*•~•Ë¡P ©ö°÷1%bïbÓÅ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨ÅüR[[°öµ°­lgKÛúÿÔ¢¶¸?rK=׎e·¶úo²à´o¸ò.r—ËÜæ:·8¾Kt»³×ç&R¸9Q¬u· ˜ér(«5‰w¿KÞòš÷¼qÃ.z×ËÞöº÷½ð¯ÕKúľÁ¯ô+ßþú÷¿ÎŽrLà3†¿N°‚|_—$úE0ƒ'Lá [XJ¾°†7Ìá{øÃLÉ0ˆG¼YË‘øÄ(N±ŠWÌâ»øÅ0ޱŒgLãÛøÆšUŽâ‚ @Ç>òOÇëãðú¦B®Hâ€QÂÈqH–Ì'§Ê©[©ì€${ÙÆHþ²˜ÇLæ2QÂfN³š×Ìæ6»ùÿÍp޳œçLç:ÛùÎxγž÷Ìç>÷ ÍC£²ŸMèB:­aN2–/<àúРѲ i:S‰®ti3äE[¸Ñy´¦GMj@©÷Ò¥NµªWm'N/–¬~«¨qìé©Ô:Ögí²@në^ïZƺöµ°‡Mìbò:* (¶²wìeÛ̳¾‘§}jÄÚÁ6A´=n ÄÛŽÕ.AÄ=r ÄÜ@·º²nƒ´» ï·µš-PP/ûÞøž ½²oK$Ï–Ê¿=ð|S8ÚAî7Hnð†ÑÞu¸Ä'^^„û˜áÁ8Å7~Êêrüã ר«CNò’;Ö#s¶øŽ nò–ÿÝ)¹ËgNóš_ â6ÏyVQ­ó9Áå=¿é>‚žž;ÅèDO:5‘î¦+vR~zl«*õª[ýêXϺַÎõ®{ýë`»ØÇNö²‹ÐéfO»Ú×Îö¶»ýíp»Üãkoœ;¤îÁ»“!ù ,X kÿH° Áƒ*\Ȱ¡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\©1 Ë—0cÊœI³¦Í›8sêÜÉs$ž@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxj@ž|öég|{þ)è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±~‚€ì²Ì6ëì³Ð~$I´ÔVëÜ%ÖVŠm¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬ó΃AÄóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀¯¤¬@ƒn8>®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8ÌáFüqÂèð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòl"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIJ!ꢄ3 áR˜ÊR®n2heg0ƒÌ`²ô -cIË®Rµ ¦-_0[l–ÈŒeAŒ‰A\Ú’–¶ÄewIËd΀™\¥-·ÌìÁ‡>Ô 5c)…]àáÄ 4oÌ;|œâ„%.g …)øR˜3˜Â/ÐÉÿÏc’óýìg繇]|ãœ=gùÉPt*TƒàthDºÁ†:¡é¬àA’Îw&„ %!<]‰ºŒ’ô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©N÷¦úô§@ ªP‡JÔ¢õ¨HMªR—Ú¶mœÐ©"„ª¤úA8µSåaºž«TÕ V $ÁªìªÊúÕ©z­lmë6´ªAµÆU®[]ë]ÏV Úõ®xÍ \¿ÚV‚ô5‚\õj ´QHB’°Å-ÜZÁ± ¬µ`‹¹jP’@§"ñ$JÓ 1C;ÚiIâ«ÚÀ¦Ed[ÌŒ0ÐV ·Åhà†4Ö¤ª-f$(šÚ´ÆÖÆ<¬`»êÙ –«”eªtá—Nàr0 !ù ,XAÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ–$Ž*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwŒ%åñÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®û|ÚìîûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"1zÿHZ‰¶D41hÿH¢ŸÈ³):QŠ@[â£HÅ*n‹?‹â¹xEŸ‰‘‹dìbζè4ªÑfgtã½8F1ä1³¢ÑèDœi±|l#gf‹BÒ±ÅÎn!€C*òˆZ! CJâgŒ$ÉHE Í}„"{2Èx©‹¥<¢*û²´r•°Œ¥,âYÚò–¸Ì¥.wÉË^úò—À¼P*¶`mÛèÑjéI¢óÚ¸äÐz‡„a⌑@B1¥ 4mü™ÐlñMp"A ÅÌ"8Í)€Zmæ,f:w&‰ÞÁœIq'ÏŠybOv `ž9³g6³Y}æ ›ÚLlI[h 8£¦¢ €à5(ÎÒi‹K–’ðDÊɇÚ"›ÛÐhÎ’)Oj‚l¤8é@’‰NeúLžþhèC‰&ÒŒ mž0J@!ù ,Xý¨ÿH° Áƒ*\È!‰†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øj B¾´† À¾ü,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁz0>ûø GHšð„(L¡ WȺð…0Œ¡ gHCþc`7Œ„Àn( [Ø‚_9ü!¿ÿ¶!€JBB´—?n¡Ü0_Û°Å6œøÄ'ÖëTt¢¬ø."$‹TÜâ¼lá-þÃYã¼nÆ0ª±]U4£ÂEuyQDl#ÝUF”‘aLc»îXE@ÎÑŽ~¤£ÛÈ®mhCHˆµHI6²ËD@$ûXÈB6ò‘Ф$ŨÇA ”¢ì#iGP¢2’x,H‰ÊPnRªì¢+k Ë;¾ “§¬¥-q)/G3 šô¥¼€™L$ ·°•ùI$AÚJ€DmPÓ”Hüa ` o΢>ô¦-"~ó“Ž4¦3ñ˜Kx¹S·ðâ=ñô³Ÿ !ù ,´æ©ÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«nY$¬+i´ëî¼B Dï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀N—?‚nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(Lau¶¡BÖüÃ\/W cÈ-ä…3 ±eÇ!\µº¶¡ $áÿØs˜-°Hø‡?–ÄlQ@t¨D$¤ŠÔr"³E'"ñ‡:´Ö³˜Å#&q‰_¼ÖÙ(€2R1C,"pÃòpŒY£§xF?BkPä£áØEk‰Šuäã6ja m4REŒ¢$€ü£’4$´Ä(Jþ£„§¸H5Ε€- ¨Ä8ŠRZðú"pJ”À—ÞŠÝ@®@ŠK‘V !ù ,XB©ÿH° Áƒ*\Ȱ¡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœ™‘Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆ~‚0LJ<D"—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®{ßþ0ýÏîÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠX,Ûï²Å,zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:Ú±‚ÛøÇ6j‘´ßmi,þX´mhC$!‡æ? ‘ƒìÐ ùGBò‹ü™#-©ÈIj£’–¼dÐ JD>R‘’ì%)Nò•ª¥ Kð»øÑg«,Á6) mH·øY# È[ØBHø‡- ©ÉOþã—ÿ@‚–©G åÑÚ¸…/‰IJtQg‹¼æ?J “‹>ûG#iËCúÖßÜY-ÿˆÍ`Âh[\§!ó!OyÖÒ–Þ¼çÐ)À 8 °Ð¤‘ ¡GƒhV!ù ,XA¨ÿH° Áƒ*\È!†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ–$Ž*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwŒ%åñÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®û|ÚìîûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HE˜ü£ŠX¤Û>²Å,zñ‹` £ÇHÆ2šñŒhìŠ?rÅ4ºQ ßH2G™­Q ¿¸Ãf ƒøñŸèÙ7lá)<`‡<¤ ¤`‰}c |Œd'ÉoÔ‘fß„9DÎàž|ÁäÀF–µ± wð#;I?öÑ•W¨Y_ ƒDzÒ–¶|dy JúR’À´Ä%_v 9pÒ“›œA'™L)hbf—˜‚ XùÊVZ³R¸ÄÌî`HO.ó–à<¤6á2[ÄNø¥:™ÍmS•Çd¦7=)rÒ¬šøTe>Í9ò3K&—áüä nvi“’®œîð².ävHæ7':ƒ) “fr˜Â?$ÐHJa ÞÀYóøüS•w°¤ÎîX‚+JÁ R˜?eVG‡ d½@ °‹oüB¥9¥Î Sl£hDÝéQ‰–Ô,uhIšP£úT¡Q5h;méÿáÔŸ•À;•„6$a‹[xÕ©µ`‹møC¨:Û¨-þ´µ«>»Eï´a ®®7ãª^Ý:×`«lÍþámpÕ¨\í]϶úXœÚâ²@£ìµáÖÇN– \ūτZÏM±FÛ)U!ù ,Xõ¥ÿH° Áƒ*\È!‰†#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ô² B½¨† À½øöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚É>2ÈÁzðƒ ¡GHšð„(Láâþ¡Âê.Œ¡ d‘dq‚ sCuÝb‡ÉñGAôd ± h— ~1xYb NøÆ?ä@#¦‹ŠpÁ7JðÈ ‡îjÂ7ÀE9X‘]—ˆ"ÈØEw±ÐÿX#%Ñ®üãq”#·ño¬ëÚ`¡É(€müñÛ`¡Y‚BªËŽ# )ÄsÙi¤@éHt’…%ÐF#m¡ IØb•4—ÉE[ØBI¤@ iÉOþÔÿ@NéNª‘ÿ %)¹Gø²\€Ü†6  <–²L×* ‰Hm$ò©ô$ í¸Jm¸RÙÔæ4QiHZþq“Šìe¼¸ÉÎurS^œ<æ@!ù ,´æŸÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«nY$¬+i´ëî¼B Dï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀N—?‚nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ôá"ƒÌ \3B[# …<€ /`ˆ ©uB‚Ha ˆa¸dð‹;xk†0üÇ?ðäðqÉàHø…^Ø­>à Á?ìPÄnë2øD;lë‘Á ·ÈÅ!1[^ÌáÉÈE%¾‡Úã?ØüÃs¸â@G$|CÛÈÖ?´!‰ ¤!¶¶± C e¢ö¡-4RHØP‹[ØâÚd¶´ñ$ ²…±E(µõFþöøG  Jn1ò•ªÜ†-QVr«&àHVÿ¸E ‹iLHR·(}‰-C Qˆæ@¨i­kþÃÖ$3«éLgJÒœáòæ9½eMIŽó)!ù , ­¶ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨Sç%±„ê×°cËžM»¶íÛ¸ÈÍ»·ïßÀƒ N\&ëâÈ“+‡êHn›åУKGz|énÓ³kß.±÷ïàÃÿn.¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿×Ýþ(à€h [ÕUwà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶è"O+cK%¼hã8æ¨#i îèã@)$D iä‘Ý‚ä’L6éä“PF)åm3Niå•Xf©åkØméå—`†)æH]Žiæ™h¦I–kpõ¨æ›pÆ)§lnÎiçxæ)bn•©çŸ€*è^ jè¡;¹‚è¢æñ‰“,ŒFjÞ6>A*饌UiW¡˜vÊXž†*ê_~ŽjªiŠžªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»p• ï¼ôÖk¡¼[áKTö¶ `¿,ðÀlðÁ'œ‘ 7¬—-«oZŽz4qÄg¬qA/U£¦P¼ñÈ$—lòÉ(§<“ÈD±©òË0Ç,óÌ4×|VÅ6ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§íã¿ß„³i.«-÷Ü ý‹kÛtGœ@Þ1½ÿ}‘$'U×ñ^x›W8ßÙm2— ,i‚¸Õ‡?.9µ‘kUy`qä7P—”ùä[iC¨‰Íºb,/¥KCŸ¤¸W­Ÿ.ûìeáKºF¬ýkwBŸ_¹;íÀƒû]›75üïÁ'¯ü¬u6Pñ$U‡]êËWß)õ³aoýöܯ8|vÐõýRáwoþù觯þ°å¯ïþû©µÿü|9ªüÑáOÿþü÷ïÿÿ#ÒŸž@kQª€—¹È@âð>l 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡Ø¢ñQĈDL¢™‚Ä%:ñ‰PŒ¢§HÅ*ZñŠXÔL³ÈE.n±‹` £Çx¾’ñŒhL£ÁØ»5ºqŠx£¥ØÆ9Úщu¼£_hÆÈ(p€ ¤ IÈBòˆL¤"ÉÈF:ò‘%é£r¾X;HZò’˜ à2¹#H%œ´s˜º?þ'”¹2%*¹Ôƒ yJÁŽ$OÒ‚U¾Å ¶lRÊ’ ÆP2—p‚%0)óËa³i8û—*×¢½c:"³„—Ë(ÌgZ³]ÅäIûüÖL…t3!ß¼¦8ÍqšÓ…á<§:QTN½´ó"ïR<×IÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGêÐt’ô¤›§N²‰Ò–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ‰&=ªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «X]¨Ò±êe”fÝ ÒÊÖ¶ºõ­p«\çê0–Òõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bk×Å:ö±§Ú%dé¢ ¤“Íl€§Y»”µ³  ­hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚÿÚö¶¸Í­nÇÙÝZe“¾ ®p‡KÜâ—?½=®r;ó宸aiî³èܦH÷7ˬ.ÁD§Ýîz÷»àtÃ2Þíd7¼øô‡N’‹Þöú¥¼îý {I¢¤øÚ÷¾øÍoð¨«ßþú÷¿°€ HþÄÀApD¬`;øÁްx®+á [ø1 ¾°†7ÌáƒPª¾#ap‡GLâ›xN>±ŠWÌâ»øÅQI1ŒgìÚùÒøÆ8αŽwÌãûøÇ@²‡Lä"ùȹu’¢ä% @NŽrUáëdç&R¶H“à‚ZyËüŒDzdü0+ÄË:†2E'å-³9ÿËp>2–ãLç:ÛùÎaT/ž÷Ìç>ûùÏ€´ MèBúЈN´¢Íèþãþx´¤£| [H"’°4w‹ühKÛb’þ‡6n‰[<šÈ¶°E¨W-jIùihNØ?>iV׺ÕAµªYÍkmX™ÆþÄ­y½êHd˜Æ¶Ð±‰ìó]÷ÕÅ2¶­yimPùÆ®^6¯·qí¢½c‘Ð6±⣙™&ÐFV¶ÅêmüZaé®H¬û6KYÒ†4µWmmÚ}» ñFV²Ùêf—æÞ½"ó¿…ìa‹ÛØÜ›3Aœp5K×ǸjŽÓO‡Úáî7ÿ,wïzÛÖÿ8ÑœWWžµ¤G]j¨»'7ç²°:miIdZÚµÊT.‘yó„åÆÒsA”¾ÀœçXâ†FúÅBtà}ÉM ˆÓBr#KÇ[Çï×_rõ¨¼|¸ao´Ú#’vß–Ç]@Û÷µÛíÊ}{NÆŽÞ¹ßýï€ïlØë~Â÷êî3â?`¾ Ízw²ß!2ù8WÞJåHæ²ytþó½AD_ÒÄôššã]ÅÞÖÄõ=Ç^OûØ×~ö¶w×êK²ûEnšñ º<ðG»ûÞ{ò˜dzzŒ/á3dËÎ óGk€ág9òK6|H´oýê.Y«ÿ÷ÇOþ;cÉÜÿHúËÏþ‰z²ýð¿i§/ÿúÛ¿({ãñùýûû4ïÖ3ô÷X€ø,àw€V…zÁ€á€vÇq (+ùW8l•€øʇ¸ èR8#‚ ¤&è]h•‚#ƒ‚,ø‚0ƒ´ Öf nàs¶Ðy@¶ ‘Pðƒ@„Hà¿×cÚ$„J¸„I€#&cÛ€KXHБàm€„ „IP„3æ\øi ! m „ÝvbþAØ%¨ `„çb>øƒ%à… q jøƒHP‚6‡àJw]Hê @(~,–‡ p†ßÀ¶ÿ‡,& @Heßð ŸpW020Vp¿Ðˆaˆ?(f'v @ˆK±± –ðRð3ð3àŠN`¶„^ȇù¥tRIˆñ w0š82 È(›(w  Ø\¿xvöˆ?h‡pR ‹0Ñ/0–Pz@è„–‡+(ßp ÍØÎXoˆˆVÅ‹o± @¨`» ²ø1aŒ°H)ä@8ˆ&Šq8™˜ŒÁþ(3`ßà‹?x†6‡ÉU‰²(‹!‹Nð !‰À8b÷h븉!Ï8ùƒ68ÉF‡2v r`ŒÊØÿñðW0Ö° I·€¹‡{!{”aŽfemzˆ`– 6©“áÁÌh•q„?X ô¨_¤öƒmÐw Z¹“ Á‘V†tæ”À†K)Q‰’a—[ù†waaù‡^X–Ýx“:·â~K• ]ê&vGã‰1^T .™æ”÷ºoç¢-PÙX&âr9è¬Sι`¢Wõzk­×n»¨ ç~å$±y`·_)ï©/üñÈ“˜ºwÆÿ¤8WÍ'/ýôÔWo½ªÑ_¯ýö§eÏý÷]/O§÷Ë‘þù觯þú ’ŸûÀ~e³Ïoÿý½™OŸþø÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺpEâËH _HÃF¥~6Ì¡wÈÊe%> ¢ÿ‡HÄ"‡FL¢2Ã%:ñ‰PŒbõø'Å*ZñŠXb³ÈE¢‹`Ü!ÃHFn±Œh\àƒÄ4ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>.dÈ9£ZéÇBò%‘"q„©r‘Írƒ EöȤ’wZ&cC0¡à’29Îó~Ò„MºE¦,R#É’Æ´1•vÒ$,-óÊYÚRh@Lˆ*‰PÞÒ”¾¬V™F ^þò˜Ãª¥RbÇf„|ÐD¦45ÌiZ³‚Õ¼¦6)”ͺtS"ßÄQ8·IÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'šÏqRô¢Í²(MŒ‰ÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚ´‡½©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT˜Ë©nFmVí G³ÊÕ®zõ«` «XÇÚ,e’õ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷j­òõ¯€…Ô*+—@¡@ U%¬bïƒÊÅÞ%§Ž¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M­jW‹3ù±¶*¶x­lgKÛÚÿÚö¶õ©nw ðÖz±‹oqõß:eÁyŸqé5Üå:÷¹Ðnq‚;êvǯÒ]dqsÒØìz0Öý.P\k’ðŠ÷¼èM¯zç¶Ýõº÷½ð¯|çK_.¶— ÷H~%²_ô·¾°€œæøÀfÌÌà;X¿@.Iú»à[øÂÎ0•$¬á{øÃ ±ˆ™Âá›Ø³˜;±ŠWÌâ»øÅ0ޱŒgLãÛøÆ8αŽ;«€+Ä>@ƒLd¡š7ÈäõM Š\ Ä¥œñ/\â8™!Qfñ”%r7"_ÙLsŽ—,æ2›ùÌh.b…ÓÌæ6»ùÿÍp޳œçLç:ÛùÎxγž÷Ìç>ûùÏ€ôF®,èBúЈ>+™™¼e xЉnH—1˜ØHƒxÍ–Ît€]äFgøÑ!´¦GMêR›úÔ¨¶&§#ËT»µž~5ZÁ,XËÚÕ¶n1­oÍë^ûz“¹vÈ®’€_[§Ãvˆ¨ì4/[KGŽöA¤mjÄÚÁö@´-nG¶»÷@Ä-r ÀÜè>Hº ²î‚´;ÜØJ6AA}ìzÛ»%òNH¾[òìçN$Í–Ê¿Cð{?¸ßDÞ÷Gnð†‘Þ6Á®Ã'NñÎ"<È ïHÆ+ÎñEJ¼ã 9DW-ò’›-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øJÌ Tøàˆ tâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡w¸¤ð< ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹`„Ò?üq [ Ä· ˆDƒ¬QoŒcDÞ˜¶hCÚÈ?þ±;æQƒ{@ò2ÒfDÈ6þÈÆÐQ Û(Hm¡Hd€%©ImÜ¢’cb""ÊÅ´$h£$!œ? ÂF‰I2B$m”P­°í±— ùebn„´1 €&ÒØ¢$ Á&÷xÊðˆ@Œ„)¹É¯Ñ•ÁääaÚPm$!•«äe$àÊ6`ràÜÜ  ^BƒÄ¤ØÙÿÍ…lr”‚±›ùÍH²Ò’|À‘ÙÏm®R õÔ?3 6[Hâ‘ ñ0sNU ž‘D$ÙËGÖ3±J K¸dŸeÈ?bj‚†Ý,æJÁiÌ[Ø3=¥`*‘™.¦£A)OùKž*ô¤4#&K°¸¯ñÓ! 5¥Bõ˜ÎMFr>ê4ùøS=ò”b+eC€8ÈÄ u …ê¡G;¥pNèÓ—F•i`cÓT ÈÔ¦-H°×SÞ“>íe‘€H’†Ò“2u&cÞ*2Óš¨|ì?N©@Ö3‘ŒT¦@$áQ°1 ym?!£ÊHÿζ!}<[BÛºUø£‘ŠyckgG<šµÆíà ¹J4bT„à £t§KÝêZ÷ºØÍ®v·ËÝîz÷»à ¯À& ‘:óþ h)P}"W¡Ñ•ào͘ރ RŸ£‰oEôKJ¡W½)#€K#Zq^’«’x&€)ùI$ÁD3ä€ BÉ ƒF%XåLu Ƀ<ö¦²Ü¥,- KÌ2hÛxfoR-þrf¨fRÌlÎ2’¨l-%wŒÌÎÞµT¦Î0ka x4þ@"kÒàR~m£g’Þ¹ÞUõtç\éé³^™ )þ²f¾zÚֺī˜Ôk?ÛøsFRÿ¥ŸÄãmsÒLá¿ I0lE#OÖ‚yžlÆä6H„øÊs¨Urˆñ4ÖŠ9¤{M™ âU º©­Uå \rbm0vÎ6»³‹™`ÞŽ¦Ïª§ÒýîxÏ»Þ÷Î÷¾ûýàOøÂþðˆO¼âÏøÆ;þñ¼ä'OùÊ[þò˜÷¥3ÏùÎ{þó ½Î_N@äJ ånBtÍún#o©ì€.“õ¸×õ1<ûÞÏ> íͽðõÙòöm–³/AÜÐ柳÷I(í«ÌjÜS¿øé‹¤ÛRàƒZÈ”ÿ¨WŸûüù#ü²lÃÈá« DËò¯ÁÄ=þb_ÎÌêúø-]øZåO¿Ø#Z•ÏÅ öÖׇ}á~ @SäGq*%K/µ+×>¬$K Xß° {030Rp{° ßð >&K¢Æ—¤{ï3héÇß0RàÐRðR ß`Ië$KÒW~\_øƒäƒ|VÂõ {02ÐJØ„KØ–ð {„|…–{õµbÔçHeAz0SO<¨ß` 303x†3€†3è—°G8K÷y­Ç>á·l„N˜‡K¸‡Mh ßðzE{q˜iAX>ò„J 6‚6Ø3Ȉ3ÿ0iÈ„k(…‡ÈNƒx{*x|¤zV–ÔG}ôI7³ƒx‡sð„zÈ„¨( W°P²äÓg…ÕÆj˜1S‘LyTWæ$…ö-5ˆ63gq± 5‰j‰/ ŒðS° &ˆ—ˆ‰HdU)FEhL*ÅXîäLUp×D3-ÅpIØ|¸Žz8~˜d²4ˆµXˆHì¤P*L{äWòÔ[úäf×ø1`XS2øˆ‘‰‰(/ N` ,ˆO&sìae‘ë xs±/µG´F‰¤dØHÚ#QÈpêÈ„5ÈŽ¬Ø!wp~²ÿôLìUFˆÄ“$铦ö"ùRé…¿h.h¯$572·Pá(–àŽRùŒÊ8¿pˈ†0N° ÛpxÄ^dÙkgT–”!’xµUeL•V¦rM2í—~ ·Ž°Grð29!—P—?†FeÙ“$Ù“dŒ‰±G„fVY°ˆm1ózéç…ex†2p|¿`3¨Lèy –9OiQ PɉŽq’~eV#™‚±ÉH$ð*Ù1P¹z° S°‡yùJ .ÀŽ „Îô‡zõQµf}™Ve•AM÷¸a~†‰.eVH>4}3ó€¥xȈ†@D{ÿ¹Œ¢)Ö¦aq™ôXƒVÅøxM˜d’õo™3‡¸8Ïõ s Ž¿)K±—ìøSÕJ$|ê9—†QHÜ}n(ŸŒ)‹@ÔQ÷3Á˜ˆß ™¹$žžy•/ð xˆš”ž)¸žõ¨Pþp[µ5cu3ȧ˜a N °Fù'r0£Mh ß^Hº—…\X¡æˆÝ‰ð —ð2°¡ï7ž3ð{ð‡°hŸš ·I=`x !£šÖRê¨EV#V~Ã5‡Ù~H‚—¤»°KKùW$ø ¿ÀUÖ¶Rhê–fe¢ž±~5ó†³5\8¶pŒ% ·ÐröF[|ÿ¨^ºæ…äpð—ÛIHP\+%Žýp•Öz+G¤é³¥vØ…–T ÅR’ Û@G8(Z¡yÊ>;èm±’äû€HždF“ºZ-%¡WjØ?Èçd„I•¤ªE eIÕ}(ª{º§¶(?øg‚a«¶Q{´ª³&K6¬'9®@¨ ã3‘´·~þp hTI¼®(ö–`š³5[dÔLÐz`v¬÷3«h Ï•¢¶ÐcÂXd´È?ï*{„Öm Ë}²—¢%(È?Ää{ëRÁg± º?}äèç{% nÔ*¯”b"…zàæ[zZ®×'z2{*~:#!ù ,è¥ÿH° Áƒ*\Ȱ¡Ã‡# ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§Pk’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möX 4ÕÙl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè§­­~ù½/Bñ @BnHÒF¹ÿ}¶Ð_Ú` [دÞKAÈ?‚°þóßö"Ñ@‚À ‘øž¢@ $Пø ‰ z°$Œ„öç=P¶hA@X‚ЄÛa$nqB Pµ°ÿ¹G‚ „þCÂøA.P†ä{ ¦(’pC¶( !’/m@ "ÑEýýp~èÛ ×ÈÆ6 ŒnŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ · íòAä@ )€ ‘ŒÌž6¶X‚6ðP“LB%yèÈmØbŠŠ¼ž?¸ m´¡ …LJ9ÀD `‹ÌÞ-` GÚ¢Úxeþ±   —*Œeö¨Hðð°LB. ¿mD¢¡TØ2“óm@p*5À3™‰7 †·Pd4«çH^úÃHàajùIL%ˆg<pIë9²‘½L‚?¶ÿB^J⇹ԆHI{JB…P€?ÜÐÍýeÐåÌà8«§ƒJB┄$Ü`‹C–ÓFäñ&š‚Šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ j•ü!Ô¢õ¨HMªR—ÊÔ¦z‰¨‚üù¤*9Pµ )ÀI¥ú6¤€hB$IŠ=¢î⬛؄ ²Š>8AMP P‚|s=ß]²W§úõ¯€ ¬`KØÂö°ˆM¬bËØ9™ô|ß„vqÕóí¢ LAÞç„Æzö³  ­hGKÚÒš–ug4HÁǾӞɀh”,mú ¨ÿ®ö XcgÇ„"г  €òj>% À €àÚæ:÷¹Ð®t§ëW°q ßøÅ7¶;]om.ˆëfËG\êNn®å5ïð€+@ ÀM€ \° º:$Ó nAê*(a|·%Hz¢í1—|õSïäø{>8^Ä R%-¼¡¾ù¢ .xü‚k]3Nês0ìá§ì—@A8ÑÇ_'l¶ »m­ø²:à„Ôh¡œÃû&ZcëMsCR0)¤oq­k¬ÛãÊ€¸Ãl¬,E\¾í¢À ÿøïù¬+KTRY•1úRëFÙž¯I(ø@|]„’ÿ¶ÝkÁ¼›‚[|ƒ¤lõ^“Ñ7Þù±¹ÏÙÇ÷ÐÌ@ŸÏ÷ˆ”É'‡MÐyÞ€3÷6K‘>W~›…ª Ç¿D£ÏªªÜ†¤¹×‚=«oÑæ;ð¦×ìn÷Σޞ[áºêZgl®ø-g¬µa]Ûú×À¶^ýjõ9An@¶ÔGè5BYØÐ޶´§Míj[ûÚØÎ¶¶·Íín{ûÛà·¸ÇMîr›ûܼÚ5º×Ín! Z ïn·¼çMïzÛûÞø.ê-¨Bjäº8E*Ï‚ËsŒ ¸ÂËùêÿØ…%\ …ÌÀð/‚ì°‹DNݽáT:Ùo·u%’‘(~û ܾyÎo^wØ®?:$,<ëzÿGÕUÓW’«ËòzAîdÃ?`·Ï=î/¼WSž/úäi×to&$ó»ò9¯|Üá]ç.)þȽۮïñ|,A6!Ûw^÷·ß¼ÿxïf~fŸú©w½f´õD–“ýìzü¥ÒöÏ3?ùÀd ;üâ[ ªwz©§£§@»$L6–6ŒrŒ$€ñÒthWÛð2p{°{à§áÿ{Mèçk©Á?x—sh×K±L$êÇ-ò´zbö·|6èv!Ï· òD}Qg<ˆe@Ñd P ’UPð{è.Úp ñ´J q r~»ç}›w{†'3 /0µDz0dC]T@e@6dÈLWÁH°×u’µs·K4M} …´†é² µ }5W–0šçvèyœgo×QMg c¸oÿ䈶àˆôDP•„‰{²'–¨PI0t/O¨”wP…Wø S ¨añ…’ÐKw‰64‹´xµ‚Ðu!YËvxǃzˆ.ÎO4§‹a R°|ö rpƒÁy•s OH‹h§v‘„‰`…ÄOæðwê"PN¥¨…3àßPÿ…»—\xx`è ·Cd˜f˜†¦Ñw]w‹‘A…{[´?!¨fìbrÆ7…ƒØß‚ÌèŒã7:ˆHÒ( !pYG‚@ 8z$@R–8Kü£Jî5Dêbw(9ƒßà}ìOu·'`ÿ€\‡~ÿˆSçM2'[H¡Ä‹WÇKg/ØGfDgœç‘ÌÇ…–kíåy—“:™6¤H”Þxu 5Žñƒî± …·Ž)O1y]8‘”uOñäƒéW&UJvõrüBzµ°ÿp oÇ”‡@ÍÈyRp §‹º–‘Õ‡z´!ƒw9/&·’ÀUÿÐv/ip1yx3z ×@X¦tVI;bÙ•IçH—Ðiip‚Y˜÷TM+Øšž6—”'Š ±Ð÷†O‡@\%— •ÿs¯¤r±É‘¸ñ‚ç‚ð‡€WMÿ‚G' –à–° PIòÄNŠ9Û™;[‡”€'jñT@ù º@YÅA!›ãdœ·3š ùrÎÙND¹¸ šæHÒ¸œ?8|¶óxE oD'jŒ8‡’4VÊ)€î韶3Jò4¡ôoÊC‡IV' A› è ¸Cz°ñ6r¢VJŒôoavÆ•h 硸s€ºÉœî×IcˆŸ?'OR˜~U <['ŠÚ×IæTJm`ŸÒw—89< epIP Qþ JTpO—˜.ê;Èôp•ÔÕ‰·…K>X¥Àãpq@K_êžÊãL qIàMgj}ÒC*DFµpI;G€®$Ž™o|ê)dÙÈ !ù ,ò¥ÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀÏN¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ°‚€öÚÎ… €ÚlÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþû>RÿüÉOÿý0H$цm(þJ@7À€’hƒ×7øO)J„$D¢ HpÚ`‹[ü¯ I@ÛG‚$¸!,Hj!@ö•0nøà@H@AILp}$€‘ÐÀÒ0\ÿ“`‹‚tßÿ’`?”@n¢ûJCƒ A¶pC ÛgÁ D´…-0¿ZPý a’°EøЀ#Äß@Ú(Ç:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘œ6"IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËÒýã–¸üAtymhÑD$ĸ ºð2"ÇDÈ1“9fÎ,—ÍÄ¥BÄh ³˜ÔÜÞ-²MƒøCŒ ±…$ü½nD—æˆ$&9bDI|‹/·aN1Þ"ˆ§A|)ÿ[h£˜øügÍüáÌs’s ·¨&C:(O$èïä´&*ƒnC~ Á- "QýMÛ è'*C™T™í´…;² •¶E$˜h¶ €$ÐÙ¢DA[üR½e >è쥮 Ÿ é&Pâ϶”Ð:¼¥DïyËdPˆÄ@ª©ÕfFÒ. ¨3,ŠÑ¬â¤¦Zã)‰\ºõ­·ÔgZªùn“žè,a>Ïb–ô€$hi4ÿ¡¿„Uf µ'5ÛÁÅ‚S‘€+AßJЮºm@ªª‰ÕÌÞò«qH@‘‰FöÅàDKÀN™©õµ°]k>áJÛ¸ÿÂŮɔhf˜Uq®„pÃ?láP[ü«Dü‡$`Ę)¶ŒUëF![[ÚZ¶-Q=¦D‘ÐÍm8Ô´C-H¥\Ôºô–n)ÍÐÊ^j²w—Õ}«\ÕrÑ™ò¹ôÜ¥6zXt›vµ¦X¥ €Ö ¢!¨@ꦾ³Ö†UñJN„ö a p¹ ý}TýGzkvÒs¦´¿½té[p뉞0Ÿóýên ²Ü$L2¦&í:ÓÚ£–¾IhCü–ì.÷£ú“ŸwõÕƒŒ˜¹t=®jkz3Í—™ëDñ@àY—‹u³_Þ§@ _~ ˜ÄV0B[ˆfxÿ.½Hœ‹MÔyÍà¼æfÙ¬½Ú2ė¦Oµ\ËBúЈN´¢ÍèF;úÑŽ´¤'MéJ+ÐÁ&™ ×ñ¥õÌßÄâ` rgïñY¼QNª—IsÌ9$ήvH¬¶Î…LrÕiöÌœs©çï÷§‡«JñyÜéLÈ Ñ¥±U]š¯ ˜×‰¬õ·¿&þ£¤måå-Ù9_€ 6ÙºTq²G³ ô–uñ˜}ZÍj†Ð¥g P\¯«Î‘¹©l'DÁ¡±E‚yæhÓÈ ¢@üá†jN6½gÁ$>nø£ÛÉ5f¦«Õ•Æ›¯ÍÜwÛÉ׋ºÿ„0È vÚøs˜…®ZKÁ•2QX½®@–»ì΀¢I¼åQ›Ïƒ¹ÜœXlïYÝûæÐ@ð Ëmk‡xf&óÈ‘ðe >\;¶­,ÇådÝ:Y‹C–±hwlÓASsk>¢Y-ˆÎLÑ[¶øP !jñ=ñ£­±y³¿ ZΛ2Ôe­ÉÜ×ÕˆC­ ÿÿ/qóÛšk?g¾1Óv²‘¤¡rA|â²³›ý|ÿ˜KG€ù”!ÛüeC4®™§k[—S·s1íûÙWbüy½¡ ö‰Ï>Ÿ³öææ/ÓvÇ[<îbÕª6 Š^ëR«Õè•;\|‚É~ÜþVæÿòis -_û>HPaþæµ4ó NµøÑcâü§EóM€{ÝÿµQP­rv61 % xj^×i–†9÷×€8Xx˜¸Øø ‚"8‚$X‚&x‚(˜‚*¸‚yô ,X9.ø‚28ƒ4Xƒ6xƒ¥Ñ8¸ƒ<؃>øƒ@„B8„DX„Fx„H˜„J¸„LØ„Nø„P…JáRX…Vx…X˜…Z¸…\Ø…^ø…`†b8†dX†fx†h˜†j¸†l؆nø†p=û‡tX‡vx‡x˜‡z¸‡| C¸iì£ ZôsH†dTô€ßc óvˆŽÿˆˆa6>ÚЈHVBÿ£@IÐ\9…WáóUH–D[-usQ@ae=qöû@‰Áukd÷VåFm"dwí‡~ǶÞCYÝÙ‡ž›(‚I!ù ,ñ ÿH° Áƒ*\Ȱ¡Ã‡!ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸]ÈÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd‹LBÙhK€g§íöš½-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûð¸vüôWT%P‚I ÔöûIhƒ$"‘$ ìü@‚þÙ¢ AÝð?öéO€µP A ø>0’à`A¿ûÄ€ñ“„v³›ú„„1!ü (B‚$¡¶paA ˆÀ ¶/‡YÛÿÛ@² ,A$na 7Ô/€’¡JІ*îψìC‚u(€ùÄ‹\ £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚQ‡ÛxÈ?°çh# é£ö8ä1„Ôž? X‚$¨° 9,¢6ùG"A…ÛhC#•Èì¹ ·ÐÆ'oA0Q$ØÆ?öˆJLjCþÀ¤-ÄìpÚÀa)W©Lrtƒ-¹ÊäщÙûÇ'·ÑGHB°\å6R¹Ê’À $a1gùJE&¡ˆø‹D'ùWþrH‚1m±¿m’`˜ƒ&rþxI„Psà )UùÿvF¢˜ÝËc ºY^þòIØ¢@üÉÏí’ƒÿ')Ùv@UN” ¹D‚…¹½X @Lä@œØä¢ÙF$° ÁZÞñxãˆH+2Ó—Úô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PuS1 ùJF„‹<RÓ„lujµ…X Ê<ŠÕ¥è¨?ƺË=²5}Õüè$ Wm<².1ZeZMvµ.]ý+²âÊÄ„ÄÕ(=Ë-ζWº¢p…{]ëÿÔ) ‹y‘C²º x"„³ž=‹ZøÈnÖ™0ìæL§¹?•€„D\¨´ºÿ&–®„ %ZÐém¼V ¨Ì«?9T $èJ’лìãZgµ…$òŠÛUÞ-·À]‰NJs¤d-H#ËÞðRѬ奋`Íõæê¬·°¬a‹)_³¼Ò¥*¥` ú¸JA²v‰L§ ò Ò/‡L/B¾ñ«F÷ºóµîZl¡]‚Px7Ó%°4û—U‚ì& ÛPéÉ6Ú‚-´‹ Vì‚lˆÃ.’`E·¾)æ?pLßÊw•µÈ§†ÿa@[Äu H±ðGb Ï–.Öˆ\ €;!(@¨¬³Bø³ÅürY²{ײ®² JF³‘«™È´0ÿI€p?—™®¸,Ær\pÜaö¶!lŸíûd„’ q&§š£9S4 ²À­2éLÛ·TyÊUVA à„˜º×V å29 Z´P¸´ü“„-âÜ?;3ŠK,ˆ@Åê@æÀ‰¨ÄìZPÊb· {´ByEØJÿ™->&0;GJÈ´0É¿-ÈbúCƒ•K'Ÿ‹iLYÓpÂŒÛ×A“S vÅk^©`™ž4!¢fË%P0ÈoôÚh³[K“Ú_=K"?íKH¢’°„.¦ŒiÀÍ ëXË:Û·.ˆÊPÁŠà„Øá·ÃŒkL,o£ªÿi¼ ¤‚_· ÊR>H•W¬‚Mð¯|/Ï8žÒ‚)·}-@ ¦Æœkß\T@ ðr¤ëÐèw:ý~ž‚'DêQmÖ»Gl]‡Jnr[|‰¤@G¦_Í¿‘„¤{¿¸r\ðˆìéRˆ*=½]8¡€ùC¾\îíÂXÞyF à½]4¡'÷zŒ;  xüy~‡¼àuxøÄK¾Qþ8% ±ÚÐ(=>ò”:¹ÊãÚÙ¾=ImsÁæõM©±Fô b¨pËÕ‡ù^°v½=l:,m±¯R¬­4//J jàŒ¹…Žåtýs+±ÊgÍÿ6h8SRÒ¥IتŽ#‘d@¢øÙ·f‹ÀøŽ´Á˜Å$Üä×OwÖû¯qb+DY! »qhì•NÚ7ZNDIÅä[(fZ×w}FB+7‰M]7õÇ–QSEpb¢[þ@p¡~©Ñ@¾u1M·$HÁÅ^ðXƒ$Hßd€¤cqv! :†‚gO@H>(‚£adlC€A׆€Ñ]|UMÚEaªUMÙ5i‰a ßðƒF&Eh„WÅwª,8[¯õm"•_úÓ^ßEYr¦aƒgŸP¸rðƒ æ&Ò%| ¡jb˜‚x?yDDGa+$N|•IÿP‚TÈO{TUcpµt¡Zø œ¸……Ä&EX‡†´‘O{4ZÚ·„j(}ìç]äTÀ%gjõM]ØN`r` ¹ˆV}ˆ&µ} !ˆ´Ñ@—Ek“@„H{„f|ÅjmP@étÏwkC8$ç§·&X€ ÑYÕˆd¸G[t6õD‹Õ”h2E@Z„?@E%X‹T1’ðMq؈Ãv&Ý÷×÷§Ñ@kÈ?Nè[ޤ h¦N.È…TèGg(V±6`¤¢(""&v Ñ´Ž¡IÐÄNÐÖ€ÉhÖ‡Ìu6ý5v'Ñqb¦&…5„X¸b A“ÿ³(ÈD8©#,)û×½¸—G½HE "ªÆzµféć<¨r'  ]D&Q‘6щ(GY"ñu‚Õ${çö”±píõ‰r¡ J°tM qÑfñ ’ MàM SÉ!²']&¦}hi#û“o‘¡…šÔ“+qswo.Æ`M0n{CH ¤A—'±‡Ę*±bBwiTÆbJ@Zf ‘”2˜j¢˜%à™AHEHx ºh—sUçM {vgÀæ¶–¦Ã™hçm@ƒñ Mç 9t. iàß–eN€š«ãš°)ß w¿é¦ÿ œ¿©—Ø)S€žRp§Ã™HСšFÙœPeUš+–eÞæ‡Ÿ4g§ãš%È‚„ôfozÖb @Ugžs÷r‘qw6í‰PÇãf ›pe‘7eBwZnÑt. x³E—ëyC–`s0± ½)¡ˆœÞF%°b·g¿VG×ì©™£ƒ™l£šõœ¨K‡g3jŸ.àŸú‰xÆØßf¢{Ã{)ÑyQ )aLP7£:º »ùxé%°64Úb.  *ZX:øÆšq¤ Rê yÑ ¢uª¦Y§ 7sÚXø6ø\ˆnA™"± ]ÿš 5z£æYžbzoÀIN}¨hCœ.1RðƒÁ©!B'—(p º€xL7eXƤšŸÕ ¢N š3¨ƒZ6œ()ð —-0‡Zš0£Jº G— ºém“JžhÊb¼ y. ¢6·` ù#Eêi¬ƒx—àYömZeÎ)š¯JÖ9Øù§âJ§ó÷6và㉘%¬ *º0›à$ð˜J£ ú›¿6¦Ëºb>÷kà˜Š\I5sÀŸ$0z(uŸ* »JHÊùß*z+–¤S–õ9«ü™™¶®êZ´ºbsêïú}]¯ýêm,!³ù¬Žÿ€e…BŽ úy+–Œ) wUDQz):êsÊj Û±Y6s®$@t/±­‘°_™$û§kq ¯7e(tåÚ²Q˜1néú§*²uʱe¯óª•%a¥¬n€Ûà %Á‰û³X¹”аyÆyôš5H¸/¡ŸšµÆô??Y»` )àL– ü {•Ýf§®YƸoc·-áÀ*zû J;¦ðrz¤{˜¼é´,æ³u‡6ù2peKèÛ`$ $°w¤üOɘ#ÅP¡ ß Q•”4Èì¦LVÿ Dð©8Ó\Þð(àUí={¦JT½Ñ(ã JÍÔœ|œË8šô36]X Öÿ´J ÕÕÚ“Õh=ÕM°Ò7ƒVŠZr]LZÄfîF`0³–†=W  nÀ‰Sv¿'B5D3 &Œ—Ì¥ úvbÝ1ß Jj°ªábz­cãõÙÚ+&šªQsD&ÙûP×3"% Œto”gÚ©ÍÉ÷W‚®X3œ[-*° -Øê>¾½×ÅôÛï“ÜËM×’Ø.p4kÒ¦± ‘ÿ=Uî¸J+µÄéCÝ´½JƒÍ…ªíMðÕ=ßâcС…SÜêMÞêS„é­Þ|}>ü-߾޳̮átÈvê´É®2FLZ8\þà¿>Çí.Ùž2½†¹¸Ñ²üÍáþ1½&±ª‘Ùà[_(áÎ>) ¬ë3Ë#nã4®â÷Z><ä+>)Nà8®c>>>hfD^äãó«On×Ó³‡St!åñµMÏQ*ŒçS¢;öšÖ¥Å™¬à̓·(-Þe\ÍkÆ>{è¸ÖbëÄÅëƒo@Š©YûK¶€‡æÉsÅslævÞ>õ7À{ÿ¾JnNå×3Çt^΀=Rð Y» [¸è‘Þh+dc´»YG<ÞêÛò¾«ô §Þ=35i¶  ¨z ù ë¶ÓÌW×>N€’ß%ð ¿ãì“H½x MÐé=Ç>ã4»è#bûÇÊg½‹­<”%(UÙês€npCqà=íëÀ#Ÿ\”éêþîðïò>ïô^ïöþ;×gUªhê£RùmŸdIàK^>«ðІ~ÎèÊ“ÑOÏ UdâõKâc€?[’øƒ±„J6×îž;ÏgÐfê‡Jœ×–ðŽ=‰¤ΖdeŒß¥ÿDã—dKæÖóò¦ä Á~óÓCòÚÅóáóé$óÐó\£•d<^Ø ÑYÐV„µN<è”d\ã ŒÝ3Ï^#mE=$OæP~¢öHß<ÕU!}S03ww° ˆUNé„QâDŠ-^ĘQãFŽ=~ì 7ÿLþ+xg†Œ•dòËÎ3Zúvò_›‘’t‚TèРڴ¹%@Áþ&%UêTªU­^ÅšU+UmnFFÚfK’-[gHy`Ó¦ß~ÉIûÀ M'–ÈJÒÆX±d·þ˜`XÚ”5øÏ°`Æ?†Yòãm"Ij»E±Ë•k¼pòÄ?9OX”rÉVæÊ#Ý`Ö¬»†;n¹ç~èZäs§œòq›©ÿ¡€@¦»pÃïz»+Í™  @¸®®U¨°@Ƽ{óÏG_°»$q#¼–g>}ù秫˳¯?ý÷ç¿ÿÿ÷ÍêÊ@Ç!ù ,ç ÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêìH`§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØÃ0Ùd§ÝàDj·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè;@úì;´~û!‘ìO IDâ†$°ýþø% A ’ [H‚nhúðç†*0 `ù Ø7DB‚‰ù&BÀ ¡íaØfŽ‚$á@Ú€Añµ Qàø$‘„ÿ­ï~¸ üØIÐ/|ïÓ ÛÿJ Àš/ µ˜%!I´!€ç‹ `@0é`_˜¾$´á‰ð £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈG7ù£Œÿè£ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊR®ñT£M©”T²ò•°<™+cIËZÚò–˜j.wÉË^úò—Gr0‡IÌbó˜ÈL¦2—ÉÌf:ó™§™¥#·Í¿i£šØÌ¦Ó©ÍÙ"=\즧¨)Îršóœqú&:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BË”‚…:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©Nw™ÿñô§@ ªP‡JÔ¢õ¨HMªR—ŠPn À©LªT§JÕàÜ€ú“„$´ANñià H€XÇJÖD¢«Ü³E ÉêÓ‚ ×Ôž6Ö*VூüàAÐJ½HUôÇ?KØÁnC­0tT£ÖººA…]ì@þ± FP²ÌÛFc€„[– ߘ¬A´B”`°ÏÓìXÛðÁ.VšqÃûN‹ÙãÿÑÕŸµˆ$Þ—Ô.ϯbDn/²[H¢¶ÃÓÆXÏŠZ¾:d‘-ÿ<+äún­Hh-7­ûÔ…ø£ëË.w{g ±’À³ãMˆd•»>È"¯±ŠõíA¾ñOÜá 3˜®p‡_|÷®lÃúz›^Üýƒ½Ø†|»+ÐîÂ/À ¦ HÁ vØ…|¡» ¬OÁÆ“-g‡[_ÜAA±Adpú $•5Ìak‹×Øã"÷Rx@B& á)XB¾ÿ(ï[¼±ºv¾—P±ô[D wï6êJäßÝB¬DØjÈ]ÈAÇN@˜Ã¬ãHAÁÐ5m{ë»Zˆ•ÿÀÁoA"<&Äßpecq[àÚí¬•,}0 Ä¿ °Bœð § 6pãko$™ pÂå ;ʾ}t¤ƒ÷ÕàV¹„–,»àøÇ ”KWžt›ÈM¨ dwxµ œ ‚Kì¶Û¸ƒ…¬kÛö}Ç-ˆSu! 9H¡ºà=ðŒe1Ö¯7ïâ¯í6¾±‹Ðnƒº\}*p9«àÆïëA»`ÛbÜ,pªo}ÞÅX –Hšþî§ÁÃo®¾ôü1úÖ‚œÒô†ÿ*Ü*?ï/ôViÐúÃBDÀVV´tå7<'l5VÑY…µ=¿VZ‘n@~ ˜<‚lú ’P è5äY$XU#vdäT°Å!ù ,ä¡ÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P)’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀáN¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möx 4ÕÙl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè¿¶ë§ïþû‘P I´‘>ò'!I$¥ >ýö³…$PóÙÏ ‘Ø_ ’P@ñ‘I@‚$ì' ~°û†ÓÀ$”Ï  üø?†Ï 4H ½·B‚ Á ôÞpB‚µE¢ß{aæÁF"†áóà ÿ ž/¶("Í—¶$Ø¢ H¨¡ÿÌAøYñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñp¼‘6âHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIK¨ø£–¸Ì¥.wÉË^ª ¾ ¦0‡ILø³˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍj²-Т Þç.nó|ß¼b›>r ùæ ­H€³ è„ß:ÃÏnZóžøÜS8 ’ÿÍ|úóŸ ¨@JЂô M¨Bå´Í~.ô¡èn&¢ÅxJ´nû|ŸÆ×‚‹†m£ȨG«Ò‘šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©ìùT§JÕªZõªXušT°Zìï«s ß6Ü€˜õ¬h- ·w‹²¢uŠqâV«§¼•}õkÓÐ>$as]^`‰ U‚þøGbÿÁXÆvˆ‘DbrKæm# g%AËÙ„´aŠI`¬ó¶áÖ´¶³ ©«ÿJ0Ùä탫¥ÄiE+¹ÿ– ŸM[ hËÕãaÖ¬’P¬ho›ÊJ¬HBk‰³Úµ9nÚÜÀ[âi㬛m¬FÜ€ÜÓ ïµ±+þ ]â2Dªâ muw‹³ÎVæ=He0_\׬Ïïî~›èn$·»]oïî mh÷ ߨÅ® ƒLá wØÄ7¾áßlý¶xÂÝñ¢v®ßØÆäð)¼`˜Á ¤ ‡]P˜Âƒým$ü;·WÀ߸ƒŠgÐ`d^ìk\3G¿ð=×Yý+€oØbŘA”â„Kpv®6«w—e0YÇ n0Ad`hƼ¯‘L»}ØÂÿ¬ê lˆKå) àA±~qeøþöÆö c%¡Á„lCÛco!.éfWÎs³Šò‚LB >žÀ@®ÀX! ·3toþ!‰áàѱpY)ømx0´àj.-×nB uöñ d@aã™ »ž­heM]Qï¦Õã=ôü­hId¼ð}3 fmìj9ÚÈ{àñŽ éJïVb.ˆ%Ð,Õ‡šÍ¸ù‡è¼y­Œ¥Ÿ6`¿” Û _µ§u é&A¶ø@ ,åhZ2ø ð_ûX rС¾Ü à,Î?ßxCÖÝö³³ë-mHß¶ÿ¸E¡¾ãpßYáø¶ N<9\"à)wµYk¡r•G±³®­½I ¯ÐÃè–Ö}½×;LAÒ‘ûäÃKêÛ‚ÜnuÄbóîÞ‚±ï¼Â¯pÒw+Ëìæí­£Nõ¹¤ò»¸2†÷Ô“€ÐÉî= rÎR;éÓú-ÿ­›im“ê0/`€'ü9tœ±F“ýn‹ßðýlX _ïÆ’@ ÔG-¶f± Ìwb/à Wu%n` *Ð.}\õ×0mÛ÷û~³q[e[ŠÖ.ng± ¯§m/Wí×\^æ/` Â6‚óçÄU_åÒ^fErñ — bu–pÿM„iswXø²V`F&<Ò%7Fšàaöß .ð– 1‡hœµ„çÆ·ó[Phañ ¿03pb.€k2 €v5a§õf9˜„bˆ;âå€Ë%Û` r ,6–}­¶ ·Ôg%Mhúñ€ ¤ IÈBòˆL¤"ÉÈFrù‡÷üaP’’ñ$¢ILnR’¥Dy½Ü¢ цlB Á iK CØ" $H‚?@‰‰$ᤌÞ6ÚÐUj’¶ Á6:L7 a™Àä-láÌQŽršIh0¡·ÉQÚB½ŒÄ7·ÁÊH¸ÁÛfJ`Îo ˜¶(A: Ò†_z;£3¿yÿJIÔ³ ݈$"áOv¾ó’x&)Ý Í{>/øæ?ˆ™ÎŠ~SÁ¬h$’Nxê’”õÜ&õvx lT•ï´e$ÿa $”˜ íè;‰y½xJ”¢q'A>¹“Z´}ç0Å=L ¤§úLBIý¹S‚hƒ¡@¥$@YO´á›þ°Å:í(½œ%JÏi¯ @ÇÈS#Ñ‚ªt ’p¤øºP¹Úõ®xÍ«^÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±½0Y*P‚¢4/¢4ªQ-²Y¨mÓ¶ð$%A ?`fU§ghÝÓËä“ÿÐF\å2Û‚ÿ”ôÚÀmB¼*€n“œ¶)]:›Ijsš Ù¥-ÂêT®óN ò[“ÄD@P ˜Ú*ë³u­¤$Ñé–oFbÚ£;Û@‚ܮҵÝ7€2 ˜ê-H°ÇĤ€XÀt/CŽ ß´´  ÔzùìŽR¸…(+­9X Ì•‹C¿A-[H‚¸±$]â:Û$ˆ­2M­‚šßPNv¢ý½‹ ^à8ÃÃ72{,ÐöÒ!Àü±[J*Kû ‘¿ôÅpq3™ÁØ‚ÓÅůÔØ*p ЄºR¹W õîB` —o”ü½èD BbIæÿ”ÀÔ’ÀݽԸH€ \¬å yÀÿø³[†ù䳪r›Ýi.3¹`8'XŒá•K­¬8¡Y~ˆˆéRÆÞNvõíí…M\O”@›Qå#½–/Kk—³)ë|ÀÁ´Œæp¶Y‹D¤¥I@B°‡óK¾ö¬Oï€WÉj³ôòªcDöDÁ*€BR|1¨§*Ä·€ÏnùÆ%Pp‰oà¸ZÇ¥ujYša¶Db‹µmð@êÊ`r²þˆñ^T‚[« ×jínc+æ·Üs¼ /„CùI»´@PA -KJ‚Öð,¸`\]¿Å-@ ¬¬­Ï®¶·£ÿU7‚\`–cë·Úp§8Ó¡ÿ–«Ù‘͹ÎwÎóžû\xÛ8·C*m¾mè¢ („.$¢óýÂ)(@ \~‘~oM(@@u‡\:”ã£z×#r‡¤ ;æ8õ‚Š7åJø#ÀÃ÷u¦„èÞ#‚@ .€±ã#jÿ¹à äit•·ØåÂÛ'[OK½h,•ôN±3j¼‰¿çi£øÓˆ²óñç ¶ÜŹ¦‡ «)yÏÈ'¸Â5¹ä–ÛÔŸþР7$†_dÐÁï nÑú$ŸY­VjîÁ’À%¾Å¹Škà¥o{Õà÷¨!*ô_« ÿÕÔêÿ(Kðæ‰`ùT1*•§;¿[DèBq(ú)4Íêÿú¥W ‰{éÚ[ÔwÑámTN!KEYqµm§‡l—á`g‚NöwTî4Ÿ‘V»GW&ô§6I`uÿ€AK/U«äkÀÛç/SzGZ´Q—žÄF µMH0E 5J<j†PsV8vƒá|¡q@Á[¢&ð7wpå‚´!€›¤`‘ I§I<øb¸T»&I FVj;ôƒI÷ä(€c(Àvár#H,ñ »Aâf w`w` ;&"+˜R PË¥r¬!ƒØ†Â—]%]¾wƒF•K^ÿøº$øE_n‚g¡ r` R`y!/öð‡&!rÀerÐY¶Š»0"+xÀ…²q%ÎuCb%H–8F&y¨vTiµ`jq YGNà~aæÖŒ{ø.qpeÔø§˜N°tb Ø1÷`µƒ¹Hp?$€aQ‚f€d6UòõŠèˆ PrEqÄu!áYæM`„9Qc"ÇuVÆu5¦Z×–0û !1ç„ÜŽQ‘v…)E¬Tl²4N&äa(Dõ¥ ²ä€ËAð ¿° &ùp.`e ç’-Pzf ð—!UxçÿEa/ømÑ‹ó¶I¨„RÉD_ÊW\ôEq'ß Šªè9r-•”¦uN±Âö÷NÈ· ‘†^8§ßà”ÔèPWæ’5–uÓ¨‡æV’¢•_Æ•¤H)59K)Ñè•|iàU)– Ú¨!(¶päD}æq—³!J7X–Ô¨’,É–0)“ we-0J·À"Vx‘@|›¹² „N`e®é—PùšS9˜Ycvà!W[ÇÔ•¨B‡ÔÈrGÁÙ–Z÷›-pÙ»ÐK¶° MÀ—M‡gày›ØCIpTÏq5– 0uÿ1uwæ™ÚãIÀaüM@r1ä‰{g¯éØÉ=Û ’*Pcau±A¿iiiHnÆcnPç `i Qw{äv6Öot=´ ÑèasÂé-yŒ. cÕƒJßàëÙžðYu7ÓEi Àž) :zˆJ¼9ÊœÁ† qg@.yÉ9 l3ÊtP·  ñ¢A-ê&:̸Nq¹º Q'Op¢mŸM`}'t“šáR0N¦!ˆq ǘŸ&¡¤mcu8:Ö0›à$0Z*6*ÊÈ¡uƒ^´´ V©—à;Š ˆÿcxª§z}ºd+Ñ’1© ©`DSz6sà—}·§RÁ„'ʨcj¸d˜rÃ~kÁrsš–×’Q'žr34!¦ q.‡©á‰ Z§eê9‘* $IþøšÚ6ÈG5!}lä`™(° ÛЬÈÄ!„ú–šàkxe ¡¡!Ñ­¿Ã¦;:47eãA¼ /€—P£$’q¬Ú5:Z'dhöö ªÄ®A„±Apz;¼ÊrSðn€)–˜1QiH Þ …ê5æé/*þ:{&!ª¢*Ÿwa­¨t cù8.× A)6ñZËJ£0«,ÿ×n—#’@–Àm‘aª/ážB{93+kBª :øÊ;ûLëô‡Z?_¶¬ Ç•™²Q±Aøª¦¶ÃŸ3ChË5qÙ?Jn[ EH´ÉºíƪNs rày*b»÷sc E|@f$¢„cæÊ4Žê–ú©nOA•²%lT xö–€¦ilS3úCÖ¹„KgH¨“!¦mð ëÛ` %]c©9qc²« §™± —@)° SÐ}úw$ûºO3¼@¡lJd D6&c‡³s B8oå±M!dÙÛ4ºÿ:ÚÊN°Ú0»óäbõÊû´9© p:…§CŸF¿–4Y8ïJ¼K9¡ø¿¡8¬ú‹>Û9R0v0:fZ¢ø¢+»¿>áç;U»Ô9,Wi*vŒ¦MAßÐR}HG-ð ºP’°‡?š–ã{4¸šE 4§¼°µwdÂçc½\K?Á䌨¡J78¤6ó ’ðoÿÆÄŸ‘Nì„Å7Óu{Þð (`_EÜ2N ` ÏHGÚð ¯´Â¢ÓÆKñÆbœ>%0w)xG??Gë9x7‰Œ¹’ô¶éCuˆüEð‹k¬=*° fOwTÉ}¼ÈÑÄ3‘Ë*`‹¾: ¶5CÆa \£G©1Cn R ^L˜:Ĥ ˜ª‡hO™l=.g ÿµ võCÌøgøóŠ¢L?Ð<‚p¤Ì¡G¯.0c Gcç…ytÍǬ=Ô|ÎC ¼aÎx”Î.“Y—NîìJ+“@2y°ºŠ;–¾td»,˰`¸Çag«ÎÖCq ëLÕL2 ÀϾŠ‘PÝ0FEyɹݰ³‡QY52™§¼ q`ÑéT¸’„R¬l1»¦—ð M[cÿ.uƒÎû1Zvk\ÈÀq¬\•1eLz2 JGÈ;ÓÕñ½O 1?:ÈÏAh`d³ »p’»° Î1v'Jµ( Ì’œ0\ì”ÏÙ·`  ·´3ÔËáÖíC®í¸P]0AM?)Њàᥠ!×s Ft×õs}†\Ø¡Ó҆؊½4`‹Ø‹ýØÙ·‘›n@PËU?=E~I¶ÙåøJ‡¶>ç›d ‘dt–>òE_‘ˆ ÅP[ÈFsÆÎÚsŽüuˆXÀ’]ô Ž}=š5‰P=YOÅFH€• Í;ä'DAd¦Ä­Ï4IÉ=ÕX,µD»½Ú(pæU.-Þq'ßÇá«ôkcÿÆF_Žþkuªâ™ÆMBˆVaæh~»àNö6=í‹nysFçÁ´ïDT\þ<(Å“D0åi¾S*^=òF‚t«‹’÷ ±ì\ô]=a%á âà¹üEP `eJ,VóSä̱¶ô¢üë9Ž® Kð¿*2mMÉ]áÖ“êN~ß  ùei~nä]†ÖóÞÕ&ˆñº”V& q…— —’´{(Þ¶cßtêAcã-ð ü%I˜„ï¶nŸÜêïþ9>Uù[˜$KB¤ï¹àôÜa ž©¼øMæÝ›þ=Û@T7ôãz M²4?ž >ì^msöa ?qK¨]Þä['´Ù¹DLÕHÆ/+>–ÔRäÈÙ5/‰´œ>¢¸ Õ”ìôJoZ Ž`Yج>£XÀ!ù ,õ›ÿH° Áƒ*\Ȱ¡Ã‡#$ ±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸/ÈÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möw$œ­¶u»¥½öÛoR÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþû­‚ÿü"ɽôçïý$´á†$mH‚@ð'·Á/ ¶`Ú` [€%p€? ,ç‰ „nˆÄû68 >0$ ý °,Œ„è> P¶hAPX‚6Ð…ëSa$ÿnñB ¤¶"ûH B …DBþ¨A dú@IÀEXP€-Ü„2J"‰úÃßnJ‰30ŒYŒ£BH(Ç:ÚñŽ Ù ÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈBþã|$ˆ?¶¡‚üãþ@È%#)L `ŸH$ JëÙ†€ÿq  ¥È?ȨE `–I(Aˆ¸Im”±œ&·á[€ˆÛ@‚*©`ðÚ˜!(%A[h£Œ¢Œ&+ =NÞr“4ü‡$z(€HØr ÛH‚.ùÊJ"¡ ÿ؆1BIÓz½ €-™ÿF‚†ñå>Y™"` eå nRœ$ØÆ%ÛÐP\S±L¦ÿ!ÐJ‚hf>j‹{6̓¹ä6R¸I7¸íþ“dšHD²ñ’·ˆ¨6€ž …Õc'þ6YRf"0–0½ $DÀIF"ŒÌ´ç9çMv~s˜¯ˆ9ÉJ) ¤‰Éœá7ù¢f¡·”§&Y) 7œ“­n%YAéÌF*Ï›áª]÷Ê×¾úõ¯€ ¬`KØÂö°ˆM¬bËØÆ:ö±¬d'KÙÊÊ ¯ A©e7;8Ìd“¢Dˆó`] "T˜p ]ç-PQ1¶s:tè\ˆ88À.hÁ/"àm©’¡t×ÚO{ÖÕ†›Ü<G˜Nµ.«½®°+'” rn âÝš5SK®%¥jÖ‚ž› Œ6Ъt9-vpÝì .p¨gy&^†¨7 eEHÚ9IÚÞnðiAN[PØq‚Bú›³3D‡þ±6ðªCR“¶%=°? úÞæu!,iK*Q‚\2Å=-cOL@vÞ/46È.~»³Û x ³]`˜‹EYö²Éü°,0V¹ØÁÿ p‚æ ;íÈ é ¤ ]Þ’©ë¼dIÝcjöÊsÉ.›U 㸘i6^Y¸c-€ˆ)nC4(¥*‘.-PR0aˆ¤àÓ8óB6ÙZ­6ÊëÕðRõ¢„Úή^ñJÉáRR _®K ²ÚÔfyÃè+@§uq ]X"ËúÃ.v›p‰;>š³ØÎ¶¶·¯-ãqµ)Ø´ó·‹6h0M¸ã/\‚”ºŽ»pB0ß;zûö“#‚nû;séþ£ ‚ëSöG¸Æ8e%–߃ š0qXî 6Zö;l±H»nAv7lo¡”Å#ÿAyÉ•ƒÝù^÷å.PÁnûýß‚iCÒýµ6 I]ë|üçÒnBÜ]dpå´œ™']8Ážjœ90w¹ ¤®‚¡;¡Ú¹8¸\ÚiŽq‘Pe×]‹CY–e¿)¸D ¼pž$ü"oХ݂ »ÀÀEy¶Ô»Lçz$ÇMüGØe™ã¸À$ §É7Ú0qF_7)¯u'_õ8Áä 1g­‘6PÒ´MžeDøMµ|cN@Á66–oÝ(ÁÜ] t¢Ÿ«’¹ÍH?} â[¶…>ÄʵÂÉohà )€Üaìph½'ßh‚Ôç ùéSÞêX/׿9k°‹=«·¼…ÿm9ü­Ü¢  À„“ŸÙ ´ü*ù†&ÿ‚Pzò ÇnÝ1,…;XÂÿ¬—!z7•TtÁI´%™„Pu d…biñ º   |×Fð×òsy“s•ç*s"ˆyòt¿á@œ‡ èE$WV…j‡yd•,áz'0vxÕ•nîöq-pâ‚{ ñFd„pJˆ6Öð@%°Tͤ•^üuÑ7} qN@uv .Ûgà5@µ5[¶äi Ä\ã¥vð ¿ n»à 4v!nù§vjW-rt.x”{”[â4@äôŒÖxfÔe ›à’ÿgµ†0çv`ƒð²sŸÛ`#h‡ñsBè=®—|yx‡Á…Þ‚‚¡Š”a‰¡YÛ0uЉg¦X].öš4:+«EÊWoÕuЖx̳‰¢6‚(µG·èh.0ßð Ó¨pÂD£¥¨óE{·„Ócn™ôŒ1y €aÝ¥:Æ(®$ à×EЉˆ>Ǧ~q°ŽÍ㊟øŽNŽÐszц#a®Ãq BG'ï(G›à$ðƒ±Œ×s òFoïf9Ï&)ð ¹&Xz+¡ v&r*áW# qP$àõˆrðeÄv,ÿ‘•c.@‰)ñl憓Q!¿ nk3.“¨59fD)Éóg_³ˆ”oc?÷ˆý—K–€/q‹r¨Ø… ’pC:iværÀm×5o s….Q‹;1— ¡—vSkä)‘8ŒUi‹å˜7ƒ¹—nÖÈqœã(„ “ŒÖ‘¡”‰1pd3ކÖ˜*q\¿ãU§ùæ~ Yžd€ÂÓš$!Q^Æ’†s‡Ž@•@vHša —`nÀ :‚WSyíx´'³Ø9v6³„µr×¾y%0jMðe5ø   99FV¡uI¯ú'Zg@z²ðg—ã6‰:ªfFVµªŠª8©Z¬I´ºlŠ{ÃZ8ÅZƒéÔÿð–Iñ â÷QX©@¡ZÜšZ˜¤Z8Šèf|Oø­$+kp§ã thw$Q7ÅOuÿ¤ ‹GZúc£Ó ZvôvªuG{êràuղГ’Q2è²¼sÉiIôóŸTºkïSž$Ç´ì4€î£ÿy“H{=´—µ¶Öãµ£ªWï“’$÷­õÚµÿ «v4vpu« xä"¸GvcÏ6«oÛ>Sè³r°¾G–ª4ƒ·©×ö¸¡©ƒ.`¸²j¶Ó6$ #ûšú±‘¸‡3û…a¾ñl@k¹“²¿á×KõH¨{0û¦˜Âa¸…gGƒ»ÔC¹º;=¹{GkøvÑ¢ôÓxé& ‹Zs{JÀF(Û¼D¼Ydšúóh%ëGé*GÞpAôy0tÿ¤Ù%*ßðT;VLH` ·K?Nð —ª¥¸ésé&wÐU€ê0­êó'³èòÔC©µ0ýoh)«zä(’)p Ö¸0i—‹˨é–Ë ?€i1á*¾áp ê´$\Â&|Â(œÂ*¼Â,ÜÂ1¢R77Fmd œÚ>*ÕAáS,¤£åsI¾äQö½Ý£RÚSL+bµAQÆÃÛ»³4@A<\—¤BPÅŠRšI=%ÈÉÓÈ–Ll¿pW 3pW°]«Ê(LbÚÉNæd»€yR0x)3 ƒvpo¢jOa¬«Ï#T&eIßpɼÌ!Bxl˜DÆÊÉÚ`Äg|Áš/0ejfÆuiÒ3ųÌ_¡*20 lýwƳuPýèdeÊ–´ :ñ3PËP/ tåÏÕ`ï,N=5©¢ô ·\Èü—$O Ëk8§PF¤t,Ñ¿Ì_ß ‹íÑ3ð2ð (ð ]X.ÿÀËfv'=Í&µ"‰ÑÊ,ð?õËôФ<ÒѳT·d 6kÖp r ­‘:/ B½^¿  Ëý¹¶]€ ÉÆcMê5Ôa RÌqÕAMÆ$@ÔÌÚ\[ûôKÍ=FÆÞtÚÕ`Ð.I=…2нT²À[ºJ¬,< ”Lc=jm3€Ìo Åq°õ<ÄP}Ëem úe\,~]×mÕX-òSØ2ý_m µÏ‘ÙÂãÃdìP"YבÑxÕSq ª ‡UNwÉûÜŽ\Ю-ÔÀ\^uIm\EΗlP&uIV€Ù@ý Ý9¥JKåràm¼-ÌøÌÑ,Q›P«ÚìÚàž–bÆ9_ ƒxÝ´â Æ“ÊJFíÑßíz ÌK¥¢ƒz[É=¤yÌÏ ÷WP«ÐÒ3p…. ö„â¶Z„ìÆ~,E€,K·àÞx c@ͦÆO¯ºTñ|=D\Èú›Š™MÏé<¹ì´´IA ½.O ®`Hµs–—RœºÐÔÈtMd\úð=*uÇ[¬YÞeÝÛ°9ÅúÅ‚WBëeZ¢º µàA!N>>|xĽ@!Ôme5,Æ]ÄëåÉÞ³Iþ@K9Üg¹=?²:Z_…sïãWL!ù , µ®ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«NJb!ˆÕ°cËžM»¶íÛ¸sO% »·ïßÀƒ N¼8ÎÖÆ“+_NÕ‘Ü6Ì£KŸÎùRÞ¨kßÎÝb«îàËÿ'í|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ¹¼ý'à€hàwYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹o­äR 0Öhã8æ¨ãŽ<öèã@ FDDiä‘H&©ä’L6éä“PF)å”TV‰UvVf©å–\v–^†)æ˜d–õZ™h¦©æšA.Èæ›pÆ)g‰nÎiçxæY`#zöé矀šXg „š¸M¡ˆv'c¢Œ‚Hc£FꘒVj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Ü2Ii·à†+î†ßrUnQ!ŒËi€ê¶ëî»ðÆ+ï¼ôÖk/HrÜ«/_¶ìëì¹j ÀþlðÁ õ»‹JÕ0ÂG,ñÄWlqOuæÅwìñÇ ‡,ò[lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWm5¢ì|\m_íõ×'±+ªÖ`œ@Ù6•¬‘$'Y§ð^dŸ7Úám2— ,iBwÑsïÿíw²}o¸`]¤öPƒTøß`iC×£‰ÍÁøc7¥KC‰£d·W™Oîùçm ¹F­±+vB‹?y:謷.@çxì¬îúí¸‡:èîÉÞö@ÙUžûð— _›ñÄ'¯|´Sç;QÍ/õüòÔWoýõØã:}öÜwOÛöÞ‡ÿù‚ï¼øè§¯þúìi~AеOì¡òo6zýøç¯Üûûñ¯ÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0œSô(2ÃÚð†³Ã¡wÈÃúð‡@ ¢ÿ‡HÄåÔ°ˆHL"AލÄ&:ñ‰PÌžÿ¢HÅ*ZñŠUL·DHpñ‹@Ô"ÇÈC1’ñŒœbeî‡Æ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈG™¨Q:L4K ûHÈB2%l;$P 3*r\ñS¡ñØØÛ=òS”¼¤lȶ8$X2)ÙùcKZ I¹¸¡”JJBY²Á˜A¢2MŸ|¥e\)ËZöìpìÊäZgË^bD”àÚ˜céËbr‹–÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨DIr͉ZÔ^áô 2/ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓš±¢6Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©Pª 3*UÀD²ªAV·ÊÕ®zõ«` «X#¶Ñ±šõ¬hM«Z×ÊÖ¶ºõ­p«\çJWÝPµ®xõÏ]óÊ×ü€©IHB$’Ð]öµ,d+AüÜ Æ^õ°mYÔJJ@À>*°ƒ…ì\ [œÒ ªT¥fß’7Øâ´l$l$ ;Z°,ˆŒ•„V RYUÿ"µ­õŠŒ*Û†S²ñ¶ lnÏò6Êúö ŒuÃl‡»–6H" n*Ag+Z榥‘xì@N›Yë¢%;‚ ,äJ ÕÂz·-‘ÜÐ%œ—´Iï`—ûÞúΧr8µ¯~÷Ëßþú÷¿°€LàøÀN°‚ÌàëómÖJ";ô[øÂ6g…p¨ ÄÃ&ŠãBLbÝЯÄL1A¶A_EÅ›pX`,¸XD¸•©)²c¯˜Y·¸±esâ!Ùj2K’·“ã#³³Ç7°“§Ì˜%S¹(R6I¯Ìå.{ùËò+2˜ÇLæ2›ùÌhNó8Å,6søÿ"nv³šçLç:Û™@4¾³ž÷Ü9ÇqPNK âaZ4Î3Ÿa•‚E+QÌY”¢MøÙLUš “vtFð&€&|c!Õ=`¤/¨} Æùz^¦Gi+[9Ò­>ˆ«OBêDšJ«>È¡xè]?Ä׉ɵj `!ÂF Ÿ5jˆÝZ0?€•í”lS$ÙöXòÜl‡À¸ÉIâ4AZà…{à~ˆ¶¡”ˆ[Äæa· m/•;ŠÏn’ &òéŠ-» ÿöKÀOÍ%w Ä÷&ÈåÍpž$ëÞRÄ5RVdÞ§Hš@x„Ø Ï¸D©q#\ ÿNÆE¾‘}dßg¹BB.ó’мæiqÉo.žã"b¦9±S^—ÿ|!Œì7%0›¿åG§1plŸG½ ôEžÁ òô«ƒd%V÷zEŽ]VG !OïºØ bF[ü äÈÙRî $æ5÷8BBΛ8¬ýï(a:Úòô~—jàÃÓ¹DÂþð¤x¸ñ€?³?ù†Þ)¶¶.ÿ7¼Ûh¯NQ;Žz ùåþ׿¶®Õö æÛ!¯GË´ÅÓzªp¾F±§âë’ûà¼}"§¼}Ù_rû˜ÊéŽR¨w‘ÿ¾øGùýA<¯²Ù7„úFšûFò%ìc¯÷Q˜ÿ÷Y’^øh» ÷ˆô¯ý§ ÿEófúÔRøÔ;pâñ3åotnhÿ!qwp„6¥×¢'XÈ2§§zqng'zWhr<³e%zd}ÄÃ} Që'†Wh 4~P0H¢÷ ¿Pº¤vµç€o¥BÁ}—°í`!¸ (õæV®t€9ýv6у qEòƒ¶áy”GcûW$ÇFa÷{HhëwsHxD„㱀O¢FX‚(e88Þ@…ƒnØ}Ó#àG7+÷WHOWnÿ×t‘‡p•†¶7EHš—V`è€8Pÿ¶~ °ˆt7n*@t Ç`If‚Qk!ˆ ‘_ç%‰á…,ñn;èeš¨ý¦Jíw€¢˜a©è» í7†qŠˆ‹ru†%‹!xDwpøV}è¢HŠ¡7 ¡v¢‹Ø`F§Šö÷·Ñøž(VÚ5ÎX;Øz ˜ˆÁH¯H[{‚âøTÛxØóWbݨ#ÖŽ­×‚h5/!‰¾¨ˆ/7Ñ(k… 1Œsȧh‹`[Çuv7Á‹"q€ôØixQŽbˆŒ(7£ÃoH‘LÕQ†ÖÑ]Ñm*y‹­§‘%™ï˜4Qÿ¨%Yr`¢Å‰I–ж0§X+ñé¸Tsàp“RQYŒgi`Ýè Èv>$y^’ó(yRéU(e©Úw€.–7V)V™iÿ°aïg­” q—rYI44(&HØb#–“AlsÙW1ù~É$hÁ(ewG5Š™#k¹[È!cuˆØ€Vxs§Œ1šH5¹i7qo™*àµVSHaá…›Yr ¼É1Ì—&ú¸x-1™‘)ÌYU¹Æ™1œ~x„6 !}Ív8…S³™¿ÿiÚ™Xb‹2ð˜&s‡Jòšq…ã á‰) #ÿÀšGuœ6Q™ 9”Tž¶ùUúùŒ&ñ™¹Ö©€ÙsdøITzCø>Çžµ#ŒºIˆ© ñ Ty¸ˆÎÖ€u¹w׉œf $'Wêü)‡2š* A1Ÿ¡žEc¤d„¢¸ Zr(‚!#˜é ¡‹]g ‡Ã£iU¡"ñ¢Q'Ã(¥¡8:0H™^õ”ñœ=‘iX:¤ —Q×lPUBªn(únìr…•yrËr8z!·\lÓ€DU Ñ 3':êT:4‰±÷ÿvšyåžÍ¹Œ Áœ[*‚Zt aI †¡U¥vH©è™<—1x‚uú¢;˜!eM©`—MàsVêóǨK%ŠhÊ-zd—‡Б•» «dø³åa•:Rkˆ zÑ1:(‰„>—§z}ÓXHÉ©*%¦<ˆœ†CÚ÷leªR㊅JŸö¬±Ž.õiR6‹hrà^±ŠaxÇjQ©ú¦" \׬¯Ø•\Š¢ ‘ªïÖƒ*–I6¦­»h¡ñªðVÑø{ÃèqÀ­:u{‡jû¶¬1weÙ¥ Á®_V§)£ÅW®!Õª!¡…aw™ªNQœ2µ±ÿ±°Ù‘2qvµ§®Ge³äïf«.´ìÇSmJ°á¯Øûs‹³k¨Ì•pKüª)u¹µÁµáµ¶!¶A¶a¶,c´.±9ká¶·!·«ù¶v·w;·î⯼)n£ª§`wjËE ƒ»{©ªj²•÷e—'³ï©~Õº#ŠOE,Klk¯±‡±±Éž|ʇ1Ä•ìC.¼Ê¸K²Î’—²<ˮ쳜—ÛP ’ », Úð œBWU~K2ËÛ \ ]ª¼h³| ³ÐÍМ·¹+ËÚ@#Ò H@XŒ%^n’öºÀüéÍÀYÖcµ JXÕûs¸œÒ̰ÛIPćËHÍH“×,PÁœfúÍ‘ ˜y?½vã,ÏÐüÎüa‰tÏ]s² ÑÌÀ˜6Ñí›Ïÿ  Ñ Ëñ§ÍËÜe²\Ð Îȶ'–—ØŒÏtfËÿÿp Ñ,gLÈÝç8ЬÑf&Ë=o5œÐ¯s½j–— ÍL8Ëß° {p30Rpw° ß}ÿp(&mÑ$½Ò¡y–—ß° s ',3ðQ-r@?šgjyéÐÄ,ry¹Ïî\Ȳ¬„qÖh=20›ðÀ§öÅKÑÚá§ì$ËÑN¶\΢EÓÿpú9&NÝ #ërð×¶ ß²l×Ã^œž—þ Ï`.£À.Þàã”Õ¯ƒÙž—ôMj àEðÑLéÞ}WÍË1á¶Ð¾þÿËÙ¾å­íÎ’Ðñ>]Hqý:‘dËÏ é Í*-âÿpÕ%?ðêÍ»¾! œÿ.IPÞß-ÜmÆçŸÍ2­Ið#ÛNä}9n )Ð*¯ûð»‚bRÞfêTׯS]ã¼ úøÒMÝ%ðÜ‘Šî/PÚˆfËvmÔÑ¡œ­|FYÝÖÿð —À×®ß*ài)àÎspöÞÑ<õ|¦à=a²l L÷Øß .ð– ­ Oàà-v!ÿ:†?÷¿°õ3àR€ßL§ÒXÎÚÑœÓ èˆË/S s` »Ðà€FùÚÜç§âQA/£-xÕoÜ÷i×ÚlícvïÑù~m“'ùÚPҮݸ/î ’š~Ë/®ÜìlÐØ-ëfä•\m]ͼ¾ç­<ÿñ?· ƒ•ÍÙŒŽ ø¹[æ’ÀXrÜ!ù , µ®ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«N `!‰Õ°cËžM»¶íÛ¸sO}­»·ïßÀƒ N¼øMÆ“+_^ÕóçУGÎôu騳k·è|»÷ïàGwÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ_.ïþ(à€h!hà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èb\­¹ôß‹4Öhã8æ¨ãŽ<öèãäDiä‘H&©ä’L6éä“PF)å”Tb5c•Xf©å–\zt]—`†)æ˜fÅHæ™h¦©æÔ­éæ›pÆib›rÖiçxØFž|öéçŸ%š è (ÞBè¡Û Šè¢Àè£þue¤”Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶I~Éí·à†Ëá¤[‘K”·âbêhºì¶ëî»ðÆ+ï¼ôÖRöæË—¡ú2kîFÿ¥¨H÷kðÁ#¤Mu œðÃG,ñÄWü˜ÃDlñÆwìñÇ ‡\¦È$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWúŸ‚?aœšÖUwíuHcŠî×§@¶Mt~ÉIX[3QØ\Á žÜgk·Ë\*°´IÝCÿÍ÷ßÐú=ÖCYÂ×!.á)xVÙеnbw<~ñT 3$¸d›[>,¿ž3˜¶@fs„ ™ŽÓMää¡·îºA 6zU±»öúí¸§êðî9nR›†ûðŸú¾šñÄ'¯|‹ª'ã\!¿üôÔWoýõ»JýöÜצ}÷à‡Þ|œßCW~øè§¯þúì×x¾@I´_,èòkV{ýøçOÜûöñ¯ÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0„Õø02ÃÚð†W¹wÈÃúð‡pY ÿ‡HÄ"ñˆSÑ!—ÈÄ·5ñ‰PŒ¢è¿)ZñŠXÌ¢k¨Å.Æ^ £«(Æ2¦‹fL#É%ªñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úQ'lTÕ2È?òˆœ‰Ù#$H¥Œ”–Z¨5H²&’¦b&mS°¡ 5Aô~Ò„MÎE¦T’#É’Ƹ1•}Ò$,7óÊYÚriBLÈ,‰PÞò—½‹˜™F ^ó˜Ëª¥RfÇf„ÐD¦4EãËiZ„Õ¼¦6A”ͼtÓ"ßäQ8·IÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑ©Œ³¢½ÖEqbÌŒzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgJÓšÚô¦xÜ(NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§jÃ\RÕ3k»*h:ªÕ®zõ«` «XÇJVq)³¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^EúšDbO% A V¹W·, ¶°…JÐI´!~…ÅKcm‘$Q±„,\ëÈHH"³Ø“fãB Á kkƒUIÙÑ®EQ+I¹@ëZ´ÿ˜)IøìØH@‚H¢µµ5 * Ûƒ6´ÁuK&90Á*–«É}Š@¿6¸A°ÑUË—PÉ[øI³€nv²'˲ÖŽï[„øØ6$¶ ´UoZPY,W´ò‹UóËßþú÷¿°€L`Œþã 6H‚ ²`‚4x H„0á #øÂ Æp7Ìá{øÃ ±ˆG Sú‘øÄúòŠW¬¼m°˜(™Sˆ‹)LÄÅ~1M´‘„øåöÁ<öî@ZëâmP¶º:Þ‰-\üY 3^åtùµ'·aÚ`l’qò.9 1¦ðc2Üm`’^É-ÛeÕnùÿ&]~²_ì5W–ÍaæW–#ñ,“ÀÆTñ™âœÞ0ÿÃ%@ïcÿ± (V ;0¢yÛ†„9[‹ {gl ’hp jAC9Z Ší²—ÿJ@¿9&ŒNð~·±\T™Æc¦1£I€_ÌW¦¨œ$B†++ ÀÉþøîtÁüµMK߈«É|GÇX¨•„?rüênCfÂÓö´·ÇÝ´L‹ÅÜÚ/¹¥Éí˜{Ýðž ºã'—dÞôη¾÷Íﶻ߸ÀNð‚ŸΰE~ð†;üá׳#NñЧæß^¬3Ajq‹mûeÓ›^0Æ© mml£Ó%ÿyË~ 1#wü ï´ÅM’Ø/¸æ‹Á7ªUޤ‰ëZá‹4Cl¡ žkå¯IuC2÷îH‚7–&Hk ó)©Zæ" õȵ~a  é ù‡³ZãÅjýMpüBtoÉS°Ã '>ì¶P¹ÐËâb7,Œì qéÁÞdÎPÄöº$`ï)¹@ySÁ7hj„°a'wˆ‘ÍrrÅ"¾!†jÃÁ^‚_‹öêÿ(ü–"ü‚R¦À «üC$Qu°,¬ê þ‡eÅ=ܲ]¦ïÕ#á†Ë&ܰQ€AœI1Ù;„öiQ,Ø ¢X¥^ ˆÄÉ»|\U¶5y_ªÿ¶’ìÚåï ñn¥ýuƒ°öꬥ0Êã‡|.% dõ7ÈæÓòy… Rˆñ Vzn¢•y¡ ÙG%ßp )p ßð *c(zçvgq{ anÅr†GmÚÖh·%nÐ`]‹¤2\Ç)xýç–UÁæiÎÕt+áuN¥t Aj~Ád¶–Um·XáÀuiP¢|P:)“`¶p í†svnÜö>'aù‡Tµ~a(WF'V%·} ( E§3JX1u†^¨Öq_8sB_ñn8‡tX'XHX‡$Ñzø‡TáH(÷`ˆ#ÑeÓµ ¾G`ˆ#ÿQ~舒8‰†Á|”ø|èUx‰QJœø‰Ó†$Š>r èˆ¤(¨g@ÂhgWwdØ…K´†z &6¸ø"‡F{þ€c½h~Ktuß° ¿° ÈCh#vhøg¨ÿ&rrv ±‰ÇBt·  —*à*PJŠ(ˆ©("¬f„m¿g&W‹Çæl]6oÚp õ(ŠUd÷è`s>Ò› vMð XW#’ƇÖx³ÑeH·€F…%ð{¹6àj f²'…'(%Pl¡·q}²„. r X–’,² Ów,)‹¨ˆ ÄÖeI€‘ñÿÃh…WZ˜€D'}àÿ`?Ù0IpŽ5’‰cqu шà‰;r`*yê^” ˜U I“X ޶x=)Ûv`7Ùi„ÆxL²‹ba‹…8N9$¬¦ –l¹‘{·@“ògfÆk¶ *¶xW‹}æ^ûÕ"09B”{¿ŒvŒÇHÙ!¶p} ñ–Y]–•ò †÷˜``ÙŒ6I2×ek“w“y"j9”$¨ •##‰mŽãt‡#-‰¬ÖW©u (zbw”¶xeXc‡”ªö¿Ç”p9_a 84r ™‰Ûv³±mYYšÛ'€‚6šÿh“_b–‹Ç/I-N` rÀžº@#j肽©[ÉvðI°“`&š˜¦€½·`ñW˜Ä{Orh0ÉhþxqƒÉg1F_Pv–aIa79cæ™™³œD¢Xȱ›qV^Ñ–4r`U™a “C‰—µH€ž†šâæ͉ ”ÎÙœ«x'.°£à/›ªXvªrI"tÙGJŸ Ê`  |]¶xÒ6£H]6–!xN¨jEª&=Ú¥$J, ijy«y!y™–6mé)Âò –à$ v`uM¨C™¢ìó–@Ç*`6M𥑇cº"FöŒÎ˜˜Ä”eÿ*„X‚ê‚j)"h½(n}‰^'Š?P©…jyH‹7ÂAj‰µG-pÿ@Ù¨ùõ©J¡r`öˆc6nŠÊBø©ñxyxаzŠÂú¢:¡$1¤"6©-±ªIÈh‘ØújÁ X–)° ïéap8¬|á‡êF6ØV?·­|a®oE=ö ÙÊ­1#³é®Eq7Ç6­G¼*-à$‰S@‡`‰!á”È!òúÏz°Á§)äª û°±;±±­Ä°+A›&'i"š±ò•°¡”#±ãö«=aèú_[:ùŠH²0û y#šÿ /ëpÊ×£JÐÈZß` JPÐ5›?‡+öZñÚa÷gè´ »¶€&¦S+R°±W%²x1µx…²§Ø²‘³6ñ—ð&«— ³Ú)¬K«2 ‹^úö |ø ±I2+mk|øx- |·™o&I(àA»IÛb;^h{•°Ûßšo[ ZµQ)º“Kn‹Pdë™ûa`;6ºž»¹!fÓ´î:¹ö qPMº« ›° ›Ð®FWº?»ÿåêI«иç2Séa.0rws`°+Sÿ8f;` °£â¸£‚º¹Eá¡›ÔÛaëÊ+oI»#V¿Q!¼Hõ½1¡¿T!¨—»aþ«µ!VÀXa|ÙÅ¿"À"À²Ûm| f±jÕº{‘`‚&$†XÁðfj!ÝÛ½ôÊ#ø–ÂÕ¶ÂÔÇ¡Â-Ã/ìÂÃÛ£è«'ì#Ó×ÃáÃÄœûÃDÄE<ÄF<ÁéQ¾JÜÄN!ü ¬‡ì›SÜUüÄZü_š«-uÅNÆ9qÈh¼ÌÛpQlÅ.`›Mй,%Æ™Á°ê»£@ºÅné ¼MLÜÇDáÇ;!‡Ñ€ RyLiS…ÿlÇ{{&È_±Èž:^‹P¶jÿ Én‘Èá&)n zZQ)àzÃ1Çt|Æ Û£ç+šlPDp¯,³lW+K©ËÉ¿±[ɹ¡ÊÿË¡Á¿±£RðN0%ªæ±³ôûxv€™$Õ˜Œ|‡üQÄ»Yü×üP^\Í(Ø2;|ÙÜùj°5¦á:¼ì.° m€’Ю¥ËÉá¾@Èàü”Hˆºð©¾üK¯±ªqPß@ÍðmY˵‘7÷%Rà R0b)+{Ì%åXáX*à‡)Уÿ´ •“‰öÌ"\åüOK*Ô¡Û +ÿ]$ÕΜѺ+͉#ù´ÒÔ!ÁAÔû\Í ç_]U¸Ô‘ÔdzÔRmW»Ì"QÕº˜Õúç’A¹øÕ‡QÓSBß<ÖM·fý,–º™Š•mçζ ‘p\Ï„“nàÔœ¨j”ÕiZ×{ŠqÝZ}­eõXÿ1Ø› ØTÈ\}µÀ¦ó¸J}Ö—xuñÓׯ†§Uº']Ön¨¥ %Ø‚ùi} eúj¡Ýk Œr}ÚžMqUz“éÆa·m¶ÐØŠý‚WÛd:}mÛs×}½Î]Ýf}MÚÃg9· Aš.ÖÜ• Üyi”vLÊh}=Êç}ÿÙk“©j´ÍÀ˭݉|]ŸpW020W@ƽ™É-‰ªæ™)»xu»` .€Î/0/0ëyÂ"‡ÜA)̬‡Uz‘¤Öé½¶ 1î›!÷¤‰Á¾×èäe¥U‘ÿ aª6èŒ àRÐtW×רHߢ­`«*á ñÞ2з šçíZbª¶x¸ßª¶ '.-P)þRp­ú´ÍÝÌÑãvtßy×$ÞeW@>Nð vðF~ä]n­j)Ü݈ xéý /@á1)î]§‘â)î¿€¡®ægå Nâ xäs.­ÿ÷ ¦)b>ï-}‹æ¾=‡™F{Dä™-²` —p‡sàvnZ¿`I. àÿúu‰åyl˜XKæ•¿c‰e ©Næï=¹ènáïj‰eÚŽ¦Ü—Xg·ë6–Xwàéz>¡¾á£Žä~ä‰% :Þ€ˆw¶ £©qøh –PäFþÞ_>“÷ùŒnãXx×hIå¯ë´†‘ij ´·ìs>çuŽ‹§=ê>à4Ú„¹-ÚðþjªÖÛ„¥jkkásná9}mšaé9NÛ”]qZÚ×k­ŒyNçή–ýpuî.âö|W~`W‡çcŽèå~ŸçþÏÿ( (éù}òɉ‘wsuD>Ÿþñ¦EY4)IŽøû €)åg¥®k )çî=™ß`·¢M³N›U:“^ÞJïéý[Þìvþ”) vОsPónòÓ™“å· Sðë¿à=zžùgú ¬Ü»MÛ ú½ªÿ° wêÆ¼£OÖ'·¬âñ³à•ý‹SúÝ‚ù †"$, “@cX¶Øƒí®^Føˆõ)¿@ŠerY6Ønqmî~‡`ZŠeÛÀÙ89û´ø‰Ù5i… *DűTØg‚½ëñã0]¹Û«×ä ñÍÍôqmñ5ØÚ×g Ž@|’‹ù!ù ,I›ÿH° Áƒ*\Ȱ¡Ã‡!’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë$.cÊœI³¦Í›8sêÜɳ§ÏŸ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „jèrªè¢ŒÆ˜h£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØnB¶Üvëí·à†Ë™$â–kî„—œ lºê¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓ.OõÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wn9«Û ”ùåœC*uç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHB‘<ª„(ôKRø$$ ,ÔIH„H¸¡ $ø\ iR‚$HÂn ÿv8“DÑÐ ?lƒ@Ú èˆ*ñaÜÐD‚TŠ,i¹`èÄ(‹:ù"S’„¤b£I`¢r©ñ$HpcAV(€+¾±%$($ÁÅ;šP vDc0D?ž$ µ`cíhÈ5   Ihƒ-$цHí‰ I˜Lf$fŒd?IÊRšò”¨L¥*WÉJþüã ¯l¥,gIËZÚò–¸Ì¥.wÉË^ú’nÛÀå?þáÄr ŬÈ1²LRþãJt¡6àQ&¤ ·ˆ-ÂÈFn£ mÐÆ6Ä)7 !›…$ˆ?"éEj¢1˜uH š¸ÍnúÑó¤â6·ÁÿÎh£ÛÈ-H°ÍàS Èæ#µÉE~šR4´!¶iÎmø¢’H¦´I:ñþ˜çFõØÌŽiC‘€-¶ñpZ´“$@‚H 2Í& µdÍ(=sc%¥Do1ÌH$ašAjA†ù‹Ô˜M-çA†Ô7þSÁt)AÈ¥cžJljTo‘„t ¥ÜFÝ¢ªu ‘Xæ+¯h bRR0Tª:QIE…jT¯™f$$ÑÕ¤1£¯„'3ÉØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨M-á¶1ÉÁÒ¤Ãü)aŽ©Ñ“ÿ"ϸõK« rÅÖ±þÀ-SKz‹ºVU—„…êA‚)Üã¾E¡'¹{ÞVOÕ]q•«âþ–-Û€¡‹yUy* xt b‹G@ŒåíéueÇÚÅ2Ä·m¨@ØøÖ¢lLéJkšm¨n´ä6%66'»ßˆð7œ»,mdó» ±0†Ïò _ÜA™YFy"©)lv_ “m„’N3 »!–rˆ–$†ÛÖn3»eñª‡ ò™d·åu±:_¬ÄÁ¶‹«?b,‹Úb½j)fXkÎ(õ·y¬22醄ªÓ  Ž RiíxÿÃmÄ­[: åX¾W¡Luèu™ºÇËušHX2tÖ|­¸ò¹!?rZúkÍœN„Ïè­+‘_ÙÞ$L™¦–D2u]-ÄÂy¹rž³‡ ÏóY¥šÈ0ÛKÒX¾2Ó‡^NpaøéiY˜» ¹r­Íòʰ2X± &jKUÊcuЏSŽí03mÌK3'§ÆåkƒIeüŠš¿N$쥖RHâÛµÀ2B›øíìúpmŽT v¿@.ÈÖvw}Ö®RY,Œ¬OœÌ¤7½#kð€ÜÅ'L¯ Ãn´\ÉÝusóÏc.–U¥·rî-+S3¨Í½·[j‹=ÜÚB·±ÿ•.®;N[¸»°¹–8./™«öæ8—‘/ëÉœû\–rHÂÅ%û]Ä¡šØ…f›`I8áçPºÔ§NõüÅ»êX1· H[Óc^]ˆÍ)äÏäyš¡Y²‡KLU“ˆÒYµ¢}c[ûÊ–š©;ØÎ÷±[È sWuÙw3ΕûãÂAµ-ß Õ%ÞD}gûý!¸‹Ý âž ƒ`odú; ©  ÕªÙU¸r„ÂáÈ7 iøÇ7ÜΡaî:. ’’ªû \™é†±§†Dž+( N4¦©¦Dh}‰©Aù NÐ ÊKæÙ˜¥mærŠ?bj½¹ -p›° šð«ñ¶žNÑpº –P;Ç%ª4Ñ¡ªdºn°ÚšÀ¹*x r€Np“±S–X± àʬ?á§|)®—S–X†ŸEÑ¡x«GᮩãUnø jت a¨¡£­¦N§¢Vñ¨ j@Èù—P•½¯=°Na°¤•ú°#Ä‚óYšp )à`ÚS—¥¢N—&xYáÚщYíj®­Ä° !¨»²,»?ñF¨Yc¥ö°ŽE³Qÿ)ß+zYkv§ÛÉê­”U¢àê– ¯Õ³D;´7‡´‡%zY6 ZšY_z º` º ®¨”„^;IØ¡ *¶GûK“ÉiÎêwš«-ëG Û¶D4µš%w`u»„–u§*›™õp¼*žœe²pËBø:¸¦„²†ÛHoËXpX‘ ú§.ðL*Ymv§1ʨžõ —€Gë´¾DhBá«Ym ³ÙX ‘¨õŸ³Äqˆ›´Ñ£$™¸¶{»¸›»º»»¼Û»¾û»À{2´UÃUL­¥O2ÛJ}§ l5ÿöoy \›—|w *‹PÏ›^ôhKËkpÏ;zSÿ àä½ÿÖV²T¼(–½ôˆT€˜g¶À{ÿ¢§Äw`øom w}÷HÏ;±ŸÔwáõovyl÷Oÿ†lyI¼)Çç„‚'ye–^GÚHè+ ?ˆ{Å‘üûFœ‘Lù‹¿ý[lS˜^"(ŽÅöÀJ˜±æoÑxœØSÚ+Áí«MÿVqSIÂÿöÁ$„‚¿·(8| éGœXœ×ÀÞ¸ {p30Rp¾ššK·ÂkÜB«‹²· s 3 /0àÄR ðä­<L¼wÁ1„‚ Pl÷ ‘yÐÄ20› ’(Ø^C|®Ë4’÷Jÿ†Äß` /¤ÿQÆeü2à—ÀÇß…p 0½„‚÷hl· Æž\¶<.œ¼ ĉ~ Ãõ ÛÈ1‹<MÜÈ3à¿ ‹ß%ÄlKä¸5(¸yãÅT¿¸yÜÄàÈÆ$ Ê9Ìa|¶ü[ìÆ¿!ƒ–ü4(˜RaÈv›¡ŒìÊ1aa¼Í‰Lm±fÍò ßXA.…tÂSÓË&¼É­œÇÊ,Ð}ÿ òüÉ\Lféͼa P Ó5 GRu5&‡[ÓåËV†[NìʲÜÈ2ð ùM|Çeü¥‰¶GX…ˤ\H9Ð4ÉÃGS\¸µ]Χ½>ve¡Ìò\Ïü øìÉrÿp &·]ëtp™ÎN6“4|À‡5?frÍÁ€çЋLÆJýýo`ÑJ É M$^H‰ärRAtŠ[“Ðr|à ¤ùüÒ]À÷,Æ5=ÕÔôo"­jÌ‹`Y“h?–…éåÕÜLÏM¬ÔŽ\ÖfÝÄR° t½Q›'tÊÁU}jLÍäQÖliLu SÌ{-Æ2ðþ½CL‰\üS¼WÎÀ!=]ƒ±D‹WÉUÌR–ͱ͌ÜÔšÝf@¹²Wel]H€ˆØ µ½%ÆË±ö{Þ8àÉc Ó 9Ä*Vü ×ë–tL"ýØSϨ5¦  |²· 3ÿ0eŒÑ3Ð× IÀ”˜–@T´}V;\Ó¬4¿SUßFEX¹\F!ù ,äÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P)’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀáN¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möxà 4ÕÙl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùè¿vúì;@ù$”@Bm¤@üIH‰Aiý’°…$Pñ½OH¨Ÿ"¡¿$¡€â#Á“@IÔO ü æg à}LBùܶOû;! Ãç† Ä…Þ«ßú’7ˆÐ{4È ‚¯…ò› ÿ&8>Q€‘ ¢ù"a‹$>}I°E°Áþ•/ H8¡·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºÑrÿèž?0GÄ1!uÜÆóþÁG7H° Ûè¡A´q’  |dmñ¿HÜq ˆYÜÂôK¤ò™¿6¸’|Œc “PÇ$”mH‚&•·üi# Ž|d(âHäp þè#"W¹0BîÆ“ÿØ0+ÉGúmƒ’§äc*y‰¼$ $HY`ñ˜È4H&³i<=j“mð‡òÊIró”Ë<çðrÉG_ä•SIâB¤DSn’Û°…=’ÿO.P ißø»q^DM¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’š”Nu,ß7"ðÝ"™‰D¨÷øøDîBße 4áÚ(A,ϧ‚o0ò“+Ÿ ¼ÈÓt‹2¥ž’TT•z–D-˜É"X/Ÿ%°Å1Õ¤•U/KUˆ6Îê½cÖ”­Ñ›êAäp;ÌÁ7Õ^ ¢¸À ÈëIKØÂö°ˆM¬ƒˆ`ÇìoW%ß6tÑHBŠÍ¬f[¶‰Í¾® ž ­hGKÚÒšöPõƒk×R:C“¨ö%š ¥l)™R»ÿà,ÿðG $1ÛY¬µmñê[‚‰Þö–%ØåkÇvÛ²l#¨±äã>d›„4pulµýÇ7œ€‚oü",ëc'>‹«]í~ã­ºUnÜ´!‡ÀSËqu+ £ÊÁ÷•CMÿw]ÈÙÁªçìMz+…¥¦@ iÂ.þ‘\ßÂ-%ù« œàÓœ `žmZâ‚_|c›Y®ïÛÛ‚È!¶@¯ˆ}Wâ‡Xb¶Ó»„%êzL5 I±l‘'˃ôõ¯¹ŒÇõÔòÌñ’ °Wƒl!–ðyiG[”@Û%È“âÓ +ÁÍãã!K©.Õ‡×Kª9-qåo€öÿ"[6Þ½ú K–®i2D6<ÞÑË#Ž=b‡o´¡ýßþá$8øwæ§@=i¶"*¸ƒ¡½bÚÅY”®ÈR g‚xƒ ÀÈ›ïyè`ªäÔ,þÇÉ a=[Úo[%ˆ­Ob‡ï¦`Ê+9o~-ØÂuz#.BHà„–®äqŸVmì; ø$.p à‚ø®D+‰9=´ml£H¸˜W¢€¥@¶ hÿañzíÄ)ù´Uôm`c­Æ˜Hb\` Þ7r·¼Š¾­æí—¤ú&I¶É¶ðÓZüâϸÆ7N ÈÕ/Ð…Hp ]|£ÿQÂB^¼‡»@)@.ÍjÏ-0|êt·³Ès„g¾£:!ˆ…—ÖTÜ"w$5Cžþº‡“$ℸ_9°—à§ÿ…Jm‹ÂX¥]B#€¨Þ’æ’[ VßIs ’†Çú!(°jOy’w|ã}WÛ“bnû'G@n¸´æâÛ&.ØD ` ;¤Ààöàiâ@«ŽEâÚ-¿ C¤À(6o“õ¥Šsº{ÀzÌk~ë=ÙµÒîÀz˜d»ïfý\pÄ]}HòW|„Œ½ ½ŸIàM÷xèE|¥×ÞÅ&6¡ Ë—Ùz’°„ÿ%8 #þëñ±çñl·`RÞ®Ó³½áTŸ(fÜêW¯)4ûÿN°·h¦8OF˜€P±WºQæ8í¶zØyô‡j•v–mPd†Ód·z/`i5wJ‘Ù6{.pwúgcí·zNñ>«§go§76§[vjÓ—9¡†°~‘E†}Tñ|…#„÷§'f4G8KõiFx»F„\§9+•wþV>ͦxnàâ“m™×ÞG>í) e…Jå  dˆ>0ˆ{WX‡JÃxvH9.pºP)° ÞpmßÓnJ°mMaèWMPÜe7ÿ¸<üLjN€ˆJÕŒHp+%\ä“mívBº—‡˜#eèórPаW>î·z˜h>¸z”>íGX>Ø~¯Џ¸3¢HTNz*àl惀-Ðp´H.vÁˆ€Äh>oçS}Ý%‡. H×O¸‰H'Ót>©vK=˜‹Œó‰'Ô|Û#„°Mp@xø= Žu–µ ‡W‰ŠzèÓž‡‚SH=*Ðh8‡ì3€ç³à8*à°Ž¹ Ù‡ƒ„‘9‘éâ„D d ,È=þ`CÒô‘ ?‘† A’º3_Œ’*¹’Ó´O÷t\ÿT+9?ž mph+ÿ™§x<0J)4Q‘ùäL y‹¿Ó“øD”ÃNCvÂ’<²%^w´ Ñ$MYÄGT‰P2)M%‘¹“ÑJù“Õ”á•'ÙbeyÇ¥’ð‘ ‰;nI‘ð‘.ILvu)M+´;SyÚð‘0$—;–ôö‘&);hI% Mw©˜i“¹a¹˜q Žù‘ùN|¹™‰F”‰¹²iÑÒ¤‰µJ¹„‡)M„–!^¶¹ Ÿi;œij uG½yDi–9œo)MÆÕbçõ wp3 3pwàa‰&¶Ðš¼É™²ôJÓµ˜»ÿ` Éö3pž/àv°`’fºy?Yñ©/âEuÄGžy?=ùwÒyžÒùŸç5VI’I›«Ñca›ër™g™Ót\5uR`ž:jžéi”Àš ¡ªƒœg˜Ê%['þ3€S2ð*z¿iœ¯3œ³µ—ðI4J›oæyžæ¹RÑù:éiPWe£ƒÉ5Ÿv„S‰.4 ›¿©^¡t 2ðP@rТ3ÐkQ[1ºº”ge ëS™æ¥>)M# `,*§p[>:¤Nð]/¤œ«!BU?ÊOñCHû#£ç¦‹D™³¤]—ÿ¢ñŸZê•j Rð¢4$M}Iº9˜TVàKŽÕ.ú@úD¤ªO³‰h£j g§¥Ž*`¡2àÒTÿpž±šž! ¡ V)M·ð¤¡ÑA¦„dt”¾ä@Ï% ØÄ.¶pIú´“úô¬bå˜Ôj ðÕŸáŸ@«^ù ]Š¢ƒ$M  œQG5NÿÐA·ðHH8MW)jZ.ÓZªQ¯[•™×j w ::«*i«Ñiž9e ²  ™LÊÔ¤½Š A™¾Êš†j.ø*°‡¯D™þ­v €¢Yê­iƒhr ËH–7*¬¡‘®÷ª±›6|D@¢ÿJª8IÓ* ¾ Òô\úÔªCꪲj²  ¶:ñÆ«0›ð±ªAHöPQ%M—ê.½y\¦GŒ*±Š¢Üª0™œ`—¦ö›lˆºÉxòUÎT[ly¨;Ƶ½å ŸjGç«J¤{eä–zN‘Ÿ©¦áOòš³x$i¤¸êÂÇ—c{–Ðéµ-ª¥%ð s°?Srõ•œšÙjéAŸä§HŽé2d0‰¸ÊµRÀ·3À·Mzÿ—’ ¡Åf£y¶“ﲘGÖ[¿Ù¡¡t Ê­ßm` s0¶ºp °†BqÙ–“JÉ[5*ÉÃæ2  fU–`—½ƒ–½¥[‰£üI²»¢{Ø«Û0G Ѹ¾”Û[™9¨5µÐy:¤Çˆ³))M)аÇé[÷9•J HS—`S wu ¾ºÁÇ HÀÀ ¼˜\{– ’Q´`æa؇S Ë;b‰Û`¹¹¥5äI©t•&ì²ü;—±®Ep´Á’v)¹Á3_HL‚DÄ0D<hH “ËšD’@»GQ ¢ÚÓ“¡šáÅÕ!ù ,õÿH° Áƒ*\Ȱ¡Ã‡# !±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀ_N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh³ BÚlK‚k·-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûð³üvüô?@ý•@þ@ÂÿÃ!ÈþàGý"qHþHà?þ¯ r@þ (ý €–@B ÚG€ÜÏ`~$ìІ‰Xƒ(ÀD(9Ä¡ƒøü ‰ €rˆ„ ÿòB÷ H*Â~•H–XÒÐ}(ˆ¢%R€‚2P‡ðb%x@ ¯ƒø_IÃzpäßâ@9¤ˆvÌ£#r¿=úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Tä? ©ÀHZò’˜Ì¤&7É7[pò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.w9˜[ØB‘„-náó˜“lL2²L¦iCÚØÆ@¶ñLm,™ë&AŽ)_Ę鳅'·™LiŠs›']ž‰IŽ3!âlf7 ͤs›þ0ˆ7 òÿ|®å‘Ä@’ÐG!ï$H%’P§ ”œy(?×â†>>4°5‡ÓÌH‘žQ $þa Š$ó‰%½¢Ðn¡ ~Ês Ú¸Å7_:–mÀ €G+ˆ„db´¥Ú@ ¢ œVÑ É¨L"ÑŠÖ³hÛ@¦:² qZUœ5ËSoJó«pªJÊRhFõ¥Ëla2…:¡MÅ4f\ÓyÓ—âÄ+[ZÚÐlƒIÈ'FÛ€Âfô›c•tÚÏ±ê¯ l¨ÐF*UšD˜Wµ*[lÑÕ‚l °¦zØ–à©Ñ’ðÎæp"’ e¥ªÌÿfv©j êN²ØtN’°jäaòÓJ“« ,.AQÛ˜}Üꬴ¥ªUm›Õ´pU “üa=yLIt•›7õ¬o‹«S`ÔgÕ­Ñö9©D›)æ^ ÐbnW ý$¯oÍ{XÚ©Æ´©@½{ p^÷hÕå¦Aª‹ß¶pö¢ù¥0ÒÂHx2‡ÒÔ_†oêI6¶Ô9¦؈´˜ºTŸ-=ñ^Ë[ÁÂzp§ÚåmT Á|úc¡%mq7HDÑížím&ƒ,ÔZ¶¡Ìz©šb¥U·ãe¨dÝ{ËŽ­šO¥&4¯©àõù×À¼k\+ë¾$óòÌhN³š×Ìæ6»ùÿÍp޳œçLç:Û9UR¥¦yi‹h&é´È)lZõ˜æ²úä+åø&ó—ÆñgD$Ͱ©B“¸Éd§läIÍ>‡µÏÔ¨e«ÚWwÚ‚Ê›*{gÊP(·æ³pëb]ÌVö~®HE¢ WÐÇj!4¦–YU3ãW}Mm=´¡Ï}®'F%¡çý-Ó»m@¯[+8Öxw¡›ª‰ÒX¬:5òMBKÝJ‚Ù.³=5æO Ò†d7§^íª? Z0K7äÚ®!i:ëA«Î¢b%磇 Ýð›`xçnÉ}̉·æªMK`ØHÑí$©$K×ñ \.Mÿ¨Ôt!ÍlÆæç­L{ÈcD/¶ÉAnÛ Îc X^%þïŠÇ&ŸOv:ÅšßÅžšÕ¡­èCÙkœU ”ö×UŒicr]50O®_‘ÉÙ(gÔ幺@VÛàÿIÕþšªÒ™YÎØ‚=ãéäì©IØcn7ºl2a>|Z=Êá–;Î1MT»§&ìl·6[IŒ¶[˜—f =YQÖŽv¬¥/}Gª–¨”RSµkÖ'ÊÔÕ¯ãníµaÚbÃÖ£-Lñˆ bÓ>æ¹þ—¸ìÅ׆šÆÆÜÑòÄa/¾*>÷ù¸Ij‹3ù`Ÿ&U3be„a3Ô¾E/ÿøßWYObþ®wN¿úÅã‚P¶À| Јé€ñÕŸþ‚L@Úï¸Z¬ÿÿ€Ø(C4€x€˜€ ¸€ Ø€Dñ~¡ ±oEáx˜5J`GÝG=(÷§(MP€zäI$È?äGx„Ó|anz$h,8ƒFc4xƒ8˜ƒ:¸ƒjñ ~¤rÔ<8„DX„Fx„H˜„’ãü§„Nø„P…R8…TX…ÓÓDzôy¤…VØ…^ø…`†b8†dX†fx†h˜†j¸†lÈ)׆pÈ./‡tX‡vXrw¸ƒ@˜‡€²‚|6» qó‡„XˆG⇆ˆ&ˆ˜ˆŒØˆŽÿÈZ nLÐG~æuk¶gXHàÆW>Æd ¾V™hXžGnÛ` Uð6‰nÐIÀF™¨nãsL´—ScÕpR%P™øuÙ#W•TXm`f•U\¥‰ÞƒLTX9ÖrRu ·–Ø=ùõWXµÈc&oÆØ‹Çtk¼HqÇÄY…ƒÔÓ]†õ !Uu{×sL\e܇LëèWXóSûpLß° s 3 /0p“R I&U°|BiŽàdž”w 30R0`9M9›Ð“&GZþç<Ykt“¶ð202ð w•z9Np .Åw……ŽÄ£’ Ù•Çô•ai“ðÆ$O–6i“– ƒÈTŒ·‘†™” ñ”NHð v°—fé>È“ˆ¶Ž×ˆ™^W˜&÷ d)fÙ”Œ™Cÿà˜6i–2p>ù–ùµ‘ ID(€0€ùcà (öO¶„ÿÙG‚6HB‡6d[ O˜„öЀ%€Ÿ@2H¿Â0Šÿk Û‡ÀHäOn ý̦6JB$l¢ ¢CÿIqpŒ£3"¿9ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòãû‡ø¶¡ ø£!ŠT¤¶¡PR’ÓÓ"É[h1ƒÈ?,8R>r ·H„D‚’Ñ»lñH(rHpƒ6 KN2R ÜÆ?Ü€„T `•þÄ.máÊèýr•’€¥$JpÂH’!$Ä$¯éKýIo‘Ð& )i@毗ÑÆ@JXð©ìå(ÀMçýC˜Ф$ ÿ€FªS›ÙF“€Âm¸óÿÐFóéJt"씽A¨$8LH”…‘¨-Š)ÔB‘ÜÔ¤§wOEês”˜¤:¹)L|B°‘0œdþÂÌWRÏ,Ô%·‘¿U¶É gþlºÑc²“¡©ô´!DvöR (4¦(C DXŽRº„¥R¹<‡:Dž\ «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®xÍ«^÷'˜PˆB´…-„‰É¿VlLÝ¥Di*ØÅ®ÏÆD¨AkËÖO°œ¼¥A˜*ÉòåªRMg>-Û Ö.¤…¨° +[*„µÿP-\piTšÿjœ$üHàUÉ ÐWíìBzɹHB‰œdegÝ€6±‘¶@H;6 €†’À-]N[,f–!Þõì[þñ®’ˆ¬r©Ô$À²¹MepËJ‹ÊeÁd/¿Ñ+ŠW!@ npÕ‚Iò6ñ°Û(olý»I‚Pšù>ÿ§‰:öW’¨ìRBÌÎå‘çˆ-#áÎÎZ8•ôMg»ÊHÆ¥!¶‹…¿qOQòjŸ^=,gÔ‚ç=ñ7¼Ñ”®¾m$zÛc„~ã»°`vA]ZáxÃlhQ€µMp ´±á6Ò(Ôæb£HغXƒÿ’–Ð…%lq‰&¤@hÂ.ReTù·ÏÙq]|,Ú$ìÔÄ îg޵Qâä¡6ôoϼÛYÙägtZÙâ|`ÉAè3ɃœòÑl®´¦e\@W¸t!ô#¥ Pmn£‰F@SÂÀw–·g×S…É[uš‡¥pÑSÕEX•åÅ’‰L§R–!Q•¹œ³ÿôÎiÛXŠfaZ„“tP.pœ¤Éz(° ‡qRp Ðqžœê‹ìé8¸RË9fß°JN°v !sꩈÞÙ4CI^×Pœò©®E¡ôiŸ(-àR0RpÃ$ º4Vi‘(ຩיß` ꟡p>jÿ°ž-Ú4+™J ‰èdr€!x† ¢ äXÞp64Cß  *¡.Acm€£š?Xsarå©* ¢B:Eh“‡)O<*/`Iú¢ñÆi * —€¥"T’a“‡Ip¥eZŠ Ã¨…¡…ŠVÿÇŸá+êra£ S`6R§[ñ ZPæƒßsÞ0¤E30QžEI‘áIQôƒ ¦Þ(y*L¤ª4iç´(~['š0‹±¨!¡Ê©·8»°J7)E™ýgbu&£Â굺dÇú7Jg0„!‘¤ÿ° +‘ŸMP– Ÿf¨9I—`gÍÊý×™w0Ž:®*«¡‰- M׳ꌡ©Zôdš0¨*A°˜“§‘¨ °®N°g«ê±) ׯ+!÷ÚÚ:„Bg WqJê8I·°M0¢TO9÷8;¦ùº¯T!?O )à %H9k·°ÿ1³Q! –`@rð±†ó¦ ÁŽåæ¹Z9ÝXs8;> ‰‘®Ð)ë=…:µ.PðˆRᨛ‰)P `°tÚä÷u¡£€µQq®W³XÓµQ¬á´P+I²@DWxa•šR·9Qp[ƶG³›+9N0¯4¡W ¸Á_RàPI?HqÇ_íº4<Ùÿš,´á´a e´˜´ñ·ïY¹A±²* ºL³ Þ° ) {Šhûˆ¯‹[J€³æ÷·6£–Ëq) Uã ‡©%·Z.pgPëº-°g»pvP¦ —° à:¦º[ÌÁtü2°¼ÎéËLGÍýyË.ðÌDÈ—C;?Ü Ÿà ŸÌL3². uZÎØ¬ª'sŠ„qj¬$<¨ÒìÎÕL2ž«¤µÑc Ìøl2OÖз+-Î1ãM°¾$ yÚÁj¸Ð*Ï¢œt ,›° »  º¬>"\À@„v0гµ¹±Â¶øÐëÿƒÃ5Ì3ãѦQžz¿4ÝÑ¿!Â.º/£Ó;=·3MÒ$ÝÄôsÓ¾„]>åéœ= Òô¶ ŠUîÅåœyÕ#º@®. Ñù‹±ÛÚe-1 š°«Ní"ëB7“óFÄvÙº­éAì1`&—°"[ [?\Ì×ðµ­Îrõ¼ý|0^ ¬È1ÕÐK· | )ppk/IÈ_–E¿É¡°ZgØèÖ ôº¡ 0ÿ0 @‚Ñ)`6®—ä×t£H— P®ÍEYÜ µÀ(·-ü%×_7Ç¡ÀsÌÚÆPGa¬0¯mx­ —gÿ£©NfÅÍ!½F­/·  ç½§Ô¡6‹zÀ“ܺÚåÍÎí/=J'àqÌ[0yÌŸõ-l GÎ9àúNÿK# 7VW¾“„ðá…cÆ!Þ~ážá¾á‚±œ„çg4wí“PÄ”¸eSè3JéhâÔT>ɇž/t^ä°d3Œ=¬{¹†|ا—¼y[ºI+aë—Jñ–0éÞQ®éHšjÉñjíz• î[KêWðw ï“áå5ÔëþÐDj„{ØvñSí=ÿˆP  ðøÍ_@ð¿ñS ëuþð–AI% PÒj×t^Ðp ƒæšžQínð.tq˜*3  æ7å ç‘¤Ó—¡†”d¼&&I¬ÈõõRU¸ÍH×4g´./ðæ:òâžÁ5mhüYœä@6cWÅiP Oë~0ùóèÄc6/t{ЍM/`õr Ÿ˜¦M5ŽöŒ!IŠ”[¼I˜å®\eä{_.ƒ¥îºGs§0ßÀèY÷ïšPU ?ä¡!YJ…x-\A¦…˜0‚K[ï~siìjm/ ’Où|.v½„ÖYåUîÓ/Y4 ÷"Ê÷SÿfA-÷õk4Dc± ‡¿ä˜ÿÈùµ•QµµœÄßNîgK¡ntízcRv áàŒ¶¾ýÛ&@€[ÿ>„QâDŠ-^ĘQãFŽ-þk@›BI$Mt˜D¡¿HøðÏ¡Gš5mÞÄ™SçNž=}þTèP¢E)¶\Xâ¡ÌMR >àâ[‰rJ"ùåD€Œ3~S @©Q²eÍZÜFB©$µ m™\* ÂÚD’)óì^¾}ýþXð`Â*à†î¿os"Îh"à›ŠßHs‰ ”+1ç.YXôh‰·H,LúíIº$+T™w&iÚµÿm߯[·h™¯áÊüöí±TN\p €®®.~ýc w÷ô¡ Zψ}élêݽ^|à*J‚)Ó’Û+äú¯€.fèú 1’ñýýÿ0@$(™Æ`.™~¹d†ˆ zA†“„sa“oâ@, í ä°C?1DÍúÇKI=­&rÁ…&´Ú†¿…ØpDoÄ1GwìO¦$@¬]þùå…Tè…^¸c—]ÌC­F§¤²J+¯Är'è  [¶aL8vÑæm$R€ô˲M7ß„3NJ3©Èp¢$ÆzH¬Ðä4PA%·l©Ó)"¸¥PG…4RIB(’N“€.Ý€iRO?5ÔPëŠèËNE1 !ù ,ò“ÿH° Áƒ*\Ȱ¡Ã‡#$!±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêܙϟ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙƒ0Úh·½!EnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ŸîÇüò×ßH ”„@pË_Bÿ„Ü ¿$´A¶ J€„ ‘hCþÚ‡„6Øâm0÷Ç>`’`A(R‹°ï@5(‰ ž~$@8ÂFâíK‚-L¨AŠ ‡ìsCÿ(€H 7$"úLHÀ‚ npaû"Á¿”ÀXaüjá†&á‹mH‚ÓG¿"ÐM@íÇÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈlÃÿ@"â…$òñÇ!!©½üà $pÃ"¢  àù‡ðÄà”Û³¤-~‰M ÀHV( pÚ@'©(IWZï¶HBÓ([ !Ø¡6þp’aŒ„–©½ms—®ìdþ‘K€RH„`"% I$¡¹dX#‘sHMªÐÙ! (rEìo;4ä?¶ÑÿL‡ùr8°@<øÁncY!(!iÉKŽ‘zÛˆh2 èMº2ƒ‹ä¡$x¸ÏDV°’–Ìe+ºÈ&ÚÂ’ßUHÅ/¦3{–¤¤A$!@j™É  $lZÈãm’’ÿ,HP "Óžõ¨HMªR—ÊÔ¦:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«`=“-È)[,Ó’†A(A†z5,ÚbÅ¢"ÙJ>$p¨X¬(]÷S_fShÌ- ‚ÓŠ,Th Ük2oX¿¬T £üd‘ Øµ$ jÝKem…Ï¢"ŸsõK3è&pà!‹&’ð#˳\ÿnögõ )Òœ¾”ž$H˜Òš±.›ýUl7ë6§|±lpÈMÀ¸ú\$F“ €—žÖg­„H$äÊ’’2]'Ÿ;×±ª²`è-À^¼l’¶»,Dœ+˜ ²W<ˆ%yxL•Ò/¤ôí‹%¿¡Dâ½²Ex2Þúêeµ™o‚ÚP]Þ3€ñm¨tS‡r®ßøÇ7t±Ñ&è³·,sù‹ß¼p›ŠˆtKÀám,— ¢tÏúH¬ñ.v¸ƒæ`‡aÙÖ!·8irÝÒHé☨©¥ë(yË‚&‡zQTà1 «³ mc÷’@[ê¸ÿŠ=)Bº©KЂ¯•³ÏË ®y/Ä´§jaô.$–"8ÿ¼³¾&—2ž Pdêæ¡-pÁ±ÈèdFú/SžŒâødXn…«]ïjýØR.H©…K —U>nµ«whNÇï—HÁ%¾aM³ÑÌIPAÂʼ0ûÙ›kÁO-gk¹ƒRàÉ̺Ïv¸E J ‹]¸Ñ.hBàK˜X{5Žˆ\ ‚  œ¾ž#blc/[Æööõ`ÌRû{–¼!O!âïïá“;µÈ¨ oé=Úî#1Æwä{rÔ–c“‰Ml]‹ÌÊÿ&sÅÛ‡î–;ÀÝmt€ æ-s9ÄÑà8ølœ0ë?ïÝÐÆ¶Ï‡>9 ÃÑäDO:ÞÞtÓIáû³Ä%hrqËÚÝ l>”¦Ý$(€ ¦ðÆy¯[Rà‰EqwðŸìó‰z-Á6ÙñÖµý&œ.­ŒÿaÀD£/ª¼bLŸØP¹X}ªÔaLKÐJK63áâkDx` þ»@J^‚&¤øm€Ÿâ:T¯CÍô¹»KDJ`Þ ËNBº`Â68áüÜ0é}Í:k¤D”Hð1>K`‰_ ÄÚÿ>ˆ-RÜaì Dç_#øVö1£ô @ ’ßKìþ Á=ÿ¥]ÕÓD¯’@Á6¾á‹Èᛸ„%6qIt¸nf~‰ÑU’ÈoXâúܧ7.Pfeæ}mÀc¨'5ŽÇc—`o. S R°y'±Hû$bæi'kA~ qÿ A÷‡6‰–+è–Ðíg)FÄffM`~ƒ¡$˜€¼—9ý&s ÀnM`nv&%yûÄw'‚}˜#s*/¨l&aIBÄMÏ“%lMPš0&ß@E ÷9 °ƒ'q ˦uÒr ¡ƒƒ—”>¶:Äø›`fNè¥f!ß%@lž3€WX‚”õ—ÿà£&‡ € ¡Rð?NÀu¨£ ¡b Hl›À=w=$°'‰lN° qPr0u…¨X/€Vè”Hˆ9*à%@d–i Xh‡*öu.à‚ 0‹ !Fÿ  1Š.Al7„ˆœ“† sPóf 僰X™ˆ‰šx9ÊF÷‡6Ñ‘£ˆÁŽ1jÖˆ–=³(fÆfm»°oabû—BG:§& rP´—` s0ާ£i/ åˆ-0„Êf„V'Ràè¥öTШ.Ð*@B%Æ’Ÿã|@1sÚç¿ð ›€m¿Ðr-ÿW: ~61o%¹‹é²‰-7€î¸9¿° œ˜»ð€Ž+‘B“#‰“,Ù9sÐ)àM”$‘”` ‚!sèV’2—–i=™Y‰:Úöýö“ñJ§)àÈè6µ€×S’]i. }î#‚ÞðFúø@w9wGlB×í3jÊ)  4Žà–¦‘iP-Šn$sA™™‹yšÉ¢so™k§3~‰p%÷ MÆ.pºPN© ’)3Ùd ¶pP©ó–ØóX?ý–nëÖn&€P>R˜ø6GmÙ>ï¶›æ“i¦V}÷&?1(\»` (ÿpE¦É>ɇnê&vV>wpÑYNYÔw>=7ŠèÖÙÈœ1GoÙŸwaØÉ>N` –  –PžáÓžÛiyŸd‡œ¤Ö àöF89vèÓv1XjÇsGÉõÓfÙd÷yö#„è&—` º‹ñƒnfÙª> :oßùm•døšÕ3jj)s·wn8ùoZ¢3§i»¢)J¡Ç(vÕI>بM:>-XÚ9š.ÛhHmdoQI‘Uê>Ð8’h¥ÝÓv0)”ew¥)¥SuÃ!•I‘èÖ15*#¹mó¦£ÜSJ0GD³š¨Ip8¨†Š7dz¨Šº¨l“¨ JGägms q @ð¡pÊ/¯Å¨œ:7zÚ© ª¢:ª¤Zª¦zª¨šªªºª¬Úª®úª°«²:«´Êûw˜µš«ºº«¼Ú«¾º+÷«Â:¬Äê%ŸZ¬ó xÄZãã‘Èú¬-#šÙ!ù ,ñ\ÿH° Áƒ*\Ȱ¡Ã‡ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P‘’ˆJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒß ¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚ+'ÐTlÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇYò×ïP ‘´‘D $$„@n{_la ”` IxHP‚6H <  è>"Á ‘ÄÿÒ†6´ÿ‹D%ˆÀH¸ï€I€[A.è¾$HB$H$‘@öᯆ9 <¸>àp nc ÿß·A&Áƒ*LŸÛ^¨Bf° $Hâú<ˆþMð…VŒŸ$ô×¶¡ŠòCB “°CùÑ $¡ýÖÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ù¶!€ äˆdŸ b þ%Á†Dä?lECŽïnØ`&r [l2’ÿÐFöW¾mèO 4"© P:PRŸ?n1ÊÿÙ”܆%Іm˜p— ÓFv$±Å$Hr’IhåÛp ¸À”e jÈfªò4Ôå?"€nv“Ö ß6ÈÈH´òÛ`¥%…©gr|þ@{)ý‘ ‹…”¤£ ÿ>KºÁïlgþ2˜ÏUšP×{gCø‰Ð†:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤Öb¨Eâ‰Ò–ºô¥0©LgJÓšÚÔ6,½)ïb¸˜o¤M¡: ªP‡JÔ¢õ¨HMªR—ÊÔ¦Š¯ˆNªT1†‚©ZõªX½Ñ.w™Ó­Ò{Û¦%o!ÌCZÒ/”$A$™NI@r­Õ,+ó$ÑMeÞ¢›±« I M³º =&] ×ä%¯ºœ 8Ä’`±é\`"UIך’°Ç¼+ É3KL¤gG8Á‚ÜÕ x=m>ãiL[жyØMìa#ÖÃÞr’Ð]`–;ï  ³4o"§‚MpVyÍ@'ÿÁÒ÷†H $!¿ËÉn&rpÃ?îêVÅÊU¥Âío Ò?C€ˆDð_ àÉ–À˜mðáÓˆZübÖ€Ð4¤i#±MÌ®R».oŒI1І,d^xÑJ–À¾èìæéÊ×ð/L¦g],Xû:/¿©Å+8<•n¸$8£? €,÷˜“$ðô^ËP ² a5s>³z85³ùÿÍp޳œçLç:ÛùÎx†IÔˆt"A“mƒ!ݼœf¿%4"“Є|˜>%Ÿ%o9>  ›øF šðèhnx{ÿð†g%¡ $ÄNÀDš¾ÀÔ5AX-K<úÖ foAd]ZÄ –ƒ%$¡ í9Z)ØE¤âk…´@ Í~Þ.u™j8Á ®@µ²m„ØŽSø†Pð‹G³1ÛŸŽ£7ÖØm7þâ¼n£òL6ÓûÞø––½óÍï~ëÙq$ôAæ>´@HA¼~>ÄÔ®^xû$.ñó¹€×*8ˆÃÝ—qYg›}HBp›üä(ŸO¹Êãí•Oއ.ùǼÚF_ÃÜ{)ØøAT°‰w~Càìs« àK $ òSÁÈ«½ïö±‡-gŸÑe9†.{}#·Ã&tQ€dkãêïS’@€4á…ö+¹l=G°Sýíp»ÜçN÷ºÛ_Q¿{ß\ ½Î ›Ø…àw±FT‹]èqlºßÏxCU¼ñ¼ä'OùŽ=¾òkSûë!ù ,&ÿH° Áƒ*\Ȱ¡Ã‡’ˆH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mšp€Ò¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìp€  ž3òiØ’¸@‰— º×¼øé’ä~rI´QB$¶Hòzå'Gž>÷Γœ<¯ @ýÊŸ¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ð3ù'HÁöl£‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒ»R±´Hor àHÇ:ÚñŽxÌ£÷ÈÇ>úDùû£ eø“©qˆL¤"ÉÈF:ò‘Œ¤$'9Pò’˜Ì$"-©ÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºrEx¥,ÍÆÉYÚò–¸Ì¥.wÉË^úò—ÀŒ¢6$ bJÂÙ6"Q8ó™Ð¤_29f‹$P mð]?AIpÃÿì œOx5+ Þ|ç;åÏwóÛ›îlQ½ô Í›žú÷7þY/xáuF»†ìx&L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡óòÿ‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHÆ2šñŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjV ‹sâ´iÍnzó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§¶Pè(¶èóŸ è?ï§~ ô  ×ú'90tPþì›ûÑÄÍÀ-!ù , µ«ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«NJb!ˆÕ°cËžM»¶íÛ¸sO% »·ïßÀƒ N¼8ÎÖÆ“+_NÕ‘Ü6Ì£KŸÎùRÞ¨kßÎÝb«îàËÿ'í|¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ¹¼ý'à€hàwYg‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹gegS 0Öhã8æ(›Œ:öèã@Ù BiäHÛ©ä’L6éä“PF©RViå•Xf™•Zvéå—`†É—b–iæ™h²õ\d¦éæ›pÆéÛ‚rÖiçx¾H'\{æé矀:X#‚j(P²ª({}æ$É¢²—dOFj©d+åUÞ¥œFFc§ †JX›¢–šÚ¦¦¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ënФ¾+ï¼ô~/V÷B½²Èï¿,ðÀlðÁã$G fKÃäækV£I ñÅgìÐÃKјéTk,òÈ$—lòÉ(;òQk¦ìòË0Ç,óÌ4ÿEqÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙhgì¯Å4Ý|ZËiÇ-÷KþÚÊöÜ'€÷q#UÿZ’uïuwxƒïÝÝ&s¹À’&†o]xãwûøU“û÷Gn Uù@—G.–6t}šØžG¶²Sº4´9Iˆ{µzé°ÇþV›¢kÔš¿u'Ôy•¹Ëîûï½NWæOmÞ;ðÈ'¿kŸÌD¼IÖewºòÔÃ:½m×W¯ýö> ÝóCyøÜ—oþùè§-ùê·ï~nì¿/?òD†ÿt÷ϯÿþü÷ïÿùtþ§­I3µ; HæÇ Œ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢ÿ&¾ˆqˆHLâTލÄ&:ñ‰PŒ¢§HÅ*ZñŠÅa"·ÈEƒh±‹` £ÇÈ?’ñŒhL£×xݱñX„çxE7ÒñŽS´#÷HC3N&| ¤ IÈBòˆL¤"ÉÈF:ò‘Š™óE±T2’˜Ì¤&Sâ·MöRÑ£'6@f]9Þ(i…ÊUÎ&_C‚*“’I¦¤®œ‹rù¤$”%Œ¹$/Ý4Ëa^F˜ÆLæÓÜæ¯V®%{ÊŒæFl)¯–A°˜ÒÌ&½É7‰š 'CÄ©ÍrZ†šæLg É©ÎvÞ|gFä)$zºóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤Va'JW 1{ò„›,©LgJÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR©Ò¥:õ©PªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²š.=ë_J©VÏ ¡­p«\çJ׺Úõ®2ƒ)^÷Ê×¾úõ¯€ ¬`KØÂö°ˆMìy°©ØÆFH¯ŽK ÒY­HO ÁÊDYY×5d² %A âЄÎ&($H-j[#P„±¦%‹hE+Ñÿ²À±…KîP»¶$Ø™mjn·²'ÚvhCf;ܶð¦H-AäìH·¹h œ ã@‘€®@&‹]çÆ!º­iB%ü¥Úòº¥) €z Â\÷²ðµD Pð±ÕÚw-Ë@%¢KÞÙ:ó¿ay.zQÜë"˜-®ïƒ×bÝö¶²> e3Ìá{øÃ ±ˆG|CÄÄAqATLÄűdLãÛ8Å7^qŽIÌãûøÇ@²‡Ld™j·È©2 ’±º%;9mÿx2VdL( ÀÊRÎ2j|©åµp¹ËLaë•‘Ød7ay!GnX'ÁræfqùÿS<¢2˜ „(¹66j›ËWæo¥y΀öŒ±|ç@:vkK¢µ“çCTÎ1ù³£'ý˜ESú(’É-.ÍéN{úÓ,4¨GMêR›úÔ¨NõCEÍê‹´Zհ޵¬gÍ¡=ÓúÖ¸>¨Óø¨m@z/5–ˆ­sMìbí×1¶«,mì0";x–úÆA”]²]/dÑ‹þóŸ±}mwI ±µµBm9=û…}^ˆ‹×\îÁ´{6 ƒâ—óåF7[#VÖn”­¼§wgÌßsÉ´¥X<…&ÚúÜfr  €Dqc&w _'p1U\!ó–a¢¼áŽû1„Àþ%8@/ÿpø@¤=c’ÜP'/ˆxwñ{§â6?ÉÅ Òº‘}Ü0¯ö 6-(\ *xÎ?’‚yÇÜ 8_:I¢¾ŒK]"*¸úLp9ˆ']T׺FN†g]ì)í@œ ®£"‰®œÕß>·'ä+—8Ý#òtÔGYÇûÞ7"^…~ð±;ÔÂvĤ~ iÀÓîxÇW¤ïi¼@0oy¸¶ó"‘¶æ-rv‘;þ­ ;ç)‚ð·“ô¡yI~û¶¼|°a_Hîk[¬rËøöŸQñïwîãÉì ayÓf‡g÷,¤½`v~›ÒˆìjŸ  ³çŽ‹Jú§>ÿA*þ!;•õo#fˆ8ßOÐW> ë¬ú¿Gü7!*©ï}Ù_ °•å×85mF^^„a72w 78ט·{­Wø§"~á{êö'Mðz ÷~·†zµ·ÿ` 2b ¶€zñfÙט+/Xÿ1ø$Ðg«§t9!‚3^€Áp+¨u X>xVEH¢vRRƒ¤!ná„=Ò&7ø€9( GX^_×YèiWhlòWç/éG‚-ae"¨oÁ„bå†Ñs#8‡)†`‘n[xW-H‡4s¸ ȃŽe‡|8„8e‘ux…è1wƒÿeëGVV*y-6y8WcØÞ ‘ |ÜWp¸ˆÑ~µ‰W±Kz'›:(°0¥'±èˆAF‹9Ñ'ngr‘~Ê'ˆ@öz1ŠÂ&‰Âx áW8„#vˆ !—†ðyH§ƒñtíçbÌ'd¶˜,‡ß m\¦8zƒŽèŠs‘pÕ8xgǀџ҂^Gâävv÷ ÂVèˆZ6q:”õ ØÀ˜ˆ3±„W£X¤]8ñuÔ´‡ÁY±¹Å>¹—{gHŽ-}ãØ…!‘Š Æp ÇŒ-Ñw½‹±z)‹¡`‹MFtA’(ÿÉ‘@’!x`‡ãxrã8v˜ujˆ`/@† uGGvPsy0&“±‘-i)].‰ü˜/yy Q\9aíg‡gÉR`û¨UŠ˜)²WŠ““`o ¡—†å—áûðÊ7˜:‰—±‡2W‡KX9Y,Ù”¡[!’`™ãÅTW—ñ˜êVâ5—$š¡]“)kIE)m©Ih03Xð(* ·{Òh“Iñu˜9W Ù…sƒ…÷(çÅ¿9Y瓦)³©1Rˆ#ÍIKšr™z´˜šI™'ÑÓ)W€ÿ‰aÉp¯Ùu¬Ø&‰¨)q uó1i@‘xÅ“Ó9s÷9û9U·)㹘÷t}'2·œ©Á’<…eÙsOÙ ”AuÕY› ™!^øa·‘¡º‰"|]5z' (áv·šÑš±'2:÷–Pµz,Z¹™íÙÏCuQ'¢Ü¹‹wžixöH\—ƒ?*£*výIŽ\§QÆeÊç •õžªŸm×çY¢á"á•CE:Súг2aj– HJjy5j\:ÏùW;z𙦿§¡—€Z<2K¦È{p5¨ÊyQÿ‡’q‰K¹¦÷ }Ûˆ£Cµ§!qž:u*zW›ŠT·¢D:(‰Éy?*¿pÿ)d` ÁuQºx§)癩U(¦Œ©‡rùw‘¹{j£‘}&öª;…lŸj¯‡©žÊa²ÚŽ-Qª?a­±ª!¶£ŠªYêTfŠ ži¤¨{ q§Eš‘ A©¢ÊúSϘ•±£ÐÚ Œ_'£÷‡ž }–SíªG‘{õJ{ï T_Ø“WY–,i˜OÕ­å:¯ˆY° ÁŽ¿™$•BÕ¬j”§êäÔœ +Têj«"­!¡­ÍE’uѦ7!¢ÿÿºT¹x˜¡87ذPÑ­7‹SKŠ,£ á.²~›Á´á´µR{SkU[WKYÛ´»"³Â´ âm!¶A¶ã÷mc‹¶e«¶g›¶¿c<‹žÔØ­v爨z¡bºI£9ay°A²c§XáÚCK´#Á8”=ÅMÛX¬ CÊÌè¸Á¥ŠC¢4¸ !f€i‡k´nºj„r+XY¸©T¢K,‰º#E±°çºœ!»!E»na»æj¸ ¶á‹[ñ˜”ÛÁ›ר祹¸ºû«ËÛ¼Ij*(ê¼!\…ÈŒ0K½~·RÓ:¼E¼jÿq:Þ{Q¸ËÊKR° ½6%‚ö‡e*æ»é›åMÊe›H²áqr^[Q)+«;Q·ð=ÊÙûP•׈ÉÁuóÛPQ¦—´àÁŽÚ‰ãa½ %±qÀ2cÁc‰Ó–»ÅÁ¯y+LP28¼iwçëxÈ‹vÀ×ÂÑ®e•!»W¿¡A¦;¹ŠÄ»?¢|§Ã·À •»€8µÚ– “u¨+j ÐÀ«¢¥M2KL")ÁWצ4릡¼ïIÃì[Æ tÄakjlñÂfÇ Õ¿VejÌvlz>¬Ç¢8Ê÷Çy‡V,ÇváÿpȈ|Ç.ÿ£Èà’ÈŽüÈŒ³ÆSÒ “®´L+cIK ù0!þ™$V÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡Å'8#JÑfMÔ&Ĭ¨F7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgºÃ‹Òô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©¼%T7ƒ¶©v&£VͪV·ÊÕ®zõ«`]2ÃJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®x5VóÊ×¾:*•~•Ë¡P ©ö°÷1%bïbÓÅ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨ÅüR[[°öµ°­lgKÛÚÿÚö¶¸Ý‰kÇâÜα}¾WoƒKÜâ÷¸ÁÙíX”Û½"×ÿЉbŸK]¿0·º?Y­I®‹Ýîz÷»àÕZtÃKÞòš÷¼èM¯zŸ8Þ‚´— ïH|2ßõÚ÷¾øÍ/t†«ßþúW1õ)ÿKàøÀN°‚Ÿ¶;øÁFÓ7"LáŸÂΰ†7Ìá<¶Ã ±ˆGLâ›øÄ(N±ŠWœž³øÅ0ޱŒYvá뉻2Ö® klãÍÅ>òÃ,ä"Ù <>²’—Ìä&;ùÉP޲”§Lå*GKVf13³Ìå.£dÂ#ÆD¦ëå2›ùÌhN3X‰¬fÖº`ÿ of2–‹ì'ÇyÅ-8HžRç˜Ü½}®ðž%è ÏùÁl†ÈŸ ²è‡Ú -xô‰%ÂˉÒtÞñ›MNcšÅŸV0§!êï6#‡vp¢1Òh‡„:Ò 6r©{<ë6ÛúÖ]‘ ÖQãz »Ñõz[ýëbÇZ ©6¶²Ÿ[ëeg–ØÎŽ6´£Míj¯µÙÄM¶µ‰…ãnÄÛwAÄMrÄÜA·cÉ<v ÄÝ€·¼2oƒÔ» ÷&H¾Mè~ó¹'þ.çªi£m|Û§nÝàë‰L;àjõ´szð‘LÜÀ°¼õÅ×Rñ„{üã _ÚÀiâÜ›üä(°O2ÊWÎr–¼å09M.óšÛ¼ÌgqÇoÎsÊÀ;e4ï¹Ð‡NtF¼èH_«Ê¡\'˜¦áAWpÆ3NÄêáµA´žtÜÖwé|=ºK-ö|Ýì]O»#Á,¶Ë„ípˆÛd‚Ôý!íÍû@À®¾«{wÿ;q«*øÂþðˆO¼âÏøÆ;þñ¼ä'OùÊwÕïdÁ¼å7ÏùÎ{þó =vf äd+ !ù ,”ÑLÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(/&Iɲ¥Ë—0cÊœI³¦Í›8sR$ ³§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦)!j¶é曵± çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öj+E ܪ뮼öêk—’ü*ì°Œ]Bì™Æ«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—|žB&§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ8æ*Úh·­ÊnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì`pü±¾hðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢§‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHF1¶¡ŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšÒh.8¥*WéšT¢O¬Œ¥,gIËZÚò–UäàÎ!ù ,‘¯ÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ Ib¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,°J TÔÀ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùågjƒùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀÞ½ ÔX "HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wظ4ć ÛÃÿd0ƒ,¬ˆ˜Áe00#ñ‰FÜ×7RÄ1ŠÿºÃ@®HÄ"vQ`3°¢ÈŀAñŒeÌ’D+V‘Œ‘‚¾°ÈE.&qDÄ—-2Æ>ÂÑ^{<Ñ(G|‘Ždlã­(€Mø Š^¬ã¿ÈèGFÎ`ÿ$Ó8/ D‘o,âvE’ˆR˜‚?üåI<`‹3¸Ã7¦ØJ~ÉAS£-¶ñZlŠÙ‡IÌbó˜È|XH„­R@ 4§°[´A¶pôQl# ·Ðœ?0°oÞB ÚP4³_ÛðG"Î=@Û@;û%j uF" Ò´'&àiò ÿ°EÁzÉÐ^jãHˆ&¿ª¹†Z -?þ±ÑHânøG6Š„%¡¡'Mi/ÿÍ[0T¥ðhÀàÒD¦"}§¿€šörœH(˜ÀÀË|Æ4,!ù ,°¯ÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF[Ò‚ÔV«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñȯ®BòŸÀüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿ¦2¼ú€÷ÏŸ× ú÷ïÿÿ  HÀð€L è”8UÿÀÁRpUt #x* JPƒ,?øÁŠ „$¡ AE‚´P.Œa gX‚Q‘ ¹¡qÈC`†?ta'IðÃRý‡:<¢BHUCÊP/4Õ§T ˆ@LuE‚!ù , BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöÛ þ&€lðY ¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Æí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜gNš?šwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒà€Z Á`b!ù ,”@ÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë— ÀœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿ 0À‘B'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Âí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnù°þ@üÏåœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ&ÇŒ`Ç è°€!ù ,‘BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ Ib¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,°J TÔÀ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Àí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùågjƒùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀÞ½ ÔX !ù ,ƒDÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸bB®† À®¼+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷9í÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.úè,©@ºZ!ù , BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöÛ þ&€lðY ¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Æí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜gNš?šwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒà€Z Á`b!ù , ­¦ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨Sç%±„ê×°cËžM»¶íÛ¸ÈÍ»·ïßÀƒ N\&ëâÈ“+‡êHn›åУKGz|énÓ³kß.±÷ïàÃÿn.¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿×Ýþ(à€h [ÕUwà‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶è¢\%¼(ãŒ4Öhã8æ¨ãŽ<öø>)äDiä‘H&©ä’L6éä“PF)åNØMiå•Xf©åEUnéå—`†©•kb–iæ™hÒ¨`šl¶éæ›® çœtÖi'~Ü©çž|ö¹¡œ~ â6‚*ÝJ†&ºaŒŠ6êh^]>*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf[X¤Úvëí·rË•¸E…«îºì¶ëî»ðÆ+ï¼ÉAï½vÙ‚o±äª(Hýî+ðÀë»TŒˆN•0Á 7ìðÃG,±K EæÄg¬ñÆwìñWÿ~,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õ€éŒSȨ]<õÖ\w”.¨Vw}obÄuF’œTÁ{…}žÛeg·É\.°¤IÜ=Ã÷Þ»êÿ½•ß‚iýÑÙB~à|k¥ ]Œ&6Gâ‰Uì”. ŽÒÜ^YùæœEnã±–î× !Þ$é§Ž·æxþë ®úì´c èí¹nRuØI^ûï†ún›ðÀoüаg§ûPÉ/µüñÐG/ýôÔŸú|õØgÚõÚw/6r?øÞ—oþùè§ÿ!ù=§~¯„¾oèò×opìç—ÿýü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì 7ÈÁzðƒ ¡GHšð„(L¡ WÈÂÞ§y¡ gHäȰ†8Ì¡wÈÃúð‡@ ¢ÿsÃ!1ˆE<¢—ÈÄ&þnNŒ¢§HE!š®ŠXÔ!$²ÈÅ^±‹`œáÃHF Bq2ô+£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ#EÎ$–Åz ¤  ’´ÒF(ÊÙ-÷‰xiü#AÉIª&lˆC‚씂>¦¤–t‹BI¤$”%Œ$)Á´ÉUNF•®Œ¥ÌΖ®J®…x²ÌeD<©­‹í¯•º æ´`¹ñ¹— A&C”)Ìf2†—ÎŒæ™)Íj¦š|ÁfF´é#nZó›à §8ÇIÎršóœèL§:×ÉÎvºóðŒ§<çIÏzÚóžøÌ§>÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:tÔ|¨DÝåMžs¢ͨF7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©#*ÓšÚô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦°¢NÝ‹#£ª$PõªXͪV·ÊÕ®zu]ýªXÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺:5¬vÍ«^eʽÎEAHüJØþ°­°u*bËØÆ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒþì°¦­Š!SËÚÖºöµ°­lgKÛÚÿædµaù‡mãhËݪkq¾ ®p‡KÜàà6,ÇÝNo‹ NèµÌî^’+Ýž@·$·¨®v·ËÝîÆ-~Þ ¯xÇKÞòš÷¼L/AÔ;öJĽ€/zçKßúÚ7:º½¯~÷»ù¶4¿ü °€LàøÀQ0‚Ìà›IÁŽðw%Lá [øÂ>d_3Ìá{øÃ ±ˆGLâ›øÄîùŠWÌâ»ØeÎ}q¢¨Ûâë¦Ð¿2α"‘ëøÇ ó1‡LäõùÈHN²’—Ìä&;ùÉP޲”¿å€)£x°Vβ–e"ä "öÚ²˜ÇLæ2›ù«]>3iA)6#¹ÿÊC®›’á|b9ÄÎÀ³KÜ\^TXÏ4…é¼à47äá3D=0Ä~ná†íôèW„8“ ñ|éGZÂFH¨«;iŒÁ†®ˆ¢­G£øÓ–^ò¨ÕLëZ7dÕ9†õXgMf‘¾§¶µ°]üé`ûØÌå5²)kìe;{ Í~¶´§VeÛ6ÚÔVv ²í‚t› ßH¸2n”ûÜA7·ÓÍîuCöºð>H¼ 2ï‚Ô› ÷H¾bãQÙùßî ÀÅ \ÞÛÙN8qS k×o8[\hÆx;‰ $ L3g|-W¸ÈGNr¤¥Z&VÞ-¹ÊWÎò–»üå,L$ÌgNó«:¼æ8Ïy’!þâëüçŽé7Ênô¢ýès:9Ò—NÖLO‰áy6M2u ÿº WGˆ®²õ†`¹ _gúláëô½*%B>{F.N¶_Äíb{¬v’Ð} w7HÚ'¢bô]ÿ»aÊ.÷ìÕ½ð­*âÏøÆ;þñ¼ä'OùÊ«ìð–ϼ櫉9¿` ™ÁæJø¸L` (1æGÏzоõ°i¹•\ñ‚Háįwò.bߨ}Däô2Îý‘WáÛ+™øº !ù , ­–ÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(–Hɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨Sç°„ê×°cËžM»¶íÛ¸ºÎÍ»·ïßÀƒ N<&âÈ“+êj¹óçÐgê:@ôëØ³Kl®½»÷ƒÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏu7ÿÿ(à€¶Â@¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶H—.Æ(ãŒ4Öhã8æ¨ãŽ<²UD@)äDiä‘H&©ä’L6éä“PF¹ŒRViå•XfI‘uZvéå—`nÅZ˜d–iæ™3N‡æšl¶éæ†j¾)çœtÖ‰_væ©çž|j8fŸ€ŽxK „B÷g¡ˆbX@¢Œ6ª•ŽF*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØÆe¶Üvë-„n.QÛ~Ûè¢æ¦«îºì¶ëî»ðÆ+/AqÌk¯]ƒÞ;ì¸ñKÔ¡#ù«ïÀß« u\ð 7ìðÃG ˜ÂE ,ñÅg¬ñÆwlŇ,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-  þrjWK­õÖYli¹\/œBØ0ÅùQ$'UmÍD^÷_ÛdC·Ë\*°´IÜ<ƒ÷ÞÂêÿ=VÕCYÂTÖ.àÎ÷TÙÐ…nbw,ž˜âFÌß’a.ù®ùn. ÙÍÑ*÷{®ºäš zU­·¶úì´ƒJñíQ^’š†Pûï“ꮚðÀo|‰§{G³ÆSÒ “®´L+cIK ù0!þ™$V÷ÉÿÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡Å'8#JÑfMÔ&Ĭ¨F7ÊÑŽzô£ ©HGJÒ’šô¤(M©JWÊÒ–ºô¥0©LgºÃ‹Òô¦8Í©NwÊÓžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©¼%T7ƒ¶©v&£VͪV·ÊÕ®zõ«`]2ÃJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p«\çJ׺Úõ®x5VóÊ×¾:*•~•Ë¡P ©ö°÷1%bïbÓÅ:ö±¬d'KÙÊZö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšö´¨ÅüR[[°öµ°­lgKÛÚÿÚö¶¸Ý‰kÇâÜα}¾WoƒKÜâ÷¸ÁÙíX”Û½"×ÿЉbŸK]¿0·º?Y­I®‹Ýîz÷»àÕZtÃKÞòš÷¼èM¯zŸ8Þ‚´— ïH|2ßõÚ÷¾øÍ/t†«ßþúW1õ)ÿKàøÀN°‚Ÿ¶;øÁFÓ7"LáŸÂΰ†7Ìá<¶Ã ±ˆGLâ›øÄ(N±ŠWœž³øÅ0ޱŒYvá뉻2Ö® klãÍÅ>òÃ,ä"Ù <>²’—Ìä&;ùÉP޲”§Lå*GKVf13³Ìå.£dÂ#ÆD¦ëå2›ùÌhN3X‰¬fÖº`ÿ of2–‹ì'ÇyÅ-8HžRç˜Ü½}®ðž%è ÏùÁl†ÈŸ ²è‡Ú -xô‰%ÂˉÒtÞñ›MNcšÅŸV0§!êï6#‡vp¢1Òh‡„:Ò 6r©{<ë6ÛúÖ]‘ ÖQãz »Ñõz[ýëbÇZ ©6¶²Ÿ[ëeg–ØÎŽ6´£Míj¯µÙÄM¶µ‰…ãnÄÛwAÄMrÄÜA·cÉ<v ÄÝ€·¼2oƒÔ» ÷&H¾Mè~ó¹'þ.çªi£m|Û§nÝàë‰L;àjõ´szð‘LÜÀ°¼õÅ×Rñ„{üã _ÚÀiâÜ›üä(œO2ÊWÎr–¼å09M.óšÛ¼ÌgqÇoÎsÊÀ;e4ï¹Ð‡NtF¼èH_«Ê¡\'˜¦áAWpÆ3NÄêáµA´žtÜÖwé|=ºK-ö|Ýì]O»#Á,¶Ë„ípˆÛd‚Ôý!íÍû@À®¾«{wÿ;q«*øÂþðˆO¼âÏøÆ;þñ¼ä'OùÊwÕï¿ !ù ,”ÑLÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(/&Iɲ¥Ë—0cÊœI³¦Í›8sR$ ³§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦)!j¶é曵± çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öj+E ܪ뮼öêk—’ü*ì°Œ]Bì™Æ«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—|žB&§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙ8æ*Úh·­ÊnÇ-÷Üt×m÷Ýxç­÷Þ|÷ÿí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒ 'HÁ Zð‚Ì`pü±¾hðƒ ¡GHšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡wÈÃúð‡@ ¢§‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹` £ÇHF1¶¡ŒhL£×ÈÆ6ºñpŒ£çHÇ:ÚñŽxÌ£÷ÈÇ>úñ€ ¤ IÈBòˆL¤"ÉÈF:ò‘Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšÒh.8¥*WéšT¢O¬Œ¥,gIËZÚò–UäàÎ!ù ,‘BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ Ib¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,°J TÔÀ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Àí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùågjƒùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀÞ½ ÔX !ù ,ƒDÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸bB®† À®¼+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷9í÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.úè,©@ºZ!ù , BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöÛ þ&€lðY ¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Æí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜gNš?šwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒà€Z Á`b!ù ,”@ÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë— ÀœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿ 0À‘B'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Âí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnù°þ@üÏåœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ&ÇŒ`Ç è°€!ù ,‘BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ Ib¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,°J TÔÀ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Àí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùågjƒùæœwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀÞ½ ÔX !ù ,ƒDÿH° ÁƒI \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸bB®† À®¼+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷9í÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜g®ùæœwîùç ‡.úè,©@ºZ!ù , BÿH° Áƒ \Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËÿO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è „j衈&ªè¢Œ6êè£F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöÛ þ&€lðY ¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þ|÷Æí÷߀.øà„nøáˆ'®øâŒ7îøãG.ùä”Wnùå˜gNš?šwîùç ‡.ú褗nú騧®úꬷîúë°Ç.ûì´×nûí¸ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþù觯þúì·ïþûðÇ/ÿüô×oÿýøç¯ÿþü÷ïÿÿ  HÀð€L ÈÀ:ðŒà€Z Á`b;iminuit-2.30.1/doc/_static/interactive_demo.ipynb0000644000000000000000000000360714332717401016770 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Short demo of interactive fit" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "1ef533261cdf44c88ab722730615534d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(Output(), VBox(children=(HBox(children=(Button(description='Fit', style=ButtonStyle()), ToggleB…" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "from scipy.stats import norm\n", "from iminuit import Minuit, cost\n", "\n", "truth = 100.0, 200.0, 0.3, 0.1, 0.7, 0.2\n", "\n", "\n", "def scaled_cdf(xe, n1, n2, mu1, sigma1, mu2, sigma2):\n", " return n1 * norm.cdf(xe, mu1, sigma1) + n2 * norm.cdf(xe, mu2, sigma2)\n", "\n", "\n", "xe = np.linspace(0, 1)\n", "m = np.diff(scaled_cdf(xe, *truth))\n", "n = np.random.default_rng(1).poisson(m) # generate random histogram\n", "\n", "c = cost.ExtendedBinnedNLL(n, xe, scaled_cdf)\n", "m = Minuit(c, *truth)\n", "\n", "m.interactive()" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.13 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/_static/minuit_jupyter.png0000644000000000000000000011244714332717401016204 0ustar00‰PNG  IHDR€ÜbªciCCPICC Profile(‘uOKaÆŸ­ )2°(0ÚC‡²uB=XQ`Vôç¶»š «¾¬á­ º/tŽÀ:Ö%$úEСºõ‚½”lój¥ óãaæáa€IeÌä –™ŒGåÍ-Ùó Cèüª^b‘Db‘Vð=ÛËy€Àçý8÷òwß÷/ìÏœø¤juiäï~[õ¤Ò%æuXg¦AâÄ®Å8ïûL E|Ä9Óà3ÎZƒ¯ê;«Éñ-±WϪ)ââ€Ö¢gZ8oìè_xz)]X[¡9HíGi° q¬CÁ&ÄÜ?7áúM E0”a"‡ ²°è:B ƒAn2æÉQÇÄ ¹)ñ_ÿþaS+žÓÐi75~pyH1›Úè1Ð{\Ü0ÕT>+8bi;¤4Xšºž]÷m ðØ@ÍvÝ÷ŠëÖ*äÿ\—?É'bzȺ½VeXIfMM*‡i’†D  €ASCIIScreenshotÿ:}ÄÖiTXtXML:com.adobe.xmp 384 639 Screenshot cö@IDATx옕EÇ)ÝÝ]ÒÝ’¢ˆ""¶"Ög¡Ø‰¢ØØ‚Š (‚„"€Jw))ÝÝÝ|ó›e.ïÞ½wïÝÞeÏyž½oMþßygþsΙÙ4ÅŠ;'*Š€" (Š€" (©´©¢–ZIE@PE@P‹€’?mŠ€" (Š€" ¤"”ü¥¢—­UUE@PE@ÉŸ¶E@PE@PRJþRÑËÖª*Š€" (Š€" äOÛ€" (Š€" (©%©èekUE@PE@Pò§m@PE@PT„€’¿Tô²µªŠ€" (Š€" (ùÓ6 (Š€" (Š@*B@É_*zÙZUE@PE@P”üiP’ ­[·–Ž;-MñâÅ¥K—.R¶lY¦^½zòý÷ß ñ[*T¨ C‡•š5k&vÖšŸ" (Š@HÇø]Pâ G}Ô¦´eË™7o^”TüqKüråÊ%kÖ¬‘K.¹DÒ§O/3fŒ6¡odÍšU²gÏ.9räHè¬4}E@PxF@É_<ªÉ)±EàèÑ£’%K¹ýöÛ£¿œ9sú4~.ýiÓ¦ *Š€" (Š@LPò´4¬"”.]Z {ðåÖµkWß¹;ÁüûꫯJŸ>}dÑ¢EööwÜ!­Zµ²Z¹µk×ÊÒ¥Kí5÷‘AƒÉœ9s¤ZµjR¨P!Ÿ¸·Þz«´k×NÐèX¼øâ‹AèСƒìß¿_ºuë&gÏž• 2ÈàÁƒ­6ÏiÏž=6Œ»·~ýzùꫯd̘1ö Kúõë'-Z´•+WÊwÞi e=dÓ¦M6Ì|Å íÒÓ£" (Š@òF@5ÉûýhéR!<È^Ë–-míÑæ9rÄjó‚Á‘9sf«±Ã„ ñCÐÐ-^¼8J”åË—Gº‡p÷îÝò /È»ï¾+Ï>û¬}Ž )Q¢„5A;âǽ?ÿü“ƒŠ" (Š@ D@5)ð¥i‘/næÎkÉÞ 7Ü Ë–-“¢E‹ÊèÑ££­ô‰'ìsH Wü¯yvîÜ9oyì±Ç,Ñ<~ü¸°Òxß¾}‚öÏ +ŠYŒâÿkï3=WE@HÞ¨æ/y¿-]*E€>ˆš¼áÇG‹a:$uêÔ‘¼yóڰįZµj´ñxÈbd“üú÷ï)ζmÛlšh#Ô¯_ßêQPE …! ä/…½0-nê@`Ĉ–ôU©RE–,Ybc„ª9~xéÒ¥³þ{C† ‘O?ýÔgŽ..~†ì×ÇBLÍo½õV¤à¬ú%Ý?þØn(}ß}÷IÓ¦M#…Ñ E@P”ƒ€’¿”ó®´¤©¤ùúë¯íÑÿÇùö9sÆ>bcègžyF&OžlÍ·,ö´  ïÒƒÔa f…/š?yxMÃ&L°Û¾(P@؈º}ûö2uêTÝ•Á¥¥GE@Pä@šbÅŠEvJþeÖ*Š@ olïÒ»wo»Øƒ Æ “´iÓ [¹„öðc?ˆg0!}¶‡QÒ !½¯(Š@òG@|$ÿw¤%TÂB`×®]Öt‹ 1çË—ÏškGV|H](ÁÿOEPE e# š¿”ýþ´ôŠ@$5jdͲ¿íÛ·Ëĉš~#EÒ E@PT…€’¿Tõºµ²Š€" (Š€"ÚЩ½hýE@PE U! ä/U½n­¬" (Š€" ¤v”ü¥ö õWE@PT…€’¿Tõºµ²Š€" (Š€"Ú¸Õ‹÷ß8¥v€´þŠ€" (Š@rBÀý/ïäT&-KÊB@5)ë}iiE@PE@ˆJþâŸFVE@PE e! ä/e½/-­" (Š€" (qB@É_œàÓÈŠ€" (Š€" ¤,”ü¥¬÷¥¥UE@PE N(ù‹|YPE@P”…€’¿”õ¾´´Š€" (Š€" Ä €ûüÅ$Å-ZHž+\¸°4kÖL *$+W®”I“&ÉñãÇ#ÅK“&´oß^<(S§Nô,.¹rå’V­ZɲeË"a›6mZiÒ¤‰T¯^]:$³fͲe‹K^WPDø–¯½öZY¾|y¤olè[Ú¶m©¨T©’tïÞ]räÈ!~ø¡ÌŸ??YÀX¬X1©_¿~”²Ð‡-Y²ÄwŸ>°uëÖR¢D [çqãÆÉ±cÇ|ÏõDPRq&wÝu—@ìüåßÿõ‘¿ÆËc=fƒœ9sFjÕªe ðƒ>°÷!W7ß|³íXzè¡HÉuèÐÁªø&õêÕ“§Ÿ~Úæá«Y³¦\}õÕòè£Êþýû#•ᦛn:È@ñƒ^~ùårÏ=÷Ø ÔHžzê)Ù¹s§½O¯¾úªÈ#¾Èy[ºtédæÌ™¾ˆwóÞ{ïIþüù…21XQGHvß¾}UGï)Š@˜dÉ’En¹åûmÝwß}vBç¢V¨PÁ~ÿ»víò}çô7Ä™>}ºlÚ´ÉMòc›6m䪫®ŠR&ðŽüÑ_>ùä“¶a“a&ä×\sMÀþ2JBzCP’q&ÔfÛ¶mòÈ#¬XéÒ¥mç@gñÚk¯YRÂyùå—R¸zõjùå—_|qÑÞyçòõ×_ûî%ÄIÖ¬YåñÇ—ÇË3ÏV ;dÈ($×WÏE <˜t½òÊ+¾In°XÙ²e³ýÅ'Ÿ|,H’ÜÇzƒ…âöÛošÿ< ôãL2± ÐçÐ÷п 0 h<} (É÷ùCó…ÙÑ?  yá…¬¹3¥WÐNa-[¶¬÷v¼ŸÓq¥OŸÞjVM$¤ô‡~™$â·`ÁK 0¹bnE›ñCÐÀ;wΚ€¹f¦¼~ýz«¤óô—*UªÈ›o¾)²O?ýT:uêä$àuåÊ•eâĉòàƒFyŽyqZSÊó÷ßÛ{¥J•²GýQ¸!@¿…V¿sçÎÂÜûÕW_ÙÉ×¥—^jÏË•+gÃÒß}üñÇÂíóÏ?¤ƒX}ñÅVÃ6pà@ùæ›o,ù¤Ÿù‹Î|K~òäI;v¬%~äýçŸÊÙ³g… ¾Š" ¤,âEó]•!!¯á!!wÜqG”¨ï¿ÿ¾Õ–½øâ‹‚I™p¡­Z† ìúí·ßFy†!6¾7ħ3ݲe‹Œ1Â’¸(ün<üðÃö5‚ ·wïÞöœL;h1³þñÇö>ÚÌ`,¾4hÑ bj¡Cu椟þÙ—n “çŸ>hºhU1×@j $Tø¢E‹%§÷E †ð£é¿á†¬O-} „É ®!Lñ{>pà€5¥âó{ÅWX‹÷øî!„X>è÷ð§Ã‡8wîÜÖ|¼xñb;‘laü¬éïðô&Œø04u„~>—”’%KÊÞ½{e„ –ì’Gæ&³ÔqݺuÞÛz®()x!hÁ>ûì³HÕ…l QƒllÞ¼9Ò³è.ètl;DL­ÁP‚¹3ß!ñH/)RÄúÇá߇Ù>:©×_Ýç¯(.D mÛ¼yó¢˜Mé¬?úè#Kúˆ ñt~}Áˆáèð!Š˜…ÝâL)×]w„"Ñ¥‹#ú¨Q£¬FâÝwß%+Û‘?÷Üsö\E ~èÕ«—í¯8Þ{q囯*мys»°ÌùÛâKÌäbÅÄó1}ÚAÈŸ4ƒXúü¦ …}ûözd'»˜›˜£™ÓnذÁ@ú$î3!öÈ"¾ÌøJ3©UQ”…@¼?ª|äÈ‘€5§CË”)SÀgÁnÒé±ò—™4«ƒC mL…Nñ.|€¸1›Fãæ]©ìŸ6>/ÌÌý /á ¢˜mYí[·n]ëCƒ†sIt™dM‡êâŒ@ [¶li5¡îGʈÿ^tÂJDLQ >Ó¦M³<Ú‡7ÞxÃ:oÇ„˜G—>SR;hûFŽ):üã˜F'ôAø³úž~¡¯`Bê/³gÏöÝZ»v­]œæ»á9A[Ç_LeãÆÖœËâ0—ÌÍ,¶ó'ølícÏž=îŽÓü5¼" $.ñBþÐð± ,@† ,èQ´÷0¡~ùå—ÖœæIÊŒŽ×¿ ÛÌ  &Å‹·ÛÂÌ;7ÒÊ>žNÜiêè<¿ûî;»D(òçȨH² ¹¤³Ýºu«`öñ >†¡3‹ZŒœ°ðS7$÷wÞq·õ¨(qD-; Çðe¦sY8W|é¢&š˜]xûw/®Gÿ 4yÐÇQ\Xœ3Q4“9sæ, l£¢()x!ÑU{ÕªU–dÝxã‘f˜ðAƒ²ï•¿`Êd¶F`˜èGiGžüÃ1«d:Æ­"‹6ØwAó†¶ÍŸAošøúÑ;_?÷ -%+žY°áVÿò ›ÿ \Ç{Äo??|I¡,nåõ÷›ôÆv΃o‘W ƒºŠ" Ä/¬úeâlñ‡ËÕµü¡õ÷ +nùFÝ"-ï³Pçl5Å–SÁŸD¡ßÃt‹¦ó²&Áh"ñã>“Eú3V+Ï™3ÇÕ£" ¤0œüែù“Ž_9̬t˜F lhÆ‚ 3OÌ¡È3óù f¾%þtt–˜80Þi|\ KìÙ‡ }dÁ NÒ8C³H„?ÊäO¨(«3ÛBFIY3¦d] úŽ?Þ’GÌÎh#!~hæ Á,|‰­°GþAø`þöÛoÖÌÄ lÄ-D‰mÚOP¢"@ßÀjý@“ZÿÐLN[˜Lúþúë/»;›-ÇöÛdÇ[ q“Jÿgh±„àjÃÄ—2Ñw±B™É»úRf‡6ÃÏ—/Ÿo74œlf¯¢()x!^“„ÕqÆUd 6´~|„Á¬€Ïœsb–¾%l‘€ãq0>|x°GAï“3t|Vî¾ûnŽÎ‘øûï¿·×hÝðW̘1£%8e¯ÿþQÒ¥>¤Å6ì÷‡ .X@JXÂL›}ùÜž‰¬ ¦Œq4‘,bá¿{ åD(+3} E@ˆ=ÁHH]µjÕ|šü@¹à~Áâ VÎòGzK—.µ}^ ð¡îá Ž;ˆ:;´zøó‡0e',BA*V¬hÿÜ}4ƒJþzTRiŒß[”½Tð1KAÓ Á1š™frf³ø°`®õïÌ)s°™t°òcNÅÏ‘UsÁHm°¸ÜgVÆ/Ø"šèâF÷ GÌIþÿ½$º8úLP‰Ñ/Ʀψ¯BDÙn†Ikt»ÄW~šNìÀ¥¢ÄD%q)¨ÆUE@Pˆ” 8(qA m\"k\E@PE@P”…€’¿”õ¾´´Š€" (Š€" Ä %q‚O#+Š€" (Š€"²Pò—²Þ—–VPE@P8! ä/NðidE@PE@PRJþRÖûÒÒ*Š€" (Š€"'nò¬{Å S¬(Š€" (Š@²E@5ÉöÕhÁE@PE@ˆ”üÅ?¦š¢" (Š€" (É%ÉöÕhÁE@PE@ˆ”üÅ?¦š¢" (Š€" (É%ÉöÕhÁE@PE@ˆ”üÅ?¦š¢" (Š€" (É€[½Ä¤´­[·–7víÚ%“&M²ÏÒ¦Mkë]£F 9tèÅbåÊ•öY|ýT¨PAHÿï¿ÿ–Ý»wû’Ö-[ Ï7nÜ(S¦L X_„ó'W]u•têÔIî»ï>9{ö¬ï1¸·k×N8._¾Üæ_„Xœ 0À¾×Ï>û,ìØ¼‹«¯¾ZÊ—//ãÆ“… F—w.¼ã9sæÈŸþ©ž.r•*Uäšk®±í€¶Èûó—PaxW\q…T«VͦCù¶lÙb“á½¼ôÒKòÌ3Ïøîù§¯×Š€" (Š@B!¦X±bçâ’øðáÃ%K–,Q’€üýïÿ“k¯½Vîºë®(Ï?.ï¿ÿ¾Ìš5Ë÷ Â…¼úê«2oÞ<ß}wòÁHÙ²eå—_~ÈB|IΜ9eРA’>}z9uê”=ž;wNÞxã K¼ù0è¿õÖ[Þ[¾síwÜ!’?þØßÓ§OKºté$Mš4ñZîûï¿_Ú·ooó~çw,¹äbñæ›o d–ºp¤.Ÿ|ò‰L˜0ÁWVÿ“K.¹D¾ûî;™1c†¼÷Þ{¾Çsnœ9sÆÖbøå—_ÚúøÆñdôèѲxñbKŠÂIŠIEÿþýBçÊ1…PÂ}ýõ×’+W.áð®;&·Ýv›ÅÉÅéÙ³§Ô«WÏ—&Ø=öØc²víZDB…ÉŸ?¿Å›ï‚<2eÊdßÁ+¯¼â#¨´7&BÝ»w÷¥«'Š€" (Š@b /f_4hJ¼?¯<ûì³öù< Æ ³$‚{Õ«W÷;zô¨=¿ýöÛ}÷Ü  â—Ƀ ½øâ‹Ò¹sgXA(~øá(Ù-[¶,R=©ó=÷Üc÷U«VÙð]ºt±Ä-Öu×]gÿÐÌ¡Yƒ„ÄU>ýôSKüvîÜ%)ð¥.`K]ºuë&mÊÜrË-–(<Øìù矷˜Ïž=Û’$´‚¤Kz÷Þ{¯­£/p"Ÿ¼öÚk6ÇGyÄÖsúôéR¹reA{Hx—¿Ú÷ÁÄ’þôÓOû‚ׯ_ß¿þùǦI!º½zõŠQÚiƒÕ7ÞèkGhTüúë¯R²dI)S¦Œ»¥GE@PE Qˆ;‰a1!Š?§¡aðö—Ò¥K dÏ+]»võ^ÆÛ9„sæÄ‰åßÿµé¢µìÑ£‡ÕÞ…“‘«Ú5rDzãÇ·×IÄ/GŽö?ÁÏ?ÿ\FeóBãŽ`fÿè£ÄKÔ\¼¼yóÊÁƒ’ŠìÙ³G ¥‘èS(ñ0]#HL켯×_Ý>ã>颙E{výõ×sË $-á÷ß/ß|ó<úè£î‘=¢©ãùÈ‘#m1ÚÓ`e"ïŽ;J¾|ù"¥á.²gÏn‰'ZÊõë×[‚™g4Í„ú…Ó.cžÇ¼_§N_pâBöМrÄ´ýÛo¿YÒXªT).œ0h[yßîlÚ´Éâê­ä æB`ê" (Š€"ÄÙç/¶eZ½zµlذAJ”() î¡Á|êÈš5k&ëÖ­ˆa0Œ ‰ &¤é/U«Vµ·0~øá‡R¨P!Ù·oŸüñÇ‚)2”.\Øj/çÎëóc„àxb„ßãÞ½{}aÚ¶mkÍâÜ›?¾Mã…^'žx"¤?#Ú<̉^_J—þ}`€©ý÷ß·éRG¯ÙÒ…õ1U.]ºÔw _B„4üRƒFÓ Ä“&„ Ì X Dß6²Šis>Äó9æê@fOHñÝwßm}óÜ$ÁåÅ‘¸~{N0q£]%Ï@ÑĬìÞ¹q{°åâ_òî!ÀNMXüS)ZEˆf8a\]^ä ñÛ¾}»»%äG>øª(Š€" (‰‰@¼¿¢E‹Ê˜1c"•¿<ü¢4R9Ú6RQØ8ò‡)â0tèPkš –&Žùhw Z¡@‚òàƒÚÁRŠy‚…–-Vt‚†ËùÔù‡ëÓ§T¬XÑÞ†äy‰ÎwÞi‰ $ Ò„Ÿ44œþäÁ?]0 &_}õ•%*h¨œŒð/¿ür°(ÖÜ‹V’Å!NœFlÑ¢Eî–4mÚÔjIÝ 4Z,ê¡ħ~hÓ´ƒ5kÖ´þ ´›hÃÜ¢´€N›æÒsÇ©S§Z­c0òíÞdÌ+h-!±þBûÄçrëÖ­‘Q~„w„ÖRêÆ‘æråÊٰᄱ=?\´™®=»G´ Þ»Š" (Š€"˜Ä ùCƒá¿˜I(q EüWSBòpªge&+YÑè9r$’¦'PÚh©iª…u÷püG(„ "†Ù‡|4hÑ‘?ÌÅh¡ð‰ ´zùÛo¿•J•*Y„æ@@”0]"ÞÅÜw~ø¢ù›)«F£üYýŠv²¹nРôíÛ×Ú@$mqaC>œãCè|Ô S˜„!¸øˆaÑœBþ¨ÃäÉ“íÊZâƒqÖ¬Y£Õà¢yÅß0˜Ð³qÆŒ-÷çÚ /¼ââ»ôÜBo×F60œ0ÞøhDÑdÓœØ='M‡½»§GE@PE ¡ˆòÇ`#}L’É`Õ£W0¡2 ßpà vÀDsL ä›s§ÙA ñC0!R4Žhf;Â9­Ä* Mâ3ð­·Þjÿ[´haÉ¢ O^N _Ž ,Y²Ä’P÷Œ£¿VÊûŒs4•Q¶<ñjúÀÒ‰éÜmEã{òäI{é%znñ m(ªW'hzÝ{#ž#Gî¹#Tly‚)–ÕÙh¿ÐÎyI¦ “#æZbëιvþŽœ{S.¤ ³W ïîåò÷5udü¿ÿþ ;Œ h~hµjÕ²¾ŸøBú ­±Š" (Š€"˜Ä ù‹M!$,pf@ÿ4ÐàáWန±H ”°ÊòÊ+¯ ŒEþâüÀ &^A›E¾Áˆ0ÌlUƒÖË+¬Æ…ÔzÉ„Œ•Ÿø8BÀxŽ˜wµ)$× ¾PZ>ÖѨ!¯@Îïbïs·ÈÃë/‡ï„ mÄÛ«1Ä_-¥#Dh1‹ºíeH›Å"~y—_~¹Õ z·¤Á¿2:ÿM9È#£ì=è0‚رÆK½ÑÑþ]z饖€ºº`Ú†´:ÒÉšw@]\nA†ó‡ ' ù¢ádò€æ:ØÞ…c©(Š€" (‰‰@¼?H…wå'ÀÌë ­‹prge@æß6bÄë³F´gÑù¹9À0AºÝÝsÇ`Vt®X±Bj×®m·x˜±GLY0ù?FüòVø’f ­éµiÓÆš®ÇŽkI GVÐ,âC‡y“•ÁhˆÈ—ÅäÁoLñ—„Ôëæ›o¶eeSã@ù7/ƒœâ§IÇÜÌû`k™FYRƒÆS&.O>ù¤Å-'‹(ØàÿKˆ%äÁŒÙiÒ¤‰5{'ð¶ œÿ!oÞ5øá« Qu[ ¹÷៚iÊøöÛoÛý ™X`öõîÉÊëºuëÚ­]8‡ÜÓV1Ÿ;N¶Ä!}půÐûmüøã>²é¿Ä[G=WE@P x!ø¯ù¯¤…TAþÜ–áM$í¿¹ÐU²‡é“•²Žp¹gÁŽ„ç/¦Ò»wo»¡3äËmœÌªãçž{Î&EýÐjA\´~ü¡õóײñœ žÑêàkçüö =äãþZ0°·œÓ’A6ñÙ WœÆÊRÊ6*h@ó,ûâEG Y<ióÊ!C,YÃdíÈÏ©éAV)RDØßЙÂ!Š?þ¸}QWˆ—6Û™@ðÐŽ9§{Æ‘z@~1õ"¼.,R×@uaÅ6¦Y·²ÛÅ t oHõäùK 4À… “„@eti°@‡r3û.œ0.=ÿ#>cRfu·Ó*ú‡ÑkE@PE !Pò—¨¦Ð4Ñœùû!¦Ðª$ëb£d£s(Ú`E@PE 1Hôÿ𑘕Ӽb†ÿÙ-¡ÿâ—˜¥¢¡C!€¦íê»ï¾*¨>WE@PâÕüÅ;¤š " (Š€" (ÉÕü%ßw£%SE@PE ÞPòïj‚Š€" (Š€" $_”ü%ßw£%SE@PE ÞPòïj‚Š€" (Š€" $_nòüЈ^É·ÄZ2E@PE #ÐïÆ^©¸öZõø@@5ñ¢¦¡(Š€" (Š@ A@É_ yQZLE@PE@Pâ%ñ¢¦¡(Š€" (Š@ A@É_ yQZLE@PE@Pâ%ñ¢¦¡(Š€" (Š@ A@É_ yQZLE@PE@Pâ%ñ¢¦¡(Š€" (Š@ A@É_ ^ÔÙ³geå¬%²oÛ6-['—® øÌ{sí‚òU÷…ô±^ä åü»žŸËÒÉ ¢ÜçÆ¹³çl¹¶­Þð97w®ß&ÿÍZ,§Nœ´aÂÉÓ›XLÃ{ãê¹"6-[+[þÛ0êÚ…ÿÉÞ­»> çæžÍ;å÷ÏGÙo‚ïbIïøácáDÕ0ñˆÀ‘ý‡l_¸}õf›ê?æH¿{^‹õ»ˆküx¬š&¥$k”üÅàõ¤M›V~ùp˜üñÅè(±NŸ:-_>úž,Ÿº0Ê3ÿ‡÷’Us—Öñäø‘ãrüHôƒÓþ{ý“²×§O’AO|(ýx[Ξ‰ ”þ‡¾ð™|ýÄGrôÀû(œ<½iÄ4¼7®ž+±A`ì'#¥ï]½eûšbàMcðӟȲ©‹¼·bt¾ð÷Y2éÛñö›à»øâá>òJ»î2áËŸc”Nr¼gË.òü§Â1¹Éð—¿Óÿ Z¬3¦ß¤/týßé“§,ñ;wî|ç4fàþñÉ›2¨(Š@dþ‡ÈAôÊ‹@ýkšË¸~ß˵OÝ.—dÉä{´zÎ29qô¸Ô¼¼¡ï^¸'ŸënÐhÑÿŠÿJ•f5#…Û°xÑümt/¦yÆ4|¤ÌôBˆL\ýöIŸ!~»«œr˳£ûØ’¡ œõãß2ñ«Ÿ¥h¥’R¹I8”8q£ž0G¬­î츇‘š¸Õʆ2"HöM„¿ØŠü½Ûv e¸é•ûb›¤ÆS.Jâ·7½(!Š\©êmê[òÇŒ²FÛú¾‡ÿL˜-E*–”‚eŠÚ{˧ÿ#sšbgãË‘&]ÚHÉêå|á½'S¿û]N;!mî¾ÆÞ>rà°Lö‡¬œ³T²çÎ!-º¶÷ö|öè¿£¿Ùc&E‰ãÍsÿö=2úÁÒìæv²`ü ÙaLÄU/«-u®j"9òå²q…o|C™?vºìÚ¸].mVKšßz…üýÍXY1ó_É™/·Iïr)[·²ÿÛg£$Gþ\ÒøúÖ¾²Œï÷ƒä.’Ovj!® 1IÓ—ž\´ä)’_voÚ!þ$W<Ð9h=O?!ÓGLÕhÔÐîšÞØV2f¾$hŠÈåÿë$ÓFüiÓ€ü¡EŸñÃD£Í_$G‘b•JKÛ{;ú¾ \1*7­)ëÿY)kü']û<"ùŠ”è¾}&g|3u¯n*ö›26¾»’† ýÞ´lY±A ™>äʇ®—\…òúŠ8ÜtY6e¡Þ{PÊ7¨*MÌ·—9{Yeú°A~zwˆä/YX®¡›½F8gÌdY=¹(YHjµk$VµÏÜ÷Ö°s+[ž}¦èþUOÁ ‹ösý¿«$Kö¬Rµe]û}¦I›ÆÆóÿ V׃»÷˨7"\Yfþð—ügê}ÃK÷HÖ\Ùý“ˆtM}Ç;Ýí}0¾ÔôEëÿYe1.V¹”´¸‹Õ&Îùi² SÓÔ«Qç–öÜÊw¿ÉÜŸ§Úûƒÿ@*6®©ÿ±ôGH¥¨Ù7†/mAùzUdѳ|1Ѹ-úc¶Ô½ª©½Ç„Y*KÎlÒðº–rĘy?à­ fÛmƬµõ¼oÓ™Ógä;£é˜9ê/KâŠV.)CISq(¹ì¶+eå쥂à ùÂßfZbæîqôæIù‰‡é(OѶ~“‡Œ—_?î‹(ü¯}%E*”´á'úE>º£—5Ñ5¸¶…9pH3¸ó£Ú¼|ì\·Í—'–¬–=f`G\b’¦¨?5åë_*W?v³Ð×-Z°®´a=ûÛ0eêTþ¦ ýM¾{ñsá{ Wpë@›-ò—iÓøº–®YAj>¾ºŒyØ þ¿#_h Y½kšI–Y-qŒîÛ?°s¯,™4_˜ Aj˜\ {©¿|ö¿7mÑ ÓeÖqø+\6†Ôþi}‚!¨Ä™÷ëTS߈ºå.œOJתhÖ­SÙÃKí¹ó¥ƒøÕnaÀ5Ä‘c÷½è5@²çÍ)õ:Dô]_=þ¡%~-nk/¤÷óûCeÖèI¾²xO¢ëç2eÍ,U[Ô±Á —/nÏ3dÊèðüà®ý–<»‡`ŒÙ–wS×” ç§÷¾!S̄җ§h~[Æ5ó–Û(ÞøÅ«”ñMÆ)KárÅ]²zTR=ªù‹E¨cHÞð^_ØY23YfóHµVuí1gÁîúŠl2‹ËJÕ(/Õ[׳ķjË:¾²Îýešœ¸µ§]pÕåÅ»"rëÊöº”ìàb2 $v2ž9Í:¦bRâÒ2²zÞ2ù{ðX»Pj…qå@N½Ð¦½ß)ÏÂýö ‡ðÒo.[Ì^óã\-X ±{ó{Ÿ 桽|a8Ùºj£%V‘nž¿Xü÷<[§¿¾þÕ÷Øíà4›<(Uã‚+ ¤«æc´œåêV1fíV3èKÄsn]=QbuŠÏIö<ýŒë“hñÓçw1páô¨(Ñ# ä/z|>Ũn‡f²ð÷™F£VËjn{ãA_ع?O±3^üSJU/ïëÌ}¢99i|ÿ´¼>6éÒ…&n.ÉmêYÿ½%“ØA…®n‡&fà8è‚=z ¢÷ZMòÑ 2>€Ó†ÿ)o7ܺ²ýJR {ªbNWQôkˆeKÀ×s Žèµ¯l,é3fð¥”Ë *,pØðïjs\oÂ}Cœ`®"Ýá/÷·¦œª‡¿|Áù;Dtûçs6›f Â'&9+¡ÁcŽY;mc?á3µ%‡òiRטÅν•¸dÕr–ô±ps%h!‚¥‚¬°wqƒ™¬ð·ÒlÍÄ,<ÓçÛ`Á}÷ãòíûñœà¯õæ×–ÌíX»Å®î}óÚ§Ìw´Å†dÑÂÊV6sGˆÃ*éѦÌl”Í‚öL$`¡Ä7ùׇÛÉ'iáöQ tõN]±~,þkžñw^ãÛÔÞ?„¼væõÙ£' +UE %±l Ì"tjic×<¿šÎ%…5f$Vø²[=Ö $N|¦–ó®iƒíº½ÿ˜ : û»ò¥ùO õ ™cÀsþt.wô¥wþF!ã?9Å/Æ­taÝÑ›§œ7ý¤‰ffNxWòperiâK…?f$V5ÛÙ00ø$H¢KÓWOR !·Àµ1|Õîúà1ûñÍðÇ"%î¹ÅþùY;ýÛo ßBV³p 2ÙäÆË£„sepB}ûæËpA##µsãÇfåü¡Ë wYŸâïÍêúoYغ醞wûRÑg´¼ã*» ø›§>¶Q‹šÉÛ¥ð_R }¬¼‡uéyÏù´#wß'7!ËÔ™ížÞ½á9éw÷kÂJÝv÷_Çï7t]EØ`׆íòùýoʡݑ}mrî»w/$<þûCÒ¦Oëë?ýá-cVBÓï°jù¯AüýÓÐkE µ!¦X±bQ¶RhD¯Ô†C‚ÔÓÛÄvsÚã‡M|C"ƒ™i¤Ð œ(¦$ü½d8³ÔäSößš-œmEÂ3&*™Í6.11ÆõÛT6\%Ž™>-e"·­¿¿.ý}}I¸B1+û§(~¨ºò½Ÿ9}:’u$P: y“6ï/Ø:!óNˆ´ûÝØ+!’Õ4S?R YUfäq‘`Z‹¸¤™Ôqƒm“ÔåÒü/bBp©1$+ÔÆÄÒ‰ë·(MˆKV³ð#˜#j±éGX`®„ª+ZM¯[L¸éÆg¸ØNÀã³ š–"œP³orzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB@É_rzZE@PE@P% °&¯(Š€" (Š@rB ]Ž9zù¨~—þ·‚^¯[øŸ,ús¶œÊ³@7ï;dû/9èiòºç_ÖPm~ý?«$_ñ‚¶§Ož’㇠³ØÈ™Ógäø¡£ræôi}Ï–]2Þ|W>ÔEòÍ›$5Ž" Ä8“¿BfF˜¿Daéü\W[ÈøOFÊÏï5„¦AmG,ËïÑnxé©Õ®aÐt”!lƒ÷ºE+å‡× Z¹»ÞL2dº@ä ¿+fü+UšÕŒ”Þ†Åk,ñ‹t3À3êÕÊx’zoý9`ŒÔïx™Ñü]À9%¡±`ü AkÂ7@ûñÊŽu[-ñk{ïµÒ²ëUrÌ ˆýî~MƲwÇ;ÝmКmëËOï‘eSJÕ–u¼Ñõ<žp}ÁÙ3gp½0aûåÃáÒý«žñœSÊNމ1±,;O}ÿ¦/ú 3Ù_:y´º³ƒïžž(Š@â gòç_Ìü% ™A»¹%Cû¶í6䯄 Â,oΘÉÖV d!C¼I…†Uý£û®×íÐÂßf“é:)V©”ÕŒ•­SÉÌÏÈ·Ïô•æ·¶“2µ+Ùð+û·ï‘NOß‘—1åB>¯}êvÉ]8Ÿ/ÍØžä)’_øÃ47ðÑ÷¬™»ÞÕÍ"%7{ôßQÈßì1“"…ñ¿8¸{¿5£pæÉ†@299°kŸ%œ[VnÂe‹Ië»®‘¼Å"L Ô³æÓÅÏ—æ·´“mêK(œ·®Ü(“¿/Û×n±³íÆ]ZK¹z‘ͼóÇM—y¿N³3üê­ëIãë[»" &îé#&Èj£©EÊÖ­,Mol+3_â ã=9rà°Lö‡¬œ³T²çÎ!-º¶÷>x¾{Óá¯bãM(˜g|?A–OûGÐ@Ô»¦™!â‡í9¸ ¡ÊfÓøa¢,ŸºHŽ:bÚUii{oG«m³ Dó³Ê”Úð?äÊ»dÒ·ãd‡Á±Ë‹wGÑÎm\²Vœ&yѳ#¥ŒV3[îìöa&ÌbÌŒ—ß×I†÷úBí9`ͽ™²e‘Š «É²i‹”üEB/á.ø–ŠW)#ÕŒY“wí&z\8ÊÔ¬( :]fÜŠxƒD:OÈþËûóM]zY-ó=4÷å¥aÒàq†Èn”ÜÆm Z«ºRçªØ“6—0ßý”› ¸>(£™3¥·»¿³œ:qJþô³4m¹\ÊæÞuÖLìú»«»E& üÉ&Í$'ÉÂö{qyéQPÈNlqÌ sš¿Ù£'[SAÁÒ#Ú²¯z¼o‰_íóÚ6L¯Ž@øg‹YpÀÃ}äȾƒRßtjG øÈ»B‡ŠßÜ13pCdfÎOS¬VŽ{k毴n9 Y‹Oè`Ù¼|]¤d/»íJYiüñtBþ6ÓÔ+Ü­(Gü «¶ˆÐê._Üž{5Šøá‰F‘Žw@÷>>“ËöU›íįj‹ÚFûZÈÖ?:œ1ù|ÒíUc:'­ºu°¾M_š÷²}õf_ÙÀnÖÙZ’5g6ùåƒa²èYö9äiXÏþ2yÈx)cˆ8S†þfM›ráÞwF‹2sÔ_¶E+—”¡Ï*”#:ÁÔ„@x`k4ÊE*”0d¨®Lö§üýÍXÌ"á”í¯A¿ÈØGH隤–1³ãÿD; GÊšAìèÁ#2ê­¯m^›–­“ß?ÿѾ3Hƒ¿tèqSP-É.ã ÉðúM«\Ê&±gË…6TüÒÒÆ?u‰Òz@àn±yùzYôûÌHdjãÒµòÅCïX“gÝ«š “1ÚÍA39 $ Ù19ðð;vr]ÃLÌð ýÑô1„6úÁ­/É>3nx]KÉž/§ü`üô–˜~"®rp×~Y>=¢ß%-×­ž»\j_ÙDöïØ'ƒÿ@†<××NÌé·¦øÓL’ÆÛ¬ñ¥ŸÄR¤¼t­Šö>ßVù—ÚsýQÄA Κ?ˆÃ†WËâ¿æú|ÿð™éfL£é2D$?÷—iÆiø¸tÔÓøËe±5cvˆæÄ_ëÄÉfFËwÛ[Yÿ§†ZÚNeâ—?K™¾OYÐâ¿çÙt¶­ÞdóE3qASµnÑ–l”m$óÃlsÜ'#Ü¥=>8à…šB|Õ ¼RºVKFçþ2U®x ³}´`üL«ÝÁO‚HЖ1c§ó.U£¼oÀÁ/if´y­»]mÏYô€‘3uEÐÝÿé3>4lt8cÒB0³2Ä ÇmLß³DÖÚÝóÑr‰!¦Moj+o\ý¸ÅŸÄKרAç>ó|·Ñ¾öðmÙ¸d%U6ƒó?þ]e û½Ÿ<éÓÒ¢Ål4·Ñ ÌîŽcbio|ƒÀ¡ÜïÞø¼/™pÊV¾AU©Ò¼–%DÌo4ДåÀν!' ´%´²ïßü¢Ñ|þ) A¨}ec£u©í+ƒ÷$ýù¶ï½çÎѺҾ½’#.{ÉÂùš¡å…(Cl£kËÞtô<æŒ|u íœïr‘Š%¥í=} M0“¬JF }Ëk÷ÛhýûtyVæ›aÍö¾€çO²ÿš7vš%¡ |ÑjˆÉ²@é²Õhù&àø+–®QÁ§G[¹zÞòÑ óÞþöÃvR^´RIùì¾7¬_´Ó4îÚ°]6.^mËæýaM_ÍD·&u*Š€"xÄ™üå.’ÏjŽnîý?[jV.²bôóûß”¾x^J\ZÆh§æÙA쯯õÕ _ÍW¸†Ä]ýØÍ¾ÕµiÒ¦‘ÊF…)—•F´^hWÏ[fµ/ùаÚ1LhÛw¿Ñ›l”óƧЧW²J(aQJ–ìY#K#i¤É md\ß‘Æ4{µ%½ÓGþiü[ûVpFŠæEɪü‹LŽü•4éŽ ñ,Î/ãç÷¿eÍèåŒ&³b£j‘Ò(Y½œ%~¤‡I²|ýKíjT®–­”Ñœ9±á Ùßj7 QóʶóÅÒÆLæJК²ÒÕÉö5[ìiÅÆÕÜ-«-s^sÀÍpÊF[¤½ %9zàˆYP¡Å8qô„/ÝèNЮv|ò6KÀñê~7E<è³LY3YÓ˜7Àé“Nð3] â¬:Ehç ½ Þ[–ÔvÇàÜ™s²ßL ÷|#|Á~ë,FCÐ>;”£áÃgÓ+ Ým6g&ÞïÃë–¶¾P™ˆ•¹û¶î–c‡Úþ—•„b•Kûú8¾ 2ê„]˜Ì©(Š@òB Îä-_Ýͬ’«4$³GO²äïäùÕÀéÒ_È­S®ÂyV#²¹Ð]û;ú»­cЂ@bÈ¿ªÿf,¶˜<†„²…3M:fÍŠ+›;–23cfž1fÕh³êÓ¿ÔhSÏ®\bˆ/ +8ëvh"‡ Ž­xÍ‚¶žð×…Â9«Ù®æÑo_•'Α•3—ÈÐ?³8¢E@ †øk¬¼ù¢wïvœónN“Ž¿`æ±á yw–'¡Óþic‚sâîÉã'Ý-{¤\@F´andëOŒ€üá_és囟´“ƒm¸Û†ä\è¿p×ÔÇ$tÿuÊ|Y Á &L‚0Qó­3qs“g… /¶÷½}P,Ç6k§(q@àBo‡Dü£Ú%ýfÆé:B:W4}8µ£ÅC¬1çùwJ\ãÿ„Ñ»¨>Ì1ŽœTnZC–š•øbŽƒpAúf|?Ñ:ä³eF| fgòÀÌë/˜I™Ï2þmt¸h ¼³2@IDATs˜Yo¸äE q•P8ƒyZƒ?åä‚úV§§¬O+OC ¦Ò`õªÓ>b†“@fV÷u·•Ãöµ›CecÞe9l|›œ8ßQœÍ»¼x—½éwïVX‡*+j!~Þ-ˆh“ËÌâp…öЉÉnø¶ñ˜ÃM§`™"fAÍT‹?f3dé”M¸—ü9á™ù¼«D¸ék¸¸!€¦a¢IC¿ƒž… NXÈHºÿBÓ¶à·vräúB¾…ë¶ØvùïŶXläöe‘›<*sRßóNô’º,š¿"Zˆ3ùÃw°V»ÆßD¬Fcéä…–°háÛ1ºÏ·ÒàÚËì^OcŒÏÚ:|ý¥n‡¦2¦Ï»šŽÙ5Žù –Ÿ¸Õ”Y->p¬¸s(ù°Â6œ­ðU\•{©/=Nðƒsæö³b‘fœð1%CÚÜ}M$-7LG3ÌjR?·p²K]²ZyÁÉ?¶ gÊya[žòõ«ÊÖU~BùŒ93)Yµœ%}Ã^êoV½^o£Œÿô{¯”1û &aHùð—#Â3˜²…F(ÉY0m?66Ff@½©×}v5,“Þ7®nÿ1Ò U¶Œ™3Y-äÊY‹?TykŠcÚcLdlß³ß5Æ%¡Trv%v¥&5ìd%&éÔ3í›Õ¤,èi÷Àu²{ã™`&p4¥Nv®Ûf±u&w_ñ‹m"§ñ¹¤}⪹Bp‹@x_?½7ÔN`p9ÁÏxÄ+í7hAWBö_X+p[`³å&7´µ‹NFöþÒö±LJ还p±En óÍ eVÿ©PÜÖ%9ý¸Øh›ÅoN«žœÊ¨eQ.VâLþö³Í€îïú0bпñå{l‡ÄÍ¢fæÌö|1Úì¨?ņ«lÍ랻Ӟ;¢=:sbƒk[˜½Ç¿9üè h Y½æÄu̬tu‚ÿ$Ê=s÷½G—Ç”ï~þ¼â¶æ 8Ôé«Ç>°É²‰Ö “¶—–»†<²p¿G· Â=‹îÈjaöÄO’½Ý`øz%ÎÕ 9Þfߨ7¿ñEkqû•ÌߦâþÿÅÄМ`b½ëƒÇ¬yÛ½oüî fn!ïÒ¥qƒÜ³‘® ßá‘íB¯¹È›çÎs‹qTw ‚ðÑÌ_¢ Ù2f™Ý$–M“ѼaZFÂ)ï ÃG]{Y’Õ⎫̊ÝQ6¾ýñ”ýÂ͈3&´]êºöív8#^ =†¼êÓ²øÇ t–øæWþ'cÞ"w}Å¡]Ѽ²þŸ•>ͦ÷¾žÇîûB#ì¶ã|ã»ÚÙôMŽœÐï0aÚ¯fµ8ékzÓåöÜ¥ã>Ç„ì¿Øf¨Û{=düg?H¿{^³ùãBsU÷ì9ûð­1‹;pAxÆb'þeõ~¯.ŒÿÑõG®~Þçþ}ÏÒ¤I{!éyqy»#ýCKó Bf™à{÷tqô¨( ƒ@šbÅŠE^qaòyhD¯„ÉͤzܘƒÑäøûôË­ Ø?êb4Œì|ïõó‹K£Ã™E3Ç,®Ù|D3¦y:aüïLËqþx¡âSÞ9ï>a+ öþºö©ÛlpþãJ¾â…ˆÞ+í±[Ö´½'²É:º²á·‰YÏþ /¿×gNäÌæøgùï“È ä·:=-÷õ{:ÊBšD.¢fçAs/føè&/žàvë•„ê¿°Nðý9ó®7_ö¼øÿQ¶ãðnÉ‘|J¿%A;ÙâöÐÿ/~sÕÔE@PR ÏÜÔRe­§" (Š€" (©%©÷ÝkÍE@PE " ä/¾t­²" (Š€" ¤^”ü¥Þw¯5WE@PTˆ€’¿TøÒµÊŠ€" (Š€"zPò—zß½Ö\PE@PR!JþRáK×*+Š€" (Š@êE@É_ê}÷ZsE@PE@H…(ùK…/]«¬(Š€" (©%©÷ÝkÍE@PE " ä/¾t­²" (Š€" ¤^’ùÛ¿c¯,?C¦ ÿCÖ-üONŸ:äofìÇ#ä‡×%y9.ÆlZ¶V¶¯Þ°j«ç.“½[w|–Üo®]°B¾êñ¾œ={6¹ÕW¾eS åV sgÏÉœŸ¦Ø¿ÿf-þv®ß&çÎ / 5éÛñ2qÐ/1Êaͼå2øéOä³ûÞˆQ¼Øæ»ßò߆€Qך~?!¾û}ÛvËÈWJ¿{^“ë¶Ì;©nع×ö»7íHª"h¾©ôÉ¡Ît˜ß¿ö•,üm¦-NιåÀÎ}R¬r)¹í‡„뤒ãGŽËñ#Ç’*û‹:ß±ŸŒ”ü% KççºF©ç—†<]õÈÒôƶQž%÷‡÷’U†¼JÒó€° Ú³y§|ûl_öÍéÊ“ÔölÙ%ãû}/W>ÔEòÍŸèÅ9}ꔌ~gp”|é«îë÷´ä)’øer…Ù¹~«œˆAŸuÆL²>úž”©UQßÐÆ%“`G¾û ÿ®–G÷’Be‹EÊÚæžŽa÷ᶃ1}¾µ¤¯ÕWKŽ|¹"å™Ô'Ÿ´ýÅɣǓº(š*B Yhþþþz¬%~×=s‡ôžô¹<;º<òÍËrhÏörÿ$}“ÛÞx0IË ™+ ‰À?Îñ%¿yÅzßyr>Ü,¼ F$'!êsÃK÷„¹÷ߟI×>Ø,¾}®_Bd•`iî5Z1äòû:I6õ,ÿ„‡¾ðYœ­;ᶃ ‹×HÃëZJýŽÍ%sö,þEÑkE Õ!äš¿3§ÏÈŸÇH£Î­¤Þ5Í}/ p¹âÒñ‰[åÇ·¾‘]· Q!ûlþØé²|ú?²oû;SmØ©…ä-VÀÎêÆ}2B:ô¸Ùâˆ^¤lJ6mfÄ“3&‡’»P^©Öª®Ô¹ª‰Mw¿I™|CSò ýî_õ”©ßý.'Ž6w_cÃ…“F³›ÛYóõcªzYm›‡w¶‰I{Áo³dã’5R¨LQip] [Wùu‹VÚø ÄejV”.“¥Š¸Ç©òÈ Θɲzþr)P²Ôj×H*4¬êÃbëÊ2Ù˜»¶¯Ýb5A»´–rõªØçgÏœ•ÉCÇË3 ZŽ2µ*I«nä’,™ìó“ÇOÈô‘ìóLY2K¥¦5¤Áµ—Iš4i|éûŸk‡þá¸F‹ýóûC¥TõòÒì–v‚$Ù=k¾üy²´½çZY:u¡,úc¶«T*RyB¶×hÚ3ÄrÕœ¥rý Ý|i.ü}–Õü\ûÔmì»ãÍøa¢,7æè£‡Ž˜2•–¶÷v´ZÒ›0ð'›ÞOï‘ü% ûÒOªo'}Æ R©quirC[×w¤Þ{P²åÉ!¶m˜ ¸1 eëV¶Z­Œ™/±×¡Ú¦ Í®3¿Ÿ(˜íOŸ_ñ‚6¸ô߸ºÌüñ/“îj)Z©¤éËúòÔE ±HrÍßnCìª-jG©3Þ ¿~à#s“‡Œ—Þ$9óç¶ÌêyËd@÷>rp÷~á£dv·ø¯y¾t¶­Ú$ÿL˜c‰ÓуGäƒ[_²¤Ž`ö|9mZKþžoÃÓ9¬œ½Ô’ÅìysJ½óÀ¶5›eëyÿ”pÓòü§’§h)oÈeþõ£á¾2­ÿg•|ñpÓ ° ÛsM§„l\ºV¾xè9~ø˜Ô½ª©lY¹Á>?¸kŸ/Ôvrdÿ!ëñ«}¾£ôć¾3ë'Ý^5VÖs–ÔeΑU0;Âßûÿh‰!lƒé‚ñÓ}~œ ž#_ýRfòW±Q5)\¾¸@(þúú× 0G×ý#ñÞxŸ¬†[ú?Nòë KV[rZ­u]©}E#™÷ËTK]ÁBµ×PÏ÷nÛ%2¯ì1ƒ¾»컃ào[ºf©uyCëÈw‚ä.œOJ%R¶Ne)ßàR{ž¾ô#æÓLŸ—3½2N¯ÑÉÎó+´¼3Ó¬9³ÙÁó²u6jM£!˜:ì³ên«Õö1°aÖÅ|GØBeŠYMྭ»åØá£V3”˨ÿ½RªF9ïe¤ópÓ(Q5‚D¹xÕ²6ƒ»öm`~Y3…ñBü´iÓ ¾ŽÚ!»PÀœãÌîÍšÁ‹‘ü•¬^Κü]]ÝqøË_¸SYü÷<¯6/Ì0SÒ‘~~ÿ[B(gLkhñ2dÊhÃT3á÷Ï”þ{Þ¶¤¦¢1ï8“1¤ùwâ<ŸÖxËŠ ömÎ {Ãü„Ó]X7?1üuKôÝýärä›Ãì…ëæ1gÿ8É⡉®½†z“zúw%.-cˆÑ2;H=pDVó$râ艀É&Õ·Ã RÜMÐÑb‚ß½}#È—k[¥ ÉsB{§ÏÚù‹®mº8ÁŽ»Œ[ âˆ:ç˜3qsq²sCDHè!cmðÊÖU-ùóÞKÌó4iÓHç绋LOùåÃaÒåÅ»"e~‘"Äà‚1œñ#*cË_Œ¶.DEÍ„)mÜnœ„jïá´AÞ;ù:âGÚ—šIŽ’?‡² $'…ÏÏ4!l˜%‚ æQ$Ã%º ‡ï€Ù"a Æ7néä…Æÿå´Ý2 ¦Qé#t$˜ßøØ19àƒøkc¢óó 7téÓÙ´múžósÆ „¤Ï1«´žŸ3g"LAÜJ—þ«ÁláíÐ=QRü)«}9™{ÉŸ[çÅí^®ÂyiíŒ}§ÍÁ¿çÈÊ™Kd苟Ùö¡/ZQ‹ÛÛ[­Þ’Ió­ÙøO|¯6þ¡Çµz5|´£œóøÈ£äpÚ¡7<çh¦q4On!@fždÿ\ùضäèÃ>ŸÈ`í5T{véù1Ïû‹ÿw7²÷@ëˆVÒEÌw]ØúˆùÇs×Iõí°B¶¾ñE0C5mÇõ)Aˆž·nœcêÉ®mÚÑüœ2}¥O4\'”Éb&¿Þï‡>%_±‚.X’YÝù¹;Ïû×Eh›]aÂÁÏ…é‘´ÑÎzÅiûNž7<ƒ : ÕÞÃiƒó5íAEHl.0ŒÄÎù|~ÌT™±£‚1õ¸Ž“Ç8)³ÇÞ“#Þ°Z;îm^¾Îèœã–¨æÔ7¾s~Žð[¤á¶\øwb„iñña¯™N0‚œáHG®Ä5 êÆö5ëý‰ @J0¹¡ÂWÒh ÛݯXGÌ@œš?%4}¬Ft1(+ýÀ”󴦓n|}kû‡_Í[ž2äa–Y¨ÓQÀ¯¤1ýC ñ3´ƒßé9Í^£ë[ù¶€ÀT†¦ÑM¼Ø£=FBµC¼6¹¿üfˆ& ‰ š…=”!9 ðL–îë÷”¯XGö¶š´­˜ÉCµ×PÏi×ìÛÆ€êÜ-öšÅ;ÑɱCG-ñ»æñ[}.¼5ø‹Û òžßN]ã–hòB9i[´Mêïú!4¬´-ž¡)Š®m:«ˆÝ5„aß<Ìâ¦`®Kœ·8°  Á<êí'ñE½$kd3« ˜?”«ÖôFQ|ßBáç-ªkÞ{ѯRÚjûCœfóòõ6ŠSHøÇþ»hÅRBϧ‡p=QQÛcbçê—>8Ê3¦>œlÙ,u樿,ñ£c@#ˆ?ÚžŸÞj?žMFmÏ JÇêíÔð_A‹8Í89{Wn1Ë£#fÅ ð!\L$>Ò`)+*ñWC“ˆ36¿,j@XhBݹ¿ÃøCB`^kßCæíQjÞ/+G›U{lˆ´}ïê-8h#‚Þ#ü!~˜³üHÑ2õ½ëU»ïÕ¥»Œ) d¢ÍÀÌÊ>Lë˜e8ÇÅêI ·-Ï^oWry®¯]˜äŸ^R]³H _³›ÛZÍ)qþ UšÕ´ÚJʪ½†zîÒ?Œ/Ô¶Õ›ì;¢ýG'þVšòñÎèX±é´lÈ\3Ñ£¿@’Û·S²j9Û¶†½Ôß.XamÚí­”1ÿ†j›“¼+hª ‹0ùþüþwvrDÊ~©K'ø¼ñýð­@ éSXaûæµOÉö5[\°HGVÖ³8’’Xr™”yM¡ä ?ÂjÜ%ÕZÖµc»I0–€ ½ÀÊùJ#T{Õ/5 ³F¿=ØæË‚Dü‹UÄF É5T˜…ÀIFÃ*N'lðÛγ ÛE@ÐBäpNîúÎ#âü3ˆÇ–*˜Š0i]Ú¼¶KJê´obI/‘$œOÎoë‘Æøày…Üi›b›†7½ºšÙÅ'8†ã‡Æ Ǧ¦5Λ§Y‰Œærˆ£6ÒüÖ+¤©qB¾%mº foýÀÅ™Ëx¿w¼ÓÝúãÌýyŠ Æ w1!ÕM‡½Í¾Qo~c¯ùiqû•VÛOå­¯?hÛÌG]{Ùç´›;ÞînÓ§£ïö~Û³ áù=?é3{Ú›žŸPíЕ[LÕÒ¥Kg¶Î¸_>ºý%jVÿï³g}šO’‰~Ê`‡TiV+JÞøMò@¸Cµ×PÏù¶i»ø41¡ÛÚW66šÓõùøîÐÄàÿ‘áÑZÜq•ù^FùÊ ñiiîḩzêû7í>n‰õí¸wLû &Lîúà1;IÐý] 3ñM½îóŒèÚæ™³gì;ÀdLnxén»Z}ˆi[‹àèÛØ„ÚI—î²eOúMHÖ =ïöi¢Ï¿\N--cV¹&–ð2ð :lÃÁ/P;§Ìh‰Ù—‘ÕÖŸÞûºmc,0êôÔí‘¢»²¸›¡Ú{¨þ_Vö†¤-cÙâ]t|ò6KÂîņ¬ùÑûŒs@`Ž ·]Å¥úç®Cµ×èžcJÇÏí2ÂV×»4ƒ‘,·eŠ3¡¹´“Û·ƒ9Ö¨úú‘Ræ`m“6M› ÖG¸úÒvÁ+XÛ&í•…n¼ƒPé69õ;¡ð Ö>ÑYõ n1­¯k›Á° Õmüìæ]xü £+§÷Y¿{y/õ\ˆ1ÉŽüŸAPE@HE(ùKE/;ªÜf‘@j²Š€" (Š€" (I‡€’¿¤Ã^sVE@PE ÑPò—èk†Š€" (Š€" $Jþ’{ÍYPE@PDG@É_¢C®*Š€" (Š€"t(ùK:ì5gE@PE@P€[½$z)4CE@PE@PDA@5‰³f¢(Š€" (Š@ò@@É_òxZ E@PE@P%‰³f¢(Š€" (Š@ò@@É_òxZ E@PE@P%‰³f¢(Š€" (Š@ò@@É_òxZ E@PE@P%‰³f¢(Š€" (Š@ò@ }ò(Fø¥¨^½º”+WNÆŒ#gÏž±Q£FrÉ%—ȤI“"ÝO‰mÛ¶•'NÈ”)S¢ *V¬(?þø£œ9s&Êsw£X±bòöÛoKß¾}eæÌ™îv²9RR¥JÉÏ?ÿ¥LÍ›7—´iÓ&Ëwéð÷/ôÉ“'å§Ÿ~ò¿"®[·n-Ù²e ZþâÅ‹KÆ eÁ‚²f͹÷Þ{…6úàƒÊîÝ»½Ž´ë¯¿^Î;%ïþùGV®\å~J½Q°`Aá{ˆ®^W^y¥¤OŸ^~ùå[Í>ø@²dÉ"ÿûßÿ’¤Úã7 Èèú3âÆõ›‰küPåÉóPukûKNuu¸kÓû÷ï—?ÿü3Îï×åìX¡Byùå—¥OŸ>²hÑ¢`Á¾ŸâÈßM7Ý$U«V£>ú(REi0t€ù»æškl!m§NŠTÏ'Ÿ|R2eÊ$ßÿ}¤ûþáìÙ³Kîܹý%‹kÞeåÊ•’¿»îº+Ù’?×ýAd2’RÉߣ>j«³eË™7ožÕäñÇ—²eËJ®\¹,ù£ýñ­¥K—.JØÄ¸±¹í¶ÛfU¨P¡‹Šü1©½ýöÛ¥]»vrÏ=÷D©3¨xÀÞwä÷Ã_RÉÅø„Â2ºþŒ¸qýfüã3>õÔS– ,Y²$Tñâõy8uKûó¯ëÍ7ß,mÚ´‘»ï¾;^ë“Ä‚µéÇ[òç_昤NجY³Úñþ’ZÆ/Ÿ}öYR#Qò/P €”,YR6lØ)¿nݺÙk¯%Ä‘ÁHù"¹|#h‰™,0H'¥Äõ›ñÏDŒ‰=Çä&qmþu¥ÝçÏŸ?`5óýFצý˰°ÉèfŠ$ÎÔó /ØÙ¿¿fÌዹäÙgŸãúõëå•W^‘cÇŽÙ ƒ ²æÐjÕªI‘"EdïÞ½öùu×]'Mš4±aæÏŸ/ï¼óŽKÒjélK”(!?þøCFŽé{_'Û‡~X®¸âŠHäï†n°Y >ÜëÕ«gM;tÔkΜ9òñÇ,& ÚµkG2ñ‘2ƒ|衇lú'žxBP1Ÿ>}ÚššÞ{ï½(&ö€$ðMð¨_¿¾5íczüðÃeçÎ6× 2HÏž=m¹é 6mÚ$¯½öšìÛ·Ï>gÆØ²eKÉœ9³}Ï|¨Þ‰CtiǦZ´-Þm MÔ«¯¾jµœho&Nœ(íÛ·—;vH=Äa^¾|y›ÕêÕ«Ì1' ÄM“&}UªT±³Ì/¾øÂ>‹ïŸÒ¥KÛòжtíÚÕúŽ;w–Ž;ÊwÜaï¹2:tȶ1Ú"߯°aÃ|q0›ðíàŽÙÄ„ìÕÞsÿ™gž±ß"&ô… Ê»ï¾ë¶çÊÄ·ïpÂv2nÜ8¹üòË-)èÒ¥‹-#Úv&[¬]»v ÄÒir+Uª4ž¯‚‰p~½zõòåD»¯Q£†½vý"Ô‘¶þüóÏ‹+û?ü W]u•}¿Ë—/—o¾ùÆjq]b<òˆÔ©SÇb²yóf¡ {¿‘PßK'œ£+“ÿ{@Ãßßm3$íÁbNYã+Œÿ7ÓñÇ—×n»wïn5ÃIeâ„O ö‡Bƒ~ÍÕªU«ä­·Þ²í‹ýí“0ˆ·®¤U«V-{èС²xñb×Þ0?ÉñýR~x„×å îaÌ…³ð-^}õÕ–ÔbqùöÛoeîܹ®ZÒ¸qcËoà1p“ßÿÝ÷,>NRä‚:s~:7F0a`Á$‚¯ÌÆíà%ryòä‘:X¿!lètú‚Ë.»L } dM›6•k¯½ÖfÁàÔ»woKü˜LO ¡¢Žt¼4f­Nð»‚ÐÐXhÔÓîìÙ³íÌÕ¸Ó¸8îHZÔÑ+̨ '&<ˆ#ƒ4>S[·n•fÍšÙNÓ')ÎĬ÷ìÙ#Ë–-³DŠÓ6òæ›oÚA‡?:ž# (0ƒxí •¶ ÃÚD?:Ú D ÷éh”“Á›6Ç¡åüé4\Ýhw<‡À0hSÿ„§Qr„ÎåAX·n»´GÚ’WãàÊyXºt©d̘ÑâN{Eøéü˜4ñ­AlÑÞóœð¾ÀÒ|{¸8ÄV\™¼¸A´yÿL¢<èëlé„1©bZ´óÍAv „H°x±-[lâñMÒh3N LvÀË+àLýWö;ï¼ÓN–xϤóâ‹/ú¢@(é; ý¼âó¾Ê”)cÄú†| …yâÊäÿò§¤ÿo&¦ã7>D&¸J Æ«ä$Úß­·Þjû=7C~{fÍšeû \}òåËg«á­+“DÆbòù $Ééýb­ã;}ì±Ç쑾Ëä⇿4dS1ïŽqe㺆§Ÿ~ÚŽñÔŸ8XeâSR¤æÐŒ¡É©Y³¦´hÑ"ŠŸDfÔ¨Q‘œ¤\„¼Â ÌŒH¡I£Ó£¤1=Ú¾4f$ø¢ÁÉÍÂì™áâ[КÐ` —ÌxÐÆAXœ_>WC† ±ƒ¥ÓQçºuëÚY{LËCçÒ IBh€ Âäë4¦1M7ºð¼'§]ñ†gW'ò†D@– ße¢l|Th ±ÌŽÐ˜!¿þú«Õºq!L3ÀQ|%i33$TÚ6ßåv³T÷ˆNMžˆj "ŽÃîŒ3l0"$jÀ€¾÷Êìøþûï·ƒñرcm8ÊOçè:A—G|ÁfíÚµvq„_H(íÏKåK!L˜×ˆƒFœÉ»óáDKV øñýB´ø#ÎÔ©S¥ÿþö9ï(” GSäȼ#Èþ¸5hÐÀ>}z$>ä†ró¾0íðí3ç¾×íÂ?ž7ß„>çÐ7¡UpšÚ nèüû6ÿòxËF´{HZV,L6Ý;fðýôÓO-ô‹Ñ}CÁú…p¾o™¼åM®ßˆ·Œñq“ñÇ›ãý} ãÁ´iÓ¼“å9c¶Óô3n1Ñ¢¿€Øà×úÜsÏÙvæ¯á¢Ä‚‚&ÌM蓪‚´é/¿ü2Röôsþe¦N($ø^±>ÒÏñ®lãÞi&bŒoô‹ôQŒ_ýµ`ey饗„猌'ŽäSwG# –)–üQ_ˆò;ö 8+pè(’††zØ_P?;a°Fø°^ ¦O§AƒÀ @ÇéÄ-¦à>áãSV¬Xa¤V­ZÙÁ’‰i‚‡ É¢Þ4fÌ  Ì6ÐlÄFÐ Øü!N+HçŸ õqÇfxþ‡™‘òFÀßÿãGKùc°‡(1žc²sæxü#!Îß}÷57P·R*mÀï‡rC0½ùó Zº@âˆÏæ^ ~ûí7;+ä™»F&!‰Ÿ+'ƒÁž‰5š¥#GŽXm˜ ìˆ&ÍùU±Rò¢F &ÔÁ?î¡á£SdÂÅ;"¸oÀûÌu–Ü †›÷ðí2r~á[Æb@û ÃwâÇÀKÙ½‚6ƒö˜Bû‚ä19€ü“›808†¬NÐnBþèÝ$ˆvç\œ˜T!Ñ}C.Žÿ1œoÄ‹§7¾÷~l¾VG3Ñ@ÐB#[Ú%±÷’z{3 ~b2þ„S<&Nh½ÂDÒmÞû‰}Îä݉ë' IˆûfѤ|¿®ì®œLž &³ôiô'Ž7Ð߸1Ú)+ˆÏ}GîМÒw9\xŸqÏ¹Ž«¤hòGÃyýõ×­oþ]^É›7¯Õ¦ÐqÓa¢ $tPN`Úщ\ƒ%,³nÒ† ›G—f¨g4f÷Ô‡ÙùÿÛ» )Êûÿãßå(”Ãp+a•ÛƒÈ%AÑ "ëA(XRšˆ R DÄŠ"‚'²ÄÒH"‡…’Ã2(Ä«‚˜€Z&ˆÈ)º š»(ìîϓϿgœ]æìÞ÷SÓÓ3ÝÏó¼žéžï<ÏÓ½~óòÑ“®öÒKC´ú°(ùët´ýûëì} øë÷Å_¸/éH*{¼ùkú•§ƒAÉ;Ptâö—Mîê©RÒ%ðÚUï¥ Œ²ÒE3úe\\\ìzhõe§ùF‚¸ùæ›iß.ƒ˜ÿTîßýîw1k£ŸÆk‡Øu:Ùiöç%-k7,­õþ×½÷¥ãQ'hµµ†ãP«èX{µ½ÀÉ+—¿Ìê¥ÖSÞçNà Æ só:5õ¢ß‘ž?õ®Î;׿YÔ²‚ÄêÚÁ_ÿ†úQç%ïÇw\yë½@Á ´Þ¿®°ôÁêu‡éLúÑ"']%¯}*×3r´|½úè}þãÈ;¾bÛG_j^ÛTw yçØüe_]Ûèý~OoûT#:oy?â5¤¦ã^óƒ½é 6ͅ䯫ÿ\|¼eSÀ¡ï ª*8ñ¿'Ëþc1Ùºf«}uŽóîŒp,f6lpÁŸ¶ó‚Fï|£íýÇ¡¾Ï¼‹xçËØãóXò¯î=þT1 UhˆRÃSJÞP¡æ‡ Psü¼+ÍŒ×ûç6<†ÿhhŒºq½²zþôK+ö‹ãvwLoÑ/|ê׈ԛ‹¨Kн»zKü(&t½ê-ðœü' }™)pzê©§"A•þ_ þ}fbÙ›¤­ùþ@@¿‚tÀ(HTõËH> ÒuCõö©}ôå­“¾.&PRà÷ÓŸþÔŠÞ}«Úwºë§àEæêÅñ|-«Nš;—¤! ÍKÔ|}ν!ÆdÊ¢ž$ÍcÑgØû|ªçII½Púœ©­4¤¢ŽÔ£†týmžLªÚVÇ®Ž Tþ¤ :®ª:¶Õ×®^>9üËêÑÖP™~¸è\¤s›w.ò¿/‘eüš„®öðFPÔNšåÍ%TnUÇ7‘Hž‰¼÷xŽÍTÇ€’Î1ÐçIŸµ°%ÿ-UtîsÒ¹]TÚWß­šF¢sŸFæÔA¡ØAçWÀjôÀKúó’:+t|+Pô¾Ûu±c*Sàƒ?ahzzÔxIàJš°­»®Þ¦ÿ—–÷Þc}Ô¯_] «Éø^Ô—•&Ç«1P¤#éâÍð®¾ÕPœ—øè”.:Ñ£†…c{"¼÷êQÁNðšû¦+«d¦_ÅÞ—±ö­9NS§NuÃÌúE¯Iðú"þÅ‘¡sïCèßg&–Õs«a õì©§@¿¦4RARaa¡ýíosª¨|º`E­ê¥“„ê ÷èàS`¡€Êû’—ÙÑö;—믂3 ‰ú“~™% È\½]jMaPR{ªìÞ¼K™XÖg[?,ä«WU?‰”EÇŽ.Þб£áx]Œ ùzjWµòÒÕæÕЕí:AV—Pƶƒ~,hˆ4‘¤!Qõ6jÈ[m¢eŒ½މì+ïU §{j(IIÃÌÉ&^èŸm}†õCOç}Ѫݔôù¬êª*ÿ0#‰ÔYçðtË €”4µIç<ïGrUeKõúxí›®ºª§V£AúþÕ ïGIªë”ÊýyóÓÕé ^zMeò¦Óè—Fî4¬Ï†¦,i:‡.þÐxú°êâ%½G=¦:¨S¼rÅÛoìkêjŸ>}º;Ñ)àÕ— æ(yÁ™Ú^âè—•’ÊíÝ¢F½€º¸À»A®¶•…×Óv´}Ç–OeSb¯ŠÕ~ýÁŸ÷¹ñ¶­“֫ͼ_„^ù4ªi j/ÅÛÖ{-Õ öôCAó)‹ŠŠâî>^yâ­ó6VϪ‚òÖ{5 §›G+©-Ô–ê±×%}æ¼e·Â÷Ÿ¬•t{ï9ÞË­ZµŠÜƒ0¶LÞso{o}Vt M­Ð<>½®aCïîUmçmŸÎG/o/| þ(ëós´äm[gÿvÞ1 UúlëøÑg:ç)íòïKËʳºc¤ª2yëýûKöÑp›~(Ç;7úóIv¹ª:ëxÒ|¼ºÅž#â•Á{Oìö:~ôV?fõ”Ž»NÄ+Ö­®þí¼rÇ~þüϽ:zë¼m¼ýè;PõS¤y¨Þ­Éôz&Û×+O¼G™õƒT±‚.Õ\hu@¨ìš‡ªù¬:¯hJ…zó¼óÞùN:¯é|¨cS.þùƒñòOt]Þ‘þÿIo‰n€÷«ÛTÁºQS™tÃIÔÞ8~*÷è¾Ô3§!îcÔ«!6}Ñ)ð«*iìŽåË¥ª}¤c½z6Õ«§öôNþ|Ô«ƒ0Þ‰þhõ>Ú¾ýù¤cY'}afâÂŽt”ÿX÷©^=õÈ*Àˆ—¼éË:[=Íâ¬î؈Wæ°¬Ó1 óIUÇýÑŽ¡t;Ô”c$GoY¶Ž—DÊšì{õùÓèOUçŽd÷Ÿí5 @¾ª:é|¨óQ¼ï»dÊúà/¶E@Â&ð¿Ë)ÃV+êƒ € W€à/. +@@p ü…³]© € W€à/. +@@p ü…³]© € W€à/. +@@p Ľɳwß pV™Z!€ €á¨îÞôü…»í© € %@ðÅÁ@@ Üán_j‡ €D üEqð@·Á_¸Û—Ú!€ €QQl KKKí¦›nrÏc÷ÍóÜhÞ¼¹MŸ>Ýð4}*++mÚ´iöÁänÁC^²#FXAA«åŒ3lÕªU!¯1ÕCHV ­÷ù5j” üŠŠŠlèС6kÖ,«_¿¾ÝqÇÉ–›í3,  ã„N°ûï¿ß®¿þz?~¼+ÁðáÃ3\²ófΜé¿={öx«xD@ )¤çüþù¶oß>{ùå—]Aþþ÷¿ÛgŸ}fÝ»wOª`¹¸ñ5×\csçεsÏ=7R¼ûî»ÏæÌ™cuëÖ¬ ê‚ê°víZ[¿~½«ÂÎ;­¤¤Äš6mÔ*¾ÜMš4±ÂÂB[¸paàëB@rC éàO=E›7oŽªÍ† Üðo"ÃÇQ;ÈÑ' p 3ÆÕ.²nݺÙÊ•+íСC9Zêc/Ö<`úç%ÍßlÖ¬™ î½uùä¨ê¹‚Ø=ß¾}{Ôú°<Ù´i“«JEEE(oƒrÛm·¹9›+V¬°¥K—†¥Ù¨ €H*ø“ À³Î:Ëõ‚y¢ºØCÃU ŽÂ–tñƒ®„ÕP·†Dï¹çžPUQuÓ\Æ·ÞzËÝÂ'T•£2 € |ð7oÞüðCþ²‡‡Â# € ê:¤Rüe¡^d‰ € G ºà/é >âäÇ*@@ øËц¡X € €@:þÒ¡Ê>@@ øËц¡X € €@:þÒ¡Ê>@@ øËц¡X € €@:âÞ乺˃ÓQö‰ € zþ2ãL. € €@NüåD3P@@ 3™q&@@ 'þr¢( € ‚¿Ì8“  € 9Ñ @ÈŒÁ_fœÉ@È Ú'tÒ¤T–¤qãÆöãÿØ*++­¤¤$•»f_hذ¡]qÅ6pà@kݺµkÃd g²¨NàôÓO·þýûÛîÝ»­´´´º·ò €Õ ĽÉsµ[TóâE]d¿üå/­víÚööÛoÛúõë«y7/åš@‡ì‘G±ºuëÚ¡C‡ì /´ŸýìgöðÃÛ;3kÅ­1å¹å–[쪫®rõ-..¶•+WÖ˜ºSQ@Ô ¤,ø»õÖ[­  ÀõL´lÙ2õ%ei3fŒÕªUËn¿ývÛ¼y³|òÉöÔSOÙM7ÝDð—výøÌ™3Çòóó9®âó°@à8R6ç¯sçζ|ùr1bÄq#›<ú裮Ì_Ú!C†ØsÏ=gÍ›7÷¯äòŽ;lþüù.ðSvíÚe{÷îµF²>a(tÓ¦MmæÌ™®]ÂPê€ }”õüM˜0ÁÊÊʲ_£4–`Ïž=Ö§OkÒ¤‰}ùå—.§«¯¾Ú s‡a~ãôéÓ#zº0`€µhÑ áG^`!£7Þx£;®úöí›Ñ|É @ ¼)ëù {à§À¢E‹Ü'aðàÁîQ·¨ÇOóÔžþyûãÿè†{ßÿ}70Lõ R]jÂq¤ö ¬ €@Rü…ãhuøôÓOí«¯¾r½zï5×\ã6Y¼xñÑ6 ÔëO?ý´-Y²Ä¶oßn={ö´I“&ªü@ª ø«Ú&î++V¬°fÍš¹¡_ ÅéÖaòõWöµ×^³?üᦠ@táG=¬~ýúþ·°Œ € øK°á^|ñEwÃn¸Á ù¾òÊ+ î!7߮ۻ¨·oäÈ‘QÜ´i“ååå¹€7êž € €@ RvÁG k…Ö v5zÉ%—¸ ðÏþóqì%÷6Ñ}ý4¤­ XÊËËíÝwßµüàvùå—›nò¬!o €_€ž¿ãhÿüå/n+õŠ)h KºãŽ;ìóÏ?ws§L™bC‡uW5;6,U l=***[v Ž [yGn [™[EÊýÒ((Ò¿xÀÖ¬Y“ûN°„ºÍK»ví\g˜‚Ûx; €¡`Ø7f=òwmòäÉ.0Ò=ÿÂø‰CþŸ|òI2¼@‚"À°o-¥?}V¯^={ï½÷lܸq lÉ[@@Ü`Ø77ÚR € € ç/#Ìd‚ €ä†Á_n´¥@@2"@ð—f2A@rC€à/7ÚR € €ˆ{«]ÑJB@¦À7ß|SeÁéù«’†@@ð ü…¯M© € P¥Á_•4¼€ €„O€à/|mJ@@*þª¤á@@ |ákSj„ €T)@ðW% / € €áˆ{Ÿ¿D«Ù A»üòË­sçÎöùçŸÛ+¯¼bÅÅʼnî†÷ç@Ë–-­OŸ>¶ÿ~[¾|y•¬f¥cÇŽÖµkW{ë­·lïÞ½5Z#€¤D éà¯yóæ6}út;ñÄíàÁƒÖ­[7»âŠ+lÚ´iöÁ¤¤ì$óS¦L±&MšØ¡C‡þ2Ï•ãˆ#¬  À­ûâ‹/lÕªUQ¯ó@D’öÕÓ 'œ`÷ß¿]ýõ6~üx—ÿðáÃ)ïÍ!µ£¿ÒÒÒ*UÍ,ÊÌ™3]à·gÏžš @­@R.tÏ_ݺumíÚµ¶~ýzW¸;wZII‰5mÚ4å…Íö5úÐC}§;vìwÖq…ê8`ÀÛ°aƒåååY»ví‚XДYAxaa¡>|ØÆšzQ@ì $ü=ðÀQ¥×ðo³fÍl÷îÝQëÃðDAÞûï¿©ŠþrïÞ½­º¿Ÿys@î¾ûn«¬¬tÃö÷ÜsO@JÞbŽ5ÊÊÊÊÜüËðÖ’š!€dR éà/¶°š+V»vm›3gNìK®aÐÙ³gGê1cÆ +//·‰'FÖyáÒK/µüü|+**²¹*¡)»? €©HzΟ¿0÷Þ{¯vÚi¶hÑ"ûøãý/…nyôèÑ.PzüñÇÝ0wÐ+¨á{ÍÓTíË/¿ôêP~@¨B e=·Ýv›uïÞÝV¬XaK—.­"»p¬¾ð ­ÿþ.HZ³fM(*¥ wêV=#GŽtujÕª•ëÅÕsÝîeûöí¡¨+•@@ & ¤$øÓÕ¡]t‘»ÙÓO?jOD·Þz«mٲІ¥²š«©!ì.]ºDª¤á{¥K.¹Ä6nÜHð‘a@à $ü 8Ðô¯¢¢Â>ûì34hPDãOú“»x ²"à uêÔ±|ÐÕB½›=zôpËß~û­­[·.еӽcÓÔ©S­mÛ¶6lذؗxŽ €H:ø»úê«]ÕkÕªõ aÙ²eîÆÏµùN±u1D£FÜú &D^WÙu×]yΩÐ+ €©È;ÐTÆîH·0!!€ €S ºÛÐ¥ôjß`òPj@@ æüÕœ¶¦¦ € €€üñ!@@jÁ_ jlªŠ €üñ@@jÁ_ jlªŠ €ĽÏ_u—C† € \zþ‚Ûv”@HX€à/a26@@‚+@ðܶ£ä € €@ “± € \‚¿à¶%G@ øK˜Œ @@à ü·í(9 € °Á_Âdl€ €W€à/¸mGÉ@@„þ&c@@ ¸¡ þ:tè`Ï=÷œÝrË-‘Ö¸îºëܺÎ;GÖebaäÈ‘6þ|«[·n$»öíÛÛ‚ ¬   ².S ¿ýío]ÞÊßÿïä“OÎTÈ@rD 4ÁßæÍ›m×®]vÕUW™ÁæÍ››‚¿’’ûè£2ʽnÝ:kܸ±+‹—ñ Aƒ¬Q£F¶zõjoUÆ•ç»ï¾ùwâ‰'Zýúõ­´´4ce #@È ¼üüüÊÜ(Jò¥hذ¡Í›7Ïöïßoÿýï­uëÖö‹_üÂ-'¿÷Äöðâ‹/ÚçŸncÆŒq.Z´È•cÔ¨Q‰í(Åï¾ùæ›mÀ€öÈ#ØÊ•+S¼wv‡ €¹.šž?A+è›1c†5iÒÄÚ´ic………Y üT–5kÖØi§æ†~5äÛ A[¶l™^ÊZêÝ»· ü–/_Nà—µV c@²+ªàO”Û¶m³ÊÊÿufgMW=}yyyvå•WÚ5×\cöÒK/e­<-[¶´_ýêWöé§ŸÚìÙ³³V2F@ì „jØW”¿ÿýïÝ|6uذaV^Ô%#IDAT^î=Íè£.úøÏþãæîرÃ_-ÀÿˬV­ZVTTdõêÕsÃàeeeÙ(y"€ €@„ªçOWú6kÖÌ ý>ú裦 ÔÛ•­ôú믻ág ù¾ð Ù*†Mš4É]€²dÉ;묳ìœsÎqÿ ’@@ f Ô Ku5ÇOC¬º²÷ÿø‡«ÖÚµkMóܺvíjÿþ÷¿3^U|ƒv=š˜­töÙg»¬o¸á†¨"Œ?Þ>ù䓨uio¼ñ†ëÌ¥²Q@¨™¡éù˵æ»ë®»¬W¯^®×ï™gžÉµâQ@¨¡ijxÝÐYCªÏ>û¬»Mš²a· € €@B û&ÄÅ›@@` „êjß`7¥G@Ò/@ð—~cr@@rF€à/gš‚‚ € €é øK¿19 € €9#÷jßšú—tƒhR|:ĵ € (zþÕ\@HN€à/9?¶F@%@ð¨æ¢° € €@rÉù±5 € (‚¿@5…E@’ øKέ@@@ üª¹(, € œ@hƒ¿Ž;ÚàÁƒ­Y³fÉ çÖß|ó½úê«6kÖ,Û¸qãqî%5›UVVÚš5klúôéöÎ;ïXEEEjvÌ^@@ p¡ þFŒaÓ¦M³¡C‡Úgœ‘ñFÙ·oŸé¦È´9sæX—.]lòäÉ/‡2Tà7hÐ ëÓ§Í;×úõëg—]v™>|8+å!S@È®@è‚¿™3gZAAíÙ³'k²&Lpyoß¾ÝÖ¯_oO<ñ„M:ÕV¯^ñ2ÍŸ?ß–-[f+V¬°?üÐV­Ze+W®´ÂÂÂŒ—… @@ ûIíÚµs½IêióÒO~ò·îÌ3ÏôVeô±I“&.°Y¸paFóõ2+--µ Ø}÷Ýg§œrŠåååÙÈ‘#MVÙ(SQQ‘ 2ÄúöíëŠØ³gOS{=óÌ3^‘yD@$Tð·uëVÛµk—ëikß¾½›_wíµ×ÚÞ½{íã?Î ã¨Q£ìÍ7ßÌJÞÊT&J½zõrú¯N:nØU½€™Nk×®µÞ½{Ge{ÞyçÙ¦M›ìСCQëy‚ €áH*øÏ”)SÜü±»ï¾ÛôOüæ7¿Éš\YYYÖòVÆ[¶lqù·nÝ:ªmÚ´±uëÖE­K÷“’’ûúë¯-???*«SO=Õ=ß±cGÔzž € €@øê$[ÅØ“O>i·ß~»5nÜØfÏžíŽd÷›ËÛ+À¼øâ‹£Š¨ KæÍ›g 4pë<õº¶iذaÔºT=Ѱ²zøüiùòåV¿~}·*¶,Þsïuÿv,#€ €@¸’þÄ£ tU©æ·íÞ½;ÜbGj§a\]IìOšk¨¤áo¥;wZÛ¶mݲþÛ¶m›uíÚ5ò<• ýû÷·³Ï>;j—*£‚;õ@Æö𩽔4'‘„ €5K %Áßý÷ßoº¯†|ïºë.>|¸•——‡V²nݺ6nܸ¸õó†X—.]êæùéMš©ž¸±cÇÆÝ&Ù•±¨Ý»w·^xÁî¼óN«]»¶{iÉ’%vÁ¸`Ýÿ^–@@ üIÏùÓ•£M›6uC¿º¥‰z›Æ~¹*j¨7ÝnF·RÑU¿º½Ê˜1cÜ»G]ÅVé[=qâD7$¬Ç 6؃>ènõ’­û¦¯¦ì@ŽE ©ž?]8pùå—»+{½{Øé¢†sÏ=× C*ðÉVÊæ_±Ð<9¨T©S§N¶xñbkÑ¢EÆ9zôèáæa*Ø{üñÇ­Q£FöðÃGný’ñ‘! €dU ïÈ0eel êÕ«»ªF<ÿè£RZOÝ󯸸Øýµ”îø8v¦aøÍ›7»9‰êL4é/–@@ ø‰GÁ¯sÆj !ð\ š4ßïôÓOÏXÝÉ@rS é9¹Y-J… € O€à/ž ë@@ ü…´a© € O€à/ž ë@@ ü…´a© € O€à/ž ë@@ ĽՋþT[¦’î=—+)WnËâyä’W&@@ Øôü»ý(= € Á_B\¼@¶Á_°ÛÒ#€ € ü%ÄÅ›@@` ü»ý(= € Á_B\¼@¶@¨‚?Ý¢æÕW_µY³fÙÆs¦eN?ýt»öÚk­yóæY)See¥­Y³Æ¦OŸnï¼óŽUTTd¥dŠ €ÙMð·oß>Ó}úhsæÌ±.]ºØäÉ“³.|Ë-·Øc=f×_½yæ™/¿AƒYŸ>}lîܹ֯_?»ì²ËìðáÃ/ "€ €@öBüM˜0Áinß¾ÝÖ¯_oO<ñ„M:ÕV¯^5e¡W]u•íÞ½;ke˜?¾-[¶ÌV¬Xa~ø¡­ZµÊV®\i………Y+#€ €@ö’ þFŽi .êÖ­©AûöímÁ‚VPPY—î…ÒÒR—ç}÷Ýg§œrŠååå™ÊÖ®];[¸paº³¯rÿM›6µ™3g:£*ߔ把ŠlÈ!Ö·o_—SÏž=mĈöÌ3Ϥ9gv €¹(Tð·nÝ:kܸ±ëÝò*§!ÆFe´ÇmëÖ­.û^½zyŰ:u긡Nõf+ÝxãöÚk¯e+{—ïÚµk­wïÞQe8ï¼ólÓ¦MvèС¨õkû÷ï¯ÙšÔ@Èq¤ƒ¿{ï½7Ç«Hñ@@<¤þ‡·@@‚!@ðŒv¢” € €@JþRÂÈN@@`ü£(% € ¸|Ô«W/%;ÚNRy_½TÔ½sç멯 û@@"ôüE(X@@Â/@ðþ6¦† € €@D€à/BÁ € ~‚¿ð·15D@" @@ð ü…¿©! €  ø‹P°€ €„_ TÁß7ß|c¯¾úªÍš5Ë6nܘÕÖË¥²ø!:vìhƒ¶fÍšùW³Œ €5D 4Áß¾}û¬C‡6pà@›3gŽuéÒÅ&Ožœ•fÌ¥²øFŒaÓ¦M³¡C‡Úgœá‰e@¨!¡ þ&L˜àšlûöí¶~ýz{â‰'lêÔ©¶zõêŒ7e.•Å«üÌ™3­  ÀöìÙã­â@j @Ü?ïv¬-[¶´‡zè;oß¿¿;ö;ëÓµ¢´´Ô,X` pN9å—ÍÈ‘#Ýó… ڹ瞛®¬¿³ß\*‹¿pMš4±ÂÂB;|ø°7ÎÿË € Pƒ’ þä½ÿþû.ýMàÞ½{›æ»e2mݺÕe׫W¯H¶uêÔ±>}ú¸^ÀÈÊ ,äRYüÕ5j”•••9ÿz–@@ f $ü©—köìÙ±3fXyy¹Mœ81². [¶lqÙ´nÝ:*»6mÚØ+¯¼µ.ÝOr©,þº*ð#!€ €I~¾Ñ£G[~~¾=òÈ#VRRâ)%Ë ^.¾øâ¨}颅yóæYƒ ÜúƒF½®m6lµ.Or©,©¨û@@š#’àï /´þýûÛË/¿lkÖ¬I‹ž†qu•ª?i›RûöíÝãÎ;­mÛ¶nYÿm۶ͺvíyžª…\*KªêÄ~@@ f$üµjÕÊn½õVÓpgQQQÚÔêÖ­[å… êqTZºtidNÛÞ½{mùòåi¹ð$—Ê’6pvŒ €¡H*øS؃>è`xõèÑÃ-ûí·¶nݺŒ©ºÒWW±öìÙÓºuëænó¢h8:“)—Ê’Éz“ €C ©àO=n5r5õîm§'ºèãºë®Ë¨€ní¢€søðá.ßN:ÙâÅ‹­E‹-‡2Ë¥²ÄV¾¢¢"vÏ@@  ä à*cë«[¶d*}ôÑG)ÍJW »¿ö‘ÒÇÎ’-KçÎ#×ôl’éÛ÷¤§ì@Bó>¼¦¬_¿~N~*O.•Åóá@j¶@è‚¿šÝœÔ@¨^€à¯z^E@B%@ðªæ¤2 € €@õÕûð* € *‚¿P5'•A@ª ø«Þ‡W@@P ĽÏ_¨jHe@@"ôüE(X@@Â/@ðþ6¦† € €@D€à/BÁ € ~‚¿ð·15D@" @@ð ü…¿©! € ø?ß “4³ÚýIEND®B`‚iminuit-2.30.1/doc/_static/mov2gif.sh0000755000000000000000000000006614332717401014310 0ustar00#!/bin/sh ffmpeg -i $1 -pix_fmt rgb8 -r 10 output.gif iminuit-2.30.1/doc/_static/numba_vs_scipy.svg0000644000000000000000000012322314332717401016143 0ustar00 2023-05-09T16:51:10.803151 image/svg+xml Matplotlib v3.7.1, https://matplotlib.org/ iminuit-2.30.1/doc/_static/overhead.svg0000644000000000000000000012063014332717401014716 0ustar00 2023-05-09T16:51:11.591610 image/svg+xml Matplotlib v3.7.1, https://matplotlib.org/ iminuit-2.30.1/doc/_static/roofit_vs_iminuit+numba.svg0000644000000000000000000022326614332717401020000 0ustar00 2023-12-21T11:57:41.899742 image/svg+xml Matplotlib v3.7.1, https://matplotlib.org/ iminuit-2.30.1/doc/about.rst0000644000000000000000000001007014332717401012612 0ustar00.. include:: bibliography.txt .. _about: About ===== What is iminuit? ---------------- iminuit is the fast interactive IPython-friendly minimiser based on `Minuit2`_ C++ library maintained by CERN's ROOT team. The corresponding version of the C++ code is listed after the '+' in the iminuit version string: |release|. For a hands-on introduction, see the :ref:`tutorials`. **Easy to install with binary wheels for CPython and PyPy** If you use one of the currently maintained CPython versions on Windows, OSX, or Linux, installing iminuit from PyPI is a breeze. We offer pre-compiled binary wheels for these platforms. We even support the latest PyPy. On other platforms you can also install the iminuit source package if you have a C++ compiler that supports C++14 or newer. Installing the source package compiles iminuit for your machine automatically. All required dependencies are installed from PyPI automatically. **Robust optimiser and error estimator** iminuit uses Minuit2 to minimise your functions, a battle-hardened code developed and maintained by scientists at CERN, the world's leading particle accelerator laboratory. Minuit2 has good performance compared to other minimizers, and it is one of the few codes out there which compute error estimates for your parameters. When you do statistics seriously, this is a must-have. **Support for NumPy** iminuit interoperates with NumPy. You can minimize functions that accept parameters as positional arguments, but also functions that accept all parameters as a single NumPy array. Fit results are either NumPy arrays or array-like types, which mimic key aspects of the array interface and which are easily convertible to arrays. **Interactive convenience** iminuit extracts the parameter names from your function signature (or the docstring) and allows you access them by their name. For example, if your function is defined as ``func(alpha, beta)``, iminuit understands that your first parameter is ``alpha`` and the second ``beta`` and will use these names in status printouts (you can override this inspection if you like). It also produces pretty messages on the console and in Jupyter notebooks. **Support for Cython, Numba, JAX, Tensorflow, ...** iminuit was designed to work with functions implemented in Python and with compiled functions, produced by Cython, Numba, etc. **Successor of PyMinuit** iminuit is mostly compatible with PyMinuit. Existing PyMinuit code can be ported to iminuit by just changing the import statement. If you are interested in fitting a curve or distribution, take a look at `probfit`_. Who is using iminuit? --------------------- This is a list of known users of iminuit. Please let us know if you use iminuit, we like to keep in touch. * probfit_ * gammapy_ * flavio_ * Veusz_ * TensorProb_ * threeML_ * pyhf_ * zfit_ * ctapipe_ * lauztat_ Technical docs -------------- When you use iminuit/Minuit2 seriously, it is a good idea to understand a bit how it works and what possible limitations are in your case. The following links help you to understand the numerical approach behind Minuit2. The links are ordered by recommended reading order. * The `MINUIT paper`_ by Fred James and Matts Roos, 1975. * Wikipedia articles for the `Quasi Newton Method`_ and `DFP formula`_ used by MIGRAD. * `Variable Metric Method for Minimization`_ by William Davidon, 1991. * Original user guide for C++ Minuit2: :download:`MINUIT User's guide ` by Fred James, 2004. Team ---- iminuit was created by **Piti Ongmongkolkul**. It is a logical successor of pyminuit/pyminuit2, created by **Jim Pivarski**. It is now maintained by **Hans Dembinski** and the Scikit-HEP_ community. Maintainers ~~~~~~~~~~~ * Hans Dembinski (@HDembinski) [current] * Christoph Deil (@cdeil) * Piti Ongmongkolkul (@piti118) * Chih-hsiang Cheng (@gitcheng) Contributors ~~~~~~~~~~~~ * Jim Pivarski (@jpivarski) * Henry Schreiner (@henryiii) * David Men\'endez Hurtado (@Dapid) * Chris Burr (@chrisburr) * Andrew ZP Smith (@energynumbers) * Fabian Rost (@fabianrost84) * Alex Pearce (@alexpearce) * Lukas Geiger (@lgeiger) * Omar Zapata (@omazapa) iminuit-2.30.1/doc/benchmark.rst0000644000000000000000000002473014332717401013442 0ustar00.. include:: bibliography.txt Benchmarks ========== Speed of an unbinned fit ------------------------ ``iminuit`` comes with a couple of built-in cost functions, but also makes it easy for users to implement their own. One motivation to use your own cost function is to get the best possible performance. If your fit takes more than a minute (possible if you do an unbinned fit on a large sample or if you have a model with many parameters), you may wonder whether there are wells to speed things up. There are, read on. There are a few simple steps which increase performance without much effort. - If you have a large sample, use a binned fit instead of an unbinned fit, e.g. :class:`iminuit.cost.BinnedNLL` instead of :class:`iminuit.cost.UnbinnedNLL`. This can easily give you a factor 100 speed-up. - Use faster implementations of probability densities from `numba_stats`_. - Use `numba`_ to compile the cost function; try options `parallel=True` and `fastmath=True` to parallelize the computation. This works best if you use the distributions from `numba_stats`_. Next we show some benchmarks to prove some of these points. The gain of using a binned fit is demonstrated elsewhere, see "Binned vs. unbinned fits" in :ref:`studies`. For the following benchmarks, we consider a common model in high-energy physics which describes a mixture of two components, a background described by a truncated exponential and a signal described by a normal distribution. The model is fitted to a dataset of varying size using the maximum-likelihood method. Our cost function is the negative sum of log-probabilities. .. code-block:: python import numpy as np from numba_stats import norm, truncexpon x = ... # data def model(x, z, mu, sigma, slope): # background is truncated to the observation window [0, 1] b = truncexpon.pdf(x, 0, 1, 0, slope) s = norm.pdf(x, mu, sigma) return (1 - z) * b + z * s # handwritten negative log-likelihood def nll(z, mu, sigma, slope): ll = np.log(model(x, z, mu, sigma, slope)) return -np.sum(ll) It is also possible to write down a ``log_model`` computed from the ``logpdf`` functions which are available for the two component distributions, but the code is more complex and the gain is small, so it is not explicitly shown here. The following plot shows that this cost function computed with pdfs from `numba_stats`_ is much faster than using those from `scipy`_. .. image:: _static/numba_vs_scipy.svg It is an order of magnitude for small samples and still a factor of three for very large samples. Instead of using a handwritten negative log-likelihood, it is convenient to use the built-in class :class:`iminuit.cost.UnbinnedNLL`. This increases the call overhead slightly compared to a handwritten function compiled with `numba`_. The smallest possible overhead is obtained by compiling the function with a ``numba.cfunc`` interface, which ``iminuit`` supports as a special case. .. code-block:: python import numba as nb import numpy as np from numba_stats import norm, truncexpon # mark function for inlining to improve performance @nb.njit(inline="always") def model(x, z, mu, sigma, slope): b = truncexpon.pdf(x, 0, 1, 0, slope) s = norm.pdf(x, mu, sigma) return (1 - z) * b + z * s # Just-in-time-compiled negative log-likelihood @nb.njit def nll(z, mu, sigma, slope): ll = np.log(model(x, z, mu, sigma, slope)) return -np.sum(ll) # as before, but with a cfunc interface @nb.cfunc(nb.double(nb.uintc, nb.types.CPointer(nb.double))) def nll2(n, par): z, mu, sigma, slope = nb.carray(par, (n,)) ll = np.log(model(x, z, mu, sigma, slope)) return -np.sum(ll) The three ways of calling the function are compared in the following plot. The call overhead is only relevant for small samples, where speed is usally no concern. For most users, :class:`iminuit.cost.UnbinnedNLL` incurs a neglible performance loss compared to the best handwritten solution. .. image:: _static/overhead.svg A very powerful feature of `numba`_ is auto-parallelization. The distributions in `numba_stats`_ are written so that they benefit optimally from auto-parallelization. To enable this, we only have to change the decorator. .. code-block:: python import numba as nb import numpy as np from numba_stats import norm, truncexpon @nb.njit(parallel=True, fastmath=True) def nll(z, mu, sigma, slope): ll = np.log(model(x, z, mu, sigma, slope)) return -np.sum(ll) The combination ``parallel=True`` and ``fastmath=True`` provides the best performance. Auto-parallelization speeds up the calculation of the cost function over large datasets considerably, but slows it down over small datasets. Only enable it when you profit from it. The following plot compares the performance of iminuit with `numba`_ JIT'ed NLL functions to an equivalent fit with the `RooFit`_ framework (from ROOT-v6.30/02 installed with ``conda``). RooFit can compute with several backends. The fastest is the ``CPU`` backend, which is comparable to the numba-compiled NLL function. The other backends run slower in this example. RooFit also has a parallel computation mode, but the auto-parallelized NLL function outperforms it by a large margin. When the dataset is small (< 1000), RooFit is slightly faster due to the Python call overhead, which we previously discussed. .. image:: _static/roofit_vs_iminuit+numba.svg Performance hints ^^^^^^^^^^^^^^^^^ - Use the distributions from `numba_stats`_ instead of the `scipy`_ equivalents to get large performance gains. - Use auto-parallelization to speed up the computation of the cost function for large datasets. Always combine the options `parallel=True` and `fastmath=True`, which allows the compiler to run the parallel computation out-of-order (among other things). - When the computation is split into several functions, use the option `inline="always"` for the inner `numba.njit` functions. Without inlining, the compiler will miss important global optimization opportunities. - If you don't need to parallelize the computation, use :class:`iminuit.cost.UnbinnedNLL`. It is likely as good as the fastest function you can write by hand. - Dramatic (100x) performance gains also be achieved by replacing unbinned fits with binned fits, see `binned vs. unbinned fits`_. .. _binned vs. unbinned fits: notebooks/binned_vs_unbinned.ipynb Minuit2 vs other optimisers --------------------------- We compare the performance of Minuit2 (the code that is wrapped by iminuit) with other minimizers available in Python. We compare Minuit with the strategy settings 0 to 2 with several algorithms implemented in the `nlopt`_ library and `scipy.optimize`_. All algorithms minimize a dummy cost function .. code-block:: python def cost_function(par): z = (y - par) return sum(z ** 2 + 0.1 * z ** 4) where ``y`` are samples from a normal distribution scaled by a factor of 5. The second term in the sum assures that the cost function is non-linear in the parameters and not too easy to minimize. No analytical gradient is provided, since this is the most common way how minimizers are used for small problems. The cost function is minimized for a variable number of parameters from 1 to 100. The number of function calls is recorded and the largest absolute deviation of the solution from the truth. The fit is repeated 100 times for each configuration to reduce the scatter of the results, and the medians of these trails are computed. The scipy algorithms are run with default settings. For nlopt, a stopping criterion must be selected. We stop when the absolute variation in the parameters is becomes less than 1e-3. The results are shown in the following three plots. The best algorithms require the fewest function calls to achieve the highest accuracy. .. image:: _static/bench.svg .. image:: _static/bench2d.svg Shown in the first plot is the number of calls to the cost function divided by the number of parameters. Smaller is better. Note that the algorithms achieve varying levels of accuracy, therefore this plot alone cannot show which algorithm is best. Shown in the second plot is the accuracy of the solution when the minimizer is stopped. The stopping criteria vary from algorithm to algorithm. The third plot combines both and shows accuracy vs. number of function calls per parameter for fits with 2, 10, and 100 parameters, as indicated by the marker size. Since higher accuracy can be achieved with more function evaluations, the most efficient algorithms follow diagonal lines from the top left to the bottom right in the lower left edge of the plot. Discussion ^^^^^^^^^^ The following discussion should be taken with a grain of salt, since experiments have shown that the results depend on the minimisation problem. Also not tested here is the robustness of these algorithms when the cost function is more complicated or not perfectly analytical. * Minuit2 is average in terms of accuracy vs. efficiency. Strategy 0 is pretty efficient for fits with less than 10 parameters. The typical accuracy achieved in this problem is about 0.1 to 1 %. Experiments with other cost functions have shown that the accuracy strongly depends on how parabolic the function is near the minimum. Minuit2 seems to stop earlier when the function is not parabolic, achieving lower accuracy. * The scipy methods Powell and CG are the most efficient algorithms on this problem. Both are more accurate than Minuit2 and CG uses much fewer function evaluations, especially in fits with many parameters. Powell uses a similar amount of function calls as Minuit2, but achieves accuracy at the level of 1e-12, while Minuit2 achieves 1e-3 to 1e-6. * An algorithm with a constant curve in the first plot has a computation time which scales linearly in the number of parameters. This is the case for the Powell and CG methods, but Minuit2 and others that compute an approximation to the Hesse matrix scale quadratically. * The Nelder-Mead algorithm shows very bad performance with weird features. It should not be used. On the other hand, the SBPLX algorithm does fairly well although it is a variant of the same idea. In summary, Minuit2 (and therefore iminuit) is a good allrounder, but it is not outstanding in terms of convergence rate or accuracy. Using strategy 0 seem safe to use: it speeds up the convergence without reducing the accuracy of the result. If fast convergence is critical, it can be useful to try others minimisers. The scipy minimisers are accessible through :meth:`iminuit.Minuit.scipy`. iminuit-2.30.1/doc/bibliography.txt0000644000000000000000000000306314332717401014166 0ustar00.. _scipy: https://scipy.org/ .. _scipy.optimize: https://docs.scipy.org/doc/scipy/tutorial/optimize.html .. _numba: https://numba.pydata.org .. _numba_stats: https://github.com/HDembinski/numba-stats .. _jax: https://jax.readthedocs.io .. _nlopt: https://nlopt.readthedocs.io/en/latest .. _pyhf: https://github.com/diana-hep/pyhf .. _ctapipe: https://github.com/cta-observatory/ctapipe .. _lauztat: https://github.com/marinang/lauztat .. _threeML: https://github.com/threeML/threeML .. _Veusz: https://github.com/veusz/veusz .. _TensorProb: https://github.com/tensorprob/tensorprob .. _Scikit-HEP: https://scikit-hep.org .. _probfit: https://github.com/scikit-hep/probfit .. _gammapy: https://github.com/gammapy/gammapy .. _flavio: https://github.com/flav-io/flavio .. _zfit: https://github.com/zfit/zfit .. _Minuit2: https://root.cern.ch/root/htmldoc/guides/minuit2/Minuit2.html .. _PyMinuit: http://code.google.com/p/pyminuit .. _ipythonnb: http://ipython.org/ipython-doc/dev/notebook/index.html .. _Quasi Newton Method: https://en.wikipedia.org/wiki/Quasi-Newton_method .. _DFP formula: https://en.wikipedia.org/wiki/Davidon-Fletcher-Powell_formula .. _Variable Metric Method for Minimization: https://www.osti.gov/biblio/4252678 .. _A New Approach to Variable Metric Algorithm: http://comjnl.oxfordjournals.org/content/13/3/317.full.pdf+html .. _MINUIT paper: https://doi.org/10.1016/0010-4655(75)90039-9 .. _setuptools: https://pypi.python.org/pypi/setuptools .. _pytest: http://pytest.org .. _zenodo: https://zenodo.org/record/4310361 .. _RooFit: https://root.cern/manual/roofit/ iminuit-2.30.1/doc/changelog.rst0000644000000000000000000014635014332717401013442 0ustar00.. include:: bibliography.txt .. _changelog: Changelog ========= 2.30.1 (October 08, 2024) ------------------------- - Ci: add 3.13 wheels (`#1047 `_) 2.30.0 (September 24, 2024) --------------------------- - Fix: root version in docs (`#1043 `_) - Allow to modify slider range in interactive widget (`#1038 `_) - Fix: add readout_format to slider (`#1036 `_) 2.29.1 (August 25, 2024) ------------------------ - Show correct ROOT version in documentation 2.29.0 (August 25, 2024) ------------------------ - Fix odr issue in type_caster which could result in ub when `-flto` is enabled (`#1028 `_) - Remove packaging dependency (`#1027 `_) - Restore cython tutorial (`#1026 `_) - Support sum(w) < 0 in binned fits (`#1022 `_) - Set `pybind11_findpython` `on` to use `findpython` cmake mode (`#1023 `_) - Fix version parse (`#1021 `_) - Improve maintainer metadata (`#1020 `_) 2.28.0 (August 01, 2024) ------------------------ - Add name argument to all cost functions (`#1017 `_) - Fix leastsquares for functions with more than two arguments (`#1016 `_) - Drop support for python-3.8 (`#1015 `_) - Updating docs and links and ci for building docs (`#1014 `_) - Ci: try to make faster (`#996 `_) 2.27.0 (July 30, 2024) ---------------------- - Fix odr issue in type_caster (`#1013 `_) - More robust unified fitting in minuit.migrad and minuit.mnprofile (`#1009 `_) - Cure error when extremes cannot be found (`#1011 `_) - Fix for visibledeprecationwarning, useful annotated types, support tuple annotation (`#1004 `_) - Ci: using uv with cibuildwheel (`#999 `_) 2.26.0 (June 03, 2024) ---------------------- - Ci: add github artifact attestations to package distribution (`#993 `_) - Ci: macos-latest is changing to macos-14 arm runners (`#989 `_) - Added new tutorial on fitting correlated data (`#987 `_) - Update to root master (`#986 `_) - Check for odr violations and fix odr violation (`#985 `_) - Improve comments on coverage (`#984 `_) - Use modern ruff config & ruff fmt (`#978 `_) - Bump the actions group with 3 updates (`#979 `_) - Support numpy 2 (`#977 `_) 2.25.2 (February 09, 2024) -------------------------- - Update to latest root (`#970 `_) - Move documentation to Github pages (`#969 `_) 2.25.1 (February 08, 2024) -------------------------- - Fix LeastSquares.visualize for models that accept parameter array (`#968 `_) - Update benchmark to root-6.30 (`#967 `_) - Improve docs for make_with_signature (`#963 `_) 2.25.0 (January 31, 2024) ------------------------- - Approximate cdf from pdf (`#950 `_) - Fix test that requires scipy and raise error on invalid value for use_pdf (`#962 `_) - Fix docstring parsing (`#953 `_) - Fix use of removed array rules in test (`#952 `_) - Benchmark update to root 6.30 (`#951 `_) - Fix: include debug info on failures (`#946 `_) - Warn on errordef override (`#937 `_) - Cost gradient support (`#936 `_) 2.24.0 (August 15, 2023) ------------------------ - Iteration limit in smart sampling to fix behavior for step functions (`#928 `_) - Clarify meaning of 2d contours in minuit.draw_mnmatrix (`#927 `_) - Support interval type and check compatibility with pydantic (`#922 `_) 2.23.0 (July 28, 2023) ---------------------- - Fix ``CostSum.visualize`` bug (`#918 `_) - Fix ``_safe_log`` on systems which use 32 bit floats (`#915 `_), (`#919 `_) - Skip test_interactive and friends when ipywidgets is not installed (`#917 `_) - Turn negative zero into positive zero in ``pdg_format`` (`#916 `_) - Remove warning in ``test_cost.py`` by using ``pytest.warns`` instead of ``pytest.raises`` (`#914 `_) 2.22.0 (June 22, 2023) ---------------------- - Hide confusing notes in docs: "not to be initialized by users." (`#906 `_) - Fix: sdist size reduction (`#904 `_) - Fix tests on freebsd, remove util._jacobi (`#903 `_) - Update conclusions after the fix from jonas (`#899 `_) - Use scikit-build-core (`#812 `_) - Fix: make nograd not use grad at all in automatic diff doc (`#895 `_) - Bump pypa/cibuildwheel from 2.12.3 to 2.13.0 (`#897 `_) - Add minuit.fixto (`#894 `_) - New benchmarks (`#893 `_) - Make covariance fields in display easier to understand (`#891 `_) - Improve docs (`#890 `_) - Bump pypa/cibuildwheel from 2.12.1 to 2.12.3 (`#886 `_) - Update fcn.hpp (`#889 `_) - Fix-typo-in-basic (`#888 `_) - Add leastsquares.pulls and leastsquares.prediction (`#880 `_) - Better log-spacing detection (`#878 `_) - Roofit tutorials (`#877 `_) - Rename keyword nbins to bins in unbinnedcost.visualize (`#876 `_) - Ignore missing matplotlib when calling minuit._repr_html_() (`#875 `_) - Forward kwargs in minuit.visualize to plotting function (`#874 `_) - Add hide_modules and deprecated_parameters (`#873 `_) - Update progressbar (`#872 `_) - Better ruff settings and adjustments, improvements to readme (`#871 `_) - Use unicodeitplus instead of unicodeit to render latex as unicode (`#868 `_) - Add roofit tutorial (`#867 `_) - Improve error message for cost function (`#863 `_) - Experimental mncontour algorithm (`#861 `_) - Integer as variable (`#860 `_) - Replace flake8 with ruff (`#859 `_) - Add basic latex display support if unicodeit is installed (`#858 `_) 2.21.3 (April 03, 2023) ----------------------- - Fix template input modification bug in template class (`#856 `_) - Better docs for limits from annotated model parameters (`#853 `_) 2.21.2 (March 19, 2023) ----------------------- - Fix CITATION.CFF 2.21.1 (March 18, 2023) ----------------------- - Fix string annotations (`#849 `_) - Specifiy minimum required numpy version (`#848 `_) 2.21.0 (March 03, 2023) ----------------------- - Fix of matrix_format (`#843 `_) - Support annotated model parameters (`#839 `_) - Visualize fit in minuit._repr_html_ (`#838 `_) 2.20.0 (February 13, 2023) -------------------------- - Fix coverage, typing, template for 2d models (`#836 `_) - Template mix (`#835 `_) - Docs: use 'req@url' syntax to install from remote vcs (`#834 `_) 2.19.0 (February 10, 2023) -------------------------- - Remove setup.cfg (`#833 `_) - Fix typo "probility" to "probability" in minos doc (`#832 `_) - Prediction for all binned likelihoods (`#831 `_) - Template prediction (`#820 `_) - Upgrade old build and ci (`#817 `_) - Add configurable number of bins for extended/unbinnednll (`#815 `_) 2.18.0 (December 14, 2022) -------------------------- - Add more checks for gradients (`#810 `_) - Bump pypa/cibuildwheel from 2.10.2 to 2.11.2 (`#808 `_) - Added visualize function to minuit (`#799 `_) - Move tutorials (`#806 `_) 2.17.0 (September 26, 2022) --------------------------- - Add python 3.11, drop 3.6 (`#792 `_) - Add Template fitting method from Argüelles, Schneider, Yuan (`#789 `_) - Deprecate `iminuit.cost.BarlowBeestonLite` in favor of `iminuit.cost.Template` 2.16.0 (August 16, 2022) ------------------------ - Root update (`#786 `_) - Fix corner case treatment of linear constraint (`#785 `_) - Comparison with broadcasting (`#784 `_) - Fix typing issues and enable mypy in pre-commit (`#783 `_) - Make fixedview act as mask for other views (`#781 `_) 2.15.2 (August 03, 2022) ------------------------ - Improve docs for minimize (`#777 `_) - Fix for minuit.interactive when using an array-based function (`#776 `_) 2.15.1 (July 28, 2022) ---------------------- - Fix pickling of all builtin cost functions (`#773 `_) 2.15.0 (July 27, 2022) ---------------------- - Smart sampling (`#769 `_) - Enhance interactive (`#768 `_) 2.14.0 (July 25, 2022) ---------------------- - Interactive fitting (`#766 `_) 2.13.0 (July 17, 2022) ---------------------- - Interpolated mncontour (`#764 `_) - Added mnmatrix plot (`#763 `_) - Close mncontour for convenience (`#761 `_) - Update tutorials (`#760 `_) 2.12.2 (July 15, 2022) ---------------------- - fix a bug in error heuristic when parameters have negative values and prevent assigning negative values to errors (`#759 `_) 2.12.1 (July 1, 2022) --------------------- Fixes ~~~~~ - ``cost.BarlowBeestonLite``: method "hpd" has been modified to fix performance in cases where bins are not dominated by a single template 2.12.0 (June 21, 2022) ---------------------- New features ~~~~~~~~~~~~ - New cost function ``cost.BarlowBeestonLite`` for template fits with correct uncertainty propagation for templates obtained from simulation or sWeighted data, written together with @AhmedAbdelmotteleb - Formerly private chi2 utility cost functions (``cost.poisson_chi2``, etc.), are now part of public API - Support custom grid in ``Minuit.profile``, ``iminuit.mncontour``, ``iminuit.contour`` - Handle common CL values in ``Minuit.mnprofile`` and ``Minuit.mncontour`` without scipy Fixes ~~~~~ - Skip tests that use ``np.float128`` on platforms where this type is not supported - ``Minuit.valid`` now returns ``False`` if EDM is NaN - ``subtract_min`` setting is no longer ignored by ``Minuit.draw_contour`` Documentation ~~~~~~~~~~~~~ - New study about template fits Other ~~~~~ - ``Minuit`` no longer warns when a function is used that has no ``errordef`` attribute and ``Minuit.errordef`` is not explicitly set. The function is assumed to be chi-square-like up to an arbitrary constant, unless ``errordef`` is explicitly set to something else. - More type correctness in API, better hiding of private objects in library - Option to use external pybind11, by @henryiii - Update to pybind11-v2.9.2, by @henryiii - Update to root-v6-25-02 plus our patches - Several minor cleanups and internal tool updates, by @henryiii 2.11.2 (March 28, 2022) ----------------------- Other ~~~~~ - Fixed wording in cost function tutorial 2.11.1 (March 27, 2022) ----------------------- Fixes ~~~~~ - Fixed a failure of ``util.make_with_signature`` in some situations Other ~~~~~ - Raise numpy.VisibleDeprecationWarning instead of warnings.DeprecationWarning - ``util.propagate`` is deprecated in favour of ``jacobi.propagate`` from the jacobi library 2.11.0 (March 27, 2022) ----------------------- New features ~~~~~~~~~~~~ - All builtin cost functions now support multidimensional data - ``Matrix.to_dict`` was added for symmetry with ``BasicValueView.to_dict`` - For long-running fits, total runtime is now shown in ``FMin`` display and total runtime can be accessed via property ``FMin.time`` Fixes ~~~~~ - In binned fits when ``ndof`` is zero, show ``reduced chi2 = nan`` in the ``FMin`` display instead of raising a ZeroDivisionError Documentation ~~~~~~~~~~~~~ - Tutorials and studies are now listed separately - Tutorial for fits of multivariate data were added - The cost function tutorial was improved - Studies in regard to performance were added, including a comparison with RooFit 2.10.0 (March 4, 2022) ---------------------- New features ~~~~~~~~~~~~ - ``UnbinnedNLL`` and ``ExtendedUnbinnedNLL`` now support models that predict the ``logpdf`` instead of the ``pdf`` when the extra keyword ``log=True`` is set; when it is possible, using the ``logpdf`` instead of the ``pdf`` for fitting is faster and numerically more stable 2.9.0 (January 7, 2022) ----------------------- Fixes ~~~~~ - ``Minuit.draw_mncontour`` now works with matplotlib >= 3.5 - Builtin cost functions now work correctly when the mask is set and data is updated on the existing cost function Performance ~~~~~~~~~~~ - Builtin cost functions are now more performant when used with weighted binned data Other ~~~~~ - Wheels for Python 3.10, by @henryiii - Bump pybind11 to 2.9.0, by @henryiii 2.8.4 (October 11, 2021) ------------------------ Fixes ~~~~~ - Pickling of ``util.Matrix`` resulted in incomplete state after unpickling, which would cause an exception when you tried to print the matrix Documentation ~~~~~~~~~~~~~ - New tutorial on fitting PDFs that depend on a conditional variable - Fixed JAX tutorial, adapting to change in their interface - Extended documentation of cost functions 2.8.3 (September 3, 2021) ------------------------- New features ~~~~~~~~~~~~ - ``util.propagate`` now discriminates between diverging derivates (using the value NaN for the derivate) and non-converging derivatives (using the best value computed so far for the derivative) Documentation ~~~~~~~~~~~~~ - Fixes for faulty LaTeX rendering in some tutorials Other ~~~~~ - Support cross-compiling of ARM on Conda, by @henryiii 2.8.2 (August 15, 2021) ----------------------- Fixes ~~~~~ - ``Minuit.draw_mncontour`` can now be used by passing a single float to keyword ``cl``, in addition to passing a list of floats - Use ``pybind11::ssize_t`` everywhere instead of non-standard ``ssize_t`` to fix compilation against Python-3.10 on Windows, co-authored with @cgohlke Documentation ~~~~~~~~~~~~~ - Docstring improved for ``Minuit.mncontour``, advice added on how to draw closed curve with points returned by ``Minuit.mncontour`` - Docstring improved for ``Minuit.draw_mncontour``, parameters and returned objects are now properly documented 2.8.1 (August 4, 2021) ---------------------- Other ~~~~~ - @henryiii added Apple Silicon wheels - @odidev added Linux aarch64 wheels 2.8.0 (July 25, 2021) --------------------- Minor API change ~~~~~~~~~~~~~~~~ - ``Minuit.mncontour`` now raises ``RuntimeError`` instead of ``ValueError`` if it is not called at a valid minimum point New features ~~~~~~~~~~~~ - ``Minuit.mncontour`` can now be called at any point without running a minimiser before, similar to ``Minuit.minos`` Fixes ~~~~~ - ``Minuit.mncontour`` used to fail if called twice in a row 2.7.0 (July 4, 2021) -------------------- Minor API change ~~~~~~~~~~~~~~~~ - If ``Minuit.hesse`` is called when ``Minuit.fmin`` is ``None``, an instance ``Minuit.fmin`` is now created. If Hesse fails, the code does not raise an exception anymore, since now the error state can be accessed as usual from the ``Minuit.fmin`` object. Users who relied on the exception should check ``Minuit.fmin`` from now on. New features ~~~~~~~~~~~~ - ``Minuit.scipy`` can be used to minimise with SciPy algorithms. These may succeed when ``Minuit.migrad`` fails and support additional features. Some algorithms allow one to pass a function that returns the Hessian matrix (which may be computed analytically or via automatic differentiation provided by other libraries like JAX). Other algorithms support minimisation under arbitrary non-linear constraints. - ``util.FMin`` has new html/text representations; the field ``Valid parameters`` was removed, a title with the name of the minimisation method was added - ``Minuit.tol`` now accepts the values 0 and ``None``, the latter resets the default - Builtin cost functions now support models that return arrays in long double precision ``float128``. In this case, all computations inside the cost function are also done in higher precision. - Builtin cost functions now raise a warning if the user-defined model does not return a numpy array Fixes ~~~~~ - Calling ``Minuit.migrad`` with a call limit under some circumstances used much more calls than expected and did not report that the call limit was reached (patch submitted to ROOT) - ``Minuit.hesse`` no longer sets the status of the FunctionMinimum unconditionally to valid if it was invalid before - Repeated calls to ``Minuit.hesse`` no longer accumulate calls and eventually exhaust the call limit, the call counter is now properly reset - Calling ``Minuit.minos`` repeatedly now does not recompute the Hessian and avoids a bug that used to exhaust the call limit before in this case Documentation ~~~~~~~~~~~~~ - Tutorial notebooks are now fully integrated into the HTML documentation - A tutorial on using constrained minimisation from SciPy for HEP task was added Other ~~~~~ - ``util.BasicView`` is now a proper abstract base class 2.6.1 (May 13, 2021) -------------------- Fixes ~~~~~ - Calling ``Minuit.fixed[...] = False`` on parameter that was not fixed before lead to undefined behaviour in Minuit2 C++ code (patch submitted to ROOT) Other ~~~~~ - Upgrade Minuit2 C++ code to latest ROOT master with simplified internal class structure and class tags replaced with enums 2.6.0 (May 2, 2021) ------------------- New features ~~~~~~~~~~~~ - Builtin cost functions now report the number of data points with the attribute ``Cost.ndata`` - New attribute ``Minuit.ndof`` returns the degrees of freedom if the cost function reports it or NaN - New attribute ``FMin.reduced_chi2`` to report the reduced chi2 of the fit; returns NaN if the reduced chi2 cannot be computed for the cost function, in case of unbinned maximum-likelihood or when the attribute ``Cost.ndata`` is missing 2.5.0 (April 30, 2021) ---------------------- New features ~~~~~~~~~~~~ - ``util.merge_signatures`` added based on ``merge_user_func`` from ``probfit``, by @mbaak - ``util.make_with_signature`` added to create new functions with renamed arguments - ``util.BasicView.to_dict`` added, by @watsonjj - ``util.BasicView`` and ``util.Matrix`` now supports element selection with sequences like ``numpy.ndarray`` - ``util.propagate`` to error propagate covariance matrices from one vector space to another (Jacobi matrix is computed numerically) Fixes ~~~~~ - ``util.BasicView`` now supports slices of the form ``a[:len(a)]`` or ``a[:M]`` with ``M > len(a)`` like other Python containers - ``util.Matrix`` now returns a square matrix when it is used with a slice or item selection - Missing comma in BibTeX entry shown in CITATION.rst, by Ludwig Neste Other ~~~~~ - ``util.describe`` returns list instead of tuple Documentation ~~~~~~~~~~~~~ - Better docstring for ``util.FMin`` - New tutorial on how to do simultaneous fits / adding likelihoods, by @watsonjj - New tutorial on how to use builtin cost function - New tutorial about how to draw error bands around fitted curves 2.4.0 (February 10, 2021) ------------------------- New features ~~~~~~~~~~~~ - ``minimize`` - Keyword ``method`` now accepts "migrad" and "simplex" - Keyword ``option`` now supports keyword "stra" to set ``Minuit.strategy`` - ``OptimizeResult.message`` now states if errors are not reliable - ``Minuit`` now supports functions wrapped with ``functools.partial``, by @jnsdrtlf Other ~~~~~ - Upgrade Minuit2 C++ code in ROOT to latest version with following improvements - improvement of seed when using an analytical gradient - fix of last minimum state added twice to vector of minimum states in some cases (no impact for iminuit users, but saves a bit of memory) - Documentation improvements - Updated tutorial about automatic differentiation, added comparison of ``numba.njit`` and ``jax.jit`` 2.3.0 (January 24, 2021) ------------------------ New features ~~~~~~~~~~~~ - ``cost.BinnedNLL`` and ``cost.ExtendedBinnedNLL`` now support weighted binned data Bug-fixes ~~~~~~~~~ - ``FMin.edm_goal`` now remains unchanged if ``Minuit.hesse`` is run after ``Minuit.migrad`` Other ~~~~~ - Update to cibuildwheels-1.8.0 and workflow simplification, by @henryiii 2.2.1 (December 22, 2020) ------------------------- Minor improvements ~~~~~~~~~~~~~~~~~~ - ``Minuit.profile``, ``Minuit.mnprofile``, ``Minuit.contour``, ``Minuit.draw_profile``, ``Minuit.draw_mnprofile``, and ``Minuit.draw_contour`` can now be called with ``subtract_min=True`` even if ``Minuit.fmin`` is None - ``__version__`` now also displays the ROOT version of the C++ Minuit2 library - Support for adding constant numbers to cost functions, this allows you to write ``sum(cost1, cost2, ...)`` and may be useful to subtract a constant bias from the cost Other ~~~~~ - Documentation improvements - Further transition to numpydoc - Clarified that iminuit is based on ROOT code - List full iminuit version including ROOT version in docs - Added type hints to many interfaces (incomplete) - Renamed ``_minuit`` to ``minuit``, making the module public - Renamed ``_minimize`` to ``minimize``, making the module public - pydocstyle added to pre-commit checks 2.2.0 (December 20, 2020) ------------------------- New features ~~~~~~~~~~~~ - Cost functions in ``cost`` are now additive, creating a new cost function with the union of parameters that returns the sum of the results of the individual cost functions - ``cost.NormalConstraint`` was added as a means to add soft constraints on a parameter, can also be used to set up a covariance matrix between several parameters Other ~~~~~ - Documentation improvements, started transition to numpydoc 2.1.0 (December 18, 2020) ------------------------- New features ~~~~~~~~~~~~ - Minuit object is now pickle-able and copy-able - More efficient internal conversion between Python objects and ``std::vector`` - ``Minuit.minos`` can now be called without calling ``Minuit.migrad`` first, which allows one to use an external minimiser to find a minimum and then compute Minos errors for it Bug-fixes ~~~~~~~~~ - User-supplied gradient functions that return a ``torch.Tensor`` now work again - Matrix display now shows numbers correctly even if entries differ in magnitude Other ~~~~~ - Unit tests are included again in sdist package - ``Minuit.grad`` now returns ``numpy.ndarray`` instead of a ``list`` - Fixes for ``conda`` builds on Windows platform with ``msvc``, by @henryiii - Updated and unified documentation on how to cite iminuit - ``print()`` applied to ``Minuit.params``, ``Minuit.merrors``, ``Minuit.covariance``, ``Minuit.fmin`` now returns the pretty text version again instead of the ``repr`` version - Update to pybind11 v2.6.1 2.0.0 (December 7, 2020) ------------------------ This is a breaking change for Interface that was deprecated in 1.x has been removed. In addition, breaking changes were made to the interface to arrive at a clean minimal state that is easier to learn, safer to use, and ready for the long-term future. **To keep existing scripts running, pin your major iminuit version to <2**, i.e. ``pip install 'iminuit<2'`` installs the 1.x series. Under the hood, Cython was replaced with pybind11 to generate the bindings to the C++ Minuit2 library. This simplified the code considerably (Cython is bad at generating correct C++ bindings, while it is a breeze with pybind11). Removed and changed interface (breaking changes) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``Minuit.__init__`` - Keywords ``error_*``, ``fix_*``, and ``limit_*`` were removed; assign to ``Minuit.errors``, ``Minuit.fixed``, and ``Minuit.limits`` to set initial step sizes, fix parameters, and set limits - Keyword ``pedantic`` was removed; parameters must be initialised with values now or an error is raised - Keyword ``errordef`` was removed; assign to ``Minuit.errordef`` to set the error definition of the cost function or better create an attribute called ``errordef`` on the cost function, Minuit uses this attribute if it exists - Keyword ``throw_nan`` was removed; assign to ``Minuit.throw_nan`` instead - Keyword ``print_level`` was removed; assign to ``Minuit.print_level`` instead - Setting starting values with positional parameters is now allowed, e.g. ``Minuit(my_fcn, 1, 2)`` initialises the first parameters to 1 and the second to 2 - Keyword ``use_array_call`` was removed; call type is inferred from the initialisation value, if it is a sequence, the array call is used (see next item below) - ``Minuit.from_array_func`` was removed; use ``Minuit(some_numpy_function, starting_array)`` instead - ``Minuit.args`` was removed, use ``Minuit.values[:]`` to get the current parameter values as a tuple - ``Minuit.values`` - Now behaves like an array instead of like a dict, i.e. methods like ``keys()`` and ``items()`` are gone and ``for x in minuit.values`` iterates over the values - Item access via index and via parameter name is supported, e.g. ``minuit.values[0]`` and ``minuit.values["a"]`` access the value for the first parameter "a" - Broadcasting is supported, e.g. ``minuit.values = 0`` sets all parameter values to 0 - Slicing is supported for setting and getting several parameter values at once - ``Minuit.errors``: see changes to ``Minuit.values`` - ``Minuit.fixed``: see changes to ``Minuit.values`` - ``Minuit.migrad`` - Keyword ``resume`` was removed; use ``Minuit.reset`` instead - Keyword ``precision`` was removed; use ``Minuit.precision`` instead - Return value is now ``self`` instead of ``self.fmin, self.params`` - ``Minuit.hesse``: Return value is now ``self`` instead of ``self.params`` - ``Minuit.minos`` - Now accepts more than one positional argument (which must be parameter names) and computes Minos errors for them - Return value is now ``self`` instead of ``self.merrors`` - ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy) - ``Minuit.mncontour`` and ``Minuit.draw_mncontour`` - ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy) - ``numpoints`` keyword replaced with ``size`` - Keyword arguments are keyword-only - Return value is reduced to just the contour points as a numpy array - ``Minuit.mnprofile`` and ``Minuit.draw_mnprofile`` - ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy) - ``numpoints`` keyword replaced with ``size`` - Keyword arguments are keyword-only - ``Minuit.profile`` and ``Minuit.draw_profile`` - ``bins`` keyword replaced with ``size`` - Keyword arguments are keyword-only - ``Minuit.fitarg`` was removed; to copy state use ``m2.values = m1.values; m2.limits = m1.limits`` etc. (Minuit object may become copyable and pickleable in the future) - ``Minuit.matrix`` was removed; see ``Minuit.covariance`` - ``Minuit.covariance`` instead of a dict-like class is now an enhanced subclass of numpy.ndarray (util.Matrix) with the features: - Behaves like a numpy.ndarray in numerical computations - Rich display of the matrix in ipython and Jupyter notebook - Element access via parameter names in addition to indices, e.g. Minuit.covariance["a", "b"] access the covariance of parameters "a" and "b" - ``Minuit.covariance.correlation()`` computes the correlation matrix from the covariance matrix and returns it - Has always full rank, number of rows and columns is equal to the number of parameters even when some are fixed; elements corresponding to fixed parameters are set to zero in the matrix - ``Minuit.gcc`` was removed for lack of a known use-case (submit an issue if you need this, then it will come back) - ``Minuit.is_clean_state`` was removed; use ``Minuit.fmin is None`` instead - ``Minuit.latex_param`` was removed; LaTeX and other table formats can be produced by passing the output of ``minuit.params.to_table()`` to the external ``tabulate`` module available on PyPI - ``Minuit.latex_initial_param`` was removed; see ``Minuit.latex_param`` - ``Minuit.latex_matrix`` was removed; LaTeX and other table formats can be produced by passing the output of ``minuit.covariance.to_table()`` to the external ``tabulate`` module available on PyPI - ``Minuit.ncalls_total`` was replaced with ``Minuit.nfcn`` - ``Minuit.ngrads_total`` was replaced with ``Minuit.ngrad`` - ``Minuit.np_covariance`` is now obsolete and was removed; see ``Minuit.covariance`` - ``Minuit.np_matrix`` is now obsolete and was removed; see ``Minuit.covariance`` - ``Minuit.np_values`` was removed; use ``Minuit.values`` instead or ``np.array(m.values)`` - ``Minuit.np_errors`` was removed; use ``Minuit.errors`` instead or ``np.array(m.errors)`` - ``Minuit.np_merrors`` was removed; use ``Minuit.merrors`` or ``Minuit.params`` instead - ``Minuit.use_array_call`` was removed, ``Minuit.fcn`` and ``Minuit.grad`` always require parameter values in form of sequences, e.g. ``minuit.fcn((1, 2))`` - ``util.FMin`` is now a data class with read-only attributes, the dict-like interface was removed (methods like ``keys()``, ``items()`` are gone) - ``tolerance`` attribute was replaced with ``edm_goal``, since the effect of ``tolerance`` varies for ``Minuit.migrad`` and ``Minuit.simplex``, ``edm_goal`` is the actual value of interest - Property ``nfcn`` is the total number of function calls so far - Property ``ngrad`` is the total number of gradient calls so far - ``ngrad_total`` was removed and replaced by ``ngrad`` - ``nfcn_total`` was removed and replaced by ``nfcn`` - ``up`` was removed and replaced by ``errordef`` (to have one consistent name) - ``util.MError`` is now a data class, dict-like interface was removed (see ``util.FMin``) - ``util.Param`` is now a data class, dict-like interface was removed (see ``util.FMin``) - ``util.Matrix`` is now a subclass of a numpy.ndarray instead of a tuple of tuples - ``util.InitialParamWarning`` was removed since it is no longer used - ``util.MigradResult`` was removed since it is no longer used - ``util.arguments_from_inspect`` was removed from the public interface, it lives on as a private function New features ~~~~~~~~~~~~ - ``Minuit`` class - Now a class with `__slots__`; assigning to a non-existent attribute (e.g. because of a typo) now raises an error - Parameter names in Unicode are now fully supported, e.g. ``def fcn(α, β): ...`` works - New method ``simplex`` to minimise the function with the Nelder-Mead method - New method ``scan`` to minimise the function with a brute-force grid search (not recommended and infeasible for fits with more than a few free parameters) - New method ``reset`` reverts to the initial parameter state - New property ``limits``, an array-like view of the current parameter limits; allows to query and set limits with a behaviour analog to ``values``, ``errors`` etc.; broadcasting is supported, e.g. ``minuit.limits = (0, 1)`` makes all parameters bounded between 0 and 1 and ``minuit.limits = None`` removes all limits - New property ``precision`` to change the precision that Minuit assumes for internal calculations of derivatives - Support for calling numba-compiled functions that release the GIL (slightly more efficient already today and may be used in the future to compute derivatives in parallel) - Now pretty-prints itself in Jupyter notebooks and the ipython shell, showing the equivalent of ``Minuit.fmin``, ``Minuit.params``, ``Minuit.merrors``, ``Minuit.covariance``, whatever is available - ``util.Param`` class - New attribute ``merror``, which either returns a tuple of the lower and upper Minos error or None - All attributes are now documented inline with docstrings which can be investigated with ``pydoc`` and ``help()`` in the REPL - ``util.Params`` class - New method ``to_table``, which returns a format that can be consumed by the external ``tabulate`` Python module - ``util.FMin`` class - New attribute ``ngrad`` which is the number of gradient calls so far - New attribute ``has_parameters_at_limit`` which returns True if any parameter values is close to a limit - All attributes are now documented inline with docstrings which can be investigated with ``pydoc`` and ``help()`` in the REPL - ``util.Matrix`` class - New method ``to_table``, which returns a format that can be consumed by the external ``tabulate`` Python module - New method ``correlation``, which computes and returns the correlation matrix (also a ``util.Matrix``) Bug-fixes ~~~~~~~~~ - Calling ``Minuit.hesse`` when all parameters were fixed now raises an error instead of producing a segfault - Many life-time/memory leak issues in the iminuit interface code should be resolved now, even when there is an exception during the minimisation (there can still be errors in the underlying C++ Minuit2 library, which would have to be fixed upstream) Other changes ~~~~~~~~~~~~~ - Several attributes were replaced with properties to avoid accidental overrides and to protect against assigning invalid input, e.g. ``Minuit.tol`` and ``Minuit.errordef`` only accept positive numbers - Documentation update and clean up - Logging messages from C++ Minuit2, which are produced when ``Minuit.print_level`` is set to 1 to 3 are now properly shown inside the notebook or the Python session instead of being printed to the terminal - Assigning to ``Minuit.print_level`` changes the logging threshold for all current and future ``Minuit`` instances in the current Python session, this is not really desired but cannot be avoided since the C++ logger is a global variable - docstring parsing for ``util.describe`` was rewritten; behaviour of ``describe`` for corner cases of functions with positional and variable number of positional and keyword arguments are now well-defined - iminuit now has 100 % line coverage by unit tests 1.5.4 (November 21, 2020) -------------------------- - Fixed broken sdist package in 1.5.3 1.5.3 (November 19, 2020) -------------------------- Fixes ~~~~~ - Fixed a crash when throw_nan=True is used and the throw is triggered - Add python_requires (`#496 `_) by @henryiii - Fixed buggy display of text matrix if npar != 2 (`#493 `_) Other ~~~~~ - Switch extern Minuit2 repo to official root repo (`#500 `_), ROOT state: a5d880a434 - Add ngrad and ngrad_total to FMin display, rename ncalls to nfcn_total (`#489 `_) - Use __getattr__ to hide deprecated interface from Python help() (`#491 `_) - Improvements to tutorials by @giammi56 - Show number of gradient calls in FMin display (if nonzero) instead of errordef value Deprecated ~~~~~~~~~~ - Minuit.ncalls, use Minuit.nfcn instead - Minuit.ngrads, use Minuit.ngrad instead 1.5.2 (September 24, 2020) -------------------------- - Fixed regression of the convergence rate of ``Minuit.migrad`` for low precision cost functions by restoring a heuristic that calls Migrad several times if convergence is not reached on first try; made this heuristic configurable with `iterate` keyword - Clarify in ``FMin`` display how the EDM convergence criterion uses the EDM goal 1.5.1 (September 20, 2020) -------------------------- - Fixed mistake in *parameter at limit* warning, which did not report correctly if parameter was at the upper limit 1.5.0 (September 17, 2020) --------------------------- New features ~~~~~~~~~~~~ - New more compact function minimum display with warning about parameters at limit - Colours adjusted in HTML display to enhance contrast for people with color blindness - Allow subclasses to use ``Minuit.from_array_func`` (`#467 `_) [contributed by @kratsg] - Nicer tables on terminal thanks to unicode characters - Wrapped functions' parameters are now correctly recognized [contributed by Gonzalo] - Dark theme friendlier HTML style (`#481 `_) [based on patch by @l-althueser] Bug-Fixes ~~~~~~~~~ - Fixed reported EDM goal for really small tolerances - ``Minuit.np_merrors`` now works correctly when some parameters are fixed - Fixed HTML display of Minuit.matrix when some diagonal elements are zero Deprecated ~~~~~~~~~~ - Removed ``nsplit`` option from ``Minuit.migrad`` (`#462 `_) 1.4.9 (July, 18, 2020) ---------------------- - Fixes an error introduced in 1.4.8 in ``Minuit.minos`` when ``var`` keyword is used and at least one parameter is fixed 1.4.8 (July, 17, 2020) ---------------------- - Allow ``ncall=None`` in ``Minuit.migrad``, ``Minuit.hesse``, ``Minuit.minos`` - Deprecated ``maxcall`` argument in ``Minuit.minos``: use ``ncall`` instead 1.4.7 (July, 15, 2020) ---------------------- - Fixed: ``cost.LeastSquares`` failed when ``yerror`` is passed as list and mask is set 1.4.6 (July, 11, 2020) ---------------------- - Update to Minuit2 C++ code to ROOT v6.23-01 - Fixed: iminuit now reports an invalid fit if a cost function has only a maximum, not a minimum (fixed upstream) - Loss function in ``cost.LeastSquares`` is now mutable - Cost functions in ``cost`` now support value masks - Documentation improvements - Fixed a deprecation warning in ``Minuit.mnprofile`` - Binder now uses wheels instead of compiling current iminuit 1.4.5 (June, 25, 2020) ---------------------- - Improved pretty printing for Minos Errors object ``MErrors`` - Added docs for cost functions 1.4.4 (June, 24, 2020) ---------------------- - Reverted: create MnHesse C++ instance on the stack instead on the heap - Added least-squares cost function and tests 1.4.3 (June, 24, 2020) ---------------------- Bug-fixes ~~~~~~~~~ - Fixed a bug where running ``Minuit.hesse`` after ``Minuit.migrad``, which would ignore any changes to parameters (fixing/releasing them, changing their values, ...) - Fix number formatting issues in new quantities display - Removed engineering suffixes again in favour of standard exponential notation Deprecated ~~~~~~~~~~ - keyword `forced_parameters` in `Minuit.__init__` is deprecated, use `name` Features ~~~~~~~~ - Added general purpose cost functions for binned and unbinned maximum-likelihood estimation (normal and so called extended) Documentation ~~~~~~~~~~~~~ - Updated error computation tutorial - New tutorial which demonstrates usage of cost functions 1.4.2 (June, 14, 2020) ---------------------- Hot-fix release to correct an error in ``Minuit.merrors`` indexing. Documentation ~~~~~~~~~~~~~ - New tutorial about using Numba to parallelize and jit-compile cost functions 1.4.1 (June, 13, 2020) ---------------------- Mostly a bug-fix release, but also deprecates more old interface. Bug-fixes ~~~~~~~~~ - Fixed a bug when displaying nans in rich displays Deprecated ~~~~~~~~~~ - ``Minuit.minoserror_struct``: use ``Minuit.merrors``, which is now an alias for the former - ``Minuit.merrors`` now accepts indices and parameter names, like `Minuit.values`, etc. Features ~~~~~~~~ - Show engineering suffixes (1.23k, 123.4M, 0.8G, ...) in rich diplays instead of "scientific format", e.g. 1.23e-3 - New initial step heuristic, replaces pedantic warning about missing step sizes - New initial value heuristic for parameters with limits Documentation ~~~~~~~~~~~~~ - New tutorial about using Numba to parallelize and jit-compile cost functions 1.4.0 (June, 12, 2020) ---------------------- This release drops Python 2 support and modernizes the interface of iminuit's Minuit object to make it more pythonic. Outdated methods were deprecated and replaced with properties. Keywords in methods were made more consistent. The deprecated interface has been removed from the documentation, but is still there. Old code should still work (if not please file a bug report!). Bug-fixes ~~~~~~~~~ - Fixed an exception in the rich display when results were NaN - ``Minuit.migrad_ok()`` (now replaced by `Minuit.accurate`) now returns false if HESSE failed after MIGRAD and made the minimum invalid - Running ``Minuit.hesse()`` now properly updates the function minimum - Fixed incorrect ``hess_inv`` returned by ``minimize`` - Fixed duplicated printing of pedantic warning messages Deprecated ~~~~~~~~~~ - ``Minuit.list_of_fixed_params()``, ``Minuit.list_of_vary_params()``: use ``Minuit.fixed`` - ``Minuit.migrad_ok()``: use ``Minuit.valid`` - ``Minuit.matrix_accurate()``: use ``Minuit.accurate`` - ``Minuit.get_fmin()``: use ``Minuit.fmin`` - ``Minuit.get_param_states()``: use ``Minuit.param`` - ``Minuit.get_initial_param_states()``: use ``Minuit.init_param`` - ``Minuit.get_num_call_fcn()``: use ``Minuit.ncalls_total`` - ``Minuit.get_num_call_grad()``: use ``Minuit.ngrads_total`` - ``Minuit.print_param_states()``: use ``print`` on ``Minuit.params`` - ``Minuit.print_initial_param_states()``: use ``print`` on ``Minuit.init_params`` - ``Minuit.hesse(maxcall=...)`` keyword: use ``ncall=...`` like in ``Minuit.migrad`` - ``Minuit.edm``: use ``Minuit.fmin.edm`` New features ~~~~~~~~~~~~ - iminuit now uses the PDG formatting rule for quantities with errors - slicing and basic broadcasting support for ``Minuit.values``, ``Minuit.errors``, ``Minuit.fixed``, e.g. the following works: ``m.fixed[:] = True``, ``m.values[:2] = [1, 2]`` - ``Minuit.migrad(ncall=0)`` (the default) now uses MINUITs internal heuristic instead of a flat limit of 10000 calls - ``minimize`` now supports the ``tol`` parameter - `Minuit` now supports ``print_level=3``, which shows debug level information when MIGRAD runs - Binder support and Binder badge for tutorial notebooks added by @matthewfeickert Documentation ~~~~~~~~~~~~~ - New tutorials on error computation and on using automatic differentiation 1.3.10 (March, 31, 2020) ------------------------ Bug-fixes ~~~~~~~~~ - sdist package was broken, this was fixed by @henryiii Implementation ~~~~~~~~~~~~~~ - Allow HESSE to be called without running MIGRAD first Documentation ~~~~~~~~~~~~~ - Added tutorial to show how iminuit can compute parameter errors for other minimizers Other ~~~~~ - @henryiii added a CI test to check the sdist package and the MANIFEST 1.3.9 (March, 31, 2020) ----------------------- Bug-fixes ~~~~~~~~~ - ``Minuit.draw_contour`` now accepts an integer for ``bound`` keyword as advertised in the docs - fixed wrong EDM goal in iminuit reports, was off by factor 5 in some Interface ~~~~~~~~~ - removed the undocumented keyword "args" in ``(draw_)contour``, ``(draw_)profile`` - removed misleading "show_sigma" keyword in ``draw_contour`` - deprecated ``Minuit.is_fixed``, replaced by ``Minuit.fixed`` property - deprecated ``Minuit.set_strategy``, assign to ``Minuit.strategy`` instead - deprecated ``Minuit.set_errordef``, assign to ``Minuit.errordef`` instead - deprecated ``Minuit.set_print_level``, assign to ``Minuit.print_level`` instead - deprecated ``Minuit.print_fmin``, ``Minuit.print_matrix``, ``Minuit.print_param``, ``Minuit.print_initial_param``, ``Minuit.print_all_minos``; use ``print`` on the respective objects instead - added ``Minuit.nfit`` to get number of fitted parameters Implementation ~~~~~~~~~~~~~~ - improved style of draw_contour, draw more contour lines - increased default resolution for curves produced by ``(draw_)mncontour``, ``(draw_)contour`` - switched from internal copy of Minuit2 to including Minuit2 repository from GooFit - build improvements for windows/msvc - updated Minuit2 code to ROOT-v6.15/01 (compiler with C++11 support is now required to build iminuit) - @henryiii added support for building Python-3.8 wheels Documentation ~~~~~~~~~~~~~ - added iminuit logo - added benchmark section - expanded FAQ section - updated basic tutorial to show how parameter values can be fixed and released - added tutorial about combining iminuit with automatic differentiation - clarified the difference between ``profile`` and ``mnprofile``, ``contour`` and ``mncontour`` - fixed broken URLs for external documents - many small documentation improvements to increase consistency 1.3.8 (October 17, 2019) ------------------------ - fixed internal plotting when Minuit.from_array_func is used - documentation updates - reproduceable build 1.3.7 (June 12, 2019) --------------------- - fixed wheels support - fixed failing tests on some platforms - documentation updates 1.3.6 (May 19, 2019) -------------------- - fix for broken display of Jupyter notebooks on Github when iminuit output is shown - replaced brittle and broken REPL diplay system with standard ``_repr_html_`` and friends - wheels support - support for pypy-3.6 - documentation improvements - new integration tests to detect breaking changes in the API 1.3.5 (May 16, 2019) [do not use] --------------------------------- - release with accidental breaking change in the API, use 1.3.6 1.3.4 (May 16, 2019) [do not use] --------------------------------- - incomplete release, use 1.3.6 1.3.3 (August 13, 2018) ----------------------- - fix for broken table layout in print_param() and print_matrix() - fix for missing error report when error is raised in user function - fix of printout when ipython is used as a shell - fix of slow convergence when analytical gradient is provided - improved user guide with more detail information and improved structure 1.3.2 (August 5, 2018) ---------------------- - allow fixing parameter by setting limits (x, x) with some value x - better defaults for maxcall arguments of hesse() and minos() - nicer output for print_matrix() - bug-fix: covariance matrix reported by iminuit was broken when some parameters were fixed - bug-fix: segfault when something in PythonCaller raised an exception 1.3.1 (July 10, 2018) --------------------- - fixed failing tests when only you installed iminuit with pip and don't have Cython installed 1.3 (July 5, 2018) ------------------ - iminuit 1.3 is a big release, there are many improvements. All users are encouraged to update. - Python 2.7 as well as Python 3.5 or later are supported, on Linux, MacOS and Windows. - Source packages are available for PyPI/pip and we maintain binary package for conda (see :ref:`install`). - The bundled Minuit C++ library has been updated to the latest version (takend from ROOT 6.12.06). - The documentation has been mostly re-written. To learn about iminuit and all the new features, read the :ref:`tutorials`. - Numpy is now a core dependency, required to compile iminuit. - For Numpy users, a second callback function interface and a ``Minuit.from_array_func`` constructor was added, where the parameters are passed as an array. - Results are now also available as Numpy arrays, e.g. ``np_values``, ``np_errors`` and ``np_covariance``. - A wrapper function ``minimize`` for the MIGRAD optimiser was added, that has the same arguments and return value format as ``scipy.optimize.minimize``. - Support for analytical gradients has been added, users can pass a ``grad`` callback function. This works, but for unknown reasons doesn't lead to performance improvements yet. If you can help debug or fix this issue, please comment `here `__. - Several issues have been fixed. A complete list of issues and pull requests that went into the 1.3 release is `here `__. Previously ---------- - For iminuit releases before v1.3, we did not fill a change log. - To summarise: the first iminuit release was v1.0 in Dec 2012. In 2013 there were several releases, and in Jan 2014 the v1.1.1 release was made. After that development was mostly inactive, except for the v1.2 release in Nov 2015. - The release history is available here: https://pypi.org/project/iminuit/#history - The git history and pull requests are here: https://github.com/scikit-hep/iminuit iminuit-2.30.1/doc/conf.py0000644000000000000000000000576114332717401012260 0ustar00import os # release and version are special variables used by sphinx from iminuit import __version__ as version # We set the root_version manually, because it setting it # automatically and efficiently in CI is difficult. # To update the number: # - Make sure you have a full clone, not a shallow clone of ROOT. # - Run `doc/root_version.py` and copy the string here. root_version = "v6-25-02-9213-g754d22635f" with open("../README.rst") as f: readme_content = f.read() readme_content = readme_content.replace("doc/", "") readme_content = readme_content.replace( ".. version-marker-do-not-remove", "**These docs are for iminuit version:** |release|", ) with open("index.rst.in") as f: index_content = f.read() with open("index.rst", "w") as f: f.write(readme_content + index_content) release = f"{version} compiled with ROOT-{root_version}" project = "iminuit" copyright = "2022, Hans Dembinski and the iminuit team" # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ "sphinx.ext.napoleon", "sphinx.ext.autodoc", "sphinx.ext.mathjax", "sphinx.ext.autosummary", # 'matplotlib.sphinxext.only_directives', "matplotlib.sphinxext.plot_directive", "nbsphinx", "IPython.sphinxext.ipython_console_highlighting", ] nbsphinx_kernel_name = "python3" nbsphinx_execute_arguments = [ "--InlineBackend.figure_formats={'svg', 'pdf'}", "--InlineBackend.rc=figure.dpi=96", ] nbsphinx_execute = "auto" # use FAST=1 to speed up doc build if bool(os.environ.get("FAST", False)): print("Fast generation activated") nbsphinx_execute = "never" autoclass_content = "both" autosummary_generate = True autodoc_member_order = "groupwise" autodoc_type_aliases = {"ArrayLike": "ArrayLike"} # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["_build", "_themes"] # html_logo = "_static/iminuit_logo.svg" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] # http://read-the-docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs # on_rtd is whether we are on readthedocs.org on_rtd = os.environ.get("READTHEDOCS", None) == "True" if not on_rtd: # Import and set the theme if we're building docs locally import sphinx_rtd_theme html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] nbsphinx_kernel_name = "python3" nbsphinx_execute_arguments = [ "--InlineBackend.figure_formats={'svg', 'pdf'}", "--InlineBackend.rc=figure.dpi=96", ] linkcheck_timeout = 10 linkcheck_allow_unauthorized = True linkcheck_report_timeouts_as_broken = False linkcheck_ignore = ["https://doi.org/10.2307%2F2347496"] iminuit-2.30.1/doc/contribute.rst0000644000000000000000000000504714332717401013666 0ustar00.. include:: bibliography.txt .. _contribute: Contribute ========== You can help ------------ Please open issues and feature requests on `Github`_. We respond quickly. * Documentation. Tell us what's missing, what's incorrect or misleading. * Tests. If you have an example that shows a bug or problem, please file an issue! * Performance. If you are a C/cython/python hacker and see a way to make the code faster, let us know! Direct contributions related to these items are welcome, too! If you want to contribute, please `fork the project on Github `_, develop your change and then make a `pull request `_. This allows us to review and discuss the change with you, which makes the integration very smooth. Development setup ----------------- git +++ To hack on ``iminuit``, start by cloning the repository from `Github`_: .. code-block:: bash git clone --recursive https://github.com/scikit-hep/iminuit.git cd iminuit It is a good idea to develop your feature in a separate branch, so that your develop branch remains clean and can follow our develop branch. .. code-block:: bash git checkout -b my_cool_feature develop Now you are in a feature branch, commit your edits here. Development workflow -------------------- You have the source code now, but you also want to build and test. We recommend to use ``nox``, which automatically creates a dedicated virtual environment for ``iminuit``, separate from the Python installation you use for other projects. .. code-block:: bash nox -s test This installs your version of ``iminuit`` locally and all the dependencies needed to run the tests, and then runs the tests. Generate a coverage report: .. code-block:: bash nox -s cov build/htmlcov/index.htm Build the docs: .. code-block:: bash nox -s doc build/html/index.html Maintainers that prepare a release, should follow the instructions in `doc/README.md` To check your ``iminuit`` version number and install location: .. code-block:: bash $ python >>> import iminuit >>> iminuit # install location is printed >>> iminuit.__version__ # version number is printed .. _conda: https://conda.io/ .. _miniconda: https://conda.io/en/latest/miniconda.html .. _Python virtual environments: http://docs.python-guide.org/en/latest/dev/virtualenvs/ .. _Github: https://github.com/scikit-hep/iminuit .. _Makefile: https://github.com/scikit-hep/iminuit/blob/main/Makefile iminuit-2.30.1/doc/faq.rst0000644000000000000000000001664314332717401012263 0ustar00.. include:: bibliography.txt .. _faq: .. currentmodule:: iminuit FAQ === Disclaimer: Read the excellent MINUIT user guide! ------------------------------------------------- Many technical questions are nicely covered by the `Minuit reference manual `_ of the original MINUIT in Fortran, on which MINUIT2 is based. Still relevant is chapter 5, which covers all the questions that one encounters when using Minuit in practice. If you have trouble with the fit, there is advice in sections 5.6 and 5.7 on how to fix common issues. Another source is the :download:`MINUIT User's guide `, which covers the C++ Minuit2 library on which iminuit is based. It also contains advice on troubleshooting, we will frequently refer to it here. However, the Fortran manual usually goes into more detail and is therefore preferred. I don't understand :meth:`Minuit.hesse`, :meth:`Minuit.minos`, :attr:`Minuit.errordef`; what do these do? ----------------------------------------------------------------------------------------------------------- How do I interpret the parameter errors? ---------------------------------------- How do I obtain a high-quality error matrix? -------------------------------------------- What effect has setting limits on the parameter uncertainties? -------------------------------------------------------------- The MINUIT2 user's guide explains all about it, see pages 6-8 and 38-40. I want to cite iminuit in my paper. Help? ------------------------------------------------ We use Zenodo to make each iminuit release citable. You can either cite iminuit as a software or you can cite the exact version that was used for your analysis. For more details, see :ref:`citation`. Can I have parameter limits that depend on each other (e.g. x^2 + y^2 < 3)? --------------------------------------------------------------------------- MINUIT was only designed to handle box constrains, meaning that the limits on the parameters are independent of each other and constant during the minimization. If you want limits that depend on each other, you have three options (all with caveats), which are listed in increasing order of difficulty: 1) Change the variables so that the limits become independent. For example, transform from Cartesian coordinates to polar coordinates for a circle. This is not always possible, of course. 2) Use another minimizer to locate the minimum which supports complex boundaries. The `nlopt`_ library and `scipy.optimize`_ have such minimizers. Once the minimum is found and if it is not near the boundary, place box constraints around the minimum and run iminuit to get the uncertainties (make sure that the box constraints are not too tight around the minimum). Neither `nlopt`_ nor `scipy`_ can give you the uncertainties. 3) Artificially increase the negative log-likelihood in the forbidden region. This is not as easy as it sounds. The third method done properly is known as the `interior point or barrier method `_. A glance at the Wikipedia article shows that one has to either run a series of minimizations with iminuit (and find a clever way of knowing when to stop) or implement this properly at the level of a Newton step, which would require changes to the complex and convoluted internals of MINUIT2. Warning: you cannot just add a large value to the likelihood when the parameter boundary is violated. MIGRAD expects the likelihood function to be differential everywhere, because it uses the gradient of the likelihood to go downhill. The derivative at a discrete step is infinity and zero in the forbidden region. MIGRAD does not like this at all. What happens when I change the strategy? ---------------------------------------- See page 5 of the MINUIT2 user guide for a rough explanation what this does. Here is our detailed explanation, extracted from looking into the source code and doing benchmarks. * ``strategy = 0`` is the fastest and the number of function calls required to minimize scales linearly with the number of fitted parameters. The Hesse matrix is not computed during the minimization (only an approximation that is continuously updated). When the number of fitted parameters > 10, you should prefer this strategy. * ``strategy = 1`` (default) is medium in speed. The number of function calls required scales quadratically with the number of fitted parameters. The different scales come from the fact that the Hesse matrix is explicitly computed in a Newton step, if Minuit detects significant correlations between parameters. * ``strategy = 2`` has the same quadratic scaling as strategy 1 but is even slower. The Hesse matrix is always explicitly computed in each Newton step. If you have a function that is everywhere analytical and the Hesse matrix varies not too much, strategy 0 should give you good results. Strategy 1 and 2 are better when these conditions are not given. The approximated Hesse matrix can become distorted in this case. The explicit computation of the Hesse matrix may help Minuit to recover after passing through such a region. How do I get Hesse errors for sigma=2, 3, ...? ---------------------------------------------- For a least-squares function, you use ``errordef = sigma ** 2`` and for a negative log-likelihood function you use ``errordef = 0.5 * sigma ** 2``. Why do extra messages appear in the terminal when I use `print_level=2` or larger? ------------------------------------------------------------------------------------ A `print_level=2` or higher activates internal debug messages directly from C++ MINUIT, which we cannot capture and print nicely in a Jupyter notebook, sorry. Is it possible to stop iminuit by setting a tolerance for changes in the minimized function or the parameters? -------------------------------------------------------------------------------------------------------------------------- No. MINUIT only uses the *Estimated-Distance-to-Minimum* (EDM) stopping criterion. It stops, if the difference between the actual function value at the estimated minimum location and the estimated function value at that location, based on MINUIT's internal parabolic approximation of the function, is small. This criterion depends strongly on the numerically computed first and second derivatives. Therefore, problems with MINUIT's convergence are often related to numerical issues when the first and second derivatives are computed. More information about the EDM criterion can be found in the `MINUIT paper`_. I am not sure if minimization or error estimation is reliable. What can I do? ----------------------------------------------------------------------------- Plot the likelihood profile around the minimum as explained in the basic tutorial. Check that the parameter estimate is at the bottom. If the minimum is not parabolic, you may want to use MINOS to estimate the uncertainty interval instead of HESSE. Why do you shout at me with CAPITAL LETTERS so much? ---------------------------------------------------- Sorry, that's just how it was in the old FORTRAN days from which MINUIT originates. Computers were incredibly loud back then and everyone was shouting all the time! Seriously though: People were using typewriters. There was only a single font and no way to make letters italic or even bold, to set apart normal text from code. So people used CAPITAL LETTERS a lot for code in technical writing. For these historic reasons, MINUIT, MIGRAD, and HESSE are often written with capital letters here. iminuit-2.30.1/doc/index.rst.in0000644000000000000000000000025314332717401013216 0ustar00.. include:: bibliography.txt .. toctree:: :hidden: about install reference tutorials studies faq changelog benchmark contribute iminuit-2.30.1/doc/install.rst0000644000000000000000000000253214332717401013152 0ustar00.. include:: bibliography.txt .. _install: Installation ============ Note: iminuit is tested to work with PyPy3.5 and PyPy3.6, but we do not provide binary packages for PyPy. PyPy users need to install the source package of iminuit. This happens automatically when you install it via ``conda`` or ``pip``, but requires a working C++ compiler. pip --- To install the latest stable version from https://pypi.org/project/iminuit/ with ``pip``: .. code-block:: bash $ pip install iminuit If your platform is not supported by a binary wheel, ``pip install`` requires that you have a C++ compiler available but otherwise runs the compilation automatically. Conda ----- We also provide binary packages for ``conda`` users via https://anaconda.org/conda-forge/iminuit: .. code-block:: bash $ conda install -c conda-forge iminuit The ``conda`` packages are semi-automatically maintained and usually quickly support the least Python version on all platforms. Installing from source ---------------------- For users +++++++++ If you need the latest unreleased version, you can download and install directly from Github. The easiest way is to use pip. pip install iminuit@git+https://github.com/scikit-hep/iminuit@develop This requires a C++ compiler with C++14 support. For contributors/developers +++++++++++++++++++++++++++ See :ref:`contribute`. iminuit-2.30.1/doc/mnusersguide.pdf0000644000000000000000000077375014332717401014200 0ustar00%PDF-1.2 %Çì¢ 6 0 obj <> stream xœUPMO!½ó+¸Ywd†…£šÕ´Ú&]iG@”ý m¶Ži{íǸH)NhäR,Åùëo±endstream endobj 7 0 obj 298 endobj 17 0 obj <> endobj 18 0 obj <> endobj 20 0 obj <> stream xœÅYMܸ½Œý œl¬[¿ÉãÆY'`;;™E;9ÈÝši­ÕR[RÛ™ýõ)’Å¢Ô#; xÀ‡)5Y¯^½¢Ê‚mJÿÿîŽW¯>nXXKvÇÍŸo®^\Ù)8SrsswÀ6–6F—…Ö››ãÕÓWÏn~½be¡”3ðÂÍþêi?ÔŸýª,‹R*N«{¿øâšË “…šû}· ¶*¥Ýl….œ¯þëPMaU”–¥mßÄŸ3†®t,˜¥ ¡J…¯¼~ûó뛵S$+,Gâkֳ͌V¤µ.¬ñÂIËpmª»}¬V¢Z&K¦>¼ë ezwߣyzÃXᔊÞñR’¹Í–»BÎÝàfáÁèÇ^,w¦öÒ ¡'Ëv}·«›Oþ„Ó8D7 ŸZðär•ÂPjéÒZXbðÚÒײ0–^êÛ°& Í]¾·ØìINåª`ÎQPuX·¤I§›®9«yQ‚¸|kÖŒK8 ΩBAäÒ–U{Ž{jX渻`^ZyážJ? 8À# žÛ©Ùžª¡:ÖS=øç[¡ ‹`ì|ŽY¼;w»©éh¤.´J&ß’ƒ àAÆÜÞÆ„ŠržPUXí¨n^½|»–uf Á)Rº}†nqž³†>#”Þ®j~ ¶HðîQXIûއê„{)ÓjÃÁÑrVY0IyZÝñ‹!ª†þ †PB^lUa ÿ_À(Bbd Á†ð‰ñÑ‚G7~–{šnלª\é ët:¡:ÚfW%KµÇ>=ÄVÈ5vü6Öu‡ •ë /”š¼'Øzœà„p6IImç)›ñyØËÂ^Ä=A-øÌg ú¡éîC0€„­HÁˆ†CmCM„8vhÆçj¨#¢-2’Ægæ°µýý¶m>„#!·Z¥½ê¶9„‚çžcÉÀ@¦s)&{d)È´„‹è50«yÄ"²à™Evýñtž"ŽM!-1A ׄº÷Ñ+fÜ7NÛ'¡¡ýŒÀ½¨qj1=š‘ •L@0¹0†¸KAº”t𰦪é¶1ØFŽñ9J§¦ŽþCMæ,@i{Þc–}g䌢0 u`¬Ð¢(•”_ñzBj“FTd¢Õ—å ý;Ek ¥§=¯Ê´ñë ëDy?µãëIæTœ°M¨Lþõ®©Úö›V&ëñÜL±o )gæ+ 9@Z„¶nví}óÝX= yIå}ú÷m}$$:C=e™ Ol¹õc%Q*JÝçC³C$8¯gÐ.ŒA™ñ¬ˆÀ]ŠøCRQ’úäP<7±Z>¸?7û †TÆ´ÌèÁÀÀi©AvE€GkÙe 5Ô®EaÍe»ÞJp ÓÊŒÈ]¬+ë[D2pìÛ³Çi±ª÷Ò»[¯ÉìÿMïu}8’[ߘ.ø‡‹@àÒÈ™ü¡ï®’Û·¨C_‘äóç¦m±'Ks!‰€«ò‰»þ< žaƒŒÈâ'ôP2_D1NlQWãC긚è'•¢àCº '‚¤–*Ë’ªC dÞ1öç˜ 9vŒÀÝ%µ…ÉœÜL²@`Œ©9í'™ÜÏJ/|ô QªGH CÍ"õ}º¢fXfº¡^£¿ä[h±Î]TQ p4¾e=“Q›=ñ8Hm ©—Ȭ Zg&¾HæCó[<Úxúgj%wЄʜ»[ åž#,qßãÍ@SÌ)' ›®¦¡Ú!®ŒáéÈH€Zó<™¦$w@e1Ç©ñTVøsA•j7õCTËà„Ô†JãP#¯úÙŒ_îAÑÃ^Åq„‹Ð«RÔ@Ž>²Æìï!ªùÁe%BwÌL^pC^Ü×]= F4*’E³öNUñ©fo6Ë$lÇd Üpù8Y€Öœ¬c£$YLvÖßíš-ˆ–´>­³;Èã !ÍØýU¤ –F¬ÊcÈðRTÇjø0®’¨‚-Ì‚D¿+Už¤Wd!w¦1`™H©H¯¿8åxh¦ G(%K)Å4 /€ÓÚ«˜MÃ2úÊ¢£:%]—G%ЊÌœQ[ælBè1”i˜ÎÈî—?^‡Á¦°X/1Å`¯TÝ@NºÒ<²•Êbˆà_ªÃ¿Œ(¿4tœÅHö ûw?EMÍ{Êm™걊Be¦‚ºÝ£XÙêf"O¢ç±ºµ iȳ(ò~éÁ™\»œÌ`Kµ´¯¦ ›šVTýi^ y•ÀHN¬ÙRÿ'ˆõâ1¥®š#ÖèMA#í€hK&.­ÈU²óª.Rv"7+l|Њ¤ã³ÚöxŽ0ÒïÏ©õqC7vÏ0³‘!¿Ù]SÕŽ=òÏQ=uºô‘Ü<ÆÚj ­+SpO™äh\èOQÔ™F€Þ÷©1€Aùfh-ɾ”3ãrÎÎÓ}ÃhKÇRÁ’åLIc)Ïn¸¾¸Å¡¹Gž-Uaô|ñ$ÿ€YÒ­Ì适ޒ@vïâÌ U„¡Û§ûñ·Ï ¤0‡j*wê?¼,9ê*ˆmZ]!!,lߘíãÂb*K=+ž!Éh9¤*ìAÒ¹™š@y¤JÊʯ89x˜±tÒó ‡u¤xhZ)³>êmÒ°ÆjÒx“FÇ$L‚‹¹ûÛz†Éúšˆ]çþJX䋘þ=¦XÕÌœßööÕ D7»Î.5ÖTà,ϧ”Ò4D2KÄy1ž/®ÅbŽò•ci|ùý÷kꔦá!Þ¸qо– hà ÞcHQ7€|åN䯲ø˜¯Õ<$5ÝW¦ ˜Y ‹üäF0ª«ÓP™4óôLYÅûú¢LXÒuÛŸ GL¾©šâØ$;Y0Ô-Ì2íþž¤%6MÆFºŒ(‚¶Í. ò‡Ã À’ó•kš…ŽƒÄ”†gÈl‘Æý|d×Fбê‚ÚÕÝБ'LÉ//z3ÈV‡þXŸ°ÛúkMEÑý…Ç~¿eÖ[>KºsÒÇH3›œZë©ßb½CÈúÙµïˆC·zÒк•1éì™ÈÎsüR䜙Ëù?5ØÓËdIØoëÉ_¢%wóeëíÓº¸GU½üLàw†êðÍë¿^ÿð—UZŽdÂóµ­´¬¦­Þ¾ûçêNþ{Åju'`W cÙž/ß½½y÷óõê–þªŠÆoŸÅ\Lâ«x ×Lqÿ€m ]ºž ã¸}Œ&UXu‰¦ÅÔŒ^’ãÒ€ßEŽ»¶‘: Ý,O… IÎO+HZŽ Ä×>%ÔXuãvéx%¶ª•óÙí¿ø±†¦¬)v 5cÉxÍ#®$Õôp¢e·=>_ÛÌøÏ|¤Îüf]¿: J¯-I—ý®½^öÝä/ºVMƒbtmºjë#â‹æ,ÑŽÜâŸüx³ùéê§«ÿÛTmþendstream endobj 21 0 obj 2669 endobj 37 0 obj <> endobj 39 0 obj <> stream xœí[ÛrÛ6}×ô#ô˜NFî—>Ö­§šiœ&UòÎÈ”ÂF’nÒ|}WŠ[y\9–=š<$Áå88{ aDÆØþ Ï×£O£OcâÚâ_óõøçÙèÅø/QˆÁdzÅÈ¿@ÆšÆJb$åx¶=»(7?Îþ1ްàºÌ®GÏšÜ5R‰S26Ö¶íÅÎÆ„ #µv'`J¢ÇÆ×®ç¥í¨#TD‹e•v&’FëÔzí>®5":~gj›&œ2DŒrf™tföFTj#Bßìý*wf5b˜šhvaÛˆ@LˆØ3Œ¬ ÂEwœD#.AO-ù®O`ÏÀ˜öÝ7/ê&ÌžÉBò‰²äÓe±¼©rÿ9˜Fbâ¼¼›†ÎÂ`³çV{.Pð~Çâ^W0Ô4ÕS?RŠ6,Ž´*CG-il¼¾™7E¹ùÉ}Ž!E£·/ýòX~ŒÀ/â`E‘Â:¾;½z; ¡„Ã?¹ˆsñ>«‹¹5@Fˆ¸ðór3Ï·~ú)£Óø Ÿ–äq KDy”€›¾#"aêJ³9û‡¥7š'ŒTËlS|ÍìXíS©&DtW &ëÞø©êŒ6RÚ!;ÃïºÊ%b: Ù.€`4ý®M„|ï/B“2û½fb¿iàÅ~Ó¿ èæ)EB$Ä¿±0pÓ.¾è>¾~ÉëbéY؉'"ÉêmØ^Tòˆ‘|ޏiéñ¸xcOx+6¾ëî\–‘^<>hH"©;ãï¡ð'=½ZGl}Ø1„Û©ój“­Áê±²Íuø”Ò&:”i{s1ˆEÃÛ¬ÊÖ9<­?*Î79ÝiáÝÅ|Ž&LÁ‚91þ˜B›ˆ†Áð×TÙ¦^”Õ:@e@ì‘øx”¤ãÈÀˆÓ„ˆÏEó!jFʪXAN´¸¾Õlßmn=ÛÍûÙŽ½x»{{‘ïïÅ£Qv ëÓäËœƒy–ä°xxv=+˜ÓŒ ¢U0LuIBìãöGð>g)X„­îâ‚ùšø$¯ªÒ33ÈPzXœ‘ù#Ú}ªl×$B(äy w˜±Í./®†è¾A[¡º±mµ“Ý)y/ù/Ô„( i8OvÔ]³F‚&aÿ°)¢iû&Ñû“íjÙÖåŸ ÝBlìN£ló#ÐUñÅ ä"\+Í8oþ“ÝüjgóïÁ‰Þý/§W¯þ”O Ïh’O;!Š#Ìû!êÎLÔ-$íÅ#~‘¯®f¯Þ¾¥`+“¡íªlšb³tAƒ‚tèáqó0PzÁR{ô $ÜjÞ)¸ÀÙ=Ÿ?Þéz±©›lµJÚ‡qçdxJðR'ÌÖ…ºÇ tè,ýhn•¯ò¬öÅ›á*: ¡N‚ÓžÚf»ÏtöÖ¼}óDÚë.¸iivˆ›ÑOý¦pûA"lÄÑOÙoêÀí C3OÉÆMãŠl¶NÈøN©kñb}´O¸­]¦ƒx'ŸÝÙ| güÜ3~dâ8f¿xçB<ÒÖé@tîë§1èëÚ¯ ­ÝÒ–ì¶ÁÑ&—e]4eåŽø8¤§„&ÀÇÝt†æm¡I[jS=hœ:_TyÖ8Ô4• d#õø)l’Zm² -¿º® Qœ£EU®¼Ó=Š€yÈ¡T‹ùSBÔÉh„G‘÷x¥#kAÖI|èÐ ñÑÂäßNð!ÅMŒyUƒR­Þ&ìuà#äÏãU:†q¬e/CõPw;M"E ì׿"áO1ùî{ŠÍt'«ôM˜&0W¶°:Qjh#p—æDx»;b÷ 7qZÜ 90Û¹77ä—tϼº¡¡êQ#ô©„ó¡J“.Ó¡¿Ì×QJD$>Aþâõ¦FB¥Þó6Ñ$bu ÊZÁß¹zg$ºXg‹Ü_Zdˆ%ÎÂ-äÉyUû«ÊÛU5ªÏ;l`YB{×0 }¼×‹9'LöܰÂøŽë„Ü—bþy•oæ. °·v±ŒÒ~çbŽLÁ§l>øÒ>ÃÀ%‰a¶™»–K"<%¯}€ØÄ-Kpg/ûP%Ψ:uTÙ%(µ«ËU™ÙòÄd0$LÂPé¯ÚÛë4éŽÆ«ªRw[åó¢ŽuqpŸ$/qv8Û/{@¯ÎX –¢Çoe0gHR¼Ÿƒè ¢EZìÆYd ›:Þ3`*](ø?5fÏ\Óoˆ Ê9lØK¨jÿ[÷ Ž„hAáš~_^¾ýòendstream endobj 40 0 obj 1729 endobj 44 0 obj <> endobj 46 0 obj <> stream xœí[Ko7¾ ý:P3|?Œ¢@â¶€òPÚ‹/yå¨VòJrÑþúÉå¾DÙ[¶eEðÁÀ,Eî.¿ùæ›á,F¤í_ñ8í]÷®ûÄÙ¿á´ÿnÐ{ó‰È>!ÈAûƒQÏÿ€€‰#EûJb$e0í1D^þîQ‰Œ2 .{Gƒo©5¾ùÄp}ÊÑ܃þ8}ï5—¢q¬Xd‡H¤ˆ ¤0­²ár<ËìÎRR5D™Ñ´i"dÍõ²MÿŒÊ¬â]L‘v˜kÃÝcz"‘T&˜ˆ´¶c¦Ò€ØcJtÊÌ€Û$™HÙ„$¬Bƒéôý»d‘žœÌæöšPˆaî3Í“å̹Gœ«Âš_]¼¾8βÅÒ!–"\],/ONnÒ¡ÿ!—H`<"÷w(žŽ%ÀGŠ!¿Ä^(6:8Ñålõu’F§"Hñ0ì×»gzuñ:æÆD!Â…ÜbâX¸ =ô:¤rPv X ÂÂjn·8öj`1Ø,½~£ÏÎ!/‹¶Ä]aÙƒwN¿ƒ€Õ!‹Ò7RªË@:ª‡MtIÿŒ—ߊ®JzºÊ“ËqêÃZTËp³Ž¬FŒðÈS°óÔØQ;F#-T#–ÑuYvîaBˆ=d°!ލAÊ©¥³÷_Î101áNæIžLÓeš/\¼3pïÄþ÷˜*¬³äºsú8L-ŵŽzÉÕd´óq6ž&“BüpZɦôz5ÎÓËÀb˜gþN˜È²JóQ2t*‡c¤•d{†…—LY -Æê¢¸Î³/‹4ÿàöÔæ¢4¬ž8*BTá`©sT›ÏVT‘ˆ<}vRÙ¸="¶žRá×áFÚÜúîtvã&®¤Lkòq’ Óh¼äH2zÀ×þ‡6]áK°ŸñÇà³ÏËdÅœb ö~äì 3ÈqÚ½ÅLŽ—šâý,›¯\öÅ@2 ¤Œ/ލ,3²‡è|ÐòZDdøaï¼/Õš6’cúþ¯oI€²e4]úSŠáeÝbìè¬@Ž˜†»Ÿúûª‹ý•/¤ƒ¤4Á¸XÍç“ r…‡ßVÍâ{@C7ÃcQ¢Ø22†IæŒqIÙ: ˜­Íï[éêE 'S…?Õ* ðõð÷i•eãìÊí¡B’âpO‰_ dR¥©ÿu®©­CŒÿKBáTID¤¸û¼q‡Ñ³/¼b*^iÉn‹8¿ótè™E ‰EE"É•ãf ªä–ÙÈ-iÉB‹&Š‚‚M{ÑPØ]ƒ‚l©‹1_‘4ƒŒ07Ã&Ôˆãaéÿ#Îdxˆ‹#Ï ÍôŽ#!¸ §£çÙùئĸF`$t£üY!±uƒöÑÊ!¦|gL±P -R`ë@ø¼úºH¯WþœK0„q9¹£ ”à:L^Ž4 á»s¥¦€=‰Wû®M›øúÎoM!Œ’ñÄÁvwHÜ>–•ÿ”9 TLÉ…z̤¼7‡³‚ž0+ÃÏÊÙ ½Ç>@gëб2T²&t„Û¯Xg[³“m¶Z†ÚŒFLé`å3·iTY¢7õý­‹JHUº”\Ùt2ƒLƒlšýc"&=«fHyK3¤“véòРhØpg¡ÞùÛTdR„>ù¦ír^âÑg9”¶¸&®T‹‡å V‚ÏótáU ·S”X&ES5ˆ‚Ìh–O“åI …œ"!U˜y›‡¶Éí^/ñ üVAâÖôÛˆ:|;¦‹Ea$Ì|ã_…ÑPñÉ*]ü\„lndšæù,/.HÄyU¤òòÀ6QSu˼Õù"·oÖÜÝ3xȿߕm_ŒHƹo1¡Öyˤ`9óŸÂoHYvŽ•¢5LðãÕÄ+ŽpÙÿûlT~`÷°{Ñ;ÎY9ŒâXõÀÁŽC±¤¢[­y„5 ©†X©e$Í%,7ðR@¶KaMçùì ˜{Z@4ƒ‡Rá—ß°¾2e7_­… \D!eÛ¤!¯áîêÅÑÛg¾p¯ Ñì”ÆbÂqTó6o¹oªîû©#Œ„é ŽG™»î±Oh%Ѹ¬‰ÞíãñâO7)‡@^žÑ'“ñå¦\9ÁÜ«QèÜ]OA;GŸ-Ô1jÀ5¼Å°]+G7ÉdH¹ÆAü›L! ^Ÿ^N7Ω‰&üö¹ˆ©æÊFÃìï¡“çFéË‚e[“㪉å(’[Ÿ9d§³ „y¼óQäEoóó›Pî eVÒ²Á¢¡'h=Qa¹ö±¨ÎÛøâ+G­‚ƒšgÁ3Ê€„%fåõ†o<Á?ë¶Q÷m’±t‰fþK\H h••ßò%n4PAö¥ïÎÈî~HªôÁã–b¬×sp{f/ØÞ€ª+m“é÷Aÿcïcï/þ³endstream endobj 47 0 obj 1846 endobj 51 0 obj <> endobj 53 0 obj <> stream xœí›MoÛ6Çïþ:)°<ãûK1ìТÃvÈ–.ÞN¹¨¶–hˆäVR†mŸ¾-Ê–LÙªÑÖ²,äà€&iÒüñÿüùPF€TþU¯‹döqö1À¶Ì½,’àõ|öýïXƒæœó¿fë8À ƒ$„æÉìŠúrþ·iBM¨†´0ÍæËÙÕb•«çìþ î_®ë7?‚k`œñª>”U4ªia¼Sä©uÞE'™£Ô»µXŸ"OÃvQÇ„Žè R«ªˆXô®M;PZ׃°o0?”D€Þ´¾I߯Qê¥D_$—0Çs†]L ¶°-®h|X„+Þï¯ö(°ð|1CX°K€ò8Üú±åŸÐ1ÝwC‰v $‡¡\}° X»èea±*‹ ÆdUšuKH%º¦£ãö+BÚ[Lé~sP çÀú8‡Ÿ£<ºœê@8yÑ$Ò}ag‘¦MfýŒƒÅ}ŸqB t½.€É³t³[LbÜàÉ7ŒÛ‘ø¶ãj-å}ŒÃM¸xŒÓè6‹q¯R˜ @‚Nž—TöŽèÇt¿ÆP·04ê©hÓ¾ò~½Ía—HbÌ@hzj2†¢ËgjnkVŸX›GÅ'ËÕóû'{öѤ¤.K}È;â¬LÉáÔþÄ˰x11NêVNGôŠqñC.}(p§&aºôvWú2íÆügYEÅœ8Ò²È+‘›E‡†É›¨ÈâÅMœÆIü”ùåL‚BC¸f_$’´y#zF"KË}yG˜eešÖkýSY"ÊQ×äͯ¯ÃEC:¼ ìf>×(øÖOPPR¹º½rŸoVÉûØ„÷§4J¿Tz}:O@E{PaMÕP=QYå¾õ´Ïž_¨ÝßG#5¡ ]T}³ü÷íi<¸ª?òKäN<}<§ÖÄ[ù|N:r1 \}ó/RðVJMÏ=M0|Ø9‚«>ÙÓd½ÿ·SûR™º5®qZT«6çðt}eDoLÑÞÛÝ.’ðßEøôÔñl§@¯I‘¹¡¬¥Û6á×\¥ßŠÇµÉ¤Æ¬b7¢$*­¾P˜Ö·/­}1]bÌNnWÎLFr\ªð2X£–*hŸ&´MðíÓªðmK†É驳ÑÎq|òªiÓë~¶¸Ü¿«@@ˆè ž¾hRéÏTiûS‹Öïôtæ!·#9slÜEû7šu¹ ±å.îaêuÆô+TßíôÉÄ–]íÍÂJsè øä9Áqx‚HƒÇu’•}ç{Køv¼›½›}˜I"%endstream endobj 54 0 obj 1341 endobj 55 0 obj <> endobj 57 0 obj <> stream xœí[KoÛF¾ ý:o÷ý0‚¤è¡n›ZéÉVbmåP²“ô×w¸äR¹)¥Ž$‚ðÁÆpw¸»üæ›×#2ÆéOþ{º}}+s¿¦‹ñÛÉèÇ?ˆ‚Œt<ù{”M c Rt¬$FRŽ'‹ÑGô½œüsØÖ¦3F¼Élt±šñíÅc¼Šîâp–ŽWqlhþ<Š×©HDAA.|¬Œ *1ÏeÉ++ƒ(•‹ÊZ¹@’ ½Kkü`e1fH.[ÂH«˜ X•`¹x¶|ük¦r&`£nô|™Š4¢ÂH·ˆÏÙº8R‚“ÝÓûÛ—Ù™mŸ3#HæTR•޹déI 5¾¤IûÀ:m?ô8ôë(ŽÑ¿aâ{ŸRHiâ¥C ¢ÌhÚ'!GX„2õQ¼‹È3±*jØÐêÁ2¤2Î\¨Îg4ÒBZÀµçˆó9•ÈÈbþu|-æáÖ`m34ˆg^}iܪsm;!¬ 2†ôPáâ`Œù7tˆz? €ÁTP]üF©Û‹é2^Y:×a­ký”Šdºê&½ûõm° _XFÀȆ¹:¨AâÕzvuõNזعDsçrÔ ¼µHøKÄùÚ·8U¼9Â+¨©‚3)<Æ›fMÎ+dÛº¤*ƒW—ò7]wsî­Ð”í 0D vsË»Ãpºïîw£”!Űª½gîÔÐÈv¤@ºD ßÇÌ®ã«0ùÝ~IO©Û‘ó¢ ;I,Âu˜¬Ú©N·kÑ.èÁ¸ HÔpq”è wÐsgbg;jUŸÙ‘•ìH›š!±ó5¤›u°›©ñ=7ë&Þ}}á·(%ÖJß§býó&ðu«VÀÛ­`éRlJŒÃ}@²!…€…»h&¹½häj¥Õi~ÓÞá¶/ìmJ¸ÕµtC¤O·j)T!!8s rÆ´äj Z.Gq¶ &6Å$L×ÑÒ>‚Wpst6<ŽMâßÖ÷YB̬À­Òä{{𠼓Nýle?Äð£çÂçEç=1i°ô©Öa¼]…Óòö»å“-gK€)IIÄÓÐKÖÖEÛ7ĺ§ŽKÏÄ纡PâB-ض÷aÝbÝ6¬–’{I‘!E<±³3ÿ:몿É}ÐKYÑ&¯·>KÞJæi‰ï¨•ŽKHQµìnZûym]4ˆ3Æ[÷göío0Œo7 ÅdÕ0:uBÛ>ôÕUÖ'â0ÉàŽ>Ñ62$CF«ò³ œ€P\à¬X å, Ê{yä›Ûj%·(«·«æs‹{]ŸðmÎA+2øÉ!¤;ÐOV:¼‹› f³Ûæ5ÇÈÃÎú£ö ¸=)-1R×év‰X 9ÿÓz‚°)®3óÇp¢†Àµ‘Q7ÀÔµ†ïXøzŸ$YæHé°™ì&Œ\ŠSøh½fO"ÿcb]õõnýðe1‹bóu~àž¡÷®k‹eàR^cTÑŽÜ$œ‡Áj—_q‰Ûÿcnæ©£ð81¨6¢Ê¨®™¥-®h­W;)5’š²†?6ñ#ÝÀPU»ì¼Ë}5ÀáÇ[³ƒ0³¢Å&ž»Ð™Þ§‡þKÖñEȯqîÆu¾v~*Ú¾©Ýu a1 nOÑ9&Óê()†ÐO`Dµ}bK7ï'㣣ÿÁTStendstream endobj 58 0 obj 1556 endobj 59 0 obj <> endobj 61 0 obj <> stream xœí[moÛ6þîý R æøþ º¬í 4E_ÜnòEµ•Dƒ-µ²’ûõ;R¢Ë’­zql¥F>$8‘Gòîáñ¹#ƒécûSüÏz_z_úÄÉü¯ñ¬ÿë¨÷Ó;"û„ #í.{yÒ'œ EûJb$e4ëpD82OFC¶Ô‡)ÄŒ‘Ðo4é¤á,¹ _E³(›_œ „.žä–Ò aB|'d›D™Ñ´³"Bö0 eV[ñ6¢šŽUQ¶PO$’ÊèBĨ• ˜"HsÕP‚¤ûà0FpÈt ²Û`z®A—ÀˆÂ$:ãÅï©Ûa°àê´úf¤jí QqU²ªaš&N±FB)$×`—ÁnRtǯßv;e ®Á.ÝŒÝ(ž„ÿl ³t«CüÕ#TëÃì*!`›‘³M|€Ý'~@í$`9PF{Ë1UÔÁ”JddÙÿ<þ0Ó7¶!çЕúá+ˆ*ì%) : Ó÷Y…uVq±wäQ¸GÚp)Èr¸¨‘“.rô-axq2Nâyææ¨}ØÓÙy69=½ Ç™cº\"9ó òé¼4øKÏq®›1˜MŠ&“äæÓ4¬U[ûf¿lÖôãSg<ÊÒ@]pÀˆ| —‹£IÌtWü@„÷Ul9Òš¶´æÎ>-ø}ÚÈ¿w·O¿]ß¼Q’CèQ[¹©µµ7z.·¶Yµ¶4¼z6£FyXæÎ£1vbÚE'¾.8åCœ%·N¥„¥“rŸ§Qà ‚ˆÒlÕÝ9Íwöƒ[ÍVqË7ãö³s>|¦ó  .NüH¥¤Ý•èÖ¸CJÙúôÚF}óé¥dõôªMv–a9.¢’í¨EI™\Tj‚%Ð+XÍ–Çä§ ,%] —r3.¯¦É§`zvÖ â¼E±èËCÇàCFK¾.Zª‘ÏÓÓhþѶÐv¿²`MšàÍ0¼6ˆ'us`ø’Ø;ùñÖ3¼æž¡B²Š8[f¨gPI·º{Dìp+¥ª°Ò;„Õåm0µžyš»!ÆèÿÕNf¥ÊTß ÀâËqÜ„"B0Òæ@ƒß#©-‹sºŒRw W«àoÒ(¶r¦îq¿Å3tícd ßvßì9·wѱn·Î5g¹á¬B1e›{òÙi¥ˆã¦A^B¦p²òò%H®lm¹¶„L´UîÕ\äeêdž¥a0Ë«H#FÊÒpCé…Ik‘òÿ&gQŸGq4»™5Ô®môƒ;DÒÊ…‡lSHíŽ?î±D ªj‰öhŠbeË´(¾vÍEÛÔ\A;«Ö\w–'ßñ«>ÿ‘mÊŠ]òÈË<§wSƒüÝ”é{š†ÓÀ†³â›Í’ŒWþÐà)Æíý¾Zc]QZW(]H-Šc]2îV¬¼Á²nH¥¾ð•xS˜Žç»Y+·Ç3lƃ|%wˆkHDûýž )_P|u"›U•îÈ|3쉮ÂÜ@Rhì…Ùµ»»¥0¤Reý=ºº.¤˜–÷Åù%R„Rß;ˆçnlªA§Z¼-Æ&º,é_¦ÉÌ‘f *}÷óÂÈ` Í m=O‘Âe ¾þ0Õ™ \öËe²Î_@ê"Å¡[â%õ‹ñÇu4.¤3?¶³ÌLˆˆ3Ë+¢ó n÷\¶8GTrïé›yn]{]¯vx_ÕyòýXrI¹ ßX‘PWRo\ ¬/ ×ïžýVeDÝ[^yÌw%êâ¥Ä´Ú˜J¬,”µ¨}=<þõ¼–6Ú’)]=2Ã[GD<"‹ÂñD²Íˆ|öìuí“4!;ýpdÿ¢c)n(a¬l€VÈ€Oa×xxþæÕó?k£*F³ãÿ®Ô»h „Ú»å,žx.§I/¦IEñ•ýÂA+ÓMWH³Eá!ÉoIìcQºHK­H#fÊésŽ£y”¸Æ”b¾wüt xð0ë¸ðÀû8´_žúo{o{ÿ¾¸ºendstream endobj 62 0 obj 1544 endobj 63 0 obj <> endobj 65 0 obj <> stream xœíYMoÛF½ý¼5êõ~Ó´4A£ª½3ÒÚb!’ Iµ)òç3»ä’¢H;jÕ‘jø``¸Îî¼yóf…‰±ûkÿ/³è]ô.&Þþ-³ø‡Et='2&!h¼¸š˜8R4V#)ãE=ˆ}·ø#¢e4,Z¬¢g¿8“BBpF[SR&™­méžpƒ˜6²}²I³´®œd¸6­9“A”M‡&BF¦‰Uçm:ýÕÄAócL/áëž }†{"‘T&˜˜r¶+¦­XÅW” é2ñ°Rˆãn/m]§ùÇ!E†’A½¶ÉP\±Ö8OïÖÞÊ–$Ä_;“F‚ôh}•æiæ¿N æ]Öú¤Ê„·ÿJëu[3’ªÖøsWÃF„ü¦P ãS$rHÿmË6‡Ä ¥¹¸?‡Û}’2n‚[–EÙD„){(—{Œ&‘¦SŒöÕ§D7)1ÚÙ0%|Lø7éû6°c¡X8‰$_ùÅÚ… A•vc“*äO#bº¤tð§'¡€5gãí5ï~±ÜçkzCŸã¾Aˆ#D3=à]1È,÷0b$1dy[Ú:©ÓÂ?”ܽB-ný qªGèx°>¢œž4£>Nš£òI÷1=­2ä1Õšu`¨êt™lÚ SÕÁ%Í›2¢ô>Ÿ÷º¸<8€¼ÆT“_´½œ!p>½#MÞ¦›´n›?$ áï–bˆ6äyåL×sèÖÄ)-XëhTøòìõo³E³j8·(,Â=çøvTuf@p–ÔÖ³‘ ®½MúåŠ9Ó+)†U/ÇáES¹ Ø˜¦!ž?ýÑ!Å»DÚòÎæK‰ßÐÂõœáÁ¼Ê\H]Æg/çÏœL(è³^}|ï–(„!ºà¾0Jwfë¹Úž‘AèUZ§>lª@ê%ûae¿ÉÓÚæ¶ò€ÐqÉÉ¥fŸã>û|Pãjœûç«U꨻¥{P‚’‡­Ëb÷vc?TëÂ?4pl2d¥êŸq$Øqåuqóû…´NšÂ¿W˜WV1 ªæ-Ö`ȳQ0²éAÞÄ‘d*gYdÛ ˆD(f©:yŸ¸G7š Qq6Å b(eªö)L6²eãÉFµ«lùm5ÅM †!"ú›¯§>ŸÔX})ûtaöTp}Á±N‡ÌÐ=yc–ìªê¦³wÍk—/{£uËÞÚÈq_{|`<Áçtð{-Þ¡gê®Î£gÙÂ&´~¤{b§3ÁÒÄ‹§ºV⼇%‡ìÄÀ×rëu¹RîÊõk”„g†§ÿvB=z ù¤û<‰O0ÂtEÿ±”J·,i†O AÈnRÝ–Å]™øŸ}¸r3âcCå¼0v–-Ñclr„á®Eú¿vnomé®2šßúÜïéÉmÜŒ!ÃìËŒ`dq+Ÿù À-é§Eü&z}ÒaÚ(endstream endobj 66 0 obj 1131 endobj 67 0 obj <> endobj 69 0 obj <> stream xœÅ“ÁNÃ0 †ïyŠÜ€CM'NrÝ MUÜËÖ±!ÆÄ:Äëãfé€1BÔCÔ/¿ÿ8Ž]ê²ûò:^¨Gõ¨1±~/ô RÇWò‹ :««©Ú Ž‚´ç˜uµP‡óv}TÝ) À½hª‰:\N;f ”.ÆÌNç·O«¦í6Äœ5"DçLg^XdaØäB’Cô1djÖ$Hƒíoê¶ÉR$O™ŽïëvïèÝid€K×gÕ) Eà Gƒº|Ÿ§•È@&ë¦ËU'’"&›á:g(%¶Û\žÚfuoNån.ÈÛ GûŽÅöÕ Ò¡(nË’Pì.Ìï!?ªìwОÀ]„¸7‰Ø#¿6rÇ ‰/Á›ÜOæßúélUOæÍÃú³¾ Vº…ü_÷•̧-·fÏóõ,_›MŸËí&ó4á2ùûÊ¥¡GíWm²óB>½ApGº`)¾M;×çIM@¥ï ²àœÈÞ¢“J_ªKõª+ôendstream endobj 70 0 obj 387 endobj 71 0 obj <> endobj 73 0 obj <> stream xœ­[M“ÜDÝó„c÷'lMà‘Uª/{³À`a‡à€9hº53‚îVÓR{<ìþø}¥ÊÊ’zÔ=ÆD`£.•ª2_¾|™Uä™Xäþús¹¹øíâ·…žÅ?–›Å««‹—ßã?…Í ¡Õâêæ"¼ Öä™1‹«ÍÅsñÉÕ/…ËòÂi ¸Z]<³õÏ𮹠gý¾j¼g z¸:,û¦Ý~æ±6“RÄá_ûGX‚Ä¢2—;1,¡Ì¤&~å›Þ\ѰÉJ•ÈÊ î«®YúaªÌ„“qËv»¬w}&(ÔB¨L*¬ \Úâ£vq)MæÌ0^dÃFñÀæø%LruW‹Ì•¶¤‡íþ¶Ú6¿W~gþWWd¹Íù×›Á6e¦L.ÏnVc³¹žÙ¬Y‘9­ÃZ…Ó™ÆRá5^,-s妟(ìäp¢3çä Þ9›sW-ɹBñá¯þ–y£«Û° l^ñÕ2k+\÷Ö2\r-[ °Ô8ßf0%L‚eѣúovÕ¾ÚÔ}½+·v¼r«à,?Þ^ÿ2,I¸ÌZFø.¬´ÌJ'âŽnÛetà±A”ÉÊ2úîþ.  u¹Š^¾>ZÞQ3ì\`˜VñÙ²Z¯ë•~)]™-—Àaðãÿ†ñ.Ñ‹7ížÐ㔌K½kº¾Ý7˜kð‚Ȭ3qwûºêÚíðeUþ6šsfò>àæå÷2ï¶YQظÝ/_3g’BfÒð ±ñ¼±˜Þ>ïê`lÌêH2o?ɆH€‹2^Áh…E@Û§&g—’ |è0ñÃ0 ‚ãëRyxºÁæ~Þ#ÃP˜°0e²ïo‡jü¤aEÃQIîBÁg–Œã•­ÛÛÿ®›!H¤”qƒõº¹kÉREs O ¬î\¸zÁ{ãY¯ýð*‚Xªhú¦§À±.¡¬=¬‡ÅË“²¿«u×ru²Øuø8¾câ£:ìH ŽÕéMn*ÿŠ@´˜VÉc¯ ^Öy– Ž•«¸*[õî.UÚ+Ý(l&øPYÉt±­ëUÇ cÓö-ùpÄ–f„û}Ó÷uøv¤‰6ä”Ћ ÁǼþôÓÙ@B~)lDBŒwÏÀïgÇe˜‰þ çÃp†9U?ÛÖÁt ié"؈1@¨¢äàßö1ÿØ’éüºë÷`rŠvq‡ÈÎuÅãœÄâºê(?Ë©‘,¢¶`J¢p‘ŽóÌëo^Ѽ¸»Èd!ã׫Ž|ï’ïƒó¦™ùå¦ZÖñ¨Ö¬`b²•™IpèB> Q‡Îe°®'Êœ‘1X›¸BWÛyc£gšÍn]oƒˆÇ‚³]ð*b[Ÿ x|݆Ü)‚Ç_G¸ǘΔž"ÿR )r•1Ÿç` Þç¾yGH–-xÏ-ë Fœ*ÜÇàC" 猌ƒŠóýZÈfÂA—^ ”l_JWž¹’‹:Ò.1òªÝFÍ!ó"æ$b!X3<Õ°N\[2VIZŒ [$ÈnêUSõu\¨q¡»}{ ÙtG©Á†fäªîžöI7n›èÅéĈsÁóU³ÛEñ)òh‚öó}EñÕWxÿ“üù95%¿°Ì*Rj9Ëxã%-É«øP!ò8åŸáAÕTJ°+…>›/›í-­‹ˆ«)„yèa» TBçü8«IªjÉ:Ê›)xßÙñ©-ç4*2pò2qâÖblCÈ h<5¦^F7‡2} eV³¾¡ìå÷e¾@PÚ\ ÆWPAYüXäyø¤˜¥ë Ùìr<,„äûÂ݉}N9*FÖ‡8Ð%B&+I„[é”νӞÁðá Ž›±Íî›õ:2¹x{›`[oë}SÐ$Ä̹£2@Yfšóƒbþj##·c‘ùƒ Ɖ °q èM²¹—Ž‚«‡9ï›êzƺ¬ÏGÄ m#2YªT<µ!`gPqq›tˆ!Ââ(½J\êÓåŠ>ÄÙ ›ÆÏ=Pøæ‰NÉßð¯K†ó·oV0\ÞFùú‘×ú‡>OTyÅÈUZs÷ÛOêÔË (V¸˜±1>™óº{økM›TI–žž×àWm“Ã#Gii“vñkoÈ!pv®Œ|ÊR9ä£;jü|$YÛÔ¨È(½¡÷õŒbƒ ïZ%zRq9cª¸úêW¢@aã”uý8-„¦ovƒ(,Ž, ß~_ù¿)˰¢ï”5At¼~òÚ€6«Á $ycÚšGùª´.Tî(†1DŸõô ÅœÞØîqªk×ÛvCHÒ`Rg“Ú·‡Û!Á@ñ¾H{4sÛÕ=…¦ˆj†£WU_Q&µR[±ªOâŒð¾ËˆðGÎñ-5›o„¥‚圗°’å’ð‡Ž‡¯ºQàÇw®Iq¸TnýRÇ66ànS‹‹›³2Q;ra³XááW XÔ¹)þš^½(9…¼™ÎXgÝ9[ôŽÌ?„ÒB·¦,Æaµ¯ƒNèIˆI]þ5ÛQ©üâÔåRê"û¡‚KÇÓJ¾|ZÉOc£éïÈÝ©Oº¯»sÛ¬^ƆŽV\έ{–R¤¿ €šB% Yõ޹5½_PŠ+S*|¶^Ëqøô,s@——ý„ê“–“ãOæ3ñ7%ãhçv÷Ùh&eIp>‘iÍÑxšH·zsDIBæì*×m¹U©Ã3—_¨OçC»xB*“6°ùã:S%w´†8™=g á ùá^¸š¨Q(Hsó¸Õ8ÄãÓ­Æ!ðÝÈ&ûú†J$ðÌ 3€"RÓ¯ÚVë‡ßëp”¢ > ~×TrªS!&DGbþgMVÕyFÜ.£q «Ž¢HŠEŽ&µbš¬à¹f9dœ 4гo³íú}8‹ï"óÈ$¸&¡-8eÒ”ƒ…»Puø£—„.Üuj‚Îĵ°³’'íëUÆlV˜qq"B«Qÿþh/¨oÙ„T´úÝ'DÍQÕªŽ²ÏHn±œ8×Ѿ·üÔ¹ŽïìÑ"Ý1?¡NM©ÇG]RúNÈLsM•øùÛ盪ÙfËÝŽ:peér3ëÊ)«ãÎsµ¾$†´%'Ç2³œüë[“\-¯©ªV†I½Ýa3òP«KËl³l·0‚7ùøˆ¥~_/þǸÚw²S7|ÅÛau^…þÚ´{9[˵ž)BâÆ/ÎiÇ®k®›5I“Ž<ÏÍ,0&Œ 6+“¿I±ÁŸÌ¯©©c7u¶m,˜XH>ÝOªü=‡p8 65÷ŒBC…*¦kP#އ6^Æ £ÙtØ,üt4ÔÙS.cÒéõcÏ$íe»Ù5tEª¸8÷zLdX¤0|ôÈðɈ`®ú ® (˜23Á„ÈC&&W}>¯»æv°­öâ …T ?ÿãÒ3ÖHàw;ÉŸ¹ù3]ºãv× nòg‚¥8ÁËB!ñMîýHb;(S1ô—õæšî³02^ŠÛRúkWaØ?æfòí¬£Ýºêá÷ ) [Ødj“{88¾ïSãñ6êÚ’OWûÙõÏh¾þ„ËòC×4½P–G÷@ ¨ÈÒ±.q•LݨSEçe»'ýŒ­JÍ—YzJV“CйôÊŠ•ag:°®„AÃ%k–®ÙVûÕÌüÑsΔÂ0;²faÀÈõǬù~ôÇPª<ºq7)Yæ„F4EnØõ{P'%%¥ýõAnÃÿ±kp— ô¬D˜Ú^NNÕËèæ‰ÏÞTA¸DÉ=žVCú!‡2“e‹á«ÑUw|ãg(Î*q.6-KŸ[!U¬Ò¬áœÓ×|€ihT'i—´ŒU„ÃÚ§%OÛ„¼"Á¹©ÊòXçå¤Ñî³]œnë§FW'öÛG‹ñ9ä@7/!:c-üíïK gý‘ÚBßr)ýòWo.^¾ùz²«¾xùãB\¼üÊÿëÕ¿_ã7Ÿ/þvñÅ›0Õì=sØÖ “`çÑ=sáý Á¹eÓEsŒv „°ñGpí}6»”Ô%ù>¨×Ü:ÒÉ·ß^o‰Ô#ûI…ÕVøsàGe\|:ê‚ù8M—,; Ó\¦K.‘ÞÒqõý¼&®6ŹR²œìkZP«)ugk@%tG†‹Ëòˆ;‡|pÔ`b“ÙãË0§˜Úö}d~ؾ´g[^¨³‰GD3݇ôüÌDsOÇlÑX*|©;àÆwš6Ä'%4G䡊•7´ïƒÏœ–L˜Ul6>“&£Þšó§9¾©¸è«–_òô¼õ»ûÊð-»U†7µ…o¡äSuîÕXÚ ]*Ì’¢äÿEà†›Iî‘‘ŽÁ4h>6Ú)0¡Ä)?L(Òƒ LÜÑQ‡¯©\êÓDÁ)Ôq… ”• eëæz_íh“…ÈSg#úש©@A¥vå%Ã)™ÒÖmEíä¥BsºZ=l«¿~—Èå:uÿø*ŒoâkvýªÞÐfßx„&ã!È©,dNüîâÿs‹ §endstream endobj 74 0 obj 3981 endobj 90 0 obj <> endobj 92 0 obj <> stream xœ­YM“ÛÆ½³\•¿À›WeÂ|Ïè+vEU‰*V˜Ê!ëDb—°A‚ÀU6¿>=_=Àr¸ö–«šfÝï½~=[dYÚáçf¿ø²ø²$n-þØì—?¬o?¹$¤0BÐåúfá_ K£ ºT²,¤\®÷‹«ïªñÍú×£…BÂ3ëíâêïvéí'ª`Ó”†¸-à%Ÿøðñ_Öþ©ùALª<<¶íì3„šQa­Üƒp»C7¾ó»i6Ým¥uA §Ë#„gŸýSîXø¯–F„ívÍ0v·}µß7‡Ûì¾ñùå×ÏÝw[•}ŠÊBƒßU‡m{é ¦aNÜAìÙ±wÍÆejEMA]¬©_·@/®x,Ðov žâ†Ä’H(++ÿ*|–æ&®Ù%c«mb ­ƒ€¶Ûéøê×U[ß…DÂ)q¹nZ„¡1ÇjãMù¨:,`ÕOCÝ;e‘DÆG½ã¥K¾,”ˆë×WÃi È4¦ÆU>[”»·ŸØ<Ì ›ƒÃ+”“¢\_]¿)Š"÷¡€N5Æó&›5ÊXAÌ Éüì¤Ö{l øj#ã¯&Ê£*Ou¨ÚûÁs˜3à02lìBæTÊJée€Ša-dXÌ ³/f}žå¿6GG* à§ü¥¯#€Å±_ÿÃ~q b%àñ)îòê¯9ºÂ \í݉$Æ ¯º~¬!9&¥}ôºÃ îyÛUíxÉ$êÝëóo*°‡W6Û ºŸÂHß÷]n#‹©b/™ZÉT½ŒÈÍ8†°Ô™^ Á•Ó¾î# ¹‚Nf0œÍæÔW›{÷èq”Äw®¯ê/§ÆÉ;„Tr £­çeL ùx9ˆg¢t.àŸ|ÀŠ:CïÑ`ë@y¬ÃÝyS뇦;\"º4EÉÄ ™ž rÓí§±á0ŸH¥ ÆËgu÷»²(%Z³WÌîT0Ove™Én©2é]1Gc2iv÷@DÁ1²Ñ‹0^$ë±­‡æ6†A˜Œ¹ L¶v™œ6àIáªã±\Ûš¸ÈA‡™Œ9 =*zGE .uŒÑóôCì,#¬òÅbP[#ëÏÿøàSƒ" ôII’: ™˜0ÐWÐBTdŒ’%‘îV_ƒ×Òå^‹”eÌ#ý (5á(qßLc}ë5BÒ„_> ;ŠH¢Ÿ—÷¡Þæ‡~”¨—J_º[) 6›æ€– Ç6Ú[²õõ6ø"™x& ñÄÁć­¦‡‡T2„ÁiX æˆ>~Xµ‰æÆr/c{Óq^Ò*6øÏÉFÄW­7^AV 2STÀtÚ;—ØÈ1DÛ:jG Þ±oDN8|æÐ¹çÀ$©‘ÉI–)øœ˜šL¶극v ^K–8\jÇ@)Ší¸m>÷Uï Î@=J8ÿÏõß®ß8Äò² &ÅÏŠFyÅ çF&©>´õÞë:4YMµ Òjù ÖÛ?<÷Ì2k¨ ¦'È1e§§÷¨†:ë•A5‹Ÿ°i«aø>ø*IhBm36žUvÀéíXºÖ€_§,¼Ã}d6ص'?4TˆR¸PE¦¨:AË3èé~:T|~lêe]Z±wY¶_“¬•í1ßÔBK„nSr×l½ØëÜûó™oºOCT6CçœÎ«~ZyªÄªÜ5U €n…a·ïÞÝ©» | Ò¨‰Ù“áÐÊãëEÞT`ƒ¸¾ÐTe%ð¤æBcÁ2SËÓ" -Ezçw¥ l%×v»®žBFœ-Tò©êT*v^pjØ“j§»˜}ç±i'–þº÷“ëìÂŽ9gà#Á7óדOËyÓ$ª”IJ‰É©f¥¦d] Ř³w1(1+––qòät¸‰i ’òì"…Ÿ‰ßœv®õ6ÿC ‹W&ÿôâìF-²ÀA-êëúØ6à̤q3?šÁyL¦AjÄoŸàdr=—êþàïÎ@#•2ú‘|\V¼‹¹(/+f,€ø¤ÚÞÜZg—Œa×ZÿáåÔWƒLÎ&ÿ¶ ØMêªoïÃë†à®µKȨ þJ4,]°@šÎ'¥gÔû>< ¢ˆàÜu!Ñ4%ïF™áO+J˜ M—Š=[hµš`~¶õ7‡ +kœLb Q0NsÞ¦=ýx —Κ™·Ø/©Ö90Mº›O‚ZCa-ó¹ôņÈrÝ^{.B*°¬8è}8D#OˆN†az‡ÖÈÐÀ`7I‹õÓãÒŽD˜‘$Y8 £ÔÒÞ{8þn‹u!TŒ/#s ÅD©ç¸?›p,BfŽNV«œYÇÙ¦?½ÿ˜õ—ÐÍ’8ç.æpÀXrú ÿ1©ô}L?щr£Y"/r·í·õà5Qd¦;Dó+ÀÆfêÀçqê ØÔš›®õL°¦vÁÆâcF>»÷˜¼÷ÇàÀ‚DœÖC~²„yŠpf'Kþ‚É2s¥Ñ×µ×2ë^%Æ’ó¹0÷|nk?7@o5ªðÙó¹<3R{l@“WÍvÎaŽÕoÁÀŸ«½ÊB¥À’…§&wBþòÇf@?fv/øøðG õ¶WÀ²Œ6Ú_ü¸^þ¼øyñâ%ĉendstream endobj 93 0 obj 2156 endobj 94 0 obj <> endobj 96 0 obj <> stream xœ½YKÜÆ¾/ä/ |’N¿r°Ð!~Ä“ä¢ 5ÃÕ2™!WäLVò¯w5»»šÏÝGö°@Ù]]õÕW_)aêÿâÿýéæãÍÇ ë×Ò¿ýióíîæÏ·bÃqJñÍîî&¼À`I½1š­7»ÓÍë?}½û7<ÍôèiF¬v ÞØn^ÿÓ?bˆqŒ¹¸T´UñþXú„#–êôÃcu¾÷«ÜªM\<4—ü0çpVXïªCyè—‘\Û¸|¬NÕ¹{ã¶±é‡âxlü*3Ä*—vôKpœà`|X »ÂcLq×ÎáUE,—ÉÚÿú%E…«áÍ>÷öƒ3Dzµ©aÑêl²þ½_ÒÄ ´¤<û%G„4J?a]Y÷»q¸tòqÿ¦$ÌIÇ×ß W`D¸‘«üêVð•T›-DX÷>àã2™Sî«WÑçŠaÄø2át™þÆ  f]òÍù¾"‡E‰o^º²%DcÈm"R·Ùr°Èöÿïh³Äé9ÚŒ÷9¢ªþ/|8£e—Л kÍïD›&Rp1F›„›½ mÔÍЦ‰0/C›fÏ£ RL+<¢ŒdM¾<¼8ð}2¹lã5¸6É’¦ x³–pÃxK»ú“p×àCKŒtV21¼N%÷üÿPݯJb(OVõ!úÍXŒ×¥î ç+Īì<£`ñ¸VÛ„MƒçyÈ.ç–fTN÷¹%ôKsëûêSyx“X›i„\[}¨jüçxç’e‡òU®&Ñ\"r»H§†> ð>uoû á9ïÞ_ÎÉ—N¦ÓêÄpÎŽ3¡MfËâ?äý= ‘Td\Ç„Õ_¤“Ë锢à±jøÜþdPq¼”ñm€¿ 9À†¬Ïïoøé¡h‹SyÑTp¦DWÞ=Â'Cr}qŽ~ä|‹‘Ss ™,4ÐXÀ·CÎ0ð+“O°Pfl¾xô¡ð6†:$<<)$>YÄ<2OÅ>ùNAN ïŽEtHî'Š®«>$¤@K¶ç$Fì|Ž(aršÅ!$Ö hi½@ùä°W–§ïšº;uL›Í<¿‰8¥Ý>À)àÇNq Oç8o)Äé"§>åë1_usþy–?­z‚â{™*Ø 8ÊÓe˜ê_÷Ép˜ _I¾ò”Óí! yûSUW§â˜À¢±´´åÇKÕ"ŒdöyUÇr© °iï²½+öÈNŠiôÜñ©dÀDëüµ*ËÒy æ>¿ë-æ73É–»¶Lä,KÞPq¶’:p¯ºŽi®’I ¨½›K}€Â.{²‚sM «]ô­ðÌî¡»e×"”‚ûÞÌa.ÜW]HAG ï™lúþ»³Ê™ãy‹†Ûtài®KwŽ òsé.úÁI›ÖöÍ¥íÊ1¡¥]÷Oå‰âX S@}$œŸj9Í®z÷®+˯bÝæ”NÑã› DÏ‚ÄÿümO6–]t´äYr ̅j¹“˜/x·!ÿ´% ¨##'© *ž‹S™,ˆX%å]Ð*]_êR)ë"‚E)öû²ë×!Õ­13¤²Tx¼…(yJ¾HÃu:gÝëqL‡Æœ3ÄÐ’°ˆ³ò8¦ŽÄ!Gn ¹ ¥áV´‘ìE’ʵ¼.%¦ô± ØœÁ\ùlvC˜¢”³™Þ¢#€W‚º Áó5WɉfÙJØßWˆ%ÕÑ»_õ€˜/­Ñý1ÚàÇeù€O$F•YLœ!X¯pÔØBHPµ m!Ö.kÛ{€aÒ”[7ÛBkÜb…»c ¡Íã,mû·  ÄS÷Q $÷/oøÇÛÝR¬„aØgô%¦ú5Ö$h¯¡bšAµÍå\Õ![%Tw©§ö‰A@cµõh·ì’4¹è¯óøòJ$ìB‰ê1»V¢zyÃ講 Ð!O4c£¦, ´· ÓJ5V·]2]Ù¡ºMÓ!tÇs_ÄËÀ~tD×[ ]ƒv˜kä3U6Ïn’ôLu/ˆ¢$Ž„ T¿‡@”~ž@ d™@ï«}(ËÚ=Šqt]¨ÌP1XnömYœ±—ãb =šSŒˆ“|Þ¨®(ôBØÉÀ`H»ÉØb&Þ!„€73,K‹:ò®‰S¯€•Íð i,N·EÝA¹:窩ßoN$?ô¶°»ªÑˆþ_>^Êò×2ÊDk°€Ç›Að`ŒÕ$ï'ÉF¡¼gÃs Ìeô$&„&#í]7é@«ñÀõ¤_î{¸ïxĵÏ./9 °äðÞ1P 8vèYAyx™~^§¬º‹YLœúiÌ^‚Š#/u ºmàpªª—Ë   ‰£(g‡Vn£Ì‰/†ã°”ç^]3tÙ¾Hã8ÐÖO5tq2ÈÂ9ô”fÍ„”Iô"Í—÷ú—2õà /æ©= ¶r;ºUçÑPWî}6EÂÙä.Ž jTäiѹ¨Ž]¬2p÷M½âˆi«¼àfÙš*°¡ð‰‘°ç4y÷u_Eáõ,¿-÷Å%¨}`d§žìë‹E.Iã{L{ Ê’Ë"s;å‘rÝÔÛ#û"4F`¾ÌwŽóÐd™jq“ÁZ[î›Ó©¬ãz+8l#ØÆ…BÃMF-&?šê€¢ áüp9Ÿ£¿î¥³ã‰w”^:K/œJ0»N[* ËGßDf¤Q’?\å¦ ÙLå“Ùl@ŸuY‚‹âðÀOC¼ÔÍtýMp­ïúqì],ÌSÊOÅé!Mè3L£.Nºýèå^Ó¡îT&_y‚»)O¬Œ-ˆÜnN׃‘ª—³IÇ•Ž›÷~ËÕOøÉŸƒhÔ/&þŸñ+ÔÑÌ:œ«rÁ§·Qxï'ÀíóÌ èIÓœù+s9poæ¯n_e&[0ÓO`‚Xì5µy¾l­aúÊêz•õ|Áúg‹«XønTÏÇtåJÊÏä®ýÜpÕÄÎäzù倳e~”²1’Û.MFý'Êiã?&†g{b‹=ñø›„ººiÛÑ·ìè‘¥OÏ—ã!B†åÖÚ@ €qüܸ4†^ãµæ‚n»’¹Þ†º,‹Ré….‚.4¹ˆ† ¨Ài“¿Ì10iŒ˜öyï³}î¿b²+“í‹Ü•ýqw]⬹¸– xñðÐ6/ç˜\¥Si¿˜BÖ@Èx"øJøþºÛü|óóÍo„‚^Rendstream endobj 97 0 obj 2459 endobj 98 0 obj <> endobj 100 0 obj <> stream xœ­[KÜÆöym @òæ(ÁZšýî¶‘CìØÈìØñ¹èBÍpµLæ±ÎH–}ªúQÝ${V²$ˆ.§Yϯ¾ªj· [µø¿øïzwõêêÕŠùgéŸõnõííÕWÿ²bÅXã”â«Û»«ðd£WF·Ö«ÛÝÕ“?=½ý/¼ÍôämÖXíüâvsõäfï°¶ðVxtêûn‹…h,ãññCwìv=üÿ¢Tã¬ñO¹Æ´Î¥Cþêå“ÎÆGýoùd©愽p4È—Ž– >»æJ4Œ­®k”.RÊ%Éï{ÿÐ5­6é„îEÄ3ñÙÁ¨Q púíëðÈHÇ’¼øÄ6Lq-I…n÷°íŸylÃ[‘þòc057àªÆµpšå²‚ðÖ"ÉwñçVÕœ)áCKgz ”k¤–)††1F›62½¯¼5¯%³mÅê‚킞Ûo¼º°¼0BRW´ŸP]Ë—êJMêûâB×–yqny’ôWVйþŽÉ$‚ðZ·œRåö>¼É! ­yäÇÙÌ~Bk8IÖxs?¬½(ð´%§Ýs(çLJ— ê¼öýèªYc4KQ}w8F/‹Æ¹àeYK©ÖRJ%Ý,Š“¤‡ßýSÞJ´lî2ÖÚy^L~ÞAnÁMúÔ®;‡ß¼+Á" Ã{ 1#NÊc@IF2ï×}ú¨ 'öÛ·1¥²ÉÞ¯ š!Øqè^lý Â4LkW µka˜‡ñ"…î;/+C´6Ó/Ì‘Î5\H‡†#øjopå5dbß¿í£ $€j ÏÝC EãèäÃñÔùwñŒ\u<ŒDô뻾;AGÛè ¬äeÉ¶ÎØÆ”b€²EJÊ*C/²üËÉ?)"´# ºíÖWf«ÈöoBMiWé×ý&æ¿sœBÿŠ›$ ù,„RḦ,ìö/ûX¨[ÇKã$CéMÞ>PbœôcüF›Í¶9¯Cž¶º‘Üy:ì_R:UjÊ9ö1ÞQPcÈ;&Ãnø½; C¦mxö]ªpùa·};·JÑ@²-RÙæ"ÖD[ÊPZð˜¾û©&(fBÜ»ó~BútQ ¥" üµ£@XFÅóêÈÎP÷ð°Ö^[/¿†2ïXʤP|™d-/sücì­¡Š’EÿXØ, 1î±2Aá¹cÕðÐ¥É«Ì /}£¶âiÅÜ41$€?%Æ®û_¤ BŒV¤¬}§@VÀsyY¡–1IéþÅo!e9¤BKô8…£hxf¯¯‡uí¿Ë;è6ÀØ} 2U–1ª¨‘s¿Ž­c¨šTmŽ¢K0ñ,* ŽL§†JÈ0çèKÇ~wˆ‡:AµýBø¶'“o!YOc„#@k‚öãaí¥5Ìë…7€6ּᦽÄlax›q fæ£þ#-¶Óxš˜`Ó±ïCAu*_™kë’•S*7”CÒïû7ÉpÙq‹8™ †2ßf-½Šå4ߦÅÉú§a—…"@ðŽ 9ãZ"ä]âÜšRîxX.QŠ,[*pŠ£–ªÛlD¤gÚ¤)ˆÇCBà1 •ËhDg^„#086¬È†(‚«Ùüù“ýá1ãM$c•%…Ò4Gwà<·I?ÞüôÏ_/ЫՄ E{mæÅæùÓH^áàëî<ë@ÇJ5(Ä •²‚1 !ÄrìR j˜yBÊ´¶’2H›f)Š9 bƒTµÀ˜42CG \k]ÂZO}(`y\îŽ ^ð F¤#pž"(«Å¯±¿Ñ“à9“IƺۮÏÛŽª.ÄE¦¢·÷ý±‡–#€žÒH{äâ4«©g[ŽÇ~ô*@IÔ¦àè›>’woFÀÄjÖ9ó¡ÔI³ë h„EKV{jð³Ê)LÇ$aÜ;zR Ü¢>»'å~z;Œ´‘ïZ9cÆ@P23ÄN5O^öûÄf$$yînêPµÙ¼Ýw»ÐKB¦JGŲ"Ô1@BË—õ´P9:Xð/UÒÓíy6Ú³ ðÇö}'ÐÖŠú@hòùšcEv £$¢´ï×ý8R) ™År¼îÇØXù´Ïü(vlÖ'¾c3!Tª¦xn΢?¹®!Weo”lŒ¹Ùf>V®“:F’:Œø.X¶['Þ/b^:iìs_ß&ƒ ‰jËÉlô¸8Ø3rÿ.¤\Ãü¹ ‡{é“·÷¹G§’x:vûdGMˆ‹ “~ç^W]Ÿ€A×Òó3œîcÍT– bfN‹ŠÈ- pá58D¾Ó‘&3`»X·)`“Ä`ÖÕ8œóA—ä›aôÙ ¥~jRŽ!oXKL±«™€aþ¸\ñ·©7yUØc(Ë~NCNލ2#°ö„2/jb`| :ýù“óÃCDMQð„çO”aSÊ?AC‘,‘xEÂkPŒš~*k,É»CB H äÒPfÁ¥Žü<ô¯«ÎBî…#ZhótæçðžmWÈ”±–Ã{@JuÛ"‹kl‘ሻFNF@ _ h«ÁYé‡a‹€“í\WŽë1œ?nåD>°ºHŠïèý¹öäpAh¿,“áûÛÕ/W¯VØ%âóvu ^_ .á4»’LáwEßÞ\}uóãêt<÷W_ýgÅ®¾úþß·?ÿÜü}õÙÕ÷7þ¨úBi&Hxe%Ê+[,Ž~¡ô¢¦Z çÀûj¶°ÁYCƒ{ïg-öWÅY¬ 3®Õªˆ„¿ÔkÊ2žCu`8æ:\ã†PÚ~H4,æGT“0_ØlöõH†2J üeõÖbhV m XoŸÂ‹1>¹²9:¹S¦±¥»¨O3¯¥èl¦N½]Ožà‚¾ÜF\¨y'X .yÓ´Z|éFh®2}™X_^‡Æ0cX{¨>aüñð‡0‚nûZ’HâÆJ‡Fój úùdvÚ4½³cÄ0kôa{TPŠ©]0¤†nZ}€!JC®»Ô7Aé¢)N˜B3jfc—j׹шo™<\¹@o]h¢ü¹~¶$”™ìÛ*X¦ÕÅ„9ílxžîî»ñƒ½Í!‘un¦²Õ¼rXfÄb*£á¼€·K·pKž§/CÚ.ŠÅeœIä>öÝB@ k(¾ƒX1z–T(öÅÒâ]S+9Þ'w ÌeBÖAhìÝá>ßR±¶Uø4®u»§Ö´¬¹ az2­ÊUœóð²2¤°#l46uÓM4+„@ŸFôV\Ñ;#懨G¯&pDZÛâw‹™N\ãòœ åØ¿:aZ$Ázœl\,dž!áêäœ@Ày¤,·ñPËæ#Ö1Å|±%¡„–†‚k¬Î‚Ø«®œª7©øoöE!–µÍ ƒ N[ÀV#ŠÍÓ) Ex1œÒ@°¼ "̇êH‹Õ»u@9ÄxEÐV ¾.ï·¥ †®Z:=¯c02gÒ&R¶ƒuö½ùß$jnCo;F ‚n6Z˜w™:aŽ‘r*k¸ Ô¤Ô¾ï}¹‰áu¾;RlZ¼åqàG¬Ý•»°y›Jpù^…ÌHu.¦Õ¥Ë¼7 oE9Ëî?ï×TÜ:—  ¦QDß&ŽéÚù~Â_N” »Òì³4,”yÜÊ”5áx8ï7‡Ï£Ù™á¬*q‹ P>F‰× €%®+Ó›&Å“„ÒÒ\"†¶–fÆÖ›h`E­Ù™·šx5N"¿ìOikiµÌëía UR‚ËYþOËûWÖæýkŠ'ç!¨++ýUð à!ù’ÃsPðá•P=áÊ­%‘}ÚSã±^'‚õZ¶³*Ð Æ»,¦K—EËXéÉÝ# ±SëÉp%¯JÑÇçO›XNÆE‰g)Óey?æ#`ºBÜ-«Â9˜ ¬îÚrVÖÅ^7‡·®I®hš¢Ó­Üiªh›n :̾ŦQ/ðsÚèÝuëSŒ}ar‡ÕE*á K&ŠK)¨дW¯®;¤kT;î"!j^ Nè4% Ÿ1b‚°Åþ˜Y0%ÄáŽ*’ju‘AÏŸ´ùgÃŶ¬ÔßÔŠƒj¸ÉM9‹ÇLgØhV‘gL^[LN-N+ãKaâö2Vx hšÒÑx¡ÛÑ#Z=‹UXeÁ ÷d°yÔbwþŽB—æ",ßĪÚίSI¤¯k Ca!ËS¦Šäë”JΧëŸþko†í6B±Ë{ÌKéÞ*ÒmØ# û—ça¼O M‹#‰ ® ü™œnÀtW¶Ú%±”™IO/ìc"uZe¦Þ­£[E {¼ Œ!ßó{Ü÷ÚÈOæ»CªzEgðp>.÷‡‘–€yE=‚¥¶é–04—Ô!»Ze+»Z|ÛE>¸vü•[’ƒpn‹ÓÅq}“øÜ/X~¹ú??V¸Ýendstream endobj 101 0 obj 3955 endobj 105 0 obj <> endobj 107 0 obj <> stream xœÕZKãÆÞSãCι >‹Ó_ȶc;ãø2®ÄÙaLQ³¤äõú×§úUݤ(ín#Ä ª§Y]õÕW_U“TtEÜÿâ7»«—W/WÔ?KÿÙìVŸÞ]Ý|OÕŠÒÊJÉVwWáèÊꊭ´"•R«»ÝÕõWûîþuEYek?3kteÌ L“3.¦ŸÞ^ÝÜ~½: ÇæêæÇ½ºù›û¿O¿ý þsûùêÙÕ·~«w <¼§ÒÍEÅBìﯗ¼,*)s¬ÎyX ¢½‡ !2@ä—â»D¥zôÙÒÝ?—ж KÌþìÁHݳzÿÁ’¥¡©YñJ€¥Ü/eKfꊳպ\öl!Si°ƒW2¹ëþšV<™2=åšiVqm¾¬—ñ+­µ¿èÙ©- þ©æXyv‚ÕzéàSϾí¡M%‰µªŒÇIP‡ð= À=€u/‹4àF–iÀ9 @0ÌóßHƒ™'bÀ{ Æ+íŒc> c)Ê] DE´µ&ã‚V®‹¾µc³"e„°³04kàõ¢D@ÔZ€¨˜ÊŠýðä©E4Iá@²Vê?$k¦ž/FT–r™¼LÖ  äÿœ¬!¢$kËY+E]@G²¶‡(I*nÞš¬Ÿ/3›”\Ši‚_"àsq²”Ú3”?;Å„ò߬]$€…§Iwz$á³s]®ñK,ñÉ(¹c1ŒZ„wõ@Ì ËGm1³dæMÝ÷{ÿœ]4äEûst­‘&=lâ1ˆfúÜÉvMÝ·ý‹‡cç9ÂÅЀ¡ÝOöh" M1úD©œ`"„„€’)XèÝ-¤¦sìúh)`p&Ø$‚nJÂÑþÄÒŠø Á¤'¨²7Ý>p´›p’ÖŒ!¡²bònèsÆG‘³JqÌW)%çeÓ1»eÉŸ„:€­Á£µ6jAÀÌŠ2T–Ì' úÓãxàm$þTµ€Ç“Y3ýéŒÚ”™fˆgyQ ïœ» ?›ž}NP‘5“hû|e¦ÎÐlö»]ÓoŸEÚ I ŠË¢–N±v$ìÖ­¹#nñÏ‹ÕdÙWž0‘/¥B¬ÇRagX? ²­‡¶~Þ51W9¦à Ì%A˜œk`{>¢Óæq!¹c“jšÆBÁpŠ"Ã¥r‘B¤§}ÓDÏ‚‚ 93^\WÁQÂî‡m s·gl’Vkn º{B=pœ«Ä{Áð:ÓL”8„Z-…ÉMœOÅ$]àÒOÃ~ý CWÿDë Éò+†¨7׳cÿô˜jD;^í¦î"p¥ø…àwÇ&ÔÚ02 JLBÃÍ„ë`ߌ?¦€9)È'ƒ\>¡îŒõæ°T¨xE2æ®íÛ]´ zÚû¸K¢GÛÇÇzŒñ~¼0Ãh‚Y°Ž#•<¤Á†++ýqLþ§NŠN8vü0 côIØu{—“’;)ž¢›3gÍ•‹*¨>†S¡åçr O2„èÐìB\Lˆ…Ò³Mõ7C9JP"Üp„íé[÷ãØQ|™Ò+mŸ´5E `ÞA9St–w òÃr¶ð®fp2)úzý¼küsž;¢¡Y?ÅE‰¥8'§] ':ßZäVEfU^÷uÉXžK賘-UÙ«öáôL ¸kÂÔ$ú>¯ÖJujÎPh쾌õ˜ârœ|Ž™c¬J¹¼mÇͲ4šU*Y­€qñx(çËŽÒäd‘ëÜœ¯ x,`šºÒ˜°«£DaY“½âÅÈøÐBIüÜF!_£æ~8ö×Ý:#BÐ+çGê4ä' k0付"ÒÊlù!(Jðc¥0Ù60Õ[ ðÒèH‰8„«ÓzÖ7ðrvt>uQJîïÇú¡y?ÒEN·ÔºÞ [Â…Žƒ"±Ç¨‘KÍ+,œØµ%ßûIw›R¸îº1UG‰ˆ …аP{ü$â´ö.ù©áÖLÆ®‰¡h>vR""Ÿªñrš›²6´A*P*²Õ—çW´jòì\ ¬3II Ôø:ŠiÃO"¥‹ëÒáÙ="RlhËæ‹æÓ¼Ú,êÛ¡y ò²HB-‚Nr}yêL¨FªruÓ卵d:Ù),Ì"´pº<¶;Ęq‘È"b¦WBñ¶Pøˆ(*ÃIAš©ì¢FNÚí Åf8Ôx „,Ã3 íøS„>“'²L‚q:|&M†Çs·mTŸàKc¸:ñÀEô™mÒºÑnúiÛŒí€=’’¨‹"´ n`%|ÏçÉlú:PÀ™“¯V±ük“BtÛG‰<“ÅôcBÆY™8Ñ(]Üuá©ΘŽëÜ@8*ý€„ïtó<Ý'ïiûûáØô›&zLrUàoLÓCñ/¶ÑÅc*LˆÂK8 Rv6˜ÄN0ô[ʈ+aXF6 xÆXP§µ„•E‘ÿuÿKƒk7K.òãþzl‚«™8’»¨( sawá¢ð|¯ÛMä`WÔXþÔÐsY{šæo à&ê bÊ¥§È\ õSæ®\Ñœí{²>R’t_YêÉãÜÎÍá¹d¼Òc8 ^ÂüâÁ6Ç!½äl. ¯š®©ÇÐ^_9NZÃv9È MŠ»ËAVà31w®# tîùºÃ Ðöã!üµO•Lmë”#‚)ØÞÙ64 ——ã3·ø)Aûkž¥Si˜/uª³Ÿ§òô<‘`yzÚ¤¡4ØÓ6]º‚¶!†"ØC,ã`Á}ùd°/ð×ý5‰ªÒ×W»fÛ†ùˆ]^;‡ló•ØžNçUþcû"WUÜ_3ÜAkÜá¢{dù^s˜æ×Þ<Ôqâ.€åæ@Jÿ‹ûKþ¢ÏZhÀ0|Ê9Åš´y½éâõ·ÆmŠë9<>rûvëc'«bˆëx¹)lÑR¶€Xw©´ ˆ"fŠlî«e¥Š qä)¢Š‘ÝêÅJ>uGÔ y´ºtK0¢â¢†É¯AŽò%¨ŽXysH±o­¢juñÉ=Ó?}"¹ïÿh.ÍÇ&Šen&È숳.Ékž À«ˆ=  Îü±m7@c$V®Ä ‘öwÀo®”l– ×W 2fƒ}×@ä`”ómçÛÍfßïwñPjG"é§Iߢ¡E›ô-GÙ¤ŠaõÂ{Ë @QÒ›¡YD)„÷ ~—ÇÊ+(-cä[HØdDnk&BYاʬÒ0E矟2¸yþ>ìWЕcí¾pÅÉNÉFÕÉ8¼”åþ¡ˆÊÚ}šbUyOs¨½\wCuDgp“ŸPêÉEë´yíö!±ýÀ5GÚ]N–Yƒ5é;›cW‡N¨Oä{ù|@ŸÊ—.yô¢”“,±Ù5¤KOÄVê8Ü´˜ŽÕ渰¡é&&«§½v1bÎÓÔ×ÑÐB^‡^¥‰Ç"7-pp·!sCåê+ Â{þ=˜}†¿'°•!褿÷ÑÀŒ¿ÙØãhª fùê¡ß†a¸»>ÀÊqæ–%– ˆQú{–”Hg¹¿º—r›/¶ Ætm +P¤FrT~[wÁ³Œš|’P~íq¡c›}`±)V@G6Ï<.M’\Žå¢X2-´BütB ˆÏ'DnB²0!¢®Ibì:¯‰ Ïšx< !^˜=ÒýÒÍlJ×jiY%Å5!½>ŽšLe†À‹kh6fu†÷-_­…1·t?øOù¾»ú7™~³Bendstream endobj 108 0 obj 3774 endobj 109 0 obj <> endobj 111 0 obj <> stream xœµ[KÜ6ÎyâÃ6rr·†oŠ^ägìb$ÞYds‘»53ÚtKޤ¶3ùõ[|©G·$‹1 «)²ê«¯¾ª¢IA7Äþþܯ~½úuCݳøÇî¸yu{uý†ª ¥…‘’mnï¯üèÆè‚m´"…R›ÛãÕó¦ýêö¿W¦àÞ„7n÷WÏǺÝ×{ûœ—…¢F„ç÷]oÒ² „LJ»j¨û˜™Bø˜üá±îk·„(à).ýè2RðRó¸î©ÝMçv"¼ßnÜÂöFèð¬~ïžÙÐ2<«§jô;´(…ŠáOGya¨‰‹VþÀF|ÔׇjlÜœ\Ѹ³úðN\2°§8?.]{ư4'xü·öìš…V¶ÊBK¦’£»Ó!ÚY °)Kökª·ÞV\†Éxü¯Ã)ã®n¼ODÁ4¾Ví÷ "@‚•¸F×ÜëÒ:,>Üuí0VmD(¡qѬÀLÄÀP»#oÀ@*êÌocáqý†OC…J£q~hÿ5öpê‡'ÿî4¬ ah!·£…Pè„óÆ5†©ø•;y¡áQÜ÷cÕ>L“BPªÓûæ}³?eÜ–X²Tlú9JÑXO!^ˆ2t…T ÀNCÝ¿p5Ø:®W·ŒñP« ´éÓ¸æ18Ž¿b‰a xQÖ݇gœ”‚ À¿Š8ÙòâHåñ´{Ú<qçkƒ& ke~ýØðußôt!J-óÐWû¦ö ÔÖÑqcá‘ÂÄvÆ )[*KxKlˆa»´!b4!ñƒ?wÀâ®òÈW”DQ4\Œü90·Ô† ØxÙ- ™P h°`"E›ß¼þ÷ÍíÚjp@^JtÃÌ)%Òòi@@Z –œ&X9³²,¾=vnàz%¢“žµþ=YP³@*l%yéîîmsMÐQõ0~~>Š^vœîÈ’Æ%!YŒPH5šNñ_'å$U€d|)p €†0üFþËh"dëÁ…”²ô%â*Hû Ö„']>œÈóDÙŽqôþ~Ö"k(…߬†ÀºZ ÅÇÇn¨ÑŒ}‚ÍLšëtfÈÁÄlR›¶96¿»IÀ6Iü^ÆX}ðyvZÊ2>ôafñ¢ª‘ ^'9`…)$ǃ~ÿíë5TCZ U…Ï–šš2Zâ6 Ïò ïC³ƒ÷ Í¡ÀX9'VÐ3’GƒMen©Ê ÇENÇÜ`U„l¬Â õØõÑ¥T££ê˜3Æ'€€”Ñ/–ÇN;& w<böS° Tæ gt§ÈU’5Ýïõ­'‘0‘šà·œ¶â?þ²îǪiÇU$`§´ÔSïAæ¦ólëíÄÊxµš"^œê_mõkÜï9Âræ†úCP4Tw?†”m)OƘ†(TÊjçÔu‹\ÿŒhäô44»fðrò!°½ìÈp2ûþD¼Lʽê"9ÁÜš bÉ>‹Ê¾ ‚ ¾. Ê”A¢(¢~樟¿iŒ˜<ºøø.¸S›ŒŽ‚&‡0„¤†®÷Øs-³¨½¯«ñÈ Ê†e®üP…ÿ í"!*æÚ$ŠF/ÕØ•%ÂiÆð¦JÙµû¼…춇²à} ,!“Êï½j„ƒªã÷ƒò!oÈÙÝañ‘:“H î“DªÚêð䳨°äf ª©˜WŒ¥šUŒA§lráȵ¶ußô5°—1Qªt5ÑBžIŠítMàý2»µÄ K¾ã;_BUm [ž&¾{¨mRyÖ€Ãæ›äzœ¥Õl(|º j1Gy@Oʽ¶†mw¿}æ@Y þy¶¯Û]l!RñPÇò Ôˆ-#$l¥Êlàa1 '(B”I…~ͨœ,ê&ð)'ÚÀÑ"Yÿ—¶ )š$¢QYB¾Ã ¿œ•ZéK¥:/Õ 5–l–Ýá1 <6Ãj®(-AÆ-œÉ@[”¡¾8ÖUëaAI’°Ž‘ç3ê0tž‚ˆm4ª >™eyò\PQG©¥„ µ2IþõY•jH5P¦%y¿–Ðç¡Êh-”@u+6ÉIºÎü®K6Ÿ:@ý™F? þrüÀªÉò(¬ÝL7ÖP';蚌³Î·©Õ=ÙP§‹¸”ø± •™@4¹TÏ„M?Õ.P M}/×÷Œ QˆËXGßg²Ú¡-pšÔhµóó“´Cצö.xwçÌø¥G°m!¢}%2‹ôº?ÆÑçjbdÙM›Â%»N%™öS°K#Òs»®Ý:»¶¬ZS–yK&øR&ô^n!ódöá±;ö1é>sÐÊ|­ÔLa2¬béqµºì^7ÆŠôŒiƒk I]–6Å;Wi1Ÿ†-ÄÕt“UÅ `>Ù@5j<Ÿ†ÝÄ2 ›žŸ÷p6?ïa™8bm6¿:Ýw“!gyH- kFm†_O•×û\Zbƒåì »|à¥^êF­á"°·3۸‡Pj°ÒNL1”ØÓòŠðEY5;qài[G&¤{TÎð’„gnkÃ2ËQó –iƒ¬€¥Tãd]j[J#m­¦ÜWý~»¯ß7˜Á)*“*Y²‘' ŸV€¢Ù²ábZ‹ŽÕl=YHn›%Ö×ã©÷Þ„ºÆàlûrAjȬ µf sZœó½Õd^€~ 78µøöõ+¨~^¾<½»{î±õC¥¢±6=×z "M.êÞƒÌ<'’lÏxN\~ÏÙÙK´zèÑM‹×úC€½\;·ÆÀB”'ˆÁÀ&$úžajòÁÑ96ó'iØÄ6tqõ*HùL¦·õ^Ô,@ñÚC½=tÛCóK‹Lˤƛ0ó±Ãx¶RÄMì}Yx“\×L&Tå2LØ"LˆU28cº‘P0aD^Êœ 5SÜǪš/†š {ééˆZ"Ò±=iRÇ:Å/¸'ø£€æ $ä/¤,B^ç:gÀË馹Iå|¢in²ú²Ut>—9ÌH •&óX&3ø˜'’É1‘€@ø£‰ÄRdJ$~£´Å…Õºs@µ¹Mºï˜:([¤Ž%ìRýY"x²ÏŒ/5ÈoäË ¢ ¸D¿ŽM-ñ׿‹ˆ”TÔ×ãÎã6Z€æ­€×ïîCÚ$iŸ«4¥,¸Yi ”jEl2±U ‘A$'I{§;š’³¿bÖ%›ÏÚ@oèùDu’Æ‚ž¶3pT¢mDL¹hRù½ÃÓäÍŽÊ#09™^ç±mÏðÀ7{`9MÓ„|å“»öjSBpý[ŒPBSh4ÇМ·sT£÷£ètc§«A+#Ä%÷Î[ b>Ò‹ß\i [ºY¶„§bÂÞI}Éw}·rå£ë-„q®.gSÓM2Åj.„|꯸5  #ˆÔ†Z)¸ý/]6 DOz=+½ÌÜœ‹¹È‡ˆMÍÍÑÆÄ}¸D¹žã7mƒzr'W#q¶Å³è–¿ˆ¬CSµ¡mËí-¢•øSÏðì.n÷ÖZ/”=ö¾|jõ'Ù,eRBÈÉ 6œú: VÙpÅñÛi¶19JýÛ›…$·—ØÄQ3¥¸ uŸí5P$šõžf[ºHWInâØ‘Ryz»îxÄ+G\§ž’jÂ.œ)²ÞÂ8€ýÆ­O÷Î.[îoçd¸|6®^Sƒƒ1þÑ®(+X9WÊv¸·zùÒ¶JyÛf·9YÞä)RWºìtÍ˵œ¹µ÷{…R ó'ÿ›±$]M( ã¶|z²µS À–ý„w}PØj#ôóUµ¯¤ÊÓ mÆØ±ù:ü  íº¡Ù±“}/^' brdÈÓö®D¡ÜKÿY_¬€£ØÛ%ÞƒkŠQ#š¿¦k'Dª+7Ž—Œ"íPј¿¾áïoܯ›†è„‰O±ðo«ÇSö.eá¢Ì8]ˆÛ:ì&¾ôwG•ö*6S>ÕóA¢vé"¼òÙÚÇí}…iø¸î$û¯9@¹Í1×|PûÅ7p;WÚ±!ðÍ3|DZ¦’… ¯0ׄBÓF÷8÷ÿ7×ädà‰½ƒ.ÝTó‹õ°„-ˆb•S+m!دžây~­LY 4^²¹{”å 2 2<У½µVN¥è6 ²)JÓU„¸«ÆäGºèS;ÉE‹:¿g'Õ 2²ÂÛ¨! ØT‚Iྯc½VRÌLéÖ·[ÛöpÅ%É…/X#ÕõÏÆ±ÞÇ«‹Dao,õ$iif*qáöÉI¿8µ¥àN \»²7ƒAYÇ—Bš¶ã<®Õ%û^yMH”°4Ч$ÀQ}¾P,?]ý- Ünendstream endobj 112 0 obj 4140 endobj 116 0 obj <> endobj 118 0 obj <> stream xœ­[KsÇΙÖ?ÈG©Š\ÍûáøÛrăœØfÊ^VÀ’ÜÀÒ»€(ýûô¼zf%Û•ªÈµìÌô|ýõ×=½¤¢+âþÿ]ï.~¿ø}Eý³ôÏz·úöæâõÏT­(­¬”lusw~@WVWl¥©”ZÝì.^¶ûW7ÿ» ¢’ÔJq³¹xyxhÜCF*£4Ûý¦ýÐnŽõÖýMÊJküÛ®©‡cßìÿ2Å*¡•H/ܳ×?K2Zލ¨°&ý> ¡T®te5¡Ô!30æŠV&,!mŒW¬҈Êo†TÚ⻯ïü3·&¡ó¿E[„uÄÇÇýºéu0‰Ð•"‚¦_´ßƒ÷0–ö]÷ÉP\ëd½}wði%PñáoûÎ/ÃTÄš´´§ý¥É+*Yš©ÞoâCÅìd¢+ûÔ™DTÂÿehwÛO~/ðnÆÒ^¶ÍÝ!®Í™žvÇ´6Æpm]°¯,1s(†Ç¼®·ëã¶>´]X¸âQ6ÿÂÛéŠ}î5/ü¨t'’Ö°«ã3ØAZçx˜JÙdœáÐn·ÑN+­¸,°Âñ.$±²=,x9×t|Š0ÓüÝq£ùûf8n°kr >¦ÒøÇº¯wÍ¡éý¬ª²Øô}×Þ¿­ -þáöå¿÷€¢R’óósoqë¬â ͶÎ)ӣ㋙A§ sg¨Â6íWM@Èu%¹FhºG¦R\;Ý©ŸèP0‘vôÔüÒU•)¬ö÷Cóæ›õ!ºµa$=÷/¡ýë®ïvÁÃø…‡e:§bJ碲éü)Ñ4«ˆf_„Î?tšAÍs§9v•Å­ `+ÿÔº€NŸ?e_rÊUñ¤rŤ¨g_AvéP±Hµ ’inâšá¥\Ðòý)òÊšl¶éÛKKºþr ¼ÝÆùÒ‹á )ë]ø1@,g!EM¦Ð¯üïõÍ¢&ƒó3Hs} DPž ²n†!ÂïõÏ|lUSq™öüîú_?ÿóû¥I„‹×…o_ÆWÇTRfÔ¼Û¿kïûz³ô6ˆþ2ǘK„ªIèšÄGš ÕCÄ êôˆD¢LÄš@‘òöÍ/¿¼‰‡*¬eÏ/…â»ý[0W³h‚¡ï× ,ËßѲ9.[DæŒ Q8ûø-¨œ~Dû) ‘&`æÜYnŽëL¼Ù~¤r6ÐS°2 u£Å¬A\€K4úÍC;ÌDe†6 … $Ì02¥9dùw‚A„Íá=®V9'Ÿ+UnŠœ'ð—V¦Ÿd„* ’ÿXQVCœ™Ëj˜…ÍösÅ-wyU©!Q×Q¯šu PãѦ郸Ái¹Âì!J.ˆ‚òt”AD‹AšORÑdõÇ^ê ´Ôßý¸„N§Ñ2½^F¥5˜öõ~¸ÀE"ÚξMR”àcŽº÷”.!p1ªN ßE½@IÖb!îC+ ¸r4ɺ‹rƒ·ë7íM8JÊQgοëu´!¥âÈïƒdŽ.ÜP¶è¿óª¹GÓÌ=™OÀ:è4óÝ:ð¸mƒ-…Ij" §AqÊ;cÉóCøã’ï~ü¶š¯¿>>Þ¾ 1q0‹Æ8T…3—Ån Úô œysE‰ˆ‡‘(Ñ9Ó~“Àƒ>ÌÊo?WƒY!)….v:–aj|.˜1†&nú«˜~À™Z !2@žÑ\ÙÈ\¥±¡¸«‹ìH‘›dª,†êõº;†ŒüTŒi ÀFsFÓ¥:‡Îùߢ\^”gtâºëCÚÖ퇀M ä‚ÙRJ”I¥ç‰2)ÃDžXäŒpß􍮩ûÖÕXªàfÒ%‡¶¤Á›‡ú¥™ÍÒ¬ +‚ B–Žª< Xˆ1œ0;ž}\ÔÊñò`1‰G‘_5ÃS«·Ý> Ö纬ÄU» â–2›°?.m8ÕÏ“I8_™Uà]\úÀÙšõîqëW-qKE'èN¬ ï¼_g¨ckA!û÷‹žcÉíc³>&ƒÃŸˆ¦ãªËT„*Ì>g»‘H°ýuç‹/ÊU«h¦â:„wP;™ûSq‰ºjeUeLþšDOD•?ieŸ%ç¢i?Gy©ð5ÿ…_ìÔ+|Ü(dhTýû¼}ÁCN0*¥=­îø:¦tî„G:- òÅ"$" Iè±jÌ)]‹±""ßŊ쀧ÓõÒ>'øóɨӔ˜Œ¦²’u2b™Æeêá÷c ¡›æReÌ€`ùä»Cb–S/L´YH$Á™6m}ß%AªÜJÖݦ;ˆ7’£‡Ù‚ó2[Ê+æŒI”pÅ«¥œ r4ð«,Ïüh ˆÁ ®Ó¦•Be¼T›îÛz‚‚󬃢»¸º€˜FdH‡sD.Õ†x˜iÑëXO•““õSu¥PNV‹ˆ¤DºË\C’ÛÞ^‡‡.*¶‚øŸÒ+©ÄZ-Ĭ%÷‘VÑR1`¶u¼“™±¥óÍ|”“µ™ýFXê†CßÔ»1¤Åû™@,^éx•­ñj¾á ñ·,_ž`¥ð²I™ þK#móÍÒv]­„c"SyêjŠ_XæÝvõ¦Ùx\KwY†&L¸îò=¬½ToæÂΡµ_¼v©¨g×.KY~`R9òÏRpêEµ’ÕFÆ»ŸƒwjÑ;'bXÅÆqˆµâÙ©SGj9&½IÖ™“ £ b^_æxOí:®Ü‘Xà!ž*d]:»Õq›JL!õ¥ÔD™± :kzgVìüq>ªÚXqi91jòë‚'°è`tYŠÇUª¬–2B¦µ(·U±°.ýܺ@û¾Ø·¡ê A7!2o“Na¼Y?.abÛEhZ‚%ä§èÈÝf‰šà0'å¹…‚ ÏvÓ°ÏfÎϸ4@WשÄhVÎê¶Ýµ‡MUA ±¤îÊ·¹*¡‰Qæ>^ŠÊHdÇ%ÅÒõ´L£gW³2çs€Œ¨ÂB¤¿âë3kJÒÃV,]å¹çX¸èZû|.“—6Vs|î1¿ºenO¹!±hâÌ‚6 ÖïÚ2tï‡zJLAâÆw&Íå² üùŸÝöØ­ÒŽÂÄI®Øæz+$Ê‘·©¡)zæ‚£ù¡c * °ZЕp€š?§H¦ÑURíÎ-Œ‹Œëò"‰ßvdÆ,mĸÑ-ˆï—H+7I×{‹°Ñ.¥™&$â•É…Ô¦G°›Æ\h4v,—g‡åð\5M™uJQ5b£ô»‹¬Êrmv\ŸÔáÓ‡xOâÛÕ$6™„½=ý NeY-¢»^.<þ”&,_{·5ÈÝTê1¨”n ŽaÉ»o „òâþ9uðE•Isý±vE¢!1¾Ê÷dñ#!ÈaynDž˜†U¤0MŠíܵè'„øTvøGš Ð>wÁ‡% Ö–ëôïÎÝÍĘÚ当ÌÀ¢ga²Ë`dâª^¢$äÒašÙaIZœÅ]Éø¾ë]á9Š{p8üpÇ…âuüøËºî°iWƒ*/QsÈ¢¹IÚ}âP-*Wã~ Û#îNÂÕ(~ºø?pžá,endstream endobj 119 0 obj 4437 endobj 123 0 obj <> endobj 125 0 obj <> stream xœ¥[K“Û6¾{ý#æèÔF ÞWí!ñ>ʇØïä6ZÃñp#Q)Å™üúm€@ !œ-\Å¡€F£ûë¯$ ½!î_ø»ñë‹_o¨ÿÛîo~¸}ñÝÁo(m¬”ìæöáÅüzcuÃn´"R7·û¯h#þÍíáœä?´¡’IøÑíý‹W?¾}÷þ?ókåº\6”H^ëÆñ0Nó{Tåïm´j˜ÔöfÃl#üË·{“‰Æ0aãFó™†ã4–Xê…qµ o¼}÷óÛÛÚ\5‚¡(ŸÇƒ{‰Ây•ˆ¿ÝvÓtkÇ墑ŒÐõq{€¶îq÷*,U¼+Iaq©áÇ~8Tu"$l£lߺWLC¸5,<š:¯!j)H|êºû&(ŽQ¡Ãã/ñçLÆ7[¿+u7„úµ|l?îžÜ_„m´bñ/Çp¤1Jóððå8½`Ì4œˆø¸îýCÞHbãÃ}¶cÌF»ñûl£»„ áî§c¿Ûù%(Ü>.ñÑ=RáVÅsuó¹À•(%µPƒ’†ùP ¿æ¦Pªj¸´&þúS7tc» *06&îå Ý™lÔÊoøˆÆmûhЋ&Ètûil÷~]Ùh\ã8["wŒÏ¶ín{ÚµG¿ŒÐ¦,žäs ‹tÇÎÛ©Î øÊ¿8k˜ÀŸÛ_úá“.BxT?¸gÖ_êBšÏàÜdwÒn·‡“ÿ8ƒhYÇù¬Eá+×t8>†ëd Ý­<‰r†%ÞƱƒó÷‡ÁŸG)q!VöE…‡Ã°ÙõC׎ý±ï¦Æ‹EáþdÜ/ ÊÒ·ÁQ„JsÁ·—P,,D\Òh7þ Rk…iwSP4ÝQ¯h·‘ûÓ]k]Þ¼¤8ºO°Uo#€ÇÔtíéiªû­7qíÜ]9©O±çÝT@âÕ9 &šá£ß?û‡à˜„¢Ê†©÷Š` I@–ÅÏ9eªô'ËÚ#ü$\=e¸Ä4o§Ñã»mݘ놠ñôáTŠtÇnÖùF¸qªs»e9ÞF;_³(ˆBïÇQ$Aç8< o›øÛ‡qÆmÆA\Ðf{'pÁÆÀšíæÀJh:´Ãï]1FHÅ~ §Ö… à¥S4êÆ§pV“î79VSsŸ SàNeàÝš=ãDŒ hÛáÔVH P%©ó 3§r´²1$ø ø!@ Ó~ËëÆûtkÆw³qçï܇‹¦VEçÚ÷C¿ K8^ëiÜÚxqsŒ…f,£Ý]{?LjF=¡æ[Ý€  ý ßÐ\1½DE8ÏÊJ@,•Â6‚˜;o·™¹ï[@߃×P….’ŽBå¼Ä°¡%ï9øî,¶„xfiTçÃü‚l,M  OqÞȸCý5RëF™L[íîišÝB€4žôKâŒ3Š^0î3ZÀœ>v»CøÈ”¨±<8JóãÛ}øþïUŠÌ-ø‰2y¤ð¦Øÿáã¤wN ”Éx’sô#®xÂ]-౤Ƈù! žb\äç„»‚sa¨š¡D7ÒÄ­ƒ©€Ì’!1/HÌCb·ˆa÷ÝË¡»¾D”@wŸÂv„-­Ê›&ZÑÖÿ ’¡ƒ?¶Ã§™¿Qêx3!”S^ÊésuæxWÔr¨ÔK›€ï<©†t~Eª—gQà;WœE#ij ã¢+:ýæã³E“ƒÑrØð¬ ±F‰úuú:fº¤Ô•0W”z!k§¡ýE8]‰g\kÊçê¼’®µmîm,p-ãÞ‡ñ¾C˜¶l%¦Jë~öæØeÉy\5~ÕrÅu“—Mñ(º÷§ÙÀ8<·ÈR°´íþÐNÇ@+`;Ê‹r~ôamRŸ­ÆÛ¦BÆ·5es ÁÆ7¯¬®ÆLß%0,éî+x{Q Ä,‚´ãtYç°»ïg›‚ˆ‰üºy%4•PTË="!ð¸ê&ùE¤u¶…ôãZà¼v#~¦v3ö‡ÓØMŒs:}Üxg÷%/%šk*2?Ðsúc8KYV Á¹uª%‡[³ŒÅy¶xM)Go1ªÂ*¬Åßb‹‰Êe…ËgÞ©fv8SìpfU# øv•'Â*ñ´X†”0Ò jí©5ç ýB ®$7; µÇ`Ï2«…cY¬NX.PöQˆ]÷Q²¤k„F“3L˜æ¦I¬ÔsYë™-½ÅŽ'0P¸R³’av®¯,äfåm°’u_oÑY×v¦ƒn¸zöçºßÛí< †G5ŒÝ¯§~ )†$ð‘g;P`."AãC÷%H, OŽãú?N]>˜H—Úbwõ}l›V1e•3^©Yr¶Øbá®®¯(Ç^&)PT}$· D«N\áðI¨š ˆ™,ØÜ R?ÎÿJÀlóîUßtM5†€+P\ý*6’Ò4Gò0ï IK%‹‡ñ°ÈMÒÄÈŒW®*£¿žÚ{wi%lÆ1³}8 ÛX"…±uþ­RÑω:p•2Âî¾™Q n]; ¸Ü¶ŸºhÒ€Kä º¦þxjQR× âfa+ÕCÆaÐ\® ߈4Òt÷¡2fÜpÀ¹¹+  Þ"wr»ë%w*ØH?òÄaP´ÀøVÕ€ÎÀP/RÛÙ»aj1šÈåŒ`‰týñ›[Í¿íÆÎDM“åØÙ›÷ïnßÿü¡:y&]Ñ;I¶;XåX4Ö,Àq¥sœ=ûÆÌ@ò¶‡¿>VH4öÐ ã"5Èž£ Êàu¡L’JápEÁR!1ø> ©M¹Tey$pT@ó¨Ê»(*,@’ü¿õÑ2©Úñià¤z5ümwí2Ó²z¹ ˜/6}‡7±‚Ç ˜K18st¼¤ŠkàÑék(¢Ñ,—Œ£tÀ\óQ:‹½¶¤q|—²û?¦ñD›j½Û›Ãâ;šN*ÿ*p¥äž©'îŵsËÞ×R1å`ŽWŒWÀë×ó°„6_%:`;»¾×æ†çZ p„T§FìÔ ;vÆ‹$ø«&å ”»•Kó)hBÒn,œŒgÄ<дB_}ȯÜ/šàc8>ÍÈ+\->a]̼À…ÆWëËí/)és垂󞋮€Ï•öx<»6W—«öWAëS¥T¯jCå‰ÏVJg„…Æ¢Lo¸R&eU#rsÄøJ™ m¸-sbsg³}Do˜g„ʼç)ø%h„( ¿oSþ‚„é±z:ºÒhàF%Þû©ÊÏg‹:Ä ¦û®¦ÚËmµ·ì—“$÷¬) òðd¼ÙK…@N0=3‘ ‘!OÅ,Ú°JO¥,ÓÇö€¯Ö¸1ðt?Ù<&‡ÈÃì°Š1 c q{}•úršoÒb-W6¦ñ§ËÕ«¹:NÄ%¹CõC¡è€ž>„é%áïjÙBc® ‰ó/XŸq¯kX€ƒ±4И*‰2Zr®xa´å(iê4€_cEà4ÅVqÑ«‘+ û×Ɔvwøê$È–¢fVŸr¹¦zžA“|ò« &˜Mwß½zû°ÎÐߋ⇮=Æs‚M)~)/æéOÛhɵ¡û šEËÚiÕ2B,Lí´ªƒä–Äy²Ü æ¿GýÈd1Òˆ”»7Y3ùåï3•ñI ½äbÀ^ãØ&È ]óêU®üíæUÖÍÇšÈmø²³`SÿYdV’fI}ìkw­¹«9©>±jQo]Ì(m!‡Ü…X" æqÛC°np,ò¸~ž8¦ø¿@õÅìXe¿Z¹¹m¤là SÖiG7oê‘&×uôlŸ³üwþH.‡£{M§þM@æKScv)®Àì&Ïàü¨†RÅ„UbS²ü`Ãõšp ql??öÛyè„dXS‡CÂê]à”ã‚,Å,ú¹á´‚?†Ðæ@Óò]ߥYú¯E2>ÿï0Q^û‰Û"™qÀ$Kßi“%36&Hjój“ìåsqe‹Ì\¢]0‰LåÂôçFø~¡^—y!ýÊÒ¥ÀtüG HO×6Ûyø˜»{•©Î_¾ô!Ûp3'ë\žÄßFÏ*3÷Y ñ¬Ñ7wq÷q¸Ö¢Ï†4’ǪËòlÙ3Mʽ1 q)28ÍóKé ¹go·‹mt0¤‚?lû},…BŽšø~â=G/~’°ëâÝS.ÞíPbVžbÙÌ-?Y8×Ì\^ÕÌu.6¦©8þšÆôü‘ËuÓäwjLóecZY<ï™Õ]±—ª}¶QÉꌟ¾nÆny9ã· •þË‘kÿk‡7\¹áèâó¾ç†þ¸® ýXëÚ{‰W¿rÀ™¿‚Ê;>á ?%K£}$„!ÑÎnŸ…)€¯®&Ìñ[Ñ4˜QßÚüN€WÃ/~î8†-˜^åv61ä¯ øþ³Tfe ) J³áçý¡s ÃW¾™á Ú³LÔ¹6õÀj°…çîÂf}“jq13yfüÓÕ½%Yù]&'#á‚Ý*©&ÿý`š0UdRåá7±ê>µD[¾?….Z¥‹a;¾öLÁVgâ¥eúrÙ*¬Êõ’­V>¼ÉR³é׆— –KçXþeã^üÇíÍO/~zñ?Q¿6endstream endobj 126 0 obj 4464 endobj 130 0 obj <> endobj 132 0 obj <> stream xœ¥UËnÓPÝû+¼L¥vzßubÁ¢@!ì²1Émš*±SÛ¡åïßWÒÔPÊÂÑñd眙 %>ñ¹ØÅCI=–‹mùvV\~¡ª¤¬”¬œÝá´´X©¥ÊÙ¶˜¸¶mÚîlv_p’1ŽQ³e1inŒ ÐÂȈõwn¡t ìHµÂ²=™LPã³Q`ÊÚíª¶ÚºÞ…êŠ‚Q"…¯kŸ ?ì]ׯ›ú|@%–DÇWݺ^ø®8b­9´ÚkZ‘ઠ0R§ì÷ûÎÁÎeÆfMm¹§¾u[ÿBH°T¥;?nS_M³™@?ê… 4ååÒ+ŽÙæ`É ¶Q*–Ù^4!­*˜H‘;õ¡ŒÍÅæ“} aN{žöò æ,£E.s]¿kê!m7.·ùægá·'Þb(IuQÓ;/7g@y&t@EŠÐ<2wÝ´K×Fáˆd4CÑ$É@+×G‚Õdí OVìU}¼:Ã|ÇòhóòhkUµg„ña'Ä‹¤’ä¤Mí|_L°údAÇzBmɉ¶G=^øøé똌x¬‘©•pæg0æÁAqMGÜÒx®µÁ÷Ù®­‚~Ɖ¤>:ê7vÒÃô)Êõû¶öó ´¨¦éE5Ö×…` QG«ÕõËéô‡[„„ÂÜ"Qцò[¸„RçÓóf¬Ì`wkÒø¾Â®Zg³ Xý‹lËfÿ}ãÎÃc,£R Mkuu5F!² Ñì§V‘‡[>Ÿ<ÿ ü3t»Òæå®¼r˼3pU°ûù ÏñjlF¼VK• óyÓôÉ,Râ0ÿnš£×›MØ`bAjqdƒ•«‡Ì.šo<6’Ãl&¬ÇC[àœ&tÕV»»õ¢‹)¨Ê^Üá41ž‘6(²†´ÎÛaÁéáÚâàv]Wˆ[ÎQÝ 5üIÿÞøûYySÜ¿ÍWäçendstream endobj 133 0 obj 743 endobj 134 0 obj <> endobj 136 0 obj <> stream xœ­YÛnÜF}×ú#FÄÓîû%oÙÍzP€2°À:4‡’¸á’cYÉϧšÝ]MÎP’c|iö¥ºêÔ©Ó%J؆úŸøw¹¿øýâ÷ ›ÆÒ_å~óïë‹×¿À™!œ)¹¹¾¹ ØÆÁÐÆhJ´Þ\ï/¾ä_]ÿÿ‚;B¹S0ázwñå•‚õv$Ž:6­·D(¦ã”ËŸÞ\^Çi‹c$#–Ã?ôºÆ¢iбîÚ0›Ë “DHÍýì­u„S°d+4qzZà óSaÀPjž4IIT›´ ~d€¶ìŸ:¦ŠX‚Ã0Eÿóõ×krMtÖMßí'÷Ã(çÉ N)ÿþ¯ü7e‰“.÷ÝqLødR,ƒF2›÷>¶¥ÏꢩǸp.¹ð!B—:j—X¢Ä8ÄRSô·Uó¹gŸ…¯ìö`ŽwÍt¼rD9L„ûz¼‹W֜겺¶Š©É9ÇÁ›(ªíInžù}±Û“)ø<§åù3Eµû¢Ý³! ¼¡x²ø}Xk$®­ú¼Jb† yüpS J#¸ŽCD¿`DËŒ àk棘ŽÚÕÿªÍ¢„Á 8¾@ Ç±À.œ›&UØh  &ÀF>zŠÇE0±pêlªÑ^È‘û¾§/RzÉŸFâ®(Bú³£"\ £˜ì ðžÿ¨|Š"Žv £P±z¼›ØØ“ó!ìI@SPê1l§Ü8o¨oÛúE‰E(‡ ¤œ¢ÝÅ|PÖ%7·Ý£b,–È쪇êóÓZˆ¬åç[ÌB¨[L"R÷uÛMÅø¶KÀþPVoÒðö« ÞÚ3ÆëÛᩃÍCúª0_‡cïi3OÞ!ÈñêE,ë‚΃âuB®IW—?þòíw«¹ IädBê]÷‡?‘¯‘Õ˜ãÉo]ªÃÌáU6.qb×îêöv lH!ì3`ƒ¤ƒÊ.ç%¯lŠ!ùà˜<û󪽪oûb·¶«ò·8óÕšuúÌ;nø‰ÈûÄÒ¬³Æ{ûjÇ>¼ŒXˆê˜W˜-[•Å>°(¸“›€É—A( '9¼cÕC¦Pî«ñ®K¹ tÞ¥t7-ˆÅæQ»rTBˆ&|™qiQ†V”ðÙŽ„šd—³sÙU99+£Žý!2ºª*¹‡2“F߀âm¸´Éò›b_7uÑGíg [¬Ç @ùI=>ãnH ùVTæ“o%CÓ½CI„¤_†BN‘¤>SšJ®ÔŠåÙcô¦*Æcà6ʦéQALý›ež® u Ä{ kÂ.X«¨Ã:ñîFœ’ŽÈÜ"± _yeºlפ·¡’ˆ‘t‰jÙMa“Ö–›­W2áÀßQw̺)—¡-39Âyê=á¿Om³Šu/%Á–!q €÷ŠÊ¾+»öæõ¾øm*Í@£Á_­ên}ãaÞ¦ù!TuÃGÿ%°ÌT{U Žd¹‹à‡`#ãtÎýÜgñŠ û,X»9·'í²O”-F¢!E@Ðk~u=¹ý#éŠü€}ÅÌŒOÛ5þdyÚÒó ñ¾ÞòÄIÛX}œê¨H6íf¤šö¼o›®@5"‰¥ìé–ÃâÑÇ?ßm ‘€´“ï¼6©ÌŠ© º ž¢ö8b¤ï¡%Óۮݾùéò¿Ó¶†P£ÓUM1‚Ëö“Ó÷¨ÍŸ=Þ>ÔûSï,ºJÊò½¹<7wΘüˆÎÙóHSóìLÎ"ApJ`|;5ÉB 6õ€¹ó+µ­|?±èƒ¼€d‡Jy¬CT˜³Žàì^ÏôJ¡z¤M‹¾úf2Aù§ ¿¶ 2üFPñ¢g‡éÄA”€–4O¹v–h ¯s(y†ƒÓ©ÆºTÂÓ5¦ŽDû‹ ÂÁó%t¢0QPÜ1tÐÀxÛ¬˜Háô4‘–¦ÏÉÊóAn §Ö(w 5Ô5žŠÂ¹íõ!R³c,w¾‰ .3yý¥ ´a×/R sÁΛB¦å¾íUÝëqûøŸìù³4×@!ÕtHüí€X5=ž O4™ã9 ‚H8ñ‰Ë@–ÎY¹KÜ’BåÎÕ‡÷7烧×[½›¬X¡ç‡Ê•»ùÔŠ'˜\×áž.¬ÎµãsÌR‚ÚÍhHçð|”*̦7x»i¾ì@|ïê¾*Ç®X÷4s@5Î>›r¯"2ÄÜ©¯W=*ÑÊËÌ£jÅ£ý1©tiN{ÜK§¼]òâäVè"å ”õCÙׇGàĨð¿+{Oäµ—=µß]ä˜0{æ*ý±×yÅ”ŽSŒM¸Ç´ßukñ÷: PoN<í¥¡;öe`U;"e¨ȧíªG> endobj 140 0 obj <> stream xœ­VKoãF ¾ûWÛ¶(4ž÷÷vÑžêC¶nïªç'§Ð¬`2Ë©A܇ëK¡ˆñT0 ö”Œ9Kèî!€ÎIÏ…F˜ ~ªoeû¶î8½­;cf‚]ïn°Çá¸Þ¶»qèúª¨×wc±ç?o‹ª “§!£O;¦X"iD–ì„ô‘»©ŽNCíÆáq<—Q¡£ýxßõÞÛ"šEŽê.èŒËD[ç9'i’Z¨«‡©/JµžK”2Ub·.3E¸Dr¸@¾.x[µcåkå aÂ#ûj?5&dÑq,K{<ƺ~q^eÁ©¾²kŸlÿ§õ*€\0AðåT£ê›åTºƒ·iʦ“í0¶åPu~,B &¨Š Šº>n–µ*2Âü±$(Ð5ì4]µU36þØcÊä›IžŠz´’÷¸¡6ÇfÞdãדÙ}³™6K™´Y¯™Ä˜[«v°}[ÔËêC<')-¢$žl ²ß,‘~ùáwïZ"=}ÑXÈÏ¡V$‰öó4Ýœ M±2Ђp1øœzp:NP3³öÀBaì OOWÔs)â³¹S œ/˜ÿÏÔ”ÝS›ß–ž ×SḙM1ôÕóE~~}i¶ÞëÏP:û ‚àÆaq.x/KáL&Á“åÚÐi`û“ )Œ)0Cth_«szÉ[,±Ùf¦”€±µÀæ§‚æÐl -/•M —*A;Éh>ƒž7ˆúrY.½ K8Ai>ž†œ/Œ3}\¸5öy@Ë÷ÛׯÑftŒla®Q b©IŠ^Ó¶™«‘þ¬DPž3„º+«R¨íû°óþ~§f§g:ÃC§f.ˆ\ŠtXŸÓÛãUôàŽh­`ÅøI´ù§]v·º[ý ’î|endstream endobj 141 0 obj 1012 endobj 142 0 obj <> endobj 144 0 obj <> stream xœ½W[ÓFîs~…*u‘šÉÜ/y¶¨DÝ-}hªÊ›x—Ä^lgÚ?ß3ã™±½NÒ¡%Òñ̹~ç;g0" ¶ÿüïú0y;y›' ?ëCòx9™½` !ÈA“åõ¤½@¢H¢$FR&ËÃäŒÑajì‰åfr&¬Hdp1+"qEi¥ϦDÙðŸ±J¦„#îNбj6V-Ǫ)¢†KUSfæ­jŒ;¢0¦Žh¯RŸöË£§õN“áš³ÄCœ'SªAŸ_¯ê¬:/oÓ*O‹uæîaˆP ñ&­ÒCÖd•ý$A#'Á•uYUÙ>mò²¨çN¿¡cEC;ÃL"ÃcüQÊ$þkFUü±¦\{[\Å/`X`BBB¦”‚„ñ^9úZ e3Ö\дç‚àJQ66¤3R²“†|qú^Úü‹žÿZB)2dà꣌ì, ¤é‡t/è îyÙGÁ=µ@gˆQƒï÷åUº?ï*z^f××­‰ †Û:"ôêÜO f«Ë ÔKRB¥s <ÁºÿÍ g/(O@ĸt>U ⟠á±Kó……^ 8ýÒ 5¢RÑTˆ€ƒ± ‡u(®0$\®²'„¼@{aYçMY½o="²Ï9SÂ’ÂâÝxÏŸ¶¦8˜'ÁüD ]Õ´Ç!œCk— ¤ •!Û»Ì !Û<^}ãhmp(kylÜ1©æA¸:û3/V\@ Èd`¡©dú­h8w]•w[B04xÙì2eÃfÝdÿÔŽÏ:):½¬3…‰Îë–£g\E­õºÊ¯ÜaŒâAu¶ñæ‰æÒfœú“A]z*<-£Û1°UÁ—ůË“À`À¦Y¿vå!»I·Î©à¿Ð_‘KFZšPg§XA˜T„ƒ.¡PlLpa›ÅÒ3%†á€>Ò…S—Ǫ%xÈ‘æ\¼LÂã ¸‡¡©(œfŸ\fTWæ²ý ÝTY¶qåg0»4]ÏÅŠnÊ–©˜akСI÷凬rH¡¶uU ã¬*fÊ6±×¯½Ë«ˆŸc³+«üÇ’ó¶úÃUd*¥UL ´åª¯=æX7kªÅm`?ÂE—¼Ïž¹êsƒ`’…0ço`TßfÕüå“Gh}[£uVh½›·ÅðŠpvŸ}8BÈíÜì¤!  ?¨~ÄéžZ‹èÃMèÕË´Ù]äWõì2/Žys²I€É™‚¸{&eá¡Ciä·÷‡òX‡!NˆJ7Ó²Ø;ø¨oô(]¯³º½Á‘d*`}u–_{dS÷ƒ¼ù¦Žüû/+Ò«}K È‚ñpÜ¡G"BLàŸ÷ž’p7ÜOöÅ>¿ªÜ¢õ­ó#EµŒpè(‡7Y“æûzõà4Î`/›Êa!ÿ; Ýx ¥P —û‡rc YŽfa9Ún>[ÏÞÖ³Ÿ.SÖ^ KÉç¡r_nóâ49C?°ßSº:»(·p~벡ìRÀQ{Â|hz·IsnC³8ü}ý ƒzë>¨ÖYºo{ÙuX[h䵬—F˜ßq)˜Sމípèg7$Í*bæÑ…ú°-ÉÈèÝ„f%ߤu}ç]æq,«ÍÜgt„8x!›÷#îÿa‰Îäêlq퉙áaÂØíü(ãSwíú„{c5-ü„*kÚc‚pm†U‡ZèÏÚÙ€ ˆîùÖÄ™w¶t<à›t»mYàTœ¾E›Uuî´£ ­ôd™<‡·´ërØÃ9lÑP2·x!©ý…çöãÅd¶¸Lšê˜Mf?'d2{jÿ{üÓ9ü,¾K¾š0@‰,‹–ÚFóKrØå¦¨Ð¿i,çóÉ_oÌ2}endstream endobj 145 0 obj 1566 endobj 146 0 obj <> endobj 148 0 obj <> stream xœ­XMoÛF½ ý:ô"Õz¿?|«]0`»ˆ£ôä@S”ÍX"’²“üúÎ~’”¥A ¬—³³oÞ¼7kŒÈÛŸð;ßÎ>Ï>ω[‹¿òíül9;¹¥|N8b\Òùr=ó¹QˆÎ•ÄHÊùr;{EÿcùiÆ$R+ز\Í^7EÖv]P$(a=³K„!bÂB—5èþ›]å)mâúº©·.¬FL*ÃþûÎ.žÜ9'!\j ¢%ŠÎÔ îvþSåîxXЂ§Óü"\Ÿ+Ûz×äEërÀH£c²ÛM &I)änR†Ê¸ï¡p‹D"NãEÝݑↄ•bå6 È€õkõ® ù(ÎåÞÕ©DéÑÔ°Shƒæµ;ˆ ¦iŒ¹*Âá¤Ûâ)¤-úˆu[vuóÕAÏà–,VôO»´`„" ›Œ#!ÝrQ82:!7RVÝ!¬&4Þª3}¼H«²)r›Ù©'Ã#( • ò¢¿»Àè›*û £™°vuWå]{r]V»²›d0SjË®œNܹÙU.m‚¸â1íl×Õ÷E5´Ý*99ž4: 1&SƒÊ»½6Õî6UÔŽP7f”¶#t5&2¥*^Ü5|ŸJòôAÔR¿o¿xJÑç"¡gCÖ6ät€í#¤¤Æ`iì ·8{yõ·‹Æ "Œ 퇲F:™„[S$ùHgøÿeB^W¿Ýïšâg¨€KO غ´Ñ¾K Lü'&ÛÏËôtîŠçÏ}›=ú³ ÔJö]ÝN·œ‚m‰:³|(FSi ^ÊÍ&aMof%lŸítÀvÀ3\3µÛ’à ²?½;) Å1ÒËCé$ŽR`"OçãadÌ/Ïb|-i¼õ]’H³~ŸË„ S °iÊ»]çCÄTJ «Vá|,Mì„]ë·ŽÊÚ`¹jÐÎE›Ch‡øxÏÈ£<`3è ì.”Ta#×Þâ6ɵŸ]ùúŽg‰…•©õŽBZM‡sÄu`ƒÙ †°vˆ qº¼y¹œ:ƦI&ž=˜*yR4mYWíôD‰-í Ó—¡/À¾$?raôÀè*_sB|»m°dàÁ1f4mt­~º¨×¡¨Xj1†ŠªT®Ý‘ßH zA]×›M›ªWÇ—ÀBR½TXXÓX±)²Ö·ŸB’)õë  ô¢õÑ|Þ]üuU“Ø@OŸ<`rÂ<~ÿ L.´5:ný >†®°ã“ºTÖ]¥=%Î/noÂå•LBóAzþYŽˆ~ ½1¤ž$>·3–Nã†@ÄT‘ xã„ ÁL&bÈ0:‚F:AÓdEoe FElIb;Z±½ì`ØfU^€ xU“˜Gw¥ï6¨Šmp5t— B ÒN$X×MüçX³•cyøˆÚë×êôôÙ>㉯äÙSHhP?Eï—Є÷ w\cibÛ‚÷ ÿ`öËùÛÙÛÙ†ÌESendstream endobj 149 0 obj 1596 endobj 150 0 obj <> endobj 152 0 obj <> stream xœ­ZM“ܶ½¯ý#¦|‰\öÐÄ7 J¥*VâŠrlg}Û 5ÃÝe4CŽIŽeÅ>  Ñ 9ÜY¹äÒaUݯ_¿n°,ئôÿðïîxóËÍ/ž¥?»ãæÛÛ›o~’bÃXá”â›Ûû›øÛ8SðÑe¡õæöxó‚ªà_Þþ÷F²‚)®`ÐíþæÅ›úØõüs% +ÇçÕáÐù§¼,œ“Ÿîª±éÚ0 lÍH™F·û0X¥`Ž}]…ç’¶¤I†ê¾q¸Mû[øæ'¦§gÙrÅ +ÍfË]!ø4ŸÕ}¶PJš`<„)˜)J.h á L¢”y[u\K€Ýàt¥cÁnƒ¾ )¬†ŸñQ•Ü1|Ò}ÕnYÛºp…ÜàÈ_ã»FÒ»u? %/œIfïîÆy!òÉÞÄùa²évÁ±&Yôõ÷?¿¾]Ý…,œUÉK_û!º`ÌYþGŒñꫯÖ&÷é<èêEQ²«!œÑÁj„‰fŒÜ™¹Å+Ë4çûìO Â[au¡ŒÝl™D¼«¶z¨û€øi‹oݽÀƒÏÎ$ ¥ò þ3V»wÇH€×¥S9RxHëÒœýªà†¥ ?ÄÜ8›,w}ÀEÁ$¡ô<ÄMÃSð§e[\UÊS<Õ‡zJ0ˆ“Ì÷6º‚Z§G1îÀ¹Òh2iÜQ)¸JËÔuZ¦$¢@¤€Û˜%§#D~ÕÇ §h‘L±ÿÐVÇf‡†ã®TëÞÒÊL¼•X‡Yp£»d’-MÚybVHíÈ÷ušD”gü™9îà…ûê|ï¾ÄC0 k œVÌÚßw= mWo»ÓØ›ÿÕáElÏÆÚ¡ áépï~?4ïÂ*²à¥Iö«É+´ÊsÆÙÂŽ #d°§Ç^8žßP×V‡»/ôø‰ôò¿â„°²&K­á!wàFì¿ÆPdÒÈ9H8ð0äмí«èró–ü&Æ<+Œ’ém7â V;äL"€Þe˜¡Â}•šg…‡"æ9˜2íó<4íbDYÉV=¤ÈCD)eÍÌòEŒùyÞ ) .Õ0ŽÐöùW¬ä_¤Œ9ýòÂd3MØ}¾ Ìd9±û©ê«c=뮦R§ mµø#©¬`) 1•Bú°Ï¥Rˆ'ÿ¼T ê›K¥ð\,R©*Xù§¤Rœ«&@ïk¤\cÈ ˆhá³HF4-+)³€#"ÎÚq{92EÔ̤-%rJgç#žx) Ë U é¨Râ]3VTÚ‡›»A ‰-û¦z{¨“:ÔšÜÝ#t&aÚví6ÌÁ!B‚œÏ‚JÚB60 Uàh+ùR¨>™2tá8Ñýšƒö]['_È4-æ/˜s•öÈçSn­v»®ß#‘(î®æÁ" Í—ÁÌ&r­vã¹: v…¦}¶u½P2AÇJ IøØIsÜÝÅ“r^HFC÷5$¤ý‘ôüB~º%ìJ Sb"bcÐû ì‚pʪìÔw#è 4¯Ò­tœ‡ªi‡! 3£nàdœœï|:%®q“ˆ&ÙN™CÆ„)f!°çË ôµ2iØõˆÑf¹Éi/¤Ò|2Zü -]²­¥õ?:Ï&ÄJ£¯ðîÜ’fÊôø±í݃Gòa_%¼Cj45„Jp¾êÑBÎN >ƒæ&.û‚Î$šÔ¬—Wüš b5¥ÓƇ$Q=²] ±ªïÎ1B|ùE ©âû¦tÇê·æˆ1ÀÝœDÁ~ ÏiÄc‘|ÍBG¥7ïûº¦$…0OÉ`z%‰`ª‘¤QÄÊFAMÖ(1¸ÜÀp¶B‰á|©»Ùz`Qch¤x„[B)¦IÚkÚèb¡|þ9õ±.‘æp9Á¡ÇÃeº¢¡u6)TÒRÝ04˜¢a)›•tr:dcIR‹|¾•%+8øw’ý <º#o€Zb‘îÅÔˆ“P-p9ÅÉBC N ‚¬¶ýþ1V’`xpñ#’eiˆS&çnÖYrª®¼æÚÈÆjÂ1‡®ÚG¿B(Èl+ŒÜÙù2#{ÔSyr¬Ñ¨Pæ¦#RDûj]g}ó$˜•{ÍþÀê"‘s#sN¤ jvß‹C{èMiþíEÆü€%ÑÏQ¯Üa”ËþugÔOY„ãKQ;“BÔñ×Ë‹ŽÈìÕŽÈ#NäO'yŸ‹¯à…!E‡ƒú¶É+¹"ˆR’IV¹z¡¡²XH$ EöL´N ʨ&c)¯g¬¬®%ežÈ(°¶cN]³ïîP ÈÁóž*íȶ©çU¥_ Ê´ÇÕ—ïgå×=€¯cHL| W{œ71M!Enb®™à:e€ÖÌFR¾)U™¦¼#© KiI~»¤P@åäÖ^ªä¹„ÄwcÓc°Á¸5júz×OÍ¡¡ÂŤPKˆMdÈj·åýc‡ï›®2Wœ¡ ƒ].H`ZðkÓ<ÝrIÍ{Ø qZŠ –ÃZsçР㺘áÖ†éfbÆ\Š™ï€”}lCr£ÝvMjXNZÛ¸¾Õ:=:•›Ô,¸"Ì›Å+]’"Ÿ¦t'½2†Í”üB"_@r`†”À[éùN³\XãAÍ{í:-CÍûË ÏܰïÎ( VÏA2`,+¤ 9)+‘¾y.zgõ-Ëuø]ßÙÙ¥¤iÖTK“ª¼IZS–v¶»-ò§oøMÓYr;÷¨“ógiœPíe&ÿ£Æ ‡² `d¦Áۤ‰ۣ:YLhéÇb¨ÎF¯áèt¨Fß~£}ÞäVø ‰XÒSÝîQÄ:¿äš6·²ÿyþ¤õs6V–2ÆjÕJu¹ q¹eT¦a؆¨‡0˜õ£¥{Ñ ú–—Ëœ%x%›„d¡Ø êëFIý`ë[áTç§]¸Oïk*…T!2¤S/Zb¢Ë‘Úþ­9V#ê!ˆ»’xkÌ×–+íu¶š„ÉL½Ûûj÷a+,3S˜l¹og <>#!?7“y|ã„æùÓZ¤×±å»n„-Ò:¹/?£Á¿ù ªäé2³êàXí›x "Û@ò¤iRV+)¯ÅaPCQ¶ZTÃ2ÚQ>ý˜o.Þ´oâf~¸&ÖY雩ÉÍX2çì¤AŒ ôWðSÂr‘2!4U–QùjÅY·ìPûÆà³êu¨Çqê©&Ž„àXç/ rõ’>jQYfÄ뛤2$Ë9 ÅÒŠž§7Ùû—/wÝy\3ˆ‘5]A€¨ñuºß°³|;ò²g%:§žÍ}yÂBKmôÀ@6¹ÿ¤ž—We'“fUÚ*KÔ©^©Þ%UæËp›95n{Ñ›mcýrÁ³`н§h–yH­,(ðÏ“ÛãïtÕ¼3 6W¹yå}}H×ÌZehad$y˳´ü´ÅlÎj”˜¿xY³QÆt;Q>3žÅ‰¿é> ~VÅŸâ°íš!‘3(M"ç¹Ýä¡|‡½ùƒjœ²¤üótáâ?§r§Z3§¸ópNý9…ÜÑ©›¤ñÀdn`ÜWͲŒ]4úg·½ŸÓ.ËË¡ÔÔM<6-^D¼D_çXºx6Ê×¢T+NÖyh~Ň– „iêMß×µ»®ï±i Îãè))®]çÎØ‹Ÿ%ÏÔÝ3qõ»ºý s‡/@¨dìû®b¶eôAÀO³íëc1v‘Þf]퉆… ¬èË­ÐN;úb7¸Á¨¢—Ÿ²Ìø@ ‰Þ„ÕSCúqÖ;ùÏm~¡ëÀ ¹YEÌ1ŸÑs¿qÉžŒ,°äØ*ˬðÙ0;%üÖÓL¾õ¬R0¹B[»„¦]ƒñå•wñxñRߪY¯zŒ7Þáë*T÷)´Eþ¢8·Ê|a{nwd %dŽ—¬h`n‘¡ðÄmÅÒ’ÎÉW>£Ž}o Ã- ´L_dU0¤#}p‘>#1Eùs¾‡ÿºè/ù‚‘šËÞËå&lޤäš•I Ô¡[»’‚š o}SƒMóen5)O–0öåŸÊ^jñC>ÈùÛ­§ïöÅ$ÄÈ^R_ãØ:÷à ̽{¿c`$4µæþ>†²Þ~‚¦°™\0¦˜Šœ5äôp‡ºÎ_é)®/0I!E ÷¥x ¢DnŠ!äÿ執›o~¼ù?ÍÂ]®endstream endobj 153 0 obj 3658 endobj 154 0 obj <> endobj 156 0 obj <> stream xœ­UKOÛ@¾§üƒÔ,Þ÷ÇVHåhÁ¨.ÆÙ`·‰ Žê¿ïx_y4=Tªrˆ2¯ýæ›o&9¡Y>~Âwµž¼N^3êlñ«ZgŸŠÉÅU¥¤dY±œøš&,Ó*'JeÅz2Ÿ?0˜iL'uÁèÖ ã‹Ådz}óp]ø¨Ã’\)¤aÇCr†ÓPÛÑȰ°Ñ<·Ûûj‚ïWc«±˜ºC†ÁRâp cD›\† ¦]v½Kæ†0Å¢ý¿µÙ-2A¨02õÙl\£œ(±ÑM3lË¡éÚÑ%€(ÁMp½7Cí4‘FÇx; Mûì°a¹‚à(R@4-š¶·®2Ç\G‡£h& •<›!Náù,«0 nÉuÓúI"8%^z[5›ˆÛ“§¼5 ª NùâŽÎE*ÒÔçí¼¬Æ÷¾Æê——Øpúõ8]tÛ§•}ùk41 òˆú¬]éP »gÊ!Tž²+ÛeÓqk&¢r–¶¶½Ý„V7Iƒ¶E6oQ(,ªÝúm`*Æ]PvÎDœíYï—á%"Òcž  å°'³­:ïÄ×rêP¯•Ç(áÒÄf§A>ùþÈQ$B¾\Ýß_\ÎñÞ ãJ¸¾‰‘ùõÍíý_*ió/•>ßÞ·w'‹áºSÊâ|¼¨õxÌÒwAÒ@ k»!ì("2÷Ï*“QY]ÿ3ˆÐ€H¢í^ ´¢íWNr €’û½ù^vgÓ…q’ë$·÷ºñ7ƒáÁQ¯u0ßÕ«Ê jÍ!?:þ3´H< £H$ «j»r·ÑéA!h“vlí_àÒª†Ó£&¢ñÉ·1"ÑûªvÔ'p/'¢úñ?"l> LÓ v4ÔÍsí÷›K¢wç& v$ž~1î‚Ât©\•£ëªÈ¾M¾M~˜¬Ó€endstream endobj 157 0 obj 793 endobj 158 0 obj <> endobj 160 0 obj <> stream xœÍZM“·½³ô#¦rp¤Šv<ø¶lœÄeWeU±´NÙFäìrb~iHjKùõyr¸++9¤\®ÕB Ðè~ýúuSUÉŠÊÿÎ׳³ŸñÿßgÌqQê­ñc=“¢ü¾¢ß ¿§ýé÷ål3cE;s¥R\~ƒ-…-Œ²¬T¢àB›ÒLˆ‡]3{7ûP°Þœôc¾.¾¿}ý–iQănïgÁVVpW•UÅ £YéŒ,n׳—?üñÍ÷õ¾yuû¯ÙŸo‹Ÿ±÷ap³¥àéfaKÎ*éo¾ÿŒ=ïòa˜ÿ™^€ßœ4'ç\ÜónVÁ¦Ë/U…)µä•>•9YrS©K#YÿÒ?lwMW¶ÝÝË»Ww/çÛÍþPì‹ëëÍËß,¶Ç÷«æ»¯î^]áÏÞ+UqÎwÅí§wþóýß<.ÙCXUºÊ±‘‰+Œ6Œ—̆X´Ç®?RÈR©°Ïß)JvíW9+CdÃêí²ßÊy)+ÃãâûK.K–·ÎWõ~ï—¿~+ÄЮJU)·ýà·¨Òjüu\Êè8}†p¥udâý¶ó›°,ɘC°ÙÒV&ÙrÜ7Ýï£1LÛÑ‘UÉó‘@æÔ½Ì”\Òie<Å:ÃS°åJHìçÅ¢½ {§¸²â.ÿã6:JH-¬=öKU)\¥Ó#Â6ä*7,¿¡M‹7Ñ”‘ƒñv¡X:ë§7¿üt% æ¯Ö¼·˜IWJ “LÖ)êý%@pU™qÐq Œ x鬱g®ÝÂM)ÇÁFd´²)^ÇÍüÐn7)6C‚C‚•wØâ N”#ü)€·°Híínó^xÝ!𧮎hsÈñaqÀ¹Bñô°ˆ¾îWAй²b€{4O¥À°Žsà€ÊKNºÃp·tØºŽ¾àÙ”O‘ü*íØoJýq·[µ (£Ìê“Ïûæäfé’É×–›0ÛX'¦ ÏPÙ €~Ü®d_.E"—¢M½nbš Kp <øknÕ‰±ÌSÖyhPæ-£Pdþ·¥Îü©&[²à™šäÇ!W4SdlÔo« °ÛR¹—÷õQ`4®Ëùo ¢À\ÂñœÔ‘ÚAÝmên}7q-›$c².ÕÐz%N…\4˜@y($~$Žë´5O¥iʪr¹Éº$—€·¯÷±ñü]ÕãáüU-s¹#OçVœ|×Oo÷A~€{¸°Éà(Iz×$žëšˆÿ!DôJ__Ùî¾|æëÊtCŽGHuÚó©lùì~<|Q9™+éÇ Ì ÚÓ·ÍáØm‚‡Ð¢J{. 9?í:'ô^ªò±|<dø¯¤²œ<î&‰•WØüõÇ¢¹¯«C ¡3Õ3JäÜ–o#0˜¤’Ʀ cøö$…öz2ç¼ÃÉEw¯Â ˜ûy^úœï®’ròüFE›ro·FòÒ ªéºm·ï‚–ÌZ~òÕâ—ÐÕpþ«; ›¾ñÛ'­¯¨WxÖ²(±X–Þ‘n€}V ÓÌ!S3ÀzFú`°ŠÇ”žÀ„;›Sœötôun8}V·•~k)ò4¹¡'Í…Hp'+T(hâ¤ûãê™î/6Un..ÍY:ù«‰x.¤È“Q:•¯ÊQ*¼Í֫؈yE]lîä˜T @йLy«Ý8ÖÑßÊO7H¼8L~ᦋIÁwùëéo£Õ> endobj 174 0 obj <> stream xœÕYË’·Ý3þˆ^%RE„ñ~¨\®²œ(¥…ØW6³i‘=3Lø2’å¯ÏA¸è&{4²“MJ¥ˆFßÇ¹çž r&ÿå¿‹ÍìçÙøÿÏ™°Ö7ÖI×lfÚ˜üy>»ô¹ß“??̶3Ѭfé`‚h>à['™3õV3é=gªJ² Usèfog?7¢ù³Ø4¯nf_þ(œkÊI7w³dh¤ãÌZÙØÀ™´®¹ÙÌž½þöû¿ÚåªÛž^µÇîùÍ¿f½i~À3÷¤eN”cÁ+M¸ûŒ=oë§Dü›÷Í`áÅ1my;ã°èq‡C㘠x|è°°¡ 8Õ0!uïðŸï³»·Ï»íñÔOË—/ßw‹ÓîðÕrw~·î¾þãíó—SëãèÅw3Þ2婌bÞ 3t÷9›žòl:•>À]Ó8+™Fœs*¯SHïמizý8…Oîy[÷(ç˜vÕ@*ÁãƒßôûÒh%§“A¥4îöÝ¡EnnŸÝ>*•és oæô‚%N9ïãóÃ}è”à–8Å“ ­NŽY…’UB ‡ƒ…·}Ä•Ð- [qÁÌàÉržä60.Ê–5B÷{žzÀ#Û<MD\ ð|Œ: ¶±Èµ” 7«ûó¡÷]i¦œ6؃£˜|W¥`ÖÁôzóÐo•Àw2/¾Ë¸“8@XWëö˜Ö¿üQ©¡1À‰ ô¢×q‹a¼òÒ5+]úãPÚÞ«îv‡¸IXf5YuJ¦ Ï<§çcwøÓ1~¸°J‹jÕ·ßO½WrÊ.¯ø°:=dÇ] Ç3Åä:‰*Ê¥QøB€ÙŒŒ'ÎUPÌpÙÌ5R#sìS9r|¸Y &Œ¼²q|"’ã±9o§Õ®7ÇHH¹ ëá¸ñ&\[¯ã:ȱõÂŽ¬è&J„f.ÁSý¾WsØ•..»»ö¼îP)Cþâ‹Ãñ”(¸Ö´ý°zŸ—ƒ"ìµ§´*ð&6M«]ŸM¡˜ó®ºM€ÆF£\‰Ö¢]/ÎëöÔ-ûPVóØ{k™¡Äæ¼ xbÝ;c,óÊ‹÷«ÝÉcʦï¦Ðƒ–Œ|óýOon¦bª sÜ”`°¸Å1‚/ž¼éíšaÉ9*A/øE ´BJ ®ÎQÁŒ›fŽƒRæ>Äeϸ’¦œÐ¦WÁ8OÞžRÄ2JN»œ…Ääµãy¿OñC3áV–õ‡U:À1ï(ç»Ä†‡Pö}Øf ¡¦åDm¡xë‡èô¨íýEÂ9 Oå}û¬c÷}h%l œvÛ®?žbæó3RRe\ÀRNÂ2,oŸ¿Èü‰B(çgNø”,®o»nÙGâǨ`G!kÄ !Y2‰V›ýºÛä»]Œgn„ ÉccH¼Nˆ–*ÈrÔaêQ³•LV½9(nè’äSw¸k]湈 éšÇ†2ê%躂fõké0ŠóRM»» /ˆfsnUÙnw>íωh€€6¯¿Oðrš ´× ýYN€ÏØ„›A»O½éØnºü¸®œÚsiZI.‘ñHË'_m‹íЇn·M!Œ[S%LGoÒ¨IŸçò|¨‡æF С’µ¢nÒâ}ŽjËÁ»ãª´¤€sêŸÃŽÐö /nœŽGâÛÚBP !”3~[ IÐ5@¿ù­9¶W4pNà'm€®îKpÝqŸI,-+³QÂWîÞ’¯ŒJÅløE1›*q¶i‹çÓÁq‘ôF¾X|‚ù|Òd7×° jr·Ãº- ‚øaÕfµŒ+k‰×øa †VK˜^v¿LÉN‹±ÍckÐ-]p*ðqá:#2Q€rOQÀís–[µnD,&›…7脲 1óE÷Ç¢9/)Í^Œ.^NýºvúñKâÑ’:ý¾= |AšÇÉÜ@&BáØÒÊ: 0ê‹*CTÕöS€¬´²VõÈÝÒŸWÅ^†¤¤Uq扳£B¿Ulª~•1êEWL½«¬Cõš}hØ´¯ŒqÖQjœ¯ß%Ì ú<¥«Ý.³ŒBÝ¢SMrå…îb™œ•/ñüËêÝ!÷rŒÏ¶I½ÜíÇ%0ÙcûLiT­ò*ÎÅ·ý!ÑŠEñQœÞ¯–ÝòE&\çyáÅe·¯ ¬$j»\mï³þrž€—s×àõ€u÷>›€]DùYRbß+îõDä%äs_ŽWBnA)c&úx¦©ïVÛÕ†tŸôÅ¡ûù¼:ä±AEcGæô<¥å8!“%, fxéû–‰SÞžÚÃ)GTc æÅÕ)æ]ŸS¢Çí}ªW]•°óZ+1ÝIj˜¨Öîpj“GÚA9ŸVù­"J…òÀ"Xtœ•I©-“4 ?Â,~ÍZS]ð¿«`n©‚ƒ\q LrŠ_ô\´èV¡‡e^&)h º$GÚ)Å-âe$•r½«ÊüÿŠ ‡Év‰ON”ô~5õ†HC"Wï´&:¯£ä~=ÙyG³Ý§µ3¯Úy‘IÓª¦é&b 0d™  ±Ê¹ß”1Ö;ŠöÇ„,ðq‘]±Þ¨Í =Õæ¤½`¢Øs<1ѸFæš ˜ªãð˜ÑRº¬6¥§.º‰Ô±úµ-9Ô›5uÖüâ—„UieÝa´z‘©?j†kv:&BŽq§a®;-Øíóþ(h;:‰ô=¿bÒvwºc“rý¸*jysb€ûĨs‘ïúÁÍ%àÿ}=¥Û¯RŠ«»\BAx5¿ìx¸¼‡O ¿í"6‡Ë;È+O\ñ(Õd­!¼ nÈÄ ±¤Éå *Vލ¸*µã„÷µVr˜,„×Õ{¨G± f~Q*›é&ŸnH¯§î¼àû©ØX+®誠y",ÞÔ´Tº¬Ú}š$£–ýÿ Èxáø™éµ”öG)2ë/£$`—UGdyMa(šçý¾\¨6JØkkjÀþKáâ7ý/Ë?Ìþ ˆendstream endobj 175 0 obj 2646 endobj 180 0 obj <> endobj 182 0 obj <> stream xœÍYIG¾[‘ò|”¸¨}á Ò@!1Êe.Ýf:²Ý¦»=@~}^m¯¼´‡ qª««ßò½ï}¯L ›Rÿ'ý½ØL>L>LYXË-6ÓçóÉÓ¿¤˜2FœR|:_Mâ lê áS£)Ñz:ßL®áD<™ÿ /}ø‚d„)®à¥ùrrõjû¶¯»í]å÷jF4S:=ëšj»¨ãì茣œm§3îˆ ›ç·a'×DXéÒ {8;¬o𴺨¶aQ#¹H‹7WínhÚmµ^¾yŒ£(7éù®ký"ÓDI™-¼k–u:_j– ®xk³‹øª žwç—QÔ1–ß+KN´q6=ØTC×| ë”HjñC}2Ikt¹Ùîöƒ_‚H#,F¢Ù¾Ëœ8+s(†5^™|ìb]õýXêf’J"„Éö¯Ë·D ž÷¿Å¯8›ízÕváEA gB¡o«¶ƒ`@šÂ×L»“¬2Hfõ]ØG¬p:>œëc\çsWí~»LÁ1Òhü\¯ð©È[%ÿG—Žë`Æ&àÒLXÂmØëK@>´þ é•Äpîq¤74¯tÕ¦êîï¡ÆëÂÁÉR‹óº85Ào h¾£ ÚʰÒb¢”Ÿä2c®j¶^€%œ<†"sÄQ„â®Jß /»ŠØ½¹-QJ:vÁ1ñ%¿ú1Ÿ _†±œ¯È`;“h|ñêÈaÝ[ö4—&”ý̯Î$lõÂâÊ夦Ëçìö·UåÍ’àÏœÌæ_F“³?M\å„ßF¾ãÔC7›9Ä Kˆ°©béBpAÙí»]X•D¨œ¸¶¯ûgñËö¸ž…Ô:_ÐÀ°÷×1 áŸV#=\êeÜãå´Ý0"ä#‰ ú×2À`ëËÃFWXÀ!ë§Ù6›æ¿À¢dÔs&-p(x‘/èú[‰)vuu¿_gÃd!ëv•âĨÍd°Ä•^thm™#J+l}ª0ÏÐUÛÞ÷‰: >Hì¤àð$Ày±{ÔTêÕDWïÀË:쉂㓡z·®Ñqg2c /À:%*>Á‚1—Ýùœ<¤ȯb2€S`݀ɔbçº~ýöz>–2¡ˆåþ~ß3œ¡<ÝÄt¿ŒfèRù£m7¥Ô¥})ô¯þ´[WÛ±ÈÚÈæ öuެå4G r¤¡MxhCXÐOÏ@ŽDËÔVƒ®`¥9L×¹€q4E‘r뀂éIø@®†O&¨úRüf Ô–à#º\ ˜U»^·Y(´æcÒ` ¶± ¥»h7‰ì„ED½k⪀¥½¿ (†"Pª.÷f%LÒîœÂÚ¾oóã„Ê%ô=ö‚³D+‚^¦•—/^ö** +ó·TÁP$9~gÊ¿¼}=±Rßæ×Tf¼ MÝ󤶀åyò»zó±nÏXÿ}W-›È2PÜjäxT#ÖùB_^L1üòö¯ ‡áÄøüžµŸ ¿ÁÎÓ Œcÿþý|€fÜ› ¢(¤Ë}b¡ÇºZ„EhF 9æ67:ƒ½U‚“‡*¡ÏMG3YFìХЅ.qÚ0ö¼Áûtv]ÀüjûPÄ8Ži¹m“a@ÆÜ'ô†$B`ÔÌaúsJE‘»uÌ=¸TS•ßt° ªu°Gy=•¿ÜÕöMU<‘ò`Ž.*eSÝ¥)„úÀšQ²ªÙ1ª°AÝ”;…Óq E*”+ý°|öì®^Ä%5¸#ÑÆ±Úð†V¦¨ 3$ ;ŽbÐò…f¥÷v)³ÌŠ“á2hðKÃ¥/[¬<ÐùÁ§¼°"¼ÒPƒJ¨HË|;„Š(«(ˆ<÷± ‘W‘`VðÉx+ ùÕ2' ÝfŸLÁåÅkªe’ƲcdŽhMA¿“ÖtòXk"X¹ä¹^¥P¸2`æDù:«KWêr¤db¥ú-:5ô‰€$wgs‘¢#ÔÈhPwÕ"Š3I¨D yÀ×VkwŸíd±²(mO¸¥²|@fVÑ“Ìqƪhm§-Þ žŒG†m1æ7W¿|‚ý=À•êÒør žvõ&DBÃPÎ ZP¥*ƒ„¹†ï Ppù0eÅiÎØÙà–h º—¥¥™°šø"*!¹†ÌAÂ`5rCµÝ¶CZç3ñðézü.Q˜6@è]æÁ€¼9º¼ûç6ŽrС•,swŠˆðs‘Öf»6©æL™ö}82\&Ñÿ~¿Û­?ÕèP$Æ|i(9¨"SÆ×Íy¸Ó÷ÃÔ„m¦|\•åNç›çŽS•nÛÇ]º¤¦h¨sˆáå²nò)”Þlvëz“¦w?“ TXTPûºÜê%QâùäôêâìZŒBÏŠH∠‡¥öâõóª½øò?XB&í¾¡lìžþLŠû=öç>ÅxÀxE‚ÛMþ}¥À·ªnH"ÈTÇïËÊþÒte¼³ì‘>ÔŸÂXÊ€&(ËIí‘úød0úiçGÍ5)ÿ»;oXì’²üC3é{Hxά_ÿc>}3y3ù”°wendstream endobj 183 0 obj 1963 endobj 184 0 obj <> endobj 186 0 obj <> stream xœµZKoÜȾ òt´ºß#ÝdìÍrrñ…ž¡$zç¡r$+¿>Õ¯ê&Ù#ÁF{ð¢E²««¾úê«ê! ½$î¿øïzwñûÅï—Ô¯¥Ö»Ë¯.^ ê’ÒÆJÉ.¯®/ ôÒê†]jE¥.¯v/¯n»WW_.o¹Ú\¼ì÷w§Ñ-s؉r—ïÚc»ëÆî8¸¿IÛ%XüÛºÝûï†Æãâg·¤íÒqÉï¦K™’qièwwÛG¿‚O²dŦ{±ï6~Ý6Œ ×ïûÖ-RÓkÒÃaû×øôÔ²¡Ä¦½‡qóæÍ}·îY¡ID2õ^—¤|Ãÿišìüsmë60É´ÍáôyÛU?E'øKx‚>ñ¥‚ë„¶&™øpÛ¯½Yc‰HA¹uK¶‘ÖBDÃÒ®k÷>D+p|CÄ劊Fø?·­,Ô6¬Ýn½Ge# zkmM0Úí±‹!0T§mïýsàTK)>×·à¡ñè š>ÿöÚ6„‹´60R@Ó騧¡;FˆZÃ’n À™d8æCŒÞxÊW6yìÅ×xXÃLZkƒ!VÍÏï@6™tðk”7R`ÎÄŒÐQµíw}0ÁÅÁzØgw§ízÿúJÀ¨!s¸8“Eׇf8DZÞõ{Øð¿íØö@Z4”ÉdMô®l4e"­µC4Û(‘l 0UpÂ0)jSˆÇ¾ƒ)ºS¿­'‹aÙÁïö!´ÿòÐf˜ømÓ$­”HœçÀ&˜¤‡Ï1àV ¾@ÊÇÄ‘Õî7q#2)HW|r³ ±!€¦‹tZ䈘#‡}=kŒH)÷ó×X¢ò›?Ä$e Óß÷ûá‚^˜¼óO[ ^54+ü½Sýw9dRNÄZÚnOÑ †%NûuwÛ~“Y$4ï^À8•çòYCÓRrVR‹ßü¾™Œ×Èi™49ÃG+®iÃáŒDJ$­eŽ]¬!`ž¡f‚ðE¹eüá2ŸÒ„– /|€iÉ%¦e*§( Á‰K5œÌ‰ è Ù|N\PQgÄ59f".Ú0^#.,°d®"½Úý0è¿, Ã:9fÀJPP€‚ïâ´[ÈÓˆ{ˆ‚‘F-qoâþ€h¶v p-³ºÄßÚè§8ïðé@%IιŽnÔ°1O+¹· 8o8XQëi/WÜпÄÞ04´d)‚ÿ‰UšCú ”_#J5&uÚ«#”âì´H …ô?œî¢ÎšCtE&ªË83$Ó/wî ˆ‘Ù gsCØdY¦¬bsYèä%[Â]Éżºí‡˜À– y> IjJšÙñØnúÀÝà5–‰Ð;H4†uÝn×§m;r†àv™ ñ QVrŠµÛ…íxžñôþ±Ê¤ibê±9ß@fÐF™²¢üögܲ„ÌŸÞÿ#nü±ºZü 9ÏSðA¡Jø{2 ;^·jÁ=Š«…”QöE|$ú”÷¦5åú¨‚A¸F¢Ó•bO•P‡‘ÿÚ¢BÛµã±ÿÄ,L¼²YÑ”£^¹Ž6Ь sI6 ÑAôWTüh,%„.íGÓoW‘à ŒP¾‹Zª·‰µž>’º-—mâû½l!«Þ‚ 3ü\KÛ ŽóèCá„J/‰¢pÁ9Mn ,»ÈA6góá:>©˜‘¥_U×õiãJ‹–Rü‰-¹ânÑà0ܠ߃+ ø®-‹Û]»Ž0¥+úoË*´‰å\æº?)µ7)È” Ï;Ç¢`@‹èdħ—ªÈõ\¦§»TçyQà~n€÷ŽŸ^…î’;ÎGž=ÆÊNI¡ùÓg²ºh#ZZv©lmkçÊÁêú¬µ T¢ ØÇ“1µöm™sq/‹Bë,=û‡òæ‘…A²ƒÁö²N@¯ç(ÓÀŽH™wÇC œÀ–é¾O:rQtFî»r¤rU/S ƒýépïݤ€o¨L{gb˜2R嬎²ÀæB*T¨A D›Sˆ+'TU”%"²¿&$Yþá´ßG·*è™%Tв)šò'†%Œb¸$ɹoß|{U3Œ0LÖDU]¸h7 Ñ…p¹zˆÁl"!\o–Q|*(XCy"”¹’™xS_!yÙW»a1—Ü!'ùYyø&ÅÌä¡€Òê×_‡³ü©JBà!…IE”y‹Z Ú–¬Å¾œ†1Š1Š­Ö·ÍQàÍÌÕLº†.1E :sƒyM_Ÿ+FÀØÅ|0º.ºÚ•„¢ö'õ’«Q*òÔÍÓƒ7‡¦êt(ÃàM øþÙéÜ•§ŠÓ‹®ý[çTÐSN{Tߥà&ÉÞ½Öu³Ù°È¤¨9ÔæèüüÓû*MÀéÈŒ }B㉇î>–!s¬Ží6* Aõ¹œÕä¸Ì®»ÂhG*ì »²¶€x l9ãÁ kbP‡J­ xÚ¦þLQ5SÀbYyd°2¥3“wë®Kí¥Ôeß±8¨"Ÿ^u‹}÷5$’U¥"VLÆÊd"…¤ä=ê˜aŃ–8H¼Dq9¯SÎ ÕŒ®¥à‹¡Ð(û*0îºÔ†LÕO/_|}}ì¶0éë(Ë äƒ–éã“Á‚$óÁ‚›mØÒ»4°¢¤°oÝ|zåóy¥¢qÍ›#MŠ×?3ÑÐIBvñÜcÇ"Š»,R ÂQ05jš.\ž«Qþ`’Då$G<¯ÂA@ÛL|w•§ŽNFa4™oK°ÑۘᶢTB÷ ¢ÕJD"CJD4¡õ9'®£Ó9ÔŸ$Z³ÿÖãèU¸é’ÎÕ7j\PÀª³¼•𨜓}¶¶¢œÑ¢þ¿›¼  ­A;­ã÷M¾]¸z ºOÔ3CÊC²ó vúÖ¿}ôNsNVF…þFä]r|¶VK±ÉЇ››nèoöئi†¤v†alÇnµÕâϨùÅAhg¹†ÎE–£ÕD‚¾¶áT£Ûßôû.°¹€­ŽÑŸ¸ªšú¯ª §¬ÎC›tMý/ öqÉ¥›Œqüìþ.c¬Aàoçò…FCÊå4î—¬rûút<Æ‘kÍ×'!•Mž8MT‘ÒÆ°âþ@AX€A‚ ‡ã‹êuƒÏL`°×økîÌlUI@ý\áIU‚ÔU†ºìÏ3ýüµïtÆ0•uP{ʺ‡~ôXanu°Þ`üð‡4¤¹ùDÒnuÎñº$j7è µ‹PÙ·SXã[$.­Çx&æêe²´¦+RÉd©T½ Ú'´ÓÊM­ßU:¥úLcÛæhZU9Þúçh¢Ä†> ¸–åA¹…œ—‡Ê˜ûc|ð$´)9'0M%^s¸yÔÈ'†eÕQãfǺY[½Û¿ëÝŒ¸f2P¡Ìèýôªöµs·‡¦‘O?9MˆËåþ”úJéÒ„M½¨)~îóÕ—‚XSR£êØgå;uÑD¹xJ7©"_µÛm@%d”DT> iMaoË’m‰IP“–ñþÏÆfÃ_`EîÆ·5ZôŽq¿!ù&üÛ| ~^£ó¨jú+…&2‘Å‘eäd ª’䡚»Hƒ\ØKa= úg1u ÆìIÐ 7”½YÞÅüæ«U·î_„b Ú"k4ä+£æ*ÈýÆA”Up••°Iƒ–® Å5Öj’ëøsËw®&æê›è‘C¦ÙÅu˜›°c¦Íë¦rúõÙº9úd\|/Ȱ=µ¤Òž¦Ø“‡)ªkzû;6׊È2Ó›ûÊ›‡`xÓòIÉ|º‚ùf?B ´šÖoÓÜ€àawíoÑ8(ÖˆÍäX¦Š/•º”×\Z<øìÈà¹,FÚžLœ=–.†éé AÔh‘9‡»±ß…銀ꙃ÷Ä༸!-~|WšˆhšïòèPšÙÈÿ) $­šQ²+ÕyÒ9C(ê~kLýôrèÒèÌj<àO„ß›Àç& ,óˆ–ÇŽ“¼çùQ ·c1†„W’ ÉV?$øIl>ÛãÆ…µZû¹q³_^ÿIžè‰ày‡â ú$BL­ûÃ߯.½øõâø> endobj 190 0 obj <> stream xœ­YÉ’ÛF½3:f~G;B,×¾èf;ìäñBßtA³ÑݰI ’ìùùÉÚ² $ØÖ2чŽ(UY™/_¾LRÂÖÔÿ¥ÿ»Ãêíêíš…µüowX·]}ó«kƈSН·÷«ø[;CøÚhJ´^o«¯‘D|½ýc%aŠ+xi{·úê·ÓíÔ¾=µ½¤ÖæGG¿äˆœ§•C×w‡îïæØ ýäŸ~ó+ÓõáÆ8F¬7ܾyßãÌ&Ž:Œ³ŒN»¾úé÷Wۥ݄&’+™Íiþô/1M˜Ékm°‚ÁÍ,n·kÆÖ¯rE$£ÙôãcîÃ5¡Ìå+6û}Ú,3i±ëï‡ñ.œ" Úå‡ñD¸¥’ùƒãØ6Çö.:7I–qSNë/žŽÝ¡ VHA´_rwsù¾»aÛ]¸ˆpÜ”·yï—,ÊU¾qã—QԹ욿º{¿¸‘`—ál½ÿ2¹'øŒ9"(„/¾~šÚ1Ù`5‚ Þ ^T§ìvlvÇàaˆbyý}w|L±0ݵtÖS36‡ö ›(¸œ•ùÙmÑé¼G›À)¤ÑìºÚˆkN å3XKœtüú—C\rÖa¨fè'°bXãd\Þâuÿº{›»%h+HGÍóÇöØt1£6ÂÁ#jc㊿Æv:í#|Æ!œB€™ T—<Æï!ùû}3Å|›¤¾¢j O¥Rgä–®I0œK/éÞÕáÛät¥\bBõO§x %ò2¤`x×p“¼¸I剾ý3› W§cûbDÄ$Ïù.'lKõ?2…+c4|ä> ?ð±`×\Ë/®=O1ƒ¤rD8KHstñá³HƒT·ˆ´äAHµçаÂ]¤+¬åWo> …ÙlaŠœ#Ñ¢±Ý·ÍΖ0†-yþ"‘+“9¼ ÁéÜÕô´×%zÄP›‰®„hGVôrÈx’úÌH¨ º2ò0$è:ar ÞEÞ4Òå•cÉ3d®t?ápn½×]eIäh,’ØÍ.ìl‰Bÿº„ðiQÕ£éØô»`…Ôè°”í²®ÚÍ"\ÀìcÀâë{¸Mµ žù#•Ÿ¤À¾ÎÕ™qhbmðþ,ÞCjó>1ÈÉ}%QUÃR³²ïÞ÷ÉG•Û´¥–¨ ?™R2‡¾M0®·`[H\|l’ï]Ó08Â×ùˆÃeAnîžöÿ b´VgÁŒep.Ð#ÈÝ‚b4ë`)C,ÅjWGWÁÉ•i® ¡¬À-àªHǘS^ÊKA˜ô3½Æ=ȳ¡•`›Ÿ"=W `»oº} ¼#‹ZRÜ%rãM Ôx§ähP1¯Àɧ¶ð÷é°¨E¹§$O#¨E_ݧ=­As¾DŸªåëúJˆwK×õ9ŠÄsƒÚN1VQáDÁXîËÁ ŠÓáEúXÏAfçú’Ù}F7]º¡ŽÝMÒ° (6‰/Æ0 e:¤ç¶ã¹…¢š_û®HáS¥ò¡¦æ¡M¥›ºé-²cU]®›Ål¡º/Š­¡Û÷Q@M]š?O}¾hw%EIò‰¼€ƒã8œn÷mLY (¥èöŸÇž"M0¢´ÊîªmI"¿Œ÷²s"àä›E#ü®áÍ/9ÀÃC;5°©š‰ÛÓÃ%Û¦¶YÚžOŠÂ™µj—¾Ÿ„ÀÛ¶67Z¬0y;ŽQÌkÆ’Á)• ˆÒú H-&1µ~üþ§E‹@Dˆh±øÿ>vûjÀ¢t6ƒú®û×.IÈTËuNë§™”GÊ`}z%JÏ5ô›TðüìKÔS”Ñ >•“ž5ri8 gú"4Ž.„¦Ú`¡Y•Vq&´nÊÉ„º iöã ÖÌ+Ó£>ŽÀÜ–]ðI€‡WÑ®\RzŠ5òb‡ƒ´M”/RoÚ¦k%Ñ~(ço2‡ì27@yRúX–E8“¾Xª™êºÌîß“nƒ­ÕÒ‘p !Ëdô6µPÆŽ âóåp¥…Ž·4„þ¸ŸSq€«d¸¤ "‡ª”mˆþø-÷_—š[AJ(SqÇòŽIw6íx‘dç³AxÝê/„sµA€sA3ˆ ."2S4ÕD·é'│?µò²Ü>á!Õ!FåÌ}õ¨š³È˜ç ”â ¨&d³1TŒn¢_(R¶D=œ Í¢ÆÁÙ|º 5Š9ŸgÆ|RÔRÑøþUVƒ½k$\i£ÿ#¢4T[1cæËÖ–‚¢;Ë©…_:¾ÝA×=%±䫾‹Ì% #)? <_$…ÃËù•W “«x;—+‰ýëÒ¾c—9—¿œXÉ˪.ôDõ̪ʅ26ÊM‡È>Û`mßšà—Ôú|P8À~×5)—x)ï®Ç!é &p¾v—§9п•!ÙŸÉ-œ£ä\„oÛZô™ðyùò¨Ý~êúÔ:r¨°"X¿ëqÌ0û¬YϤhÈè³Óøg¿Ñ|¶õ]Aº˜Èˆãü>¾ S†çŸp•õù¥b8ˆ9‹SìÇvLÑQ³Æª²<߯¿"Ù3?’¥â»&æò[Ò]û!ƒ e+Ž5)?çuÐèp’©ë÷3Uú™ænNXû.þÂø_]È=ǤwíMŠ’ôÓ¼ÏõYÕ ó›Ê._1ém ï‘ÌKËrïÄ©òÃvýËê—ÕÿÖ578endstream endobj 191 0 obj 2331 endobj 192 0 obj <> endobj 194 0 obj <> stream xœ•WÉrG ½óo˜£\e¶z_|LU’ÒÁ©XEß|Q-jR³È3CÉÎ×Ó š[»t  ìF %¬¢Ë_úÜv«¯«¯ ¶ü±íª_7«Û{)*ƈSŠW›§U¼À*g¯Œ¦DëjÓ­nQD¾Ûü½’Œ0ÅÚ<®nþ›~±rE”.Yça?«#”9™¬ÃÓbcŠ¥òýùÙ‡ƒ‚peòÁÑOû68¸½gú0º5’^­Á³ g7ÑÁí½8:…Åx~_ŽhÂ…ã:™öývn†þcÓ7ݾ»ô–…„çéü¶ŽyRb$ÉøýZá´I¦%ËK9Ç—Œ³ÌgÿàpDI“}‚HjgŽ!:9¸Ÿ_"ÆÂò6g:5ÝKû=Ø!.γýµ©/ÁÄ,‘ª\ž?|ئÚÂ!9Ôå÷INÓÙd¹ ·– Žåßš¶ ™3¨9gñÈÖp}-#ª5“©À0æçìUJ}¤¥@S|ÈÁë®PÎ}Â.)‘c­ûÇÄD@33Ñ+§¥"Ú‹XÕ³¼pb¸Á²>×sjë\~³™8!Ô0ÃPuçÁÿÜh†"~‡1\‚XŠŒ»åÅÔ·Cxri`žŸ|]LЩÔÑœG=6u¿ ÷×Â1"­8¿«ç±ù–hf´ÍοÜ4±™%±¦@ˆî;{‘åÔꦭZÿå]àÔ„J¬l"Ñ‚S9ßNCʺ»Â·mÀ‡C¬šóc( YŒE(ö“Ϧ (t9æõ12»ƒ C“†&ÓìîÏÏw›Ký!–¦U¹$MînãjHjoC˜äò!#]©ýΧp•¡ùòR`ÂB]ë‡9¨“#L ØC¾Ç.°ÜÑÂÈiï›~ o-aT†Â/Ù¢¥P)G%ª_^ƺ˜ÞXbÑùÎOS½ó¡¨ `a2?u÷”Šª–¯NØcW^§k!C¡ë2ˆÊÏS-±+Šwúøòô}zKv¢È»ÕØø»vxH²¢—ØœÛa}[/Ã&bm@áġ¥Ôá ‹ãÉÿ²m|"eP%§ÄÐâÒ™ó’!O¯0r쨧ÔÊó-ê;\å»Ðp$ÿxc€D( ®€F)£? ¹DŠÑŸ`¡ ÑüD¯¡Ef V¥Q8_@C0êl;é°s;¨”$ÜþW¥”…ItðåO)G|ò)u/ˆ¨Ù%€˜Œ¢‡É(˜6Çm)ß KÆ-މ{L"sè)ªCVÇ.í0b¯-6Y`‚é³cxjNW¥¯pÉ—m*+À?~²J+z:ð ¥+kRX ìH·Þž›mºB™[ä9‰‹)@ìš×<ÁÊäs+Pn΋ƒž9çŠÈ•Kè\ÅWpiC¥¾N(%ýš0xiRð„ñV\Z”À¥¥mz_yÅÚaî]V‹Óô¡é ˜é’ ÜÖž86»®ã^šH!lv1O£Á ó²*dads”´ëW Ž b 6H7L1qKtéõi‡~×hØú˜§eTëÊ·&®¥§%âš”‘v±Bþ3ÈÁ ²kë`‘†ub “6¯ð gËW¿mªO«O«ÃIÒendstream endobj 195 0 obj 1234 endobj 196 0 obj <> endobj 198 0 obj <> stream xœµYMsãÆ½«R•¿Àòi]µ‚1ß3º9‰SÙælGÉI˜%$$( v׿>o¾ r¥”S{v0=ݯ_¿•[•þ_ú¹Þßüzó늅±üc½_ýéþ滟ñ_f Δ\Ýooâ¶rZ]Z¯î÷7ïä·÷ÿ¾á®(¹S˜p¿¹y÷Ña½ÀŽ…+ ëm!Óiʇ¿ÿóÃ}š6;F²Ârü§UÏÏ»f] Í¡õ“+¤Sù˜çîðØUû}Ó>úŒ¹Â²ô­ ó™*LÉóü¡î¶ÕºönalÁŒ\Ýrœ'Ãç‡wßÿøááÛh—+& !5÷FÝúûa²0EiÃdY°4±äÓ™BãÄÒ¤ÿêç˜B)_Ä¡c»ö·ùØ´Íþ¸OÐ+Æ \,&eÁ•s+j4íþ©Ž3Ål&ǬtÓÃtÁ…ãúÕ‡Yx^pž½Ö¯ñ ™ï0ijá'Œå[ŽÃóqðã6*›m8lÃð‡µêÚ{oRó[Ý…&!D^Pµ›°@V»Œ„uDÂ$σCÕ´}ŸU4w<‘sç'þV݆ð [R«Õ-L.΃OE)óN]ÝwCá?Ȳ°NÛô!E$Îηï‡j¨“9Nñ°¨Æ`]vJp*/JAŒ‘ÃT€â$R¢( EªòC8¥t.óBC,gFÕìª_váta4–çþñcLÏážÂÑ0GK=O-YXCÇ2Ü)3¦[[íÂ9À©à'ÑE•.ß¼þ<ÎFpD>7)8]ýŒHÔá„á„Ø!pC#ÀXÉæé`˜âyèÐ%˹> q ÄÔ©àca _±$å„à’_;¡«‡c×&çA¸Ú×ÃÓ!A€Ã›>&¯3¦ÈicÁ ‰éKD_‘Jjî™ËDqwwìëîÍï2#ÎyIˆŒËW|¿hCZ;ÍÀcàý;[÷c¤| K‹9þ¹)spQjD²¿t …å’É92Ïïá¼+Ã=äïíå?^ª˜ÊH2*m]Sµë‹Î‡gQT´ qWѳU—Q&É¢B†½u¡$åïK³©7EÂ)çå„ÒúH HmGUs]µ‰$çÙÕ \–¢Þ—†ç!Ü/æºAQ$–êÊ1 ÛúSbÓrlÚ\b JPÂÒz!ij•Î6W7L5‡Ô„ñ¥Ÿ\^m”°ÈZeÊèû(dÉ eL %¿_Õ6ÏÇ]Ø/øÓx•@ÑKÄĆç*c2xá+å„¿‹…Zƒ”=\¨þ J„ò¿VƈÁÆH+¹é+~îbú„‰/EV†}’k§×‡q!hÅ‘öûasw·>DœÚc)â9ÏÜ<%%m‰ª“•Ûüx9*Õ³þ_©T¨²$~Ù5›‹) *ÑŠÛ‰hû%(X*‡ÿ±në®Ú¾„̃d¥ª•“·Âž^Õ| *Ä"#€.…R@BSEL¨áŽ 9ì²{—e•$T®yL ]-ëaŸÀo Ë÷zxºcýÍûô…Ûó²ªÊ™‚ºMùʼ{'h r38uÛÐÉ›f“˳"yõ’ Â9RNQã ¼ÐâëŠ æÚòSƒ¸E(C¨(A­PwlÛ”þƒK¢ŠÄôö(aºÃŠ.‰ À¯Ôyúßòt®â‡,Ìå§ú%å´+Éñu÷ž·™›Ù©Gí—)ÀçÊdg­«¾ÎÒ\Œ|Ú 1:Þ7ÀêŒMSºð±‘ü`¹£*õ„–0ѪÖš:çš™1{¢ðö¬hËD$ }-ˆ¥pŠl±(ˆM}E;×ÑÍFAl¦¡íáØnÞ'ÑgÇPŽô‰Ó'}šZW.ËFa(ûGOŽªvÇ: m!ùˆÂÝ.‘²$Œ/üÜú‡‡mµëëoŠ(Òg¥)[ÿ\W}ÀsͼMºÛ}å5U|V¡Aúûù¾E;Cn"nHbè\Éù ¥XÐË슒[4µ.c#½F¼ƒpã5Ô¥2–tZj›Á6%Á¯ÚíÉmhmóê¥äݤs £Æx›è9òQÍív}ÂZÉè6OQ•áŠvlô–Œ¯[š—·¬??UÇ>û3—s’cv¡ xË=3`‡€d6› ‘°ÛäæÔÒ¦\õ­³û×}’Å`&¨¯y9rʹÎY4k©ÇFîÅNËq"½Ž0yö:2ÛòL%ñùÛuÐÖ Ë<üŸ6¢ƒÎæÌû”êÊ­0¾u‘S¾Ð#¹0ò3‚a½+,‚#»Ö'”ððH³àÙî1¢i(Kz¬ør>qÈÚá4‘ʾ“oDÕBP:÷)O”!¶óå:å‰^ˆÿ„ RëÔ„ 8ÿ°Áç!Ÿeöò.‡7=·„¬Ø&5qBÕÐ5ŸC°yxÜ2S–û~³i¼ñICYtÍÞ«OA¾R|G&·ú:“W8êK_© j`§x«GÆ×44dòô5íë8oÐf©^ ˆ(AZç+ÍóY³! º yÒkð%Y>ï5¶/ÕnÉóM>i©u~¿´™/–h¬Þì/îehé±ãÂ^ÜXêwÚíº½üJÁB¿Ã#ÈrÃ+§­ùÛèÊ|ÛMPµIë8Y¾úûînîÒSJ€Áb.¨rßzžêbäåYYÕ“÷škúË÷ÿ¤¿½ª\@¯°—:ÁgZ9‰ØIcp܇ˆ¢cQŒøs9/Þ)–#¢,{}@f°<‰‡l9’-ÄcöNûœŠ+ Ùõš´ˆ1'§2dâKÝ Í:ì aÊÕX»—­„ˆ"Û4}Ž (ƒñéß2=ƒ|­ug¯Vl)îè^ËZnüÀù˜&r]žüñäì±HxpJ Oß<¶ÑKÀ±•*£ i‡Äðš¶^àk\Áp8#«§fР§¾EЧ¹V9 1,!TT¼ÿïüU2š ÞæØ%ÅåÿR¨©új³{*‰âïŸ êvDõã‡ûÕO7?Ýüú endstream endobj 199 0 obj 2254 endobj 203 0 obj <> endobj 205 0 obj <> stream xœµYMo7½ þsÊ*€†Ëï#Y 1 9H"ßtiÏ´äÎŽº•îÅίßb“,vÏpF²ƒ…‚9ì"YõêÕ+’¶¢þ_ü»y¸øóâÏ›ÆÒŸÍÃêÇ›‹ÿÆåŠI"¤æ«›»‹ð[9CøÊhJ´^Ý<\\J¿½ùÃO§|>_hb(5ðÍÍöâòº}Óµc·ï‡0YŠcÄ)5Í]§Ék>³„…¹BÏçJF˜âêÈîíå¦k‡Ñâ$¡.NøÉhÂ…ã:½y÷c5Ôß\ù_”$Æ A ° Ãq¸`cßnƦk¯›¶yØ?|sûmØ*[luÍ÷_ÍŽõƯÐï7c\\0ðD0Yµ¥ã2Eœt§Ü¸\O ¢ãqn÷ÁÏa|þýuX™ƒsMç»ë»‡iBËyòÜø±ž 8â¨I›Üuÿ¯iq4eæ2pÅzy2I‰‘Âà·quÉž{ ‘Ú¹Õ§É;DQÇ’¹j×lKþYÚz6R%·YN¨áÉmÄOYK.‰b9@tˆÜÛmã U»is–0-Í7>ª]ŒÖD2™,ÞuýäHC¬ræÈÉ’XŽ‹ÓLF„“éõ¦yµ)ÝùäLø}쫱¾ÿ\„…(â*õ86íý´U)•,żêSÌ•0i}7 j¢$îê©ÙÖ[RNfisbµv–Ìüùdî#b9C(Ôp¦.:J¢ÃûÛË)gÀËlžq7Æð9£2ó¡?vÅLè”E„1J”*dàë×a¿Æ-è ö{ Xšû¶ž–dµÚ¤•›vŒ>¶°nr|ÑÀ5M¸é?]ʼnZ[ƒÏv¥&Œ+w`×Ê”ÎdÔ¥!NC¤“ÜÉ#¦>·ÄÚLèÕn³ßAVLk)”bÛ:2”æ<È]¤‹é|’8L¯MGBb'§yÄX+ƒíî"ŒèF@TýøS Ç£Ý3š´™¿šñãd^ƒ±îë@0•Q$ŽÈë h‰bž 2áóÖaìû Ð_§ ²ÜäZ 5EÏ…/>÷j tê\½¶%ƒ@ÏT» ¼¾ÈNÞ M‘€D¦œM¦$€OW 'À¢Ê°úïN®`Ù|…Ǫ)[fã8õÖ¶Ýþî¾ J¡\Î’ûþsPY·: šçiŽSèaÌPùíå§«Ï!{×’B¡qó‚újµN'ç+LV”·œ¬Œ)æH4‹´|*Ÿ`Ñ,^¼hþ쥼ØÁr\íþ:Nï äæ>qƒRËÃ,ý#_–¥Èû0Kl2´«Ý.²¼£xÆY_r…€E²€iÛJdÛuª«‡x1¤Ôû”åòsÕ7UÀ")-Yeb!Õ,Ø·—Í]<Ä#m5H^¿I ‰ž‰ü:öšï·«Q¥üüîýÏ7¥CAo!¹ÊÑ ®b2XèÆ@KÀ¼[ÆEÍuë,â‚¡ßÚG¬n‡{e<‡ÂêÅyÜå²ËÑ Q±CEe‘@¾pA .çë¶¾«ö»1V?Íh²â«0‰_8ƒ0¿ A ®°¬Fý Ä xVG°OÖ¡š¬º]оíìàq> ±,G†MeÛþì!¯¢YPDòÈKF.úšXjEÎ×¶®·©Ù f¬Õˆ ÐÔ±C}QGKiŽKÕ}Øã&mk[¿j›$=¼RA˜‚zm#s´R@oA©dó\kÆbm¬°ç ´WÆ”eQl «GhBt5/`=?W¹çF zFyn½m=4}àqà!e¤Ì@xµ­ÛÍôm©Ý»ú OÃ’ê]bK•i»T%5›HÉ-!û’æÅdóDù-F‘ÔAûssäâY/ZW›H:67 SM[ö>'³¬Ü2 jÄÀ²%7,ûÀM8þí%!$ɇ8Á÷uܹ ¿˜÷'p/¼Ž:!ù²Ëø^èD‡eåaßÓ5;owÖa¥±Øa9ªôËVJÎ7WfŠWaßÇ*¢õQsuÔFKøH¶%IQnë\“b¦K òSïÍ/ïn~yÿÛ便€ê C|fr´g“S²Ú}štc¡…ç’5tC¤'˜9—¯ ÕbÍ[ÜiÅJ -G¾€ôI7eÀÉØðêcèWÓ–Vßöá6E q‚Þ…ËÔ6¤PÅ®HÍ òÃsx@‰Y¨Â\Ð2˜»‚Ö™‚Bk/vüaJ¼m¼œ<ºmRÞg_;hXrÇCM0Y£ÖõãIí ZGŽõ Fïºi;ÜÈ ÍñŽêÄ>¨ÉÍXÓúV©îBáRN/ã:µB6gö¹þY€ÉÍà?꜡c…­[ñ—÷Ïs¤äþÙÍûç„ûCCh†nøŠ`[h© CuuÜ¢t~8¿ÓA1‘JÓÐì>§Ü”xFÐm”VÂáMëh¹žI»¦½/žŠ›•‹ž{Óí‹·Jø•º…ƒßGÖÂß ³òµÊÚXïbµ{æmäms_oÿ #‹Ù»Ô^Ò2ôúâîK@GaøsÀšZ„1˸N‹Aþ+Ø9¡é”Û¸˜D@£ùb ¯Dù±È|ÓE¢5‰Òâ =£ê“}ƒr»o>ÃÅÑb¹nßÃúoº§‰;5ó5y¤YG¢ò°s©Ö,Üã¹|5Z–GiÎ\‰—½yMHzo¡^‚h“ÛðÌ(™ëÞ0†„…±¹­½º’[Àx ÐSSÅ’Ê öγ> °jÖ¨¥—’Ó¢Ñ#,½òÿy<8~,øB#³7Gð«³Ê¼M5ñÉP*å°ðNOàD—!x‡D#ðÁ­p›P÷I°Ø©¢ù·”A‰/R ¬ÆÌbª³xºˆ[òEHá|†ÉYºœe XϲÆ$¡Ž×Óóë/å¯YÀEZt%ÿRWF , ¶vÅ-d%ôùI&º’¹’®œ½À–œpâ~z®¶ÏÞO®‹7º¾€q|ñÈ¡’.THñEíëê„0&GhöôˆIÝoëØçC æ¥ÝìÉZÙÃ'ëe u¯‡t©å4¦Ç«>¾öO'É í´9j(ÞUý}´ Ø1 «ë³¾È÷©à‹àgùF}k£@]M?òI<¼½YýzñëÅÿßü1endstream endobj 206 0 obj 2506 endobj 207 0 obj <> endobj 209 0 obj <> stream xœ¥YKsܸÎYÙÊo˜[ì*‹!Þ€+•ª<6‰Ú§6¹èBÏ@“y™äXV~ý6ˆFƒä#9®=x‹Â¯»¿þºQlU†ÿðßõîêãÕÇë¿¥Ö»Õ_n¯þð—+& !5_ÝÞ_Ű•3_]Z¯nwW¯d!_ßþ',/ùp½Ð…)K¿¹Ý\½ºÙÿÓ·­+™^1V8¥ú…×iå5w…ìWÿ»îâR1Z*Ê‚s¥žßSšB9mqa÷Ð/âðkm~<µ¾é¿J8süº®öýGVÀ5ÒÒzßvÍiݵáOÒ¼ÔdÞÝx…+ë¡pŒÆï¾ûåÝíœB–+™l<„5€×Ò‘1Ûõi[uþMø›âE)ÈÐ÷á“.s â§~ð¬u ?}³¯»xuWXMxlêßúÆï×¾í7_Â.n ÖµSµ«k°)z% ]G|¤(˜É–Cƒ¶kN¶û¦‰Ÿáhpnºæ®êšús{Xk“©·U‡Ë53ék-d Ü)¢u¿q¸¼4S¨z)>5üÌýš“ûïOÛ-~µ†.Í ß…-¤µiõá¾?R@ÐÛäúÖ¯û ®…‹'ó6¾©?ad9¡ÓU¿2r&’+¢½¶)‚ 2Øt¢(éÄ|¸x¾È~ÝÕ‡è)–V?bqîß1ÀYŽz¿ŽÚÂÉ’O#RXé.Y°>5M=¢ŒüÔmcHÂÕ,]¸ÇÜ ©’œ\5uõ~ëI¡u:íX5ÕÎw¾Á8 ðKúUÄžóÂX—«îÍp…PN™ñ‰F:F÷mb.söRlÖ]óTŠ1?9À…ëÕuˆ‰~%8©`s%VÅ'u÷êîõ,ñ¥Õ™øn_è_¶½‡„+8Sü‰)fšf…n²SÇõŒJ hƒâ 3œL¹ujgbÑàÖw]½ÿÐbú—’¹ç¬ev`íÏ])þáiÖXS”:™Õ;bɹwßCèö(;! 5ës-üt do›Ö£’_J¤Aù°œ)&X%2]ùuýÍzîvàu®ÌËn§CuáÏÂX59F ÚùØÄLoJ²êS½ñ‘¼|¦¤jÏsþ1b µGQþl· ©EJM…?Ÿ(‡#2:gNQŽV‘aI<ß,&“1À}î<—ÎPW€$]3àíÛh‚&èÿÏ‚ž=ÓªºEúVоˆú\:~ÀMtèöP¡k@jhC€`Å·ÂiÚ“bLfßc9†BªÅ1R9ñ;êS¤ˆ&r¼[5ªà¢L†/«±Cª&"»F'â†ìËÄí?gk |t(´ƒjx×ç[ÜMÀIzäQ`âKÑüí`SÀR)²+ÿ ‰“I9•€<ð‰XßGD”’ 陬¢ˆ$cª1ž2ÛmÞ¾ýÕ¹ \Êôû&þ\•#ôáÿ KKþ8w‚ƒÂïHvm',½g[A5!$ÿ4ð"”ÞD°1êz%#åPÉ,^tÀ17û_À¿?ô·=Î9KLn(ò†Ž;“ý`3£üÅ"` J*Ócì±ÌïNÍóÀ}IªlOiƒAӀɇçd¯¶(~ Èñm† ð”×ÈѪs·¤1_‚ösWu³½pžTAŠ˜20)܉OSÙm‡cPž˜`À«ù¢Í‡ÓΧVÁhÊï6 5 N'³ÿ b~;ë_ø”Jðb¶µH’ñsé¬JJÁ»WÕ‹£!jdŸkh|¤›Þþr`]½Ãí9Åþi‡›C¬¥Í÷‘1 AÓãe@¤6Ë´L,Ä+©›â¹‰Œò’ «aƒäZTÿ„!¨&2ëÜw¨[ C¦6ëñ¡^#çAmLæ> w+E¶Íëì½Ð Õ3LO3ªq™M°iw8Æfú+G;ú jñ|âš øP5€¬Eù¡péåÙÄMµ~¨÷þ‡§Åkœk›³1lÿ²6`ºÿt_3`U”JÞ&À¬ˆ%¯,JKL™ÜšBrëþ«)·-³iõq“bÒT”ê®õÛ>Vƒ¸Õq”aB Ü4%G‡ZY‚×ÉüI¯3EHL;Jª€ø5Šý0&P#±ÿ"W€œÔ¹̫ݴf¨wÕKô.ø¹Cg¢• )xl„Á¶Ôƒ0y·Ù·k± 0Aýö×ÅÉR®K]3ãD‘ ¡ñÛ4íz$žÔ O§ß5‡*43Hµ²$ÍqœÑ»G2w£’tXV˜ tlPô"©Ac*š-¯µr\ƧŠº+¨¬ƒO´¿Ì÷/°.YCeþ6MÕJDÓ€ÁÁ·BÅrÄmªÒ¸<ãÚ#ù:û¬0…ÖApœêyƒÎã´ *á.uO1BM$-–h®/GýØÊ‚(i’÷ø€£ª2HÀI÷=ÓÜ„XH:à¿ûž 2:yë1ñ@Œ)=ð.eM˜N³æ,ÔFÇÿý¯ßÍ!©æ8UÒIýB½¶ ^9?¯¬÷‡#ç¾’F¬}$)¸©ã"iÒaMT Õ”]µÆEŽí@Ô <•gëõ©©ÖOȲd6 ~Xj“e·ñÓpxñt¼Fg1ÐÉ£9P½Ž¶Çÿ P¶©ÌeES¬rÒ'INS¬}Äm–i4Ç~*a4—êH~ƒšÄÜù•½ÏÌ‘ì`%š½C>—,¦+˜Ä„\A‹iaéoâJ[B3ê²àWswWðÒ@ñn6;·]6Æ_h “óÖX"FÖ,HIh´+Iý2%YhªÍܦú#âá|; –æ|ÿŠž´ƒ.»Š1 ”,Ó^qz~㻦^ßÔûzWÿÏÏj$tW”j8#½• zzYê êxht)þ<ìÍ>-M k’ŸiiÁ74Œüà÷¾Á*À‚íÄãñ蹤Z¢9¨rÉþjÛ2Òzy÷ú ª™G™€dèbVÛøä¨ú…IÌì¤üO·…Þ:ßv2k„ WfÉ9?–­úc{nR"œþö.=} 5¨Eð8WÔ¼7¾«ê$4 Œ›¹‹ÒˆÈ·é½†‡z–®Óv.ô@ÖƒR™÷‘ùQu[ÅõSQ*ÍÐÓt]”ôX9¤ÖUKï`&?HÎ9iƒÍ]uÞ'<¥R™ý5S*£Æ©lóÔ£·ꢴ”¿Iñ(™ßéx¨Ê?mOï[ÿñS"„è(uÃáYX_FªíP;€? x¥;½Q© ·¦‘—›¥x¿x1ýx˜DŸy êì…‰/Ó#}ž—6`Ä ¶’Ú„& ÛvqôµMSû­8Ðr »]CK^h`îkàÄ2É{íðííêÇ«¯~V^†endstream endobj 210 0 obj 2697 endobj 211 0 obj <> endobj 213 0 obj <> stream xœÕYKsÜÆ>äÆÊØ“‹ªhGó~°R9X±otl™ö‰xK"µ‹]aQʯOÏ«±¤âJªâÒ*ì`¦§»¿¯¿nPÂVÔÿK7‡«WW,<Ë6‡Õ·wWï>0½bŒ8¥øênw_`+g_M‰Ö«»ÃÕus~s÷Ï+ƉaÒÀŠ»íÕõöØÖþ)·ÄQÎÒÓßü#MsyÝ—ð*#Lº¼¨ o¾û &§sXDH‹~õK Láæ•¤7Ô¥']Sý¶¯oë¾k6·MÛšÕ]Ü{v3ªˆ”*½F’MŠ9›¥·«¾9¶ádN,eùœã.¼! ×VMo1µz7´›¼…Ôĺ¼zS…gœA¹˜zË ôVØ’QB Ÿ;z-©€¥lµ;äKÞvDjGñý¦«7ý>ü"±Rä_†sÓ>«±Z¾ÛòÿYx ‹xöU³‹·pÊŠü¬=Ï(¢,^öTuÕ¡îë.¤§rÄPÉómÜC(§òzXY•èXb¬Óyù9¥˜á]ýqßmC¶¬…åD›è}o4,¸KÀ2ßù0K$íäŒÌ&wñ0-óáÛaS‡ó ΡMU´Ifq÷àcK-Ë’`Žá Am9¦OÁ‰xÉlþ—ܺëŽ]Ú@J“?TÈÏÁPHZjÅ€0GÇtß°·ÁhÀÇ´{zl6Åپǘú€2.ä(õ1`¦Üe8Õ>%:@H †‘܇LL¿ØË¡Ý×çè{ lÇòVOÑÏTp•3ªêÚ¸½Th÷6¨b%›—vÑfôkóìÝ)ÆÈXse ƒ†LWC [B( à˜¯vÛÞ6]µ½¿ÞÛsˆ¼…W®ßǼáÂñlÆû¾­Îõ7!8JãDÎܨBS||î·77Ÿ€^މð•9Ø èŠŽMð?ò‰]º…ƒ4r6[¹=)p϶‚Øcþvy§œ½ñZknà˜Ré|76¹ƒ¼pTcjŸ›‡¶Þ&ëW™Dš¶¿³DÃk.\œ®ˆÎyïÓsDBÐ’Xå2$vñ!䲑BN‘Ï¥\V¬öÁE„DîÈ$›~Ñ…ñÇ Ž¬Rw»jSß$L|&9QJgÓ¾ÿÃÒ \¸E«ªv›GI'1îU×'¤Ká5BÞóS,p@¾ wØùà0& {É1‘ýÖ©šh"@ŒªI®c`1ȹÅD¨VC»©»¾Š’²¶ï¦>"ámͳéÿ8ùz”`½›í³p±BÔòª¯¾¤¨0ËòÑûúS’BL²œjõ>5*âí¢ˆ‡*W(êçÑAóXi¨Æx¬Ÿhž)úIç-ëHÜH |J¥B8$ÜzÓüùã +€ßg„Ëÿ?÷¶ýå\w?†¸ÀzÎ'Â`*¾R©Í¼eŸËq ý=a¡l¼@ ³Ÿ„È#›‡Ç”¡ÂâÒ—Ë7OU4)nYõÍ8ƒ$<›ÂP~õ(4¿ P ‹ 0sÛ­x „ª†Ûvä>°Ç¤P½È[¤ë-Ï» =i7àæŒ#€þS´8A´nñG…ËÏ=¸x2‰¤/ž“cóÍàJŒÏ¯—€Ú Hw<„c@üÙ©ÕТ°Ý û} 4cÆa¢‚)¹(q,%÷sèLNüKj6 §¦ó´ÆntT±ïƒ6 R¼8CEžZéÛË‘u¥¾Ê_DÇiÎõò§Äö´ΩolÞ¥®%xYCR˜lësV¢ä¤\0…òˆ^Nmã[Peg©-_Oíã)AŸ3¬uÐ{F%É¥ï©rÖÝ_G¿­!–‰5ããæ&n$·ì+¶»Ÿ0;(6CE÷I˜X… y¨>ï6íÛDÜ ÞŠ@…–ø.»þ¸‡ã1äó\WP>¥.ƒáœº[ß4^ì“M I±¥„àBåàc,ɉø¦vE×]ÂÃû¹¤¬¼âEeÕÕýе±—ƒ–S±YŸ çXmŠx=û˜±^2trÊzá0üP 3 e¡!œ+1‰sµX"(Aß,cš:…ËpXº»å~¦ÄÇù¦ö<̾'GûÆŽÄfªê†\¦˜×‡c’<ÔmòÐKÞª_ ›ÅX2"¤ábqcDùj…Ê}¼-*tqHw]Rîã&‘€>CÒg"ƒ `-ÓšCڣˢ§Ãh·ˆ3Ÿñ4&®bÊÞ—Jq—RÁHœ,gFc ÐöûsÒUΔg×Ç­!RžmGXšN\ò­éË2•\léà¼Í°GüªÐ‘f7<5X˜œšO‡Ÿ)¨×1¾ýñtJXá·Œt~”€¤»¼dÙþ˜|°Î0\'ŠDØy6}J#]tÓc,XpQ#1·Úcb~‰uД©vݧ ª5p}tË$ê°OåU¼[÷ô•€<‘Ï@)€ÝAI¥GQõÐLôrW£_èG¸Ò"H3³/ò: Í^íª" 9ÑlŽÂé0pÒùƒñ¥óŸXæ´¨aŽ™Zg'ìnùò Ê6Î"`p0ê›øäfa‘#«OZ´ËâE ’e*”~H4¦ÂÈ¡3.Ýû$¦5 ³§DZúÝÖ»*˜yÜ@ÙP§ÄWÅÍ;ã¶$àòý¡bI¼?NX!ÀÙÕ4î?VAÆ‚ŽÌKn–Lž"±x°·É) ¾18çi2»Ûù˜Œ’ÆÂPͱ8ŽˆÇ ¼<£$IËôáé1¢D€,ÀžèJ=î—ësêC0DŽróÉИ @ãn"FA÷ЂÞm8ç¶òŠgǔۊθGÌÊšendstream endobj 214 0 obj 2450 endobj 215 0 obj <> endobj 217 0 obj <> stream xœµZ[oÜÆ~ò#ô”Ú€4ûÅ( $nˆÜ$V‹>è…Þ¥$¦»äšË•­þúžáÌœ!w‡k¥Má³äpÎíû¾sÆ”°KêÿÅ¿«íÅÇ‹—l\KVÛËoo/þø‹—Œ§¿¼½¿/°Kg¿4š­/o·¯$ÑD¿¾ý^zú‚d„)®à¥ÛõÅ«øG °ÄâRå—ᆺ¸Ò7Õ‡M}S}³ºiÚfÛü»îï^ݽû³Ùþ×J#¬¾¼æŽÈñýÛǺt. £ÒýÏ')‚QG²•ÍÞ??%MZk÷CÕúuA‰e.}thª¡^ë‚8Áãòaß´ñieezz]ßW‡Í0þàˆJÄVìßVCדpÀyÜÀ;œhØçZØè&2óåm£Ýwá£Û aš%'ýÕ/iÂ…ã:.½}÷mµ¯¿¾*‰qÂÆ_! qd w½$Žà‘ÿSÔš¾ë»1š()“mOͺÞÇÈp¦SÀöõÓø¬"Réôº¯6~• "‘qµ çSÔ¹tÀ§°d$æEÝoºj2C"ÀÔÃã¸…à„ <»Þ—œçQÏžbY2ÝDbþ}j†ÇñäPç<™Ó××~íZ2(%¹C¨†C?æ6¬ãs«ÀP†±Ù–ƒÊùrJÚÕÐtí½Ã¶d€å„Üb¬Ks6-݆T#UZêÀ™! ë…´Bû!ö4Ù?„„dŽ8jVjJ%AÏXôö]éÌB¨q«»Wu“Ž# ŠK_ȉHµKi¶»M½­Ç_¤%–‹ôËPyW¡ÔÔ£#†ª»/所·jÙÿ¡¤‹‰#͉ÓõÅíÁ{‹ÛßWë¦n‡¥ÏX Æ‹ä"`µÁ]ct8õ;ŽDÃIŒÆc5 gžÐk¡Ø9îùÐ<ÅE«lZ?`¥¸N%ö›¿Û´»C@j9‡˜),sWõÔuÝû­+KñZR/ÇXzŸxÔª~ˆL!9qìKµ솺†á9dzÃÛ 1¦kÓ!5çé!sàAe1SrIHŽÖ¬ë¯ÚÈinÊ^÷]¿­†}¬6§¹ÅÄ/òQ*â~X¿yóT¯B˜¤¯K™>sNÍ èT–ú§ÒÄßY$×î,QÜ ¨­øs);ç;]•>l;£›öïš?¶CržÒ¦À^“Ô8¡Ma±tŠÅ‹éêþ믿P)Ö¥æÙr÷:ª./á‹BêHîÀ#^óuk£üˆâƒS>}V€Ÿ(BîM{3ã¬ù¾ D”V)ÄU».ïÈ9h:âÛnû¡ô<«À›Š>U•o+À’@ü  , »È©¹pJâ™°f =_3÷‘àÆ(B±?°d Éà9àÔ®ÀL“-—„Bx’—fY?¯ô›¾ÿ囿”œ³NªiîCu:gÓA":zŠÁ \wè4¬NÏQmôܲ“tžYê³äø£\!%RO)pµ©öû«¨á ySj|x ´š)í½ü]Em£žÿ1BéŒmB&d— ˜ËP™ùßÿpóÓßýsA—Q‹Ô~.¦ ]•Bg6嘂Á ³S MŠÂ˜ÞWÍfiTYÁΘ» )Ì Þ%Oô8‘·É×uÿPX†9ö6w1A½hàŸ ãUýÃ!‰èü´Æª Áë$:á¬Vö‘µñ™‘ö\Ú B—oúq±¤ ¡¦C°Ü¾Hß+”¶…L5§&f*|?Ò»VHïX|&7M÷ b_ ù⢲¿™uÞ¢õsiKe€&‚w]l ‰Õèðß¿‡×˜ò/±'ZsvW g¥Ø¬+9aGÂÞš#v´/eÇnAÄ'‹ 5G‘Áª &Þýí}ùÁÓ\I,é>x ¾È%¶»U[mž÷a&bCe^@üp95#ÝYár‹cMî Oõ^^ƆžÖ¨iºÔ<™œ_Y…[}ªÂÇ$ÒžaÓOŸ»Ð–x“%â@›É;Žm„!8œ85JáqS©[äºà£k §¢ÔÎtþh0x~ õªùª^“RðÀ&p.|†ÎÃҲܢìßVÑ P‰éôÏñ8\£>_ œŸ¨8!ÔŸwÍeøåvú, Xfp¤’^‡Óõh Í²’XU›Õaê4Œ›„oÌðP‘ѹo%PŽôØÜ0DÔLQ4gÔs”4ÛÔ×›P°‰AŸì›vU‡R0€õ“ùÈcý 4»Æ¡úWÌL†Õ2î.&ÍåjÕÚ-±n‡ð([Ó×´]{½Å[õÍЄú7JRåÑd’]yÈ” FOê£ïÀòm,d«ŽÛ_踲ø”N—§-õfÃÇ?ywÂOóB„h[—=„`TÛðèTªœx;±3XÄÝQÔÁ"c0êhºqhúCݦ¹¨ -2éۑGÆ¢Óp+ýg•\N3³ÛùcÆ­Ñm^Ô¥jžM9¶ÕgHøMó!÷'¥¶ˆ©Æ™áGáC læ^U»8ð£ BãÀ/"Rq6ú¹þ¾³ÈŽ=3œºÙ&hA‡¨ä~ð†s‹ ¢¾ PsµF@µ¹yˆåàIËaÖhùÎ%ý0që|v½+Íø¾ ¢Ã8#~”°j)…!CítŒúñPïãÔÿ$†šƒ‘«PDÓ)fu7…¨€aмäÄÿôج"ÞA%¦MO›ƒo–õcÒè5Î4ò*¯—¼¸¸„ù U]&ëýÐívQ˜r‡/û!®&ƒA¦àJ›…èðX > endobj 221 0 obj <> stream xœåYKo¹¾ þs ´€¦—ï‡Ø{؃쬭ä¤K{¦%u2Ó#÷Ã’òëSl’ÅîÎH»×Àv±X¯¾*’‚®ˆûþnöß/¾¯è¸ÿlö«¿ß^üüE𥅕’­nï/üteuÁVZ‘B©ÕíþâR¦à?Ýþ>àjú •LÂG·Û‹Ë}ݺ»Ë¡éꇦں´½B‡ uÓ»Eª Âbs5®ñ‚(+ÂÚT„PÒ‰ÐEìË—M¹Ûuw?¹ßÖÌ ³|µf¶㆛æÆév}Q‘rZ%òuÁõ±ŠÚœRQ3iω˜«øó:·£-¬’<ìÝ”CWunWg" .ƒ ÈÌg¤à4l¸ùíÓç¯9ù\”ȨzÕ¶‡ÖmûP¦ãrÙ”»×®^s£ ©À†TÞûoàZZpõÒW-|7ZADó訧²-÷üšSZÊB1ïÛäT‹K4ê6š1ItA[õCÛŒú ˆvMõÂP ÒX·Œñð+büÚ‚:BE±9uàÖVÓxòsÝ?Žú¨B¢Žýc5®‘‚0ï¶0`3kb,<û%ÂÈŽ. É¢rwŽò†§§q§},=óõ7·‰Æ!°ÂÒah¶Á»áV™‰w÷£Vpzžw¡(,9ïBÈ}cÉò:´Ð]Xn·u_BLθÄ<‚Û—îçñ. ›T)É‚¾ÒZ‰yÓy@¢rÂÐ-å˜ „sÜ{h¢³$aüØfzb³q£)¨AƒoÃn\æ¤`ŒF¥šCcÄGT*jyï*‚sd¡Á’Î9Îðëm-iŒpÐVݰës¡ÎY!,šê‡º¥)Ô7eÜ&Ô9C žP–®Yvõîu4 Wñë§Ö{ŒÏ­@?y,…E*0}†®n²WÇýÑõÛëkpJŸWœ©…ß2/|P) äq»Ü ájž-6«qŸ!ËG«ÁFðq´1¤Éãh_® "I4žO·¥BkJÝ®I}úežk ‹fÍ Ê•™‰¦ìÝY½ÔuïäÂ~ü¢‰›TKºÿk LÆ„ðF!ÂÇD™ù¿«·1Ó PD/x 9*P¼ 1åt‰‚`_”(_yÁR†P 7”5÷)+wIÐs´2wi×àAc‚SmØ ð0Ù uVò›æ»C6±Öqã”Z¤Í‹¸lÐö ïr¸DϦ:2I„”ìóä~Í?~þtûùŸ_²f— þËí²P†b #çëÇ_>å$BJª’£Mƒ‹Íʲ- ³VaÒ¿$p¦iµ¢VîNäªQPaé,WxÞæ§ÞUw—y¶Ž›“o³°»­îËè Z'Úvhº¾6½·¢‚BÇÑýu ^îêÿzbf'áë¤È®ê{@Oq€Ô ,5Ù\ÍFNÞÄÏu³=„ F ±÷ªªÐhµtÎ;‚+ÈY ]sG°·qx Ç@éÄbÑ–§@Oà×Fo­5ÜnïœÃÌÄ××^PJÊÍ;¤ÝyGa1”ñ×±ˆü¨6þCá¨Àôó—’³¼àð?Mã‘Í“NJ¬™•©§²ÎK³.géû¥m÷]uåÿä$*×– kÿê°¯ÙRþ'É' P¥dÜ4Ƕ¨_+”I3…çxÀ€°ôcôž#ÈÀUÌ¡µ P¼õ” ¢*AzûîòåêÕ+êxÒØ„d]`ŽNªJ“q‚·¶¤ø½ê8Á YÓ§0lnc lƒRþçÒáî2¹¢žAÔ„Ÿ_àÄ«P#Œ@œ¶;QŒDË¿N¶[Ef8†Ö'JMÚ„ÿ‹qDé=9BßÈ!v"Gõ Œ°iÄÖTjWbŸ4Z‚GòeHÀÍÐ…£ ™Ôö-Äcê'«¢n!§\™Çœ r¡*Rh+Í4'éE˜jÔ<¤²$–FÛ”»ÁŸèp["Uô-ÙœXd«„h½1J¾û<ç£pŒdÆù(É’>?ͦnš¯¡ÕY …Z­[´±Ç`0圬§:Ï6A )˜NΙdÒ`Á$¡¡U3vyjL¡‹`ìÈ|’ ùNxdÜ(!·ñë`}s‰Cç/ŸSƒŸßÍãHŸŽ2B§H)bèÈß)ÈØNç´l_Cç”[¾ìÛÁ½ »Tx9Iá·ßúp1¢iÔÖϸp¡wÂêØWë1â¹5‹ÑW_ï«hq¥ƒ)î‡]hR¬@Ö¹™à@n¶­¾ áNÒÍ4ÿÿ¼S G ×ÝGý>4ÛhCˆ1…5½  i’PvÐ|ƚͣQï®/Û>ˆ8´ÖF]&ŵ˜W¬„~¬!Ü`LOÍúqA˜! ÓL«l†}Õ„cµR©V_…ÖB0û¾&h©Å&ùŒà)“^,Íà&£ß¦Œá´%†)4i½þ^£õY¸§à;8?©]Àk]fOñúþ… yïàFäm¹Íá¥lCœ‹›Ïfÿå¶è‚ë§Ó°ƒÈÐH@ÚÚÅÜMÕ·õf–‹RJ€EŠh”m!ä³ã­ÓnÄy¶«kÌ?¨‹g W=0гÏOe(±Lḧ½ k›ŠÅ3=~&˜?†D*È9f$U ÀD™ «s¤>îŽg89ïóU¤·TdH! /r™ÇúáñDÌÝÈWOûã¯X‰Üƒ‹:.äZ¼³M ÓÈ’L%R,‡œ¼§+„í{+‘2<Àd:€ÎÅ|>;jØZ²¹B°‚}Ï©ñ 7zrì ²É“i®|öYjMJvø)EàÔ[¥Ä­ÊM tŠïá"$ÿäMŨśÊ<Ô³v(Ý»œ0vn²Y–ù‰T=©y@õ\z$„“oþá¹4ÁqPz8´â‡Ò¦‡ÃÓh‚’Q¼w©´I`sßö¹,¥¡å»v‡ç,Ïa„ºÖh-\Rø Ñn㯷«ß/~¿øËA^endstream endobj 222 0 obj 2660 endobj 223 0 obj <> endobj 225 0 obj <> stream xœÕYÛŽÜÆ}_ä#æÉ°o§ï! 6` «ÈÑðƒ^¨Ž–Á 9’+9_Ÿê[5Éá¬VAÀÒƒ„²»ºêÔ©SEJ؆ú¿éßíñæãÍÇ kùŸíqóÃýÍ_þÉô†1â”â›ûýM|mœ!|c4%Zoî7ßÝw÷ÿ‚§=- “ÒÁ÷»›ošñ©ùž\¥´HOÿˆ%Â9›—^î‡úì—%Rqž–ëjë™"–)™ K”æLZê·Uû½_æŽpeXZnöéQ¥ð¤Ê/9b¨s:-µõ§ð® VãUŽMÛƒEœPaUZÿ*—­lúp #ZÈlѾÛ]0I(â¬ÉÆuÚ€r“mzï—4±Âéü~ÝaSKåùðSu®Žuò”RÄH—·x KDQÇ𦇱î/Rƒ·’q"À-·B~9×CÕ´õÎÿ,a/-³ÕU¼¡„ÐAýPƒÜ*Ñ™CØŠ! !û.܃p»È'íÇaŒ IŒ¥rá>D;HÚbfXˆ\óïjhº¶Xƒpqšß¹O!äR|i;žƒå@+t>µŽ`á‚ëüö¹îÇÃд‚—,áTçðìÏÝ1º–JX7Áµ>¾„dmfHvh³ʼȷü)Ô{ó§C7 )¦‚åg»°%ÓDr<½ SX<¼‡Ó"-,‘Îf—ÁÕÕ!lme,Ÿ9öÉ?À3€àY.3îÚ7`Ü_xKb[Lu„*gsÒEó1Î)DÃYÄ2Id.‹ïþ¡K×WRfì~J‰á€ƒ&yQ¼Â$z¥:Î]‚¿u2/nŽÕP'g®ŸˆÕC•àÏ$Ïž{lº1߀3Û§Ë ŠL´jÕ~l·÷$zÌšxõ–Eàv›[ÈäZ€_ DÔä’·€À»˜WÑÃËˆÝæço!ÉãÞ/ÃC7Æ‚ dàÂòe)t«‚º·¯^¾^-%¼ˆ¥Ø0Xš Á±K„lKb%’;’tÑÇ)‚  ˜JÁ‘õvsHÀñ°Ã‚ÂàiŠ6åÿ«í9nÕ ÉjÐŽœÞœ¸ÕôÎïÖXÎXcíò$ŒÐJt­|²eÀWÛÜûiJúÇiT䈱z™bÀOÅü>å èÛc×çJ :çt†‡æ1Q?×i Ok¹“ôÝå"ýgÒqÈ•ÁhvÝËu»©/©ÇÕxÁ`ðFa°³wm?ÄV ¼+V­ÒJzÕÁ°›˜ ±OB„z4õ®kë’OsYVôä|OÑ¢'W øœÆ,ô­Šå³Ó˜›—î.¯f8ËGª§z…ê'ýþ‚êõ$%sÄ Ë.…àL?A’A¡1-žöž¸î¾]s®·Ã!üDî°u•Š@È¥"ø8pìÐé8²‘G6m®ÅT—½¤{öLº>‡;jw!½Ô”×?Žà–¨*Ôi}úée¿Z*¡昌OË>Ã/eßäì¬Ô=;Îfž›Nyò€pØp¡ÐËÔ~ÌfU‰R¹Š•ùSÖþÚàœ¬ËuÇjEY)p).îÆmF#ˆÈ…žŽÞ¶]2Qk¬k¤sSµqKè$üàKÐpn>¯w»\PdjÞ킨_ƒí¼ÛE¡ø lcµµÀ­Óú§˜Y\8ìÄ^½þ ê7ßg9á„ÅK¦=@7jŠËý°{ñâR¯KU!œ2EÍ0&à†eþºv¸1u(xwÝøþP¯nÄ…©ü·«;aǯuË , 7a‡?îÝp§x7 æ(¶Õmß|È£Píg™ä›vx÷ݪæÒ·L|Òý½òÎ9à…pgí»Sœ—ñ§‘âÉñp(¨iÎ=ŸDbÌ,•ëˆs!qAûj[¿X£/èßTéh~zµ>z&¯Èö,ðáMéŠ|ªÎ8¾vòˬ^P3±2ž8&òýmªQš>bä:ƃ³öb!h{œMœ½h&‚2¤¥¤5u9~øª±Šþ㻓ð‚õ^¶ÑšŒà âÕPø=…YdéCý˜ådiõ!‘/ c½‹Ò*|Ç–ŸŽš´ •Œ(ªBjœ4^/Yâ€Ó0O©\‡ä^o›?Õ»uÎ…¢f§sÊ}Æ€ñÿC¹wí¯Ðɼ ¡çK·UEtr¨M9·’¼ÈÌý€z4)Çÿ G8I(…ç®s„ÿ]ptÄ%òG6@)¨5þ,p9uù)+'G%Ÿo•6HJiShb–Âz%14¿–Z¯'†YÚnÅ—œ*PRܵ‘%$1ÓÆù©„ñ“Cq1 óåï-ŒqL¢¯ÍK ·LñÇM™·xùzÚ\='‡ç›+¹cŒ˜Ú;Ü^Iíʘ(ÏU “·s³Ã×clƇlÆÌäëfüŒãkÇ’òn™>³ÿœ43ÄâÕ¯¸ñæþÛk™bã·×ÉÇéY™•!À˜!ù[›÷tcT~À²èá⌉φ»ºÏÊB@œœ”kY옘Å$æ+p•†¾ÞÁ•Ã2·~ýÇûÍ/7¿Üü¿Õøendstream endobj 226 0 obj 2430 endobj 227 0 obj <> endobj 229 0 obj <> stream xœ­YÉr#ǽ3ô898²Tû2aû ÑÈá–†¾áÒŠd;€ÕÝ güõÎÚ²ºÁ9£Pè0¡F-¹½—/‹”° ÿå7û‹ß/~_±ø­ü³Ù¯~¸½øþW)VŒ§_ÝÞ]¤ lå á+£)Ñzu»¿¸”Éw·ÿ…BOwHC¬avÝn/.a ã„3§ò7ß7ã!|æ’Hiò×~}¹~¾^[I”0vuÍ‘ñ·›îS»ÜùÏïß§ 'š»·Ï[_»¡½ïü6ü®%N ÚnŒ¶"Œ*¶í›Ïw›î*ü áÃuþa{8þ¶óá»Ð„Y–?‡\ßm|²ýû_Ù,Чu9|Ó?ä3—Å}ÛµûöÍØºè#B+YBx£"™%‚ºÕ5“9*ãƒÏ  Ó;9%Šš’€Ÿ>ü¼dçÄh\Ôt1>\&]¹·÷ã±ï¢¹ò®X‰l¾îÑèýpÜÅ€ N¬2äcI¨Àüßú}<ÀZ³˜Üd*Ì–•ÍR1(ã²é§˜VÂ…ÃD»MˆãMˆéq¿ä»å„Îóz–8b˜³åÓÍi> |)Þ9ú~ß^Çœ§‰DÕœt͘3̈ux‰o!h}ü+éóƒïòjc¥> 0 ¬æè.;óae%HM¼2Êê¿¥ÀX°°ÜåÓU°ŽN*r·Kؘ۵¾lû*!T®8ò¹Ýƒ‡»/¥Ü祧±Ü¹––2ТJ#Æv-Ê @}.|CJrØ> %†¾ԇİùaŒ&G'Á>iЗ§ø‰é š}?¶’x´äÊbʶÆ€ò|E”–%‰yÀ4açxÎP «9U#˜'Ú°¾\Š#8ªªU¼Y "ð¬~¦„Xˆ”´ÅŽ6l±3»óËËP.0tM·È%@ŽRrô5“Ý_KUŒf“”= e­¦´u›Ó-„bȶþ®)üáˆJÌ“¤¨cåàfw,'€ ŸÄ§ŸŠ@¹Ú^·³Ø½8޼—XB¡IŒ¨ÄHJ^*¿¬/ï3áJ§Êg`_Â×ïH:sÞ‡¯9°%ÐÜêZØÇØ‚U¦ƒIËýwºÐj'Š3Mßìý˜Hwh]0“ùpäjš!FH5§ì{ÍBB)[ê΋QÕ€W žÒ´©§C˜ÖnŽ]“K="ãpqs—}áÐF ‚·ÙÄ#± ›çCbw>áÁÓn«Ž#O©Ïò¦ûÏàûg 5ȱ‡5©X¹¡åKü§±Y®9KŒÀfy•H(Ê”ý¹P€5§%.y•µ’¤Ö›)9–f΋[ÐsŸ û+…ööÛD Èûó"¦Bh*‡b »k˜ *Ó¢Þ–­¶ZgU¨b¾~xªÂsx Ê*ÀÛŠý¶$ÍÅš›¼GÝyš›ë²­Vú-*®¹˜šQÙמï,ä´”Rõ„^(cSúœeX~c[úôf' lCÛÝçÕÊʲú,³np~ÜŒ‡þLˆL±SÊ1o‡8C̯Ó%QC¸¿¦Û>üüC3ø¿D (@Ue/BÈ™ 1«™}E†ÎfhQ$‰3Vb›µ2“¨7žÚmÒz@Í’iŽ}Ê<$U_}’Ðvµ3(í±¹¡hZ%»C³M ÚC!PM‡¬3˜Ð(V†¥@'Ž×'ZTgŠh‰eõ ÒµpÇá*ΨñêI·ÆÙ"wëDR ÿ3£®?KÎï ±ŠQ·±þ¸„­öpï‹ -¸ýÔ[Мötàas$DåúEÉɳhιñK>ÑnÓùXºâ}‚?ð(ÌeH ¡x÷IKèó\ ÆžêÕp¤W”Fó‚„×Qk‘×¹ÇÇ‚:¨. uÑ-ˆ2Œî3ý¾p­ÕòU"øgßl[ßç®±P×$nªš(ßÚÂŒ|‘1È«*ãS¶ê(QT½‘hê}û”?Z…ùt·agªtÞÜͶ{<!3a¶ÅIûd„>SõÁ¡+p€(Îkl>¾W÷„E÷¶þ»ü^4ö©ð*ÐŒC†$ŒÎÑñ¶"Æíû÷O~“ò&¦©D™¶«JE ¡ÿ¶tTuøÐSß^)E/þ±Øég']-]f ,°¾]_‹<¸2¬”ô2ãt-5Ÿ²ð’·ã"R5Ÿm¸\…9\»8 ù†..¡¢PËñ¼–òébЇ &±‡«ï¿, ¸¼¸ÊƒO>U'"”áúÞ2LNqv2ò‹©¤XzoIs˜\—À@Û<·pmN!Æœ›¼ËlŽ; ó„Þ0&Ôbÿ®O’ šˆæøQe¿ (ûl›Ç-n±¯l}ŸØ áJ¸ð)GB27d¡ÿë¥ÛÄkžø>Œ|™8èØ);-¼|Z©ÞÔ7$ß­ ºÿ¯.‹.@52¶ï‚îº*)èÿî’QµÅúçl¼`ükxT¶¨òòøõÚ X ú¦ìëÄ •`8ây2±¦§EÀÔ…ÛdêˆÏ™dKµ&±!­ÅÙl6‡~[h7þ•©>ž8¯:ï<ăÖAˆÿ=šÄ¡ñbÏgKÒ">’ Õï“5ºÜirø·%gúg2P–À•ÔÇB<õÏdÑÏsC¹¦à&ùüøùq×nÚ1Ó0W”¿LhÖº€ÊÓG$ x©H½¯R<“ËI哊ÚTr$cÝÛ>sšRáB—’o¦4(|L)­È¬cÝÀž¨b¶´ý°v¦ÉßF‚0¨lò¸Yxv‚ pÏ;\øþñvõËÅ/ÿî1Dendstream endobj 230 0 obj 2406 endobj 231 0 obj <> endobj 233 0 obj <> stream xœ­ZKsãÆ>ä¦Êà)¥-‹È¼[‰Þr%®ò&q¬ÜtÁ’›¹(Yþõéyõ HJë­=ìÖÓ3Óýu÷×ÝK º îOü{µ½ú|õyAýZúkµ]|w{õ×ÿ ¾ ´°R²ÅíýUØ@Vl¡)”ZÜn¯®EAYÁßÝþ;¸îº0šrØu»¾ºîªþÇûŒÉB &ãòóÏ}[öÕÃËÝõÝ» e|®)ÖØøùÍÜA¦`ÚÁA«u}Ø^’L /ˆÖç%skË’ÿY?<Ë¥£MK&iAA=Kf áw~¬úGÿxGZž®;·FeA©Pq­÷ßQQ0%l>Ø/ÂCj®Ûû5 WÄÍÕªþóÊ+ÙLjü4ÞØý"dÁ ñ—Mõ£‚¢”M1§¯%5¤Ðv±ä&>ËÛ^x©#[ÿ»¬Zÿ\S¡Ò3¶¨]IÄH GZ¤Œöf-þÐDu.“Ìr½®ûz×xóIRXÍåÑq¬ \™±ÒUÁ³ÒïwþºÔÔðt¯ºY×OõúPn¼lBôd}Ý1ø 4`¤H/ûØü¯«Ú»§Ò}¬á3¦Ò%ÚºlVÕÜË—ÔkŸ½f$HÑBQ©fUÁá;Žª¨ƒµ!\i¼  3Z›(4Qõ[_µM°µà…µ<fµK"K"¼×ÈBK)*¯Ä-€Ë¦ýÛ²oëßüº*,3éÄuÕÕMµö'ªBË&pT…ÎpÝš!FÝ'­LkðŽrå| †Ft»{/‚VÌD.Ø™RÑ, } NÌIümøžÁW9BµUwØôáÐåãàÉÆÈñ€N•=d[7õ¶þ½L÷Ö×”L[îâCA¥Bæ‡FƒqpAÔÞÛí%à}zb¯àg€"0^G0ú8‚iîK5DP&ÆÇiaiÚ[µ}05(SHaÎp ¢ÚÄA{„‘UçÌä ÊÉfj«=¥ €ÈÃð—¾ü´ 0…ÖšfÐÁ˽½dt†™ñ‡>F/›_³*´!K)7]Èð 䢂>yç…˜mUZò§»ÜšTÖ}»ÛFÅÒ%Öe_Þ [Iëûcðî:O2»L…Gg:rt0œd~±©¶!C²’ÃnŸr ðäqR€5¸ÃY¡eÛ–ÑGAiûKH)Œ ]¨Š„²Z v7Ñ<T‹$v)¨s“q¤É ¢ÍqrÇ‹}¹:N¿æô˜´³N–×,£×–ó„N?Œ3@%™)h£Ž4€Gh¢Îè³*6os"ÏI­ÇLƒ <•§¥“f*ÙªiÎl~ÃsØgÆe-„ ¬ñOsÎATY™^xw=w<˜XŠyÅñ“Jdtü71 ñ¬:šz|¤@H2ÚßçDCŠQi+bÊ¢eß&. %Ž–| ΚâƬ3f4àähÆYÞ×—ÁuH]wPoöû¸¨mvƒ¤f¨±!à’ÄÃaS¶1®É\š@ì#ç9T`Lâb&&Q“«Ø—-ä϶ö.*yœãDàú%Fº»ŽÖÑ’å¢ùó¡jB €( 1£øQ—›ÍK$Ìò¤€›à0zfM›Ã6S ^ óÓ;™‰…aóM¤÷‚åU"‹ ö匆Mw×$™û0­.Á¢ËäTà·¯ä~pÖ œvC¡Ñ˜«üE(^DS¼Hâ8Ô)>üœ½éÞèOjD­Þt÷tA ü½b–„½A, EÏ>>œ¬y€CÕO)7Œ!UÀ›¯èoŸÅyö®Ý gŽÅDUéJ³uÃ'ÒÚiNðÎmR%É×{!Á¥ïî‚Ct±à51X•=† ²½CØ®`8•Ù æÐ\éê[bjJ¼c¦fʼÙ×aÞCŠª!OóAûïRTtf¦¨?ï“r€·ß¿$r*YŠR9`kó«/ Ð@Å‘ÓÄÐ(W.Ÿ dÛlà0]«† ªö®-×K¢˜ð æcÅ \Ž‘´!6\«sÊs½ÙD×Ö¸9c—²³Îá¬ìS—ŠQ ”Ø@f¹{Ž@¾'Gê2lšU}ïLÙlS5ýãÓá î¤^ì&ÄNƒ³]"v.ìP4ÒIb‡x±ÿMÜæJÀ¯Dì’EBÐb=㯣U6;(e}¹‰ü^B E°.«3~rß7Å,›A¤ˆÙøßçR Þl‘÷©¥ó·©æÒ,€EÓ=%3}°Ÿ¥e‡<êÑ„eK1HÄRè0ç¢*$즞}ÌÅLgž;Äû¤7Šù«jË :×óEm¶n1  T#t®bû›t5ŽÕÆÙžÀ‰á”šÇEóY‚ §§IâsÉËIâýû ØÇ95_ £¾¾R–ܧP9šV€iŽ-¯‹í‰SL×O>—TÜ’ñÓ$J«UÕÅV®€ŠÀâðô©.#° 5“ã$­ëò/ƒä,‚\?šôú—`U3ó¸]Þ xÝtNìpìÄUej•W¡Ù—3kä“ós[»Éáì´ Ðëú›v2tñÛËC·ÿxÃs×èÀlž —†]Óã1‘®¢>ÃyÑp¦fØ?+1g³öXòØ¾y.·M%µq !Ávµ)».’&®¤yp¦rªÌG´`s“³Á@i:9K÷}®#À«Î_8w¥½•€Ê ÓÎR$¥ù¿´Oj„æ!|bÞ­ ¸Éÿ4VáR VqxBf†'`\“‡'8%!GÝ篧§t NÌSº¹ŸCŒ œÉ\tmbæK͹½»CŸf=î? `Ô˜û6_׿48˜J‚cb›™%Ó)èkž+F^27ׇ”¾t,Xù_8q¿|»øéê§«ÿ$dendstream endobj 234 0 obj 2604 endobj 235 0 obj <> endobj 237 0 obj <> stream xœÍYËŽÇÝä¸Ãr×»jdaü°t²™M‹Ý#vÂǨ›IŸ[¯[Õdó!É0" Q,ÖãÞsÎ=·X:«ÜñßåæîÃ݇õcéŸåföÃâîûߨšQJ¬”l¶x¾ _ 3« ›iU¥f‹ÍÝýr·ýnñŸ;ª LÀ”Eswÿê†$ÑÂÒ8Òöû¶q£Ìa…‰Ãÿ²%\Â>ql¿ó r¢°ilÕúAK¤Ð<†¶÷K ÂàOíÛ—¾Z¿° DçOöõ»µ_†b¬NG{Þõ›zïÆ¹&¢Òã³Á9*mÓÙv}÷´Äê¼r:²Rxäz½ÞÅÈiuýè‡àX’ɼœÇ Ow{>ôpgÿ7DsÉ'"–Ý·}½Üw»-qŸÍ¹¶„r1›SA„ŸðO7®‰”‚§#×}½iዃO• •§Ò‚§”þ↾ÿi€ ±$Ö` UœñóÛß^„Ycèp@B%ÓBËÚ߀Q"K·zç†1ܪt)Ÿ)C¬e*¬nš"c4%êé¾ißlÛæé;ŸsK˜M› /1ÞÜŠtÎvÙ=î¶ïýdF,ÃSÔ!´º²6MÞB”N·Œ—üòúÐF4JƒÈ¨·õ  §ê¶Ý¾«×!Y@(«¸O– —Ãõv t©C¦…&ª «¦‚P+lÚás8 Í\#! ‚—I˜KE€wt6<TÀ:ð7L棌Á¦Fç›5ÍÓ=!$Ä÷8»ó4yœ`Æc±J¡ à¶òŒà à©R(›©°GÒü²ý¨îA,„c´-& ƒŒ%öGT?>^>µ ”UÊr7 -EÚt‡)¶vœõ‘¬­wu¥üf¥È$2 I´_õmåÃHTÁÿv% $À¤°ïž£¨ðʤ^¶áVfœd‡ÐŽúœrñ—ÉøR8–•e‚AÈ/ aP&…a¹òA¦ŠÊÓµû¿>ÄËU,Mlvׇ¨XVTfôÁt¤”ìRÌàp‘¬°,ׯŽÉjX&ësŠ. 0\Mç¯û.Õ·(Pó8¾ÓÑ­€:¤ øÒWG—Þ]E2ÇÑê(ºW?à·åƒ[¢äD>Ød> @œäƒâ™#›—‘‡¯£Úïa,@ö QüØíW‘# 1·î6Ý~ˆš¢žåé~½Cò Í>†ŠRq&“x†ý|áÆ:–%.—n}xy‰DÛ‚ý)ŠG@¡j6¨Ô7åëix–ml*»çØÆä%¶ù“†bsUEѬ…8KˆÂ$¯æLÁž/Uêß«àØ|™Å ŽN£ùérƒ€r• kä·8>J= Ýûm€¸V!²kºe;à¹%Ñ À"–½¶^úAI Å¥=”áL¦I@±†*—öû¸ê–’6Ã9­aiv—Ýz'rÊR@ s• æ 8Ζ@T²QŒ>›Púì΋×h›ë!Þ•g›Ž–YåB—<†þÑûæññµ]†ûe…ÑŽZ,«Q¦àÿ4M{ümj¯E†Žx1¹ Áó÷)Xx±'}Á—^ò!Œƒ¥C?¾ý¡ÚÇÇW -@…M˜ú… ºŸ&·kTPNI  ø´‹UhrœK“˜ÅM[G„>%š²xŸ¹€ ¤¥¿éƒ>1Yö Çè5½ SPøªÓÞM‚ôf·Ü4þ0Рñ €÷mÐx·cn›€„í§(ý²J÷©"*Á›KZЯ&Q˜¡ª•ËrDMË2…˦:@È—v‘ì\ +b_&¦ã'Áó €V¬ á²^/ëz¥OšÒÜçN¸ÊÈz†–ÁõÑ!쥧¼OêSÜq0òÝvèš6¹s@ò˜XR‰ròãÛ‡ø}èWÓFß"º`é*#Jd‹¦ÓADÖgøÅ û“ø¥5Yhƒ™‹ Z/n'%”æ§ŠvÝn°ÀIŽô ÀëK ©ÇZùþѾ@·(RX^²°c×2tÃtHU'= ›Ší¸Úý¿bZÀàÉKE“5W`ü5x=× Š«ß;l]} Í“¥¬x&á>º­e–?F!.UÊa¿Ý=$³¦±ºe­U*ûÕo;í{9$·xå™4kÞeØ’=pÌ`•:ãá"Àë§±üèšžñýå×qñ°## ÷;÷LqT¿´2Kä%ñpââªRf² @(G%wlo`êvwF¬Aeˆvud®Š®À"9·Ñ¯ï …^ t©yÖxS¨=Z*,^»©• N&“ó5Eåäüî•ÏO‚…:·¦ù¤(Œ`°P•]SŠÎ‡C;`÷İáÚÔ± ±\{>GçŸðˆàηÒ®ì|…âͧ¶ (öq?Îb¡nç;‰‡Hy£Q ßö‘wB£E؄ؖÏȇ@AÿdŒ7?wMëŠMÖÿœ8-¡ ʵ{8:’P~“„þÔ÷»X¨ÂíúRB ƒÔê# =û½RB%$ÆêlÅÃõ5Qô6 åÎNH(ÈÃ÷µ6žÄɇÎ5óœ#åXÂÏjª5¥¦ž½)j*´b•Æ&ö’¦ 'f§šêVFðGÜøèð# >f‘‹u*²¥3€úèy :?ÝCb7u|Ò+Ê2ƒŠwÁÛÔVºW†[ÔV±Sµ-x:ùsAm©¹Em%½¢¶ãC|‰Úž°—ƒ™v°:b¯¸ÎÞ7ŸJ––oÞ?/Ù¨˜=vÂFÊ¥¸ÌÆi¹Ÿ4Uר$ó{»;²ŠØTvk*6bÍÇ®]"\A뇄 ªN^«ÏxèÏoA¥Q·z£®¡ »ûiaô{ËYlÂŒìΔƒ8çPò: zè  79‡ªøK Î*±e±š+=ôÌ_‹-hÂå5lˆä˜ã±`Ê5&öYvVä€Á†7ô P©4¶xé¢4ïþÒ·¯Ýî0¬Ãocºì®œ+‰›.ðÿ©¢¼º®¢§Hu}‰†Oç6Èäþ·¾Ÿ³_ï~½ûÑðвendstream endobj 238 0 obj 2261 endobj 239 0 obj <> endobj 241 0 obj <> stream xœµ™Ko7ÇïB?„nuŠŠáðÍS4è¡(À½ù"KëF…,9»RÜ|û¹|íCÚµÓ"‡wwÿùͦ–Ôý ÿo__–à×â›ÇåûÛÅÛO‚/ˆ•’-oí°´š°¥V”(µ¼}\Ü‚¨7·ã\•OMŒŽOÝn7Muú}÷¸;5w7„»7î‰Uܲb–ˆþ¶ó¡Ùýu¨¶n§D×á]»ÃÉ-‚"??û5N8µ"¬mçû}åÖ¹$šBXÞÝ’!LZßùÜ>. ã®?~~jÍû :3JDúô±‹ ÆŠa‡1ÙwJcH,D«6Ÿ×ÁSt?~¿þ)xj©Žk‡õcå=àœ0ÊøÀƒ·’ª—+´AL‡à;ÂÀµÈ.6ncèVZ=}ö¯Ã 4ïeE kâÚs»D9Ãw·KU¼×F«°¶>lÃG”J8?=ù–hkáÊÓ÷n µÄsŽçðF‹¦‡Ib&Êîi]cèOUL7-C!%±ÆFgcÑ²Ä KYG5]•<ïNŸ½-Š(¦‹|}‘f°«—"A¤TÑ.ÒÖ"ôKb-ÑÌÿðÛ1Xð+ùê·QÔcúrU·BÒ.Ã1#»‡1“ñA3¾?>ZÌ3I*;¯)üYK#R}9¯÷^¤”HÜ9G¿Ù‰ðùiì“€Ÿôî 76›º>„Ú”vò»nsÈ QÙs,ïíî´;ú'$š¥è×UsÞŸҚЅîŠ9)X®¸ Eëy«gñö϶¸Àlél GNIaƒï ¶ áëÏ–h6 CÉcÞ#šÑÙG3Šnͨk5  BN°U.J¶^÷!WYbTî5â Ü8B\äéeâ2S÷ 2 É ðdò\ׇíaâ¸"NŠ™ˆCùÓëˆÃÇž äy1Œ!ΨˆCVÙÁ®IÄ!ËÁ&¯nC@‘n,’\õðSŽ`)³Þp†-0—{Ó²Œ‹B‘éÃñÒe”ˆYÒ×â<;¥kz)ÑV¦¢­ëvÉ0kã»^Ú-•JbØ»çÑÄZiû¼1óæ;o“>&K“4¦BðlÒ¨2Л_øº”°$cV3”4OIP¢Ì‹¡$µ½`w&¥ñRöÏvûù©€v¦ÀºZ²KÒ™ìÂáaŒ]T\fxEKöâ ¸è¥ @£04¦^=~âûϦ8D˜!âÆ§¸Yˆãô5ˆ3X’9ró'Å\ÄQcþ?ÄÅaŠçO_ooóˆ†çUT"ïÍN­®_«9‡ÖîÎ’C€¥.i[‡ àÐ…Â)OˆÉӤʉíZ‘a æ"ï:!h—ã†!2´LUì>4f¹fƒŒÓ®ŒÀ?Ûöû` Ò".>¥:NeÜ4»Ì%wPb½¿že8´£ÑŽÚj¦Ò‹¦<‰]¯rèœ[!v¦ÎTån3Yå̬^Qåø«â6R?V¹Ä:¬rŸ‰Žk›¶ÔðD%XB?Òø ×´W¸8µÓø±uýÍo+ÇñÝ!¤VKËù~˜Å62lö’—e»««;ù­[Îâø¡hº›mÁHÀæqû[;\áa1nºk¯¥B] ¥À ‘¿æ^Өɉx~h1Y#ú•ñ°F ÂЃaÓ5²;l«®#>lÉŒµÈ.6Cp.4ógmOp¾k ZþÝ ®?¼4ß Î]øeqJÄIL¥~ŠSºHSUÎr7müÅfk®`Ädq&]é àQËúÓ ÏÓJTÉJPwjæ%›/iŸ ½I­`‰p•c†9Û7ÜH”N¨»&{pð]OÝÌž<ÝV? p]úζ3áK?æa®hÜ9q¬˜åÃ%8wÅßÏ;¸ñ3]Í„ø‹ñ¤±u<6ùñêÔµfÞ;¨ûÁMQn›õ~sÞ¯ÓŶu·`¬Ÿý‚*£øy@¾ÅW´âîÜé!Y;=†š¦N²çÆAö:Ÿ:7UýcB©@EÇ?´cÉâ—~ù#DEÃ{w3 |,øÐ–ã–©ôª÷ë¦z÷îèËG:”±ݪ^Ÿâ Jˆ¢i]œúh*½»7íŸnOñ~lQ¸±Í ÷8ûõvùqñqñ/óH endstream endobj 242 0 obj 1894 endobj 243 0 obj <> endobj 245 0 obj <> stream xœÕXKo7¾ ý{* b8|3(rhÐC šD¹ù²‘Öñz8»+÷ñë;ä’Ü•DYk')ZØ€ Š™o¾o¢ ê~Âßåföeö¥¿ÿ,7Å/‹Ùó÷‚ÄJÉŠÅͬ?…Õ„ZQ¢T±ØÌ®üåÏ¿ã®ÆG¤ ÒRwp±š]mËMu}E¹~æ6Ïã§sf‰íØoÛúó¶Z¹MZe87ÔÛÎ-‚"Ÿˆ×ö×=o£Q’ 65U·o¶­Û((atø »­Ü"C@„æ#KÝ*lXÝÝøÇ9áÔȇŽß• ^ÐUûHJbýQw·þúÅtrkUýÙû éØ|_Š_ÎK…ÿi·~ zÏ…ò[æfZsÄ¿&Ã^ÊÆ›… FŠhØ›íǶj~ónpbn—nI¼9-—?teWå,•’…{À“H%Q^®Ë¶Í‘ Q`üÔ4´Y3fǦIt˜Ú‰–)C °øüÎã me‘=]Y÷ÜáȰâ0ø'†"ÌL?ÝÐ6g¤ÐDh\ g·^Ìn‚9š™3÷äFçÍ ÐGäÕîÞ›Å0Ú ¹ìªËí2 3Dq¦Æô†ª¶ñèë^°‚P>@\zˆ#Ú¤x~êe¸U‘}þE D /,› ƒè}ŒpБ})jŠÙAVw{ÿn#±‚ßTwMÕVILHU–øÿi]…û…ÕÑ›]³){„ ¡TG„''J|n¿Ž!R i7õ¶ÞÔ—]½Û†äwX´æŒ¢¥*ìÁM—û䔂3¾2Ã\»Òz§°R ™¢Ñv«/î«e·óW*WžÙìïr;DÿÎYl Pkb> endobj 249 0 obj <> stream xœÝXMÛ6½»út 6@Ìòûc‘K»M{Z iÝžö¢ØrV…-m$yô×wH‘ÔÇÒ^gÓ @ÃEμyóæÉ‘ Ûþïz¿ø°ø·þ¬÷Ù/«ÅOp–‚Œ4[mý $3 ÑLIŒ¤ÌVûÅGD ùbõ¼Áäø ®V„Á[«Íââý®~—ï®®n.n^ô»Éd÷2l_Rƒ¸{eu[ØÎ—ÜøsöEw[ÛeFaRûåM*Bϼ\hÄ$ g5EwhªÖnä°Gåäv ^c!˜u]µ] †ÒxÀ¶hŠjíÂ)B¸Ô¹Ø2McJ]Ÿç3ˆ@`Ì’©M«Ì0â4¦6¢õèa#‰4ïšC‘:Ž2ÄÇ•Û>KD6e2ňJur±µX¸e´V¡=ÊÖ·,…pî{<6„Œ’~™ì —˜Pöm¾kÓ™€¤pEæ™(3©ê%/È`• Ä”‹I)“5¡ ô¼šöhM–Cg”XbÚ¥#ù E UmAcµkȺùX¶EZ°(°\3:W,ýk{Ÿïl ¿ìaˆFázò™Åf%aÈN„ÿA¼ªíº::Âņã Y?oáU7 Í*È}Y•ûò_7´.û£ô´ "¶û— Ï0äíK?&Gݹ45(Ö]±ñmž …âƒUiºÒ­B b1ÎwîLX“&Ú½dÊ+,@ $Ÿ,€CÐvX©8G^ÿzDŸD‚¢yôÏÅþT øcò$ð«Þ•bÔ$«^Ì„]IïæVZ…êÔ[¿Æp„æh¬óÝ®õÞ‘°ÐæÐ”Õ{±‚â1ýh9¼$ôÈPžÙ2réÁ†A' f°®à‚2K/aZD¿p]½{»82T„*vè6­Z0À”1‰˜¨‰¶õn績œ NýèS|``|Äîo»ÍåeÝvM‘»’Hn?"Ö}ÓPÐý¡A›¼g2ÁcjM“ÀÎÀÿT¬Å«WÉH‘qRÖ‡îîзhû`æ€ú«q «.³f•FãÙ„*bi³)žU}³a•æÑbU¾+‰ˆ)4Ãgγ]ò[ˆ°Ât˜ŠK7×88d=9ò>¶ôG ½%†º¥§Ø3™þ@êǧÿW)â mÇÜLXõÜMz -et=~±í÷[¯” ZìûÚöàaÿüÈx§À"«C£„FsŸª:öw뵃è(ØuÏ·©}<ß”™³­ÏŽŠÁÞáâTϘö E'W< K  ³c°5®ö£ÍDšõø{÷1œ¢©ú¡få>z½»Ü[-—•ÃÄy´UÂAŸ†“€°ðÝgƒÇ›ž'¬MçÝ\$ äÆñ=b &I‘añnot ˜w>›h¶Ïñ1Û…Í#¶ËK¡1ÏáXNÏt)@'-"&Fâ07Ì–if4`DkÅ|TŒÏpÉZ«‰¿ýÍŽmëKbðp& ­ªðf‘›«*ýžTõó»¥=ª³Z™}¡Ì*>—ÙÓò÷„øSÁƒ9S„„›ÐA*$‰œÓ}t?I"¦¿ó­¾‚àÿߢü§âMÚJ D¥“js µUµ¿üòÞ¦3n¼^eooÿW¦Éßendstream endobj 250 0 obj 1560 endobj 251 0 obj <> endobj 253 0 obj <> stream xœÝVKOÜ0¾§"';õømÄ©õT ÚíKºHµ›,N€¿ß±g„¨ÔJ(‡Dãñ<>ßÄ 0gáÞ‹UvŸÝçméµXå_æÙçïRäˆà”âùü&ë7`î ðÜhZçóUv(5È£ùoÚ!ôöiÀ´k~6ëàƒ8:5ØJ_tM0s RšÁêû`Šmôe0m<=Jˆ6Oa®Ûîúä¤i;_«ƒã°ÃRãÎâà±hê¶‹é.ì`þV]6¿ŠåY,M9p˜–¼/—EW5õ°FU¡KáÊOWG}]¸S×LÒÈ|F‰dô½ðU3#XnSø® @ë’­yèKd`¤ÔÉñ®œ€œPñ×}L5>Gè=v2ã Á—τڌäP‹?ÛÒ_„)i»a¡ˆ@7,Y|±*»Òÿ芮|‰\kÐâ­Ä 8å3bÇ}b‘ó‘OwÍr’/‚šÚw¶6Õ—æàœO&ƒøìÜûQm§ÒJâbÂâx*¯£œÕ;yϚǘG#hTiÍWE½˜ìn&œ†<ŸÑ‰ôÇVÔד‚ä`¬“ÿK(-udö©?” «ºiϽ•Iz#ÿšê¸Æ=_©tªLC0˜ÈÓÜ µfÕ¶:Uì\Št[=£Â*›4SÆÞPr<Å[ƒ’^ Ž5À$ß§ŽùHÔ9kê®yðñLÚ¹CéßÌ55¢ù³=ÁÅÞÍÄlP¹bìÈ•ôgØIË£ƒuÒ¥iýá&¸J¦XD÷¹{¦»  TaÛ“‹ð¯ɶlz|xœ£¹Ø¼¬ê¾JRðt|ë8ád²Rú¸&:ã©Ë[_¬ïªEl‹ÐÑÚî@2“ä.­ÜšÜ\¶¤J„‰± GÅD®3Ýæ˜“£0{W†„yöVPbú'iJ˜QÔȪª‹eb˜LtÊ©RWE¼>ÏóËì2û'sÂendstream endobj 254 0 obj 746 endobj 255 0 obj <> endobj 257 0 obj <> stream xœ­ZÛrãÆ}Wü|‹]%Á˜;&o¹8‰ª¬õe•J*µ/Xá%¥U’OÏ¥{$ÄÝØ)?¬wvÌtŸ>}ºeÁV¥û/þ¹Þ_ý|õóŠù5üc½_ýáþêëá¯Ìœ)¹º¸ ?`+ K+£ËBëÕýþêKõÕýOWÜ%· 6Üo®¾ükï×d!¤4qíÙ/•…°¥ŽKSØ& Í ‹kÍä/¤¸oÛø5Q(cðÇCû¸«B0ü¹ÿ1…±´±îFÿnÉ aÊ*®6C|wÉñÔC¿÷uÁL…/¿sK` Ö)li™·EUÅð ·oþv{·éc…UŠ»m7BØB1³‚ÿ)då7߇ËpUˆRZ¼u_ïâjUY€I‹ç9œß¼Ç6ÞTxYî8F<)ˆ ºÿñ[OmßxY<És;yìr¦I÷÷gUt†—hjïè°Ô…c1F›Žûhf8ª¸à¶!¢ ¢MŸ"ŒIBØ“?-`ÎRTÕC‹@s°õ©ü5+¸–â`R™Z¿ñÂ0â…¥#¬ûã0ú×ÝÀв Îr0vOÙ{×0 Ø%³Ì]SªSP»ç‡¦ÞµcsíwW…Õtšæ‰,Έ*ºh_e9â²í"ÑHA¬wÚnÝvá¹Þß•¹°¿vKÀ€EÜöE×NMäS#5ž Þ÷Ç.º„ý9ÙYºX4&DJEÆœÚ}Sø3X¦gÞvÑ.p rçP`×áÒÇÄòØïƒC  œ!òèÇãþ@@×(¯B¿ìÃ%…¢`™b.Ð)e¼Æ3è @…O«7ML\“‹ë÷«’,ÙÃK,JJ8‘{Á¥¹*Ûšø€\þÔ*£¹ê¿\'“/½Ù ¦˜Š®Þ¢'4Ÿ:l|™dœÍÁ¬\bµ9Œ|¼Ò¯ciú¯o7‘üÀtpÐ,žóZæëݱžÚîó!y ¢­¹  ©§x*ñÑ”Yïë9#^»ÐâI7+ÔƒÞ›·¥öu|äME>oPf÷Ú4Mð¥+!øiš_Új¡Ö?a ßTÊ^˜Iü?äç,ÖÇa:˜¾d‰f”©T%¨#œE   —bgP`%…v}8ì@À§ÆŒë`QOï9Ö'€'[JBI:²Pªÿlªÿ éV¬k éL5n¢¦8æS~gÙD6uôêàGC RÌŒ{¨Iäæ9xÖ`‰O²t©£¹;†.5Èqd[ÔkUFõfÓfOe3¿É×?Š2÷î¼Ý}wûæ»·‹ pT@ ˆ, B£âŸå“üóœñ)ÑÐLu‹-ÃÊž*ö’Se07'd£%sBÉe$X/¹á£F²4h(­%ÇJÊጀ1N¡‘íAL(x¿k°kS¦)QO-Ù¼#‚Ê“ Ø51`J¦?kàØ˜+À>rŠsGàÀÆ¥«T¿`ËѦÁOðÔ1R¬´“KŽ,!Åžš¿À‚°ADÆâCeM'Š4]°ÓH´Åñ 8•`œ‰…zh~à )&ƒk¹‚ÝÑó@¿¡áq }éüIRëîö/?þþOKØ¿Á©YAõ˜qe'¢Ç2¯Ì/Òú‚ú+5_ìµ(TF¤$ nÑø]S%ÀÙPùÐq^t/![(  N“¼[œK*EѲt»:¢B]¢®0Œ¹Ù7Óe`C5ÀzȽO˜ ]õ¡“&³ÙW6‹â<+š±vt¾bÔÛµ$çuš €™ÖºI»o¯#›*6Ÿyx. ¨§É’tît‰úgVPV<¢!#鸡NuØ‹†×!%AîÑÔ_möqì#]Xб(q}±5ÜøE7Õ"P}Àv¤d“Ô¦ÔÐN½oÈ,Ohü255o¢$q26oÐn? êš1Jã¸KÌAÆádÇL¥B͉VŽ˜Ò “©Y0bÛ6WÔ"þ¶Œøû%ÀÒ$žîÑ0*bÛwCr•iªÛzÂfƒ¶ü,)X›ÚkˆN0œžE‰uÔK¸ÚõáDtÈçïBõÀÁ¥¤*k¹kÆIÞl‰»º·Ó‡||Yâ/?çäsèÜÈ M!r2%ã;;ãþ×»I&tõö6 Ñߚ b%ˆT¤“Äg9©Ôÿƒ“\‘uî$±è$~ê$™õ´¶íã}âk›Ò~Ê'Œ}®OœžB¿†Œ®MM¾ÙôCæMØ]=¥`œè­?  ~z Ñf?›FáÀ^ò4°§š¥Id6?Ñ©[–®£½á<Ží»¯Š˜^põ6މ ƒ–:1¨@H´:i©5Tp´]#}hÓÔ,*³êY«Óöølç¦9 ¢Ÿ¦Û`²gÔÀ€º7Ÿ¥2㩠鈙 Câ«‹„×Ï#n¹Ë¸k6¡št¦¢> Ëåù,d6<¢F¼t-0J;Íɲž ¢§Ž”ÊjJœã5ÝŽ€YÇ CÊ:u»ãc!{#Û1µp˜ƒ—g±o÷Á=^bH C¬RغUœHŒY3ix‰V(™NDQ¯¡X… ¹Ç‘ }rûåŽç}_²p`üBÛa^K¼ 8T™™¸ð9 û&£¾Üã ÖG… ~-Y(ip¨ /ÉËð*–QöºÞ­;×¼ñ•®GŽ®w/Ól˜f •­ïÏ- jÿ™½óÏ|³Ä|NÑ%²zj .ƒõß}ó”ûvMd.êñାYJú4@Ÿá•ø¡J2)ÏU2Y¬ö£þà éz5gAéãlääÊÁ…a´LEÞà ¨Å}öÝO~«OtSYî]ë(KŸ~:2#†kÿv •ƒ¤ây‰[^o‘Öº4¯Ò”ï·K6 uß…‘ QGº¶Å¬ÌÛ7~´uD™tD}@ 9áAÚðc»§Y\”CÙ3ìs´—`> endobj 261 0 obj <> stream xœ¥ZKsÜ6¾ký#tLª,.ÞŽy¯«â¬ãh«öà Å¡4LfH…äXñþúm<ºÁ—§’\…F£ûû¾nˆüšùÿÓ¿õùê÷«ß¯yÃêóõ×·Wÿ|¯ä5ç…ÓZ\ßÞ_Åøµ+ q]Vs}{¾úB¼_Þþ H6ÿ@ñ‚k¡á£ÛÃÕ¿|óÕOq7óY78íF¸B…©·ÇvôSEY(S¦ïã…*Žuýæq˜§ Nìü˜+¤†-ÒØÔt‡æàÇ¥+˜sÇû°¨*œU.Û®=·ÿk^ûŸ´*8“¸LÕ…5„,4s* þz§4jMƒc]uÁ`É á„ÀýŽM˜Ê`j‰FÜ_ºzjû.l¨\aÂeú.ηç?VCun¦fšB[:O5mÏSù¡å×Pâú~Œ^žÚsSý/dù›)ùÙiÎÓØ¡Oc%sèûfL[1Q¢ëq\®¥yO~ÈL ^h>†i¬pŒã¶ñ4°œ0´ÜÐLU¼M Ûè­5#'Þù!SXéL¶0ÅBtP†­µ¿?:]uºÄuÁ ]UuŸ< Qè$Îmª:¬© Ë5FÀ1§ttjÿá>!¨KYâç#Æ›t?í„NsØæpMë›´‹á³]ŒÈRÒšý} ïÍgplާOÁͺ¥Åeȃ© Sp:øMÁ }²¦ò\Ä<_ÂÇõ^·çÒ¦=r¨Ï@Ž7oßýøÝÿ*xØB24ø¡ aÄKŸhò¥MÙ£œSúoÑãršÚdK7ÂáªShYÆøÎáý¯¥(´¡Ï‡þ2¥­À\«ù Òd¡ò-]ÆKuŠ·“ §È›ÙEsë9¢ËX…9O}ÚG2õRZ)´UNÁéXu{7t£±‰xâ‡`îÛ7?¼ÿêÛ½k’ƃú#äEYh …Ù{A ·RÉeb:ñÏN ´;3gÄ —ÃŽWC‚oåIm<4C |vÒd|£¢K®ñuŠ.$EI˜¬*Õ:Õ'ýå© è®ms!è3”CKS.ªRóÂÖ£Þd=l9ã– ”\КÓL%Ô…Œƒ°.Êøñ84u;¦Ð× ,„Š˜²z¹Ð:¢‰Ó­|ÿÍ®X>íhR]êË)d]¼c Ƀ™­ŽðZ(çX–»|„€‚û Ø’Z)ÂÛ¡¿K<[– ÇŸÚéˆ B› ÍøH¡IlÓÔS M®˜X^àffó‡¡Çx ´Óó ü0\êéü¡ ˆ”….â~È­î¶o¬õHÀ òO¸³H:G2Ãÿ†ãi>[`29KÉD‰#59ò!¥¢Hµ̈‰ ˜]\¾…S[Ý” #—´Ý}?œ ÊÁ…LâWÕÝ}ú]!/$Õ,/:ÍÃ%é´fú!Ƭçܬ:º,Hi‡µE> øéXM1ß!&™ý ‰%æøþ‰ã´"äYF+:LÝàÎy‘$a¦¡ÏoJÃ`èC`[À¼¹'ŒˆÂf–LÙ13TWÂMŸ‰†¼´§£Ff Óüñ˜#gœë)U *AĈœZæÜ¬û•‘’¦TŽ4äðÐ$jœ’½ªë L¹_ÃrÇ‹ÍRê†[¢Ô B$+À·ä«Ë9M…*(ªÒš<ÃA©œO—ûªk'”˜À0K¹x€¨7³â!aSÀ¤rŽM Æ[â&¡Š-i×t»^žlI4çÿ=>Òiñ¾LÁˬÐÃpRŠû:n¡Ñ!å3dÇ¡§ª«SR‚¼“ó%=Åòrà9øæF@c/ªÉèÿ5ãi@÷ùÝ·ow¤œ¥'öâE™qðTA<%ý éH¬ÜGéøƒ€aªÆOÈ4÷NŠ "êW<Ÿ´ÛB6Çy{yœä ä±ÏÍy¥šÆ—¿„,/°¯öªé·„°›³‹ý/P¹ÐÞ§õJgåÚt“•ö¡= #4eÅ_HáTåÀ,ï&(1ƒ.æ ä<€‡¯LÀJ?Y"ásɨ"ùþÔbv˜@Õhªº0Ø4£‰¹ –º|x~c¶Õa›J Î’{^)¥xƒ4 ·Ãù.ˆcb‡7?ýçÍíÞjžk Õ¿¯.C$^¯,%•RýeG„S‹b¦-›?šú‚üæÓBrêд©Â5^ldˬpŽ¥9 JK|zÄO{Dp{žR®à†ŠÀ«X·ƒ·²vÊR’‰ÜlÇË9ž[AѤ̬hšö2t£7ažÓ¹@ ùd*˜!l v˜Œ¦ xÐEÀ³ò!E–Ýc½ kò²äkw…×Î+|üí6Õó€¦/Î ¶¿¼ &zÀü_Bý3ß~±{ÖáÙNM÷5, g¦.Ù}B ±©2b¹² ¢(¢@C‘=j¯^ê' #1.¡ Ô”14J'å&\l–6ûç¨ÜfL¡1kØýÂήºú‹v\N¶2·+Bòà=2FEÊórl‡m÷ìúæX=&O@éÅ,-ðï.¾Û/ìÛº”Þ°2›§÷®Ù9ñå× [â‡Y:@ð燚ç{‹åšúV$´Uù€¾ÌÚÝN½ìîû>©áùøOIŠ-}ÒÔ)gtnt»ö÷D Û”Ö«nçØšmîè çúº¿;5ç¸ÿƒÂÍ Q赋¹•ȃˆªºOñÊ|RðÅ;cŒöÝGf¶x]†IQ>{Mþ¡ÉÚ¸Dˆ]@Ѫ¯í}û€O8:ÉDpGŠà-u^ÆJB¡XZú5Kò2> £hKlõãó[øž’/b}Ebg±W!fÀxþ=*&tè‘¿ÐóB‰ w^¡!QA©iÅR,»Ö³3)”mþ¤†W¨èó[¦KÆ·§c3 sºâßÍl/ 'Õa"ßJR)+©æÂ?Ç ¸¥.Ðuh0:ÓQ »EX#JA¨•lÝéò-´Yß»§¦«±X¾Ù<¸Îjì¿+CÞ;VcZÛÍÞy u«»ôÁ´é:óƒ´³é±}ë‘ù!¥#R@¥W_#d¢ý{U‰É-Èû¡?§Ø4ÔÕR¦õx®êéÁ@¿ù¿‰ÒóJ†æÁw·×?_ý|õGSendstream endobj 262 0 obj 3151 endobj 263 0 obj <> endobj 265 0 obj <> stream xœ½[I$GæÄ¡ñàVò[šÎ‰}ABƒ–lL³ú’S•ݸª²™å™á×ób{¹Tu{ÁBbä¬\"Þò}ß{/šTtCÜÿâ¿ÛÃÕ7Wßl¨¿–þÙ6ŸÝ^½þŠª ¥••’mnï¯ÂtcuÅ6Z‘J©Ííá꓾}xüôö?WÔVÚ ÷Üî®>Ý%]Y*Œ—í±=¸ËœU„›tçéP¹‹LTšZ/~qô¯4•_ùØÄïH¡y¼ØÁÕÞ?o+«‹—ëãîUúÃ%´÷þ ¤"ÚàŽþµŒTÖ0¼èßI9lRàú»>Üi*%uZéSÝׇflúÁý&aB¤U´þØJaâµcS‡õÊJPwŽáVYibu¼¸o­·#Ó•Ð"^­ÇåÒ¢i®|K¶¹¦¢—î­Ãà->>†3ž´é{‡:®Œ1tŇhFjðá·î’ª ·*­ß¯ÉV”2%/ܵ­Oƒ¿•« l§¦{¿Ðìî±?5)Zzûì&ã ¸µ —h¢tí¸kš^WD >µ´¨¸AK×aOà%«J7…`£§ÜLcHT,;*øsúùÒÀjf`¢ìÒr²´ïµpî²ÜûÜeê ¬ÌÙÜÊT– •½=Ûÿ†Ä’JÒ¤ûë!U ¡.yµ;„ωÊ–|w÷vßùÐÊPŒ§­».µL%ë}í¿ _ÁkvÇ'…b 6÷‘4všJU ™}t›B^U’<ë—Ü–¤P:vý¡Þïý/ îF#==ÅWèÀæSTUŒÚÃ+àf­ÑΈTÚ"RåŒ` }…øãí%Älú cÝh ¶¡‹ö’íµÝwCB6" ÂAºuþ`ô]F)xQê²*âpBxÓë½w\çÉ’ß_Kbiúx½ÇD7 }5#Ãw ª z«  ±ÉÓ»]¼ÍÒ ma7\Z™¾pÚíÓ>% Ä}Zzçòú+ðFIм ççáJå¨OØ»œÈ©ÞˆJi·wç/ÝŸßnþä+i¥<·^Ã^ῌ…ŒÙhF zŒcèÏn®^ß¼Ù8ì»zý¯ ½zýg÷Ÿ}ù{øç曟]}~ãß´Nã†LVi\BÊ)iØ DÎâê'¬ïá…ˆW€QÃ0¸–å0xžf>XbÓÖ•NN¹ùë?nn×¾Á%øX&§<õ!rT@ÃØ<=EU*ðÅ’¤=OAJ9ê£]dt¢‘ºî@}|MC\L¹„“) Y››0¿yóå_>ÿ÷š9l“eï> ãÚWY¡¢D–%òÐìwÝ!ò¨É„ô´”\PkI‚J–Ö«8êê׉Œ 5wVÒÝÛ}šWPs ‰BêíiŒB•ñÜÁɦ×/00;NçêI/¥boˆe£@èŽQžÒܯûnœ?Ä8Ó+¤»OÖœK‘Y¿¹ùÓW¿ûÃjqÑ!øNW¼ìÀžkågvò¢vÔíìÇ“÷ Ðø¼—ãj6ÛfêÞ¿dà¶öº¥9ÝòÛß.VU´š×4®#¯—Õç²oÃá2ömBó‚³lç“sÝ,ጌݬcfKÿJݱ ¹LÁ1çãahŽíG± €S4N+XðìÚa¬ÛÐcåÆU ¢pâ}àΊÍúð>fpO¹H´®)€¹ÞT©#I9Þý®# L²"–# ¾9¾iúz÷ë_ÍøO¿xÇäT^¸û¤ªª€ ¤€wItN¸Ç§bÑTÛE ìLKîÁØu:!€«ÛŽÅeíüó*XQBÙgi‰®+üÐôd>õ\7^R;3 ˜+²t­u¡aòÑû€<ÞœµcsxŠïfJå~Ý·¡9Ë]ØalÄ2Hðiä©ÏÕA& Ddå»j€ëþÔŒc"6l>Ühõ8_ƒ« *&kA{0¶˜Dy› –mÚwa@Ž#{`ɦ¾…%m°ÃZà\3ã:* ³!–ÃoŽ1zÀüó}×T¿Ô4Æ*š u¶@¸¯¢‹$Çnô»Ç¦O &ˆŒ"’‘Üë?Ôcß¾]CŒÌPÄE®]N1;ƒû¾sÏ—± œ’'?±Ñ àIÑs}óq9"îÇ,8ó ä±;íÓÐO°µ&ádÎæäËrc»=õõ˜ØAVNLdÃæ+6ïÕ–<hÛ Ó8&E990kW;æ.ÚÕñV¯MÐ?,>ÔüÃÐ Ãt¥Už,0ñœgéË?£|…‚¨óÐq{V‹Æ» Õ…¨¸F¹r¤Š eæÈM’ÚB#ÂàØºs‡C4Ü\ûî±ÝÆìwñÔ Œ•´T?AÑ~N“MµRqP€jÔƒ  ‘ õ¡˜Lq1´Qf0W´bÑé·ø® –vŸu°×uÏ8øø+dpUã1À=bŽ—Ü}ú*> s™™Õ5s=¨‹‚-†¸ë6P•k°:ÍdBòÈÉ@ô÷bÖ]»éÌ >À›È³CŠ!â”Ê”«J*[ÁâVßÔ°Yÿcšö‚ØÒ¨þ_%&¶¸Zô(„!„Û|¸ÃJÅ[ªCƒÚ¦ÙÒxr¤Nd¨=ØDEÕo‡n h$Àƒ†"˜tÇP>hgø©0ÆrQvÅ(uæèiÏÝá7/­ ;œhD{Êû‚[›è¦Ã0“u”£+s=–Ž#…#8lôû(I3!“C¿_L÷M=ÄâWÁÙ&¹£8ÊÍt‚¨—aøíZG½ }«DieWÂɲ4+ÉU­“+|@˜,ˆ"¤1$«ayq„7Y^=¸r(fȳN<*›£à>À}ø tǺ +—¥›ê°bX’&V@‚.'VgSSLM(nÃkÀX2×'c›r$Oéöˆ,{x,e2DmúÈy–9?UíÊ©2ÿö•Se ®™ÉÝyßfúÊ77ýâïgtœÐõ±ÞBúCE[œþ@H(šPüÙFv’Ì”¨mqÚû5»Š`‘wàû•¸âRÞð¸ÌVçJ`îè âÔ°òê.À=„Uqt¤Öì6}ò|¿ ÅòÜïºÄñ!!ÔÔ’ÌáˆÁ$ÙïcŸÏÕÅÙ°gîŒB¢?Åþ@€aJæI,ÖÖvè%¤W‘çÃôÄðHY(Õ1üv]ÜNqt°IÁbswñ˜åX>®ðÐŒ‘Ç•ü1§öV.§ö/8G”"Ö¢æúÇ*”ñtµÙ×Ée”4>]ëÆšy;‚¸AyŠâÓω W¿åŒ–6Aþùü×6r£ÄÌû‹.:=|hE Š÷UaÙÜ„‚:e©ñèæ .×ÃSü>ËD¥¸Æ2#³^w5¹BMj°ó!&3‚)ÛÓ>·u/N)Ö{§îCÃT.UèF,׊B{­ø^ íÛx& $2Ç–á)β䀆j uÄEAðh”GÓƒ9¹Ô:%ú !' Z´(™7nHY¥^d_’Ï?õÍpÚ1Hž8`;Wç4:_¨¢©£ñ ôiîÉ®½oçDÚ¡ zÆ5 V¼ï›DŠ€yLÌEL÷6T¹rM? ûÈñ¦oömZ$8H,­úå"Çb ÆÁŠPU‰+ —„“xþ^ ’¸M0õþؾՇ$®#=kW¸CC Ó Ö´ïWîø K!==ú½è•Q#Âr°Wö¯tbÌýÀq¢7óýz@œ`ä¸"nˆ#²ú^Ë’ó§µuqZûáÔî")ÀÒùdaòÆ º:‹ž»;ì^BÑ"v—>^¾à™“êÂQ0–»÷#ž½cT.OÏkXkè`ßÑ0TškG—Hžš{º8ZÕE$×®åW ù®à‘ÅXiÒÃCLÖ"žéw¯PÛ¹‘fÒa€®„qæ°˜.8²A^Ëã…Þ_#X^QIÍ4{VÞ\l4¿9äÕ¥)df•U¨_vŠ•ÛØö‡”g•k¬݆bÄkÜ÷pŠs;FXë hL­'“¸õæYU¾¼'æÎXãù±÷ࡊD«ÄÜÿ nrÑÞ$¾2lïû&Í ¨;8G§$ÿËάÌÃM<Ð Kƒ €®Y$%ôn¬¨ -UM±ƒ B`‰àZST5¾ã@fl5) êPûÀ:xöÂZaÓ·MªýÍ¥Å^%ÑCRàèøñM«K;8.7p:>%Ä”‹*¨ ·xr^*œ\úÆOž€Š\¬èõG‰-D¸)œwàJº#Ñ/:LZ ¹·äåËQŸ—çdlæõSðJ›Cr”WF.cì^:ÿ¢é´„ŸO§ ;ÓpTn šÞ{\˜( –Ün/µÓ¦!ISTÜw§¾ŠLVÌ•¾8®¬óCͶ³ 5µö ·­T)]Æ8‘.'dT0Ïý#”ô¼8J±">zbzjisg¦ˆßV rÂʲxqX¼éî.¦§†´ Á=¬øÛðçE~v4ÇôçcèËkˆ‚\Ô¦ãqŒ,Aq(lü¹’ΗÐü'ŠylàÎ(ÛIÃ!°PîúG:|(çON¦@yû‡” †]—ž Òå¯cq ahÑq>0A¤sZÌeã`…ÛóäÚŒq¼0kO® ÐJŠqG]òøb•+/²‹/W–ìBÉŠ -0Å7CkѵŸò ÛÜí¤P•­¨t¼-¡|×zÁÐ~CÒ¥Ñ"ÞÝßið9k3×Ù+VqÇ ²Uꇺ ígê;?;Á:ÂrZÅ•ÚOg³K'`GÆšY[‡m2ýUròa»üãè™Q=Ê”2¡\Sëæv ¸Át’¸q?øóª»ú•±F‡endstream endobj 266 0 obj 4410 endobj 267 0 obj <> endobj 269 0 obj <> stream xœÕYKܸ¾Œä/4ö²6àæò)’Îfı9Œãµ'¹ììAîÖx”í–ÚzxÆÿ>ÅWQRË/öø0I‘UŪïûŠM ÛP÷/þÝ/>]|Ú0?–þ쎛¿__üðŽƈUŠo®o/Âlc5á]PR›ëãÅÓ¾=ŒCÝ6ÏŸ]ÿçB¢ c`áõþâé7¤ˆ––Å‘vtCL&­Žc÷õáàF9'–ñ8شݱ<üÒc¸3Oš½_- ¸o=ø}9‘Z¦}‡»º÷+)¸é47d\¥³Ê`¦¢ÖÚ¹å,[NüŒ0e“{—·ç‡®²o㘦ètÕ7ßû¥Ümø×k»ßžG ç‘¥zZ^à)GïS„s«¦Ÿ2J,MÎöUåÇ,\)Å8ݕ޾­¤î”o¶L|ôae‚Ðìã}×6ݰ(ˆà:Eíƒ*chÒ—Ga0´Ã?ŸÃ ÔéüÛöphã°T9Bu8†[𓣟ƪÙU1Y´’iëð£êüÄïæ³°à––qáÃÃCX4Oz—;mŠŽCžªI–%ãe «‡“_i£,Qí†Ê§®`ÄX^ÄáÓ]ÜTY›–~éë]é‹B°²Hû~ÆLei¨<ŒÁ7Ê9F¯ —·dýÕ9ÜieW«¡òÓJSØñ±»yöb-VÛ´r q;]5WõÇ®ÜÇ„â˜u~üæ)!äæÙ_¼iAN¢°ˆôÕðoçÂÍSùBM€L)“Ë„•ˆz7ŒÁ\ ¨dÊÔövÍ8S“\xýrÝADN¿²- ifè4p3ÛÛQ@˜ÔÌŒù±ó’/\LK>‚‡äQÚ¦ò ãÒ\$H‰@ª¦¥ÜÂT×Ç(]‚¿¶@ÚKð ߈VO0Ò%@à8…IŒœT‹5°)O'íÆ®«|4wù™ny|ª˜ÄdX3ªâÕ[ƒù6Z†«žDT6¬H[FÀÜ9úåaί~ìOQúHn“ãPæ‘=4¥‹ðsJ(ÇdÙ×Ú¿Z€›ë ‘<-²Dêϭ܉¼¬Â`m¼gMÍå{~„;ž|F$@õW%Б£ ^È0G¾(÷ûUÒat"¨­ X\5/Ûf€¬õÎ`¡F³ 33$M+þ‘ý Ì8wV}` HÁBÐÚ|¥žA%©>®Ð™¶N¨ÚY A‚ÃÉÔí¾>VM „‹–ŽñÓa7I0™Ëƒ(@€pÏàåBáE1 %ò䲉^(ÆÒ%A6žºj(ZJ„E”phà,¶³,ÖF°À«®kCf…• pÏ}XC"]'Þ0(2O•]ÓP@¿3†!øÐê`ð«›}@V ãˆÅÑ/ ša¾k! ~µ‚Êg(‡(ååaë´>J¯º3öwu_½È"5x})ZŠuYƒâ§.?Ô‡ÐA)P1oÏZJK´\:Å2w]ńћб0ÿ0/†öòÍ¿.¯×6.ÒT¥Í¿OèÍ™^wÀ:*@NP(¡>–CÕûÒS”X#±…~ΠbGb: ° ~Ú»D…­£¸/ÀŽ“AŒzšÇ±ez/ÔrŽM3­Ér¢‘t!+47E¶øK„b‘Ôjú–; XˆYsp+DÕõ@AT¦ò%Ì'k˜³†[¸Xö܇®S“²|ø]³Lhá’a¥ÈBb_÷»b7.€¥Œ²óLœ©¨%ôd±¥ÒÞU§!æ oqªwñ\“ûÓ0‹ÌÅ·Ú«²‰W)5\&—öª yžO‡îäu,hêÐãøº±„U³ªn¬`ÎUËË'î eÕÕáµÄšÁpÀìÕ™c.&Óöí!Äê|Ñ OôHб_Ó°ÕèêÕ图ÿ ^pŽx¨ ¨`M¸áç:Lç”'@ßSWCÄÄ.V›ö©’Œˆ,Κö³&Â@fˆdØxZERÈxmò«G$w.Ô"¿²~óÌ;µVk¦-l™ÖòsôçCÌ9ÔD‹³ÑÓ£z(ƒt.î5òdŸÞgà!C:T©_c’˜¥!ðpãÌèlI ý¢ýZÄ­;ÞGŒýæˆÏãݾ~,|WÕp×FÍK¥Âæ:?‰ ‰R~O¤„ÅH½½sÏ»ëq‘„Ÿ†1¡I°PÚ)é]aÀñ€Îz)Âø¹‹Rt©øN¾&Ý—/öZ-¥:ì/ÔBªC×1•êîG ôD«ÏÍ ­œs¯¿çËÏxQ“¯*AhŽ€æåD þ‘ÞèÔ¨œ3÷ˆ†‘ÕóFIÈYÌì]Ùuu°X¸§g\[víÊ[c`ë¨Ä´ÛÙ9?꾉\ýcÊŒGÁ §Ÿ<‚ÍB Ù ò⛵d:nþ¤ÝS“˜^`Ÿu†{Úšû;Tt–b7–”q!ìÙi:?Yᯅбe[º:DLº‡à¸²(«ÛqˆŽŽñ‰6ûá¬s¿(õCP©ÊÉÚ4Ó´ç«!”1žnÓp—VùÅï>ÂÊ™º«¤ë¹žÄý Öê²E_e~鈥³'4øóóS1O~Ù\3÷ßn9ÕP÷Åf ÀaEX7óêzóóÅÏÿß:°endstream endobj 270 0 obj 2541 endobj 271 0 obj <> endobj 273 0 obj <> stream xœ­ZK“ܶ¾o\Î_ØÊɮڥ‰'ÜYqtKëä²j†;C{f¸âCÒ*>  Ñg8«õ£tX‡ýøúën”»,Ý?ü»Ú_¼¿xÉü³øgµ¿üÇÍÅwo˜¾d¬°JñË›»‹ð»´UÁ/+]Z_Þì/¾¹ÿöæ— ]au/ܬ/¾éÚƒ{ÈTÁ¹UøptlÁ…4ák²6½¶mÜC^FW6ŸšÕ4¶Ý¡p¿)SXËþöϰź׵FZZ¢Þßïš+¿@Y”¥øK=ž¾ÝÚ±­wíçÚíê?ªx!Ei’˜ƒT€"¬Œ›al÷õØ ~^0%i›>Œ«*žö—ið»sÇ5l®ƒk ê×J_^ƒpÒÿ2Œu?¶‡ûYŠB1Ëñ›al¼%¸,”áô´ýdáºÐ,îZxb®éăÿ6VêxšUûU³ö§Tð9™ã]P9c6Zü!×J[V'†,9}9 MïmÈÁt”òÙÝØô¨L©HøÚ=úî(s7´p®TUtþ-º……È&xwÝMs ÷Tn*Shnmüò¾ïÞíš}rU‰üòÎ_Jɸè¡CÄ`%w1¸©£»+®iâêõú—f5¶üé`uK§ÆÐá¼p«§ÐiÃéx!Ò®›°¼c¡O‚ñ¸(!¯ª’äà÷}xžB ÅÝ4b–Œè‚DaKóè¢Á¼…EU€íyzû€®Èy<Ԟ횦*¬àqáWÁÝáS°†--óQ‘SE=¿|ýó˛Šý¤ HnB^²k¯\g!£7zTI{XÀ›¹Ž’lëÃ*(!ÈÃuô(£È£þˆ=+D)Úu@Û‰’@tÁÈè~îµøÖ]ráFE?ívͺf+ÁÝE•ÃàÛn-À ‹ZüÐ-à‡ÿAœ)JTíæ0 zieå±B€tØ?E! Ž@¾¯OÍÂX©-#½¡¥­!%}.@KA©äß/⬋å’+8åbæ¯Ê”<ûæïáXFäǺ†= #ÅåµK Æ¿û×¥óæ³þÏUR>ªû"3ØG*òá=äœzâp"#Ë@<%˜õ´BŠaΉ-­§>­ngñŠJa +ö@×öÈÕ<ä^©¢ç™+8< êè*œÀ*{\Ì™õJDLüÃ\ ÜqVkœ·ŽN¡G¬Š¥D™QX`áÜdì;äÖUé8u$1ÊS|Ú7±Àâ,Y¾_7H À-B\Jkr¯}½2nZûe hdZÇ×}þ Vr…‚ʸqfÁv™pÓýb¤@†ç†ƒ¯2Ãe„ØYÉLî~P!p@@›Y`‡~.µ¯vClZZN¬r@‰€®MÔ'frWO?ÕϲÍùšð ¤Gç°óoƒ”ç]ß7;o 5 [dD]ÁpáëU¤u•™HŽ4¤äKù§z5¦rJâ—ïÁIÉÙÚpx•|îsÓwWH¶lU.XS- kÈg µ”Š„»¯ûzßŒè¼ ²?—Y®ö»Â–ˆÉ¯X¹‡&®ýñ\Å@î†Ò?¹ÊRêX²rp(Æ8•nÓa…yXWPÆQ<|lÇ-]óÓÒ>K£Òg2' È+~cæ°T{ûmàÊÜÀ‰Y^âÜlÛØÍá$b{X·«Øs’¦à%9Ö‚thO¨O uûuUª¾›O«æÞé>byå:W‘žµ_¯¦'Ü(Œ¦Ú«þ+”EˆÔ¨@"ãj²bÔ™C'ª©>nÛ¾jKÊ*Ûȶ+1a[v–ìÌQZÄ6ð/1ëÁ¼«×ˆ WEè€ÑÚ·ŸCPT@J·¢õAf›Ìë%È…m>´k„€GV-W¸RW¸ÌõL¨-tèF<ªMG=ëÃ.2™|ßÔŽªßM;ÄWÁí#…ûªž‚Ë_ ­‹Òä1þPiy"±J,R’H¼mÛn¶¨nåÔMu/!Ðü(:¹ªñ7áÇ¿c–"!maÌ“ 9 ñÔ¦; ycR–Š, !ÓÒÀÖD ÁÔ¥Ô© »qa| ÂB¥ÎÙ™^*8ºädÖ:ú¾¦.ÃkÝ”šÊ#_I@’\%-e¥a'XÚ]çP`Zfó`z¬Hö"F^ö+%Ð%Ân oJ3 slì´” î ¯ÅÌ!!yQkãl™„ ³ÔS¯©öZõuŸûäµ*¡YÑ@ÏRDOðî¶`,0-§”þ¶i8Aý›5û:°ˆ…;¿ ¦­ª™iAþ?4# Üâú¨Š†€•Œúž=gêo åi°îÑV"ëJ@Ô,Jb\¥PI>ÓR’&¦¼ÈCpXòâkؽpäã²A{e˜³Ä‚B/”6””Ò–â œ}ÖÜ#Fž² ýeêÑ&êU¿ºÝ46!ž,£Uì8Ä+Š7 §Ê·Œ1ùbËX¹®E\¡$™eÍÄx•H/æ‡é‰ãÝÞBB s&çáš2bȦA÷$ÚßpaÈãqáU½êàYNF4”feîø)îJž¾ý=&Y¹(ÍÎø†i“ ‚/úck“ ÓFIl¢+v:Øq›&º—Ñå”Ðû¾]±åš ¾×R;.Jã`‡rEOŽÅíÚY±ÄjuðmÖé)ÄüÏ·NÜæ sÕ% R»}66¥.‚²©­yØEª!ÓÜ'F^0CZ¿ÃV8 W¤vjDÊyA €µùöù³×K ãÆ”B§†Ê.v0¢|ýqÀgUj$&“Y3~zsI 3G¼*’%•4»ÄîÚ»¨KD«¾ÇÆ*œÆR%ñÉ¢± ¸ÃN݉ŸM—%ýjê?`fÔ61>ç½¢KEôê- õ®îqSé~‰ZÊÚ!G:Zv29È"'&*òP”ÌJ²î´Ç¦b“Ñ‹À<bÒdæIÅ{hǹB‰Þˆ”'#ȸ ŸÿøúæÇŸß¼]r2é ò¨¨€YªUo‚îä‰ü®3óoš®>þÊ‚†TYU' r×~+«4šèS¨î@D1ø„¬$=AV(eKÒFß P=ü4à%ÔK>Óœ–âNŸãÛ£“›zX"§Ü0n;º½aåÆÛcÈw7¨;ïûºÞ•€eUZ$:´¾ýýP§YÜbÒŸýówÜ}âìWÑ!,µçE3MÑÍ«ÔØwPÚRÏïZø 6ÕøX ô³r••º!œLº:±±íSCáw3?×ÃÒy‚† ^9Æs2—œRߪ›z´¼«åé(ð}‡3n‡ƒ6ùZ ÞÈ‚Y Ô‘°‰Þg‹@4¤ H¡ê˜ £›‡!Üà®®§b{l*#zc³"|/ãšÛCû~Â{®¼Ô‹¦<îèŠjÖ}ØI€Ó%ëŽ(ͱ+æE~øÒM yò‹5Âx†É'Ô•% ®‡‡½ïxQ5‡ð6 y2vÄOf÷ó>Aß¼ŸÚ¾YÇ ,¥L bXŒˆ¾Ä]_½|ýã"ªÎ#û \^ºŽ„«Ìý,ÔemÈÃÒ´BØËíê:ââÏC^—`F̈Æ`+Ü4Ø„WXézD‹37ôÈöw2Ü,M„ærú¾!½wlgOÍ‹àÉ~‚^R+.¼'+•BlhãWû¤+/ÿ[7_Ú±9`Gû¹qý±Ëk DòKøëêzÂß nDªc°¦cÚ…uP¦>â ä"&gÝåÈts0Þ³C&/Ô/Õ蔑W‘èÔØÎ†hiÌÝÒ`¥Ì£¤R!¦0]R`-ƒ7Ò+Kn‹ÏtðE6ͧdBË<Ë›ñ»‚A0(óYZ]L8¥ÀR ´ùš• Øíp-^yûŒúárÍÇ Í«Îû}h—f¡˜öy5Ò¢™7WßB«8áM0öR‰KÏZW{6yP ˜Èéç<ؽÇTôŒç©º¼g©…š[q­ ²¼51XBæ—C’…vÙív´Çn„Õu÷ás ¾sŽŒ¿½Œ¹”‘¸åJ¦Œ‡·»nßDñFy“g¹ÛvckíâVµ[¹ü­þ!<{õ«d3à‚­sB×·ÿùëJïÍN±Æ…,Iï] n sÈî‡1EXØpŠúã6¥¤K²å‡Õ*Û}Û¦¯ó†3šéáp¢¹ÖÒ¨È:O[ô@Mˆá0¬ãÒ$» »|Ȇ ’¯i0‘‘g ý `›Âq2HŸÍÄùú*8À ´¢x½†… ,fêcX 0ž!ë-¡<9 ºÁ Q|‹Èb ²ì!β©¹åÏ ‰i ÙÃaQ¹ðá°Ûp:¥]öׇ~xü>…!Äf†kÀ6í U×0kâŸÓ{jöü§+ô«äÖ–@ù=åœa£yùUÎA~ÊðÀ€ÍbføX–Wþß‚·wU°O޶ íW aH“ÇFŠeç F´ì qð ?•¤Iž [K¼t=lƒ§i¸m‹ÏÀ*gÉ;c³P†D—@¥¶Š’ãØæðã”`åûæã” Urˆ2NÎëgÎŒ/š†9 ÝÛ~Í(€ ,åíHZzA*¯È§!ÅS:íÜe<…]‘¨ZJd´’\ âyßNct˜TóĭϯUsZkŸÙ$!ÑúšS: ‹ Ì3uhWB+Ë‘´×RÇUŽšºÖ;aúeåQ²PB*] j¢¥Ð”»Ãðˆ–…T—Þ¬iÄ’wtCJËäsÑ‚"M’Ȭjaó®kÓ<£7œè-› 56˜ NPbn3®kòRK:fAÎ ïàÛÀ…DÌÃà€{“œ„*°k7Î… g`w3wÜ"òi ÂónÐÎVäßeWTú¬”/®ŠÄF*Œ_4sÃÞQôUB•Hë ž1"øëÒo-]H°¬˜ñ_ÙœþRÐw¶ÿýJ@HÝwí€X§/k"µe­×Ϲa:ìNTÖÁƘósGÐó GpX9âªÎ}¡7l`uôr-n„dÝÇ5]6ŠÏŒ¾Ú%DÒPÑ“hÞ¼Þc’#ÌTÿ˜·Î¥¥Âµ(+ þOûá@ôQ´È0¡pÂ×%ëC´È¿c ÷í±ÍñÊŸ íºËï§—ÄôD” áüy@€Í ¤ªræ©Û}ú¿mŽ>”4ËF‡eçê°ªx‘sF½°I#Î9îØöhcÚÂçï#&rV:;À¨Ti‚œ'z¹Çz8ÇR$²2ÈŹ64 !”ª%¨0Á Œr‘ ‰ësL›ïuÓN©æw*ÍJ˜dD±Pj×Â÷uT9À©3D·?ÿÏíÝìÊ@&:/ñMv;TGšÄQŠÎ¹àÊ ÂÈ!D,¬ñ"›@ÿ¢àÍ·5A™KIeQ; Ì Ðä=.CvY¨M>]ð&„^sÁ -}ÿ4ô¿º]´¨,9ío«R­Uèܧ΂_¹:ø»qLÖdà¶KŒ¥1Ö‡>õQ`|ðMžtè6Ý4Aa˜©ä#Ϧ½^Ài/(çwíøˆ{ 3ZBЀúPí`‚„¯ ^4¥&õfÁÇrš’Û$#·Wý”¿•ž§5ñ’BgJd€-¦†øãg­DΟ‹êØI$ Œ_:k§@Z’–jÖó€€åˆÒ<ÃÁ#΃, ⺞Â:ÿ39LÚ»Å^¤´À3E]xÊö¼‘û‚(¾À‰ ]Øqêv/QHÇȧ#F.÷Ä_(§áÅw›6«Fî¨Ùß ýZÕûþ¾ËÚÃñ"3ö™k½¥`Ù©A&}M@ö&SXÀxòÎ1T+¹,‚Z/GÜãîðË- ìKË}»1ÚZ‚âaóÜdž+‘úíþiÓ'‡it‰õL¿¡v týcz7¶º(—šF»S7%t…eJ¢¬çŠ:qá[ü±ívO(‰¬æ—]]dßf×e Åó ¢Æ "0¬Y߬Ú/fUðfuа"Ý? ‰|CæL‘ @ÁBAQEÿ‡JÁå(.@ì‹û@?ŸöP b=n@>ZÒ ýÐn6§±O‹ÅŽå[Z·ù˜AIò ÉfU  ÅC©‹º (©ÝÏu-‚“+àÔ><¥`S,(lBá ®©ÚµJ+ª^ß!jÚJ ä¦îòLæóG2È©áDJÖy…XÆsZÙüB`U!4àÐ3±y…Ãj]8a.ýՊܧþN»Ç» ´Œ"érí¶c?¥°báÄ€„óÐ}|B8QJÃ>œïÝ#6wÙŽ°E^Ö¦ræWõý©írNćÄlA¡¡a¿ 0rnéP¼ËÑ;—IÒÁz*2¸bk×CÈÎääùxñŽŽ/s\ćãÄñÎÈ7Ÿžr™¢J÷ûÝiŒäß3Ýêpšå >—Øq©jŸçÆv¸NA<×±ßS~•£•Çd{Hn]ÂÿÞ8Õãýq›+H®è 37~X¨sJ¡˜¯½ûr„ÙîâÜé¬[žÍÍ©©OY¿;¶UjO@aÅ€i@¤t”á­?ß­þ~“`COf~t°V[AÝÚáÜ„Ã?~¹ðãíÍ«Û׫ãxên^ýuÅo^ýWø×¿ünÿ´ú‡›?ߦ¡Þôm`-¡©~ÞÀƒ *dŒ¿o¸r¿‚­›pÊ®†Î-˜v–9mÚH}ÞF š™(¯ûo|änSt ™ï.‡cÄj¢pìç©YÝ.­%D"g2âb t‰o¿` ±Ë©ÙŠlc¥/çt%Ÿç£…†B¹%6‰ 0Œ#4yŸÔ€T¥}ޱÊÄæop2ˆhœ.ÜP™Kœ3_RôƒÓTÊ‹6ß0GGÇE  V—& j %ébì¿_>ÿ¶héЗãth[_Ápót‹·ñc…ËS†<æ;ÛÕ¡ö!Åž°œjîS²+ëItਾS L‡²"IèW-–l½9‡ÒѺ!_õõ (²År!êÊAÍ}>0’@­¯ÊŸaHW1#M^‹õÌçA§*=¯n –[ÇpA&ÝÒµ+eAÌp‹©-—8™¾X‰3¥Õy(æÙ@Y«ÐIŒ÷¼ÄWÄÊ[|¤5=ún!¢^-RhôKòf»ËFBa(©›¾éÆp íEE¹¬•;C0“b…QÐ̇C„K·4ó·rµäVÎäg·¨e×ʆ|èû¨¬Ð'îøËÍÿÃÎ%endstream endobj 278 0 obj 4317 endobj 285 0 obj <> endobj 287 0 obj <> stream xœ¥XMÜ6½O ä/ôÑfñ›Ü½l6Ø>lÉÎÞrѨÙnÅji¬;³Ù¿E‘U”fÚŽÀ€m°K$«êÕ«W¬?TñOþ·¹Ü¼¿yàëþÓ\¿¿ùögnœ3¯µ8ÜŸnÒüÀ…aʬ©˜1‡ûËÍë~sÿ+˜ 0_y¾šÃÏÖÀ÷Ç›×o~üÏ›ûdµßTj&•VÙ¬©ûh$`'d^œã|#½Âý†y]“pšòh7\ÂúµcÎ[žWç±ýÐÖ]üA*&œÃ³–·Ójn˜3 kç)t§ÛÕœ3î*¨ûãj-˜¬<îÑNÓÖ]¤`B[´+ó?ÿ—«¤¿³ÕØ·ýÛõcͼUxãç°FABŽ*ò¸s„UxÎ1Ì¡™×óï¤ÌIs¸ãŠ©|ãõ ^xübIk‚iON,Ó’âóíϲÚå¦b¶¢kýðý×Q•Åð=D¨ô ç5Ü2®žù¡–‘å¤X+qýßK“­xòy]ª˜ÖþY„må½ù¢d5¹2‡¥[Ó)áVNºÏÜ>Äô˜Ê¹~‡µxï”1®!®·a/§î)þ¤³^#TYJ™®zRæ™J9ûs•Ä+ª¤º›†ŒW[3|Æ)cKð ýÞTŽ–¥r†wë¨Æ†nʾCáᮿ¼©FTL%0ú¡ºKÞ¿@T½¡œÿÝud©è6Fó—o¢…%ºÌÇsÛdá6n‹¿Kb¡«(=çÐ¥K9Ç=çó‰˜aUH³éƿɴ¢+½J,q'­gPM©Æ=Y³ã!–üwrëÿ2̨¸ œ îE㯓¡ÚÂ!¦ù®Ï©ðZâµÚ®û=9«³=fx˜Â1£¡òýz‡‡.\صœh nqŒë©^,/µ:¬¯y Ê{àȹú:š³ÊS§Cî:ðXõ˜mÝIkșǜCêŽ)JNè¡oÂJÙÊ®ˆ¦²µ•Ø'°P ¢­c;Ý¥¼¹ŠI-7yk–i‚»¯»Cœ59_?d*"wÖ+3 ´„ÎHKà†( jg=²ž¢½_’Ña\÷ÐøŒCćßáUßΡS‚’‚¯(ûÿŸÇÜg 9^jX†¿Ú&¡Ò*“´{`Ê´å«}Õ¡ý9…ÏTœ]ó©=q¢Ú«ÇvJi°°õf9üåÀÿÚ®ý­?S  D€˜Å.²0AÁîkTÖpªæ svàUIƒÆã°ôÇá««À—›Ðý/“½×ÄŸnB ¢ºÌ“@ŸZø6<Û”*bh §%1†cB9<žŠF+*šðX2)¶¾†£>õ+€‘Tºs¦'( #HwÝ£Õá©næaÌöJ3%+Üû´ôM)v0×q³ck(É øoÜ)˜[‹þ=´oqÑÕ]©­ñ)›iIî¾_òÉÑ1ºÏ»MwŸs¶2Vaµtüºi–±nžþz °©µoéšëqÎbDyàu Xn# +5‘hбTã§z,´E±‡KVªª¤ñŒ·µ¥f¦¡[æLcÏ¡ ×± óža[È+=ÑB-æ9#@JLÊ¥Æ%ê)•‚v¾B\eUù‚2_òYíŠÈE5HE´ôçÜË´¦=MXÓ çLÉ´>möÔÔí º~Û·—ú6»‰Êôjö§(Ö8Ÿl´SÛG’FeωjŸHËRpÚÛb™ 6" Ë÷!ƒŽÃq ȵîž®"|ò‚zXÛ7Ã8 ±îb¢ @ÞÆKݵÿ­?…š; }¼Ø`¡£,÷Ï펎tí»Œx!JëÚó5–Tb[&"‰.v̵¡¤A9kÖ€©MåݳjصûØÜꇶKÙXËÑí  ûWE&:õö°­™HÇ}¼¤üIð°F¤0­ÈïÒ"žÛ{ApŸ'a¦Àw;mHvPn[ g´é8®¡qêt À tHR½Ÿ-»çÅXAr%ŠÞî²›\§é(¼Iæj!¾„þ1líD°WåŒ,úÀî9Â`U}ë2ïŽÙ+SBî– ¹K’À›…Ñ6¥D‚¤ÃñbQÞ¶[ª/Û’f­\)“FÅ·mÖ¨}?1D©ïÖFýøÁ— ù²ÎR〙c½¬a’rÞâë$ Êy…xlÇÑ(y‰7óè3¦PC‹«Ó„ež;Ræ÷ç¶<ÈØ=$à›‰¥ÏæR¹¡G]D8¹Múèg3pͨHùæÝ'ŸãÊ´|®¯ M¡O¹UP=¸úæT¾§T§êð›g ¼ŒU>÷qóí´ä‘z•"e¤žÃñ6c'ÖµßÑ@V/QÕùalrU)Ü&€+§‰öêÈ1µ® B«2(75LÅS­¦t9ÔûñL|îY(ÇmÕq×B÷­ÑEc‡p˜ÈÇHh!7Zòˆà“â‹_˜2kªØ¿Ëó`MÌ®^g{Á±2H¡>bCôqxÌ1åå=”ÉŽ&€¯aŽÛ¼PS2¥)µýc&ä7)I办ì†eFcn5ùý Úþ;˜«Ý¿ƒþU^ ÷{{þ8³ª¢ÊO<ûżȠ\eÆzâ…roaʽ w'I¸kûSl{(5 \€ :ŸSwƒr³Öÿ¡ÈŒsuécÜém~aP•‘§79Cp¶ý@OˆýË~9ß¾äŠ29˜âîòªaÅ2Nݹq9cܱ/R¡bsÃìžÆpd¿B˜þÖ„±gÍùjf¢8¢!2½4ZQ‰Ï*^09¬Düé÷‡Ÿn~ºù?/?±³endstream endobj 288 0 obj 2124 endobj 289 0 obj <> endobj 291 0 obj <> stream xœ­VMoÛF½ ýr¨lD+î'w› @ãÖM6šDGC­,")‹TãÀH~{f¿(R”,´|5;;óæ½™YÅG±ùóŸY1z=DØÚÂGVDog£éGøŠD0gÑl9rp¤À%"FBD³b4³FD¡˜(³Åhü»5a„1ÅÞ”UÅf­mN$A˜páOôcjŽÌ¤ÆHqNLÊ ¦!£ ¥ˆIëþNo­/IO0óARcRˆK¥oZîÖkë#ª5ÌÆ8’ÌÕÒØ0EXJÞšÄJ´¿4Ö!™°`ËkkÃHP²o¶ºÖ¥±C 1n}½xiQQÄã$°³¬ÖëʓƸ$Þü%/ï}­’c³Ò¾,Ìz®¬?tQý•îêúS^ l³AŽgÂ"¨2áx¦‡HMˆ&ìE°E/ ü8T5s¹¡$%é»Zo­½~PR'0`a¼åäúêö¸Ê˜C-ºˆuó†pÌ‚t¹©°p¤2 ŒÐ–Ô´É+G6C‚)ÚÓtú‘öòÆ4n5¾6.ªHwuû6­6$#†Û Ägwã¶ç¾ÚFe¤ÂÏÉÕ¥¬¨X„’­r×Yy ‡ˆqÂ{0Ùó]¯lOa8kð‹ †%Äi[j3ådèJCAÂ0 `•‡Æp­az…ÞƒjíQ¢Bì]™qÐê¨ôÒÌ5NÎI¿ç«ÏOá äH±vù,ôÚWJKÈÄüÞŽŒ½­.OKÏû Ì%JÌø •Ø /òe¹Ð¶ÿ˜‚u×öêÍí£Ê#º{wgœ&Ákãã˜x÷óRÿ]e¶Þ-lÎå$ùºH›Z½±7ÃQçf¶NëÚosÖ“¹Ã¦6• ÝþdÃaBŒ™ çšf³û¼Î³ß,×Ð=Œ½óñ¢_í<Á':-_íÝ5‹6[ç÷ΪDÐ3ÞYUÖMZ6ó ;Ó°…ûÍ¢†I€¡ÌêÃIí5·Ðæ62o[ÒÙÕŸòû"8§<®Bî˜ÂZlЧo- C·§öûþrl¶0ï_Æù§)B D.ÚÅe†wA¶"žÄˆ_ÎÇÛ`µÿ» ßîOw: ìñvúæFÖeÿB$o?p¿8ça;4Ã44_ÞÜ sþý²}k‡}xðÊM /åÝ%íE=Üi›mþoÚèã ï”ÞaXÜ2÷Gç[µíñÿ~¯íÍöHüU¯þ7{w_%].òå0Út:ìÂÕá¯øul»g/3qY5Ž΢££0@€endstream endobj 292 0 obj 1085 endobj 293 0 obj <> endobj 295 0 obj <> stream xœ­VMÛ6½ëOTH€Ô Ôc~SÜMsHš´— š…Ñ“…"É]¶äèÃ=,Òß^’%Êòë$ðÁõæñÍÌ›‘à™_ÿŸìƒ/Á—Û3÷—ì÷ë`uÇhˆ1(ÎI¸Þ]•J@ˆp½0«õ?À9á´NƒÅïq[×’̳Õ>ÙÒ—D³ë‡Ì 1Õ³´uVý\w ù ”ÁÂá>¼ûxîB Š$íA›EO4Áèû8SøDö96&ÉÛ•Á( ”ENFSš3Ì C I¼KÚ]ÜØì˜ÆKâ5]Ê«;>I lPýS‰P(AI„±HàD2 X)iäœf£O).}äf‘”û¾ØŠJ—ûç¼È‹¿Í9ÀDMejY‚ ²ÆÎL;‘ÆMlÑÚ&˜‰þôß¼yp§Zö„W{C¤å.uáØ)91’ï»úrPL9£¥Ùnsç,²dp!´É´Û¤°è—ù¶H³mß L¨SxûñÞõþþûNWu½Ô¡y‘]M"P¤¿¼Hvmjã9ʇR¼¸Í‹6oVÚÇoã:ƒ‡–ÞÅñú˜%MY½y*2ÙÅuÝwW!ÎÎ8^G:^Ûb ãxÚÏ»<±ùS@˜ñqþŒîya­¬„ö·j"h¸aR&§ÈØ´¨;fD“JÒ“ÖMz}Ýeû:-5SöæUǤ9Cí³¸þ¥»^pHÙFò¾ŽyZŒç1Êž˜h+"$=‡|ïþWÝZ™F»224BÏέί­²}V4õÆf»¹êó5Û•ù¥á–uÞäZÞÆèwPãâÆÿWy\$™¡µ’,MùÞWUYý–m7 ý.Œ´{„[_;-fOûûߨà.PRÑ4¬;ò‚ŽyÕ´ñnî°®œsK¶GOõâ’ƒ®':ôXeM[s~/Õ›NAÚÅŒyå¸X\yȪX›ÁHôlŽ‘^ÓèœiºŒ0å€)ö3º±Ò(Åz_2¿pgX:;Šz³2z©oçd澡l¾AûÒQ„ÌîöJ÷,y‡Ñ»sÇ|ƒ²a\G#MæàYºŽã ü]ãä ç±ÌÓ¹©ë¬çq4ÆzïFîfýò:7žÃmJËͯóÝ“Ž“`äщÝU~Ô;þf×Ö§õÔ9Ã1K;4iöŒé N»óÓSãîïaíJýØKçëM¿d½w}V¤ùvN·ZÍ¿7N?üÌ;"óíÃuê3À÷ëðSð)øbÂendstream endobj 296 0 obj 961 endobj 297 0 obj <> endobj 299 0 obj <> stream xœ½VKoÔH¾ûWX - Ùéq¿Ý“„°p ɰ&ãq£±üXiñß©~Ú“)„H«F©ÇW¯ºÊ Âq¢ÿÜo^Eߢo162ÿ“Wñëe4¿`4Æ)ÎI¼¼Ž¬Ž•D$–„ "âe„=\~F˜FËutð>ºî]^£üîNkçXLáfÞ|FbÆey[hKÂN˜r8YÞÙFË)GI"±“—Õݦ¨ŠÚDNQJ¨pš>ëËÆÈ)CR(êä͵–aŠh’ú,{r~A·’#Ð&½ã;m"¡Šøo>¼Îºb±hLm\&aNW´Y߸B“NÚ®V‡û¥Žå¬Vy¶Ùk“½D‚)¯ùb“ÀX‰Ô‰þ5õ@ª©ò]9+MáB¹/r(ûÕáÂÕ™l‘Fˆ¨xÆJRcü¼¬óͰ6m%åÄgð,PzûLkg^=ÃÌ1ø óPçšœ’"E€8ɳ®+ÚþÕŽ«Í|Ý _6ÆQ”`v5[†Ctº©;ÓANPèˆ ÅBS»~½XüSäàybƒ¼úÃZA×qVwYk ¦ RøiÐQ &H%Ü‹¿›"¨‚LA6©ßÖ¸Òp¨+ÿ+üØ` šJOO,Qê «ÃcƒŠ5¦†N&=pÝ×F)G©J}…7Zmb~N®þ4z- z­ÀV“‚Ç·¦äÊ&£„ý%ùmIÆVùwvêZOHh}‚,2¤«°RÓ’®5CÝ•7µ}/R!9¾„²îÝä"¼äÚE #¹û‚ï6wçÉ®'¬“³"ë†Vo¦¾ Z@&µ»<: ã"Uè› xû©“—5éØÄúÈ¥!Sˆçù„tΛ®ÔœwŸë+7Hœ".ý™íÖu¯ˆÑv¾ Ûô¥e<%ˆa6ååè[Møíèó1:xŽmÒÞgm™Õya}íüØ¥éÄ&Ów×ýÐÖûGõ8l ò{(ó Øü ¢L˜ ¨\88îéK8]Ñ9 ;& < ðê_˜uÄ8Ì]XGUf7:ƒ5/DØ5msÓfÕÞ»Šuž‰Úº«¥A&F¶"p”c0w ·¯ŸÏàˆ4M2`Ë=£o‹ª1Ëæ²¬ôéßv0\f!åÿvwÞf}ö¾ø=8©p@ç~y¿e5Tû øCÌcÕŸ€îó XôE{ _,† _8Â^nýɰA …+ø£òwyŸ·°Ÿ˜üY Ô¯ŸÒLQ7ÝÓ Þ4uß í^”GTs¾i|Cv>ÍàË@ @äð‰+ŒãÚð¯eü1úýg<шendstream endobj 300 0 obj 988 endobj 301 0 obj <> endobj 303 0 obj <> stream xœ­WMoÛ8½ûWØ‹ÓÔ´ø!QJÓ.°íihá[¬Ä$ÜèD¢R£Åþ÷J”B•²«v>àofÞ<ÎPÂËÈþÜ^.KÜ®õy¹üe»Ø¼£°‚QÇd¹½^tð2ãˆ,9KI–Ûr±úIéü®)äÙö¯E#û¶Åbu©öµ©¤(_YÛº7®IŠ2ÒîPÚXa(N8uÇJ¡ônµ;³FQ„Yì,_zBpêãl6Ö‚SDiJÜæ©e%ÌD\æV†^ a„]¥JxÒ¯îV8ŠÜ2Ï’Ó›ï÷OݾÆY„XÙb†Xk~#šºþ N¾‘Únáâi†ûp‹›ÖÙîìE{¾·zYÖ¦¸¸x”¹ÙW—žùx'[b1!ÛSu˜ÜËn¢Ì÷‡`¯2j¯kKwçÇà7ʼ°gy-¥¨CBޏµ››J–Ò²õä9‰QjË žãïHøQT³†½Jè\N% <§GÅ”ƒŒ;)ùú×?Cç×Î-­-~£ g™ŸV+„×¹vÊ$ÔW& îZ:Ÿ;dÑÔëyÈ2$pxújËFiƒ¸k „&ÎPQ¥o»ô(îY‡P×û‰ªÜ‹J”ÒȪ=°&”"†±§µ®È!ÚÁ•“‹‰ G¨c!á(ΟƒKBrNs RKô²ÞWåñ áåÑcû:9tq˜4ˆå=¾ZÛ¿è*Œÿ´ ùáð5 ݪѵºÑ²ÞdïWaSN_8X<00qò2Fœx¡ ÒöNÏAü8ºBfOÀž4¾‘sqx6J;ÁˆòqÚÿXC4C¤g ò°±EùÞ;U•5™O6}Ñ¡Š„ -r=)6mЮ93ŽhFçtçøLó‹a`“”@yè7‚>6BÿPºQ&\¾1¯Ÿ”¹Ý7&ÌRÃ7* FœO v/ª¯æ´÷²ø/s3Œ§3_fš9<'>–“¿³=ñÚÛÑ}Sß~ø(ò¿Ûf¤;íaøÄà´¯]…ºµÓ _×¾"?æ©­¶™Íp¾ ÿÒ>¾à5)+EF95Øo š%?VY.Ø}†àKÑ‘¹y³Ïÿ Lá9’Œ9b;,±û~ß.ß.Þ.þ‚a‹endstream endobj 304 0 obj 1013 endobj 305 0 obj <> endobj 307 0 obj <> stream xœÕV[oÓ0}﯈úÔ‰Öo±³•îB¢ˆM…§J“›x[ I·Øâ¿c;Nš‘nÝB >Tú.ÇÇçû|”À ´?ÿŸäƒ«ÁU]¬ùKòàéb0=Á&AL) gƒºAÀ… Š‚E>eE¦OeY‚ËJ]œ®Dòi92øËƒ£ƒÅÇAL $X¤w¨DÄÈ•N§69 ”#s®%¥ZÚ8Á „„úxnpóì›,m*‚€DûÔr”Ê3Q­µMQ F¬AÛJ—U¢7åòÀ¦'q#Ö!üA”™X­å\ê2KæÝs aæ Øƒé Ùfj0Ÿßs§†{ÝãS[/«"ÑÙ¦pàUn«bnnám¿ ""Κàc‡#r94Šz4AsôÒ†_>sÜ" ¨ÑõíØÅb`„>æFx)ʱדVëfº~œÄ"@ݧÀ¦Ò—•¾áþJ§‡‡‰)™Í†y­Á¡ƒ@1Q1œÍLr6sÕ²H×Í @QîGoϾ×h‘®N»x¦2wãWa£¸O)-ŠT”©_2LÛ%ó ;CׯãFÌJeŹ ãÄ!%><ýêäÉóZÈÈiç ÷yfÖU¦ûq3?‘K-Kå¦Èea³É_2}á(™÷ÍÚ5+L½ª…0L:ŒæÅ{%Ëw×0ah²í"Uæ@?ïhm“@¤ér4Ì¥(†ã~¿½NŒ·:m­£5…VX•çÂãÂÐ\¶Á-s5îßõ®°Â¨¾‹­ß‘íÃün»·ø`-5g]©çÆGÎK±sOmÜ;Aýî}@ÄPg„[úÆÚ¸cÏïolžËo8›}®¨}D õ–¦R¼‡Þ ®ãÉýmÛ¹ùißâ:gÕzí·—Å­lYaÞ HZÃé4ì~ڻ̠éØ|®—©îh6YU+%¯*YÔúaDÅ|Ÿv­P]þÏàŸv·ž]üsë›æÿên"I¤R·Œ¯ÿ5·úêa0naììú¯@oú•J꾡¬ÍNj¨ÇÍ÷OL~UÄt¾qu×ÇhïI:Sœ„æãþÒÙÜ#›ó MO`Ôý²ž {ª)ŸPg¬¶‡0[ùbŽ?*òð endstream endobj 308 0 obj 828 endobj 309 0 obj <> endobj 311 0 obj <> stream xœ½VMoÓ@½ûW˜œR7ÞïÝ. z¢H­rÌÅ8njÛ­íЯg¿ì8Y‡¤E "͌߾™y3»1€a¬î?-‚Çà1„ÆÖý¥EøqÌn±²@ )Eáâ.°À"DÈ ˆ…‹"˜Îf‹ï€PTÈbLÚˆ Œcg¬j?0IÓ¬i´`CBý!©“"k3ó ƒ(œëÛO&/WÙ³6GP€¤#¨ÎFƹU` ÉÚ/y‘·Ír ßÊ»óꢉTQŒ‡R€0â;Ï[åY^¼·øŒó0BB•AŒåŸÖYÒf~Z×ùºNV¾½ÈKEî—M7‚1Dða×åîSÅÓž_aìËi{Ÿ]}új@Ä;.:ýž=á ùù»üÙo^bâj„„‡=rÝŽ41®rð¶ì€‚\N'E–”G%6$$:ÊbTBI¹ò]ñ Æ•ÈÖŽ÷Õ¶LÛ¼RTaÛÂH¨³Á÷”‰ôƒË¡>ß®Ò}11âS‰TÛöaÛ:qZÇŽ\Ó®./S2ŸO KðÒž,AŒ:ˆÉ|®œó¹‰ÎÊÕÆpA'ÔÙ&K«F©”Ù zÊ%8Ê®¥õßµu\†e¥„^û¹TeæÄçk$Ï¥yRhûK"Y'VD‘–p8çj+Ž—ì% ÔÉ2tbžбQ ´ÔòÆpO‚Ð× ‹ú3…£TÍôëì‰P/4"GöJ/³ûºµ²¿rŸòöÞõ‹ñ¾_Éfヴ÷uf02¦ä0CsõERË¡hǨ/U¯r{Èþí1Îgc®»7ˋÞ¿Ñ_«òå{ñ¸,ÑQY¢W˲¨~Œ\Ó£­´õôƒ«ÒÞõ·“°¾y)Ä£Ö$ºÇ‰Þ¦O=°8îÞ<ý~:ûÈ>ÞƒiòµS$+í{ê¹j›¤ÿc€úu©¦‚‹~*NÍÕàzÎÕáp®¨z«Š“cUVOþ±šLeõ¹¿²öæjv Ùð•,( ª9£æ¡¥ã‰ÐŸáMpü¿Ómendstream endobj 312 0 obj 787 endobj 313 0 obj <> endobj 315 0 obj <> stream xœ­VKOÜ0¾çWD9Æo'Û´‡VEê¶ÀöÆ%Ý Š$G+Zõ¿wì8‰CvÙU{Èj<žoæ›—1">Ö?û]åÞƒ÷à#ë?«Ü¿ôN.HŠ„ þòÚë.ŸP‚B_IŒ¤ô—¹wpÚ«&+‹³¬Èò6?\þð¢Q&è/×ÞAžLKF*¤oµˆPDiDÅ›*Y_\¾Ñ‡Ç„D%õiˆ"jTNN̵qR{­l›û¶énØ¸Š¸9¬›õb±•8òÎC¶06˜@„õÐAk7ãØè§Åú®wA!¦ˆcð¯–c×§?}$ÜQÛäè:ÍË¢nª¤Iõ¡bH†öèìÓç/—†$‰",¸§UUVV¬ÂAœÉÝcÕ‹R F»XZU©Åå aÂEœmÖÌå÷I•äi“VE*$ŽìÙ¯¬¹µ•jÈhúKS¤XG‡è\:+¾Õiõub”``Kö€- ZÒ­|dSŸ¡d µäiRGóëZ~4§ *}RN‚l6[g7ybí Áöv«¼>šÇºÅ¬ Ö±›í›ÜÕò=Ý}m^u3Íå¦ ²ßi5R*‡“³b¼)b‚ª'íÙܦ§>ç#ŠUÔÉàè½ûœïÙÒ¼ûŒ-¤:I½d²èæìÕÜ:Ýê$ÏíV§‰¯“USV#°äOø.JÓ<6™c+ë Û¡'Â1¦b§›†˜{~(‘cSúsü炬‡âaR¹•oÆç}’Uñºl¿ß¥GÝçÁL÷vðÜ—>sŒ;™3,à!ÔÃNO'ü~ä%ä¿@Ò—@Òä«6Ÿ› »úœ, Ã9b.ò–ÅS/æUÌV$Å!ìŸm;F^̧j`®Â|¡‚»Ìš5ŒZX— ´žîXô3¹káŸ1¡YO®Þ¶ý…×PpuÏű$Â#Ð#ØmuqœbtUµaÞz9¯ÓUY¬7<bàãV>È^| ž¼€(ÙxCè-¸h,¸`,3Î'ü§dGàäÕÓM?`ÐÕ+¼oð°7õ:GxuØe’s*9åoP—ÆÐaÐI˜ÓEfÙ!ÉhZpmKôðB’áîwâÉ‘“guÈà ³.µ´ÞÇ¥î{ÿ_ôÞÆendstream endobj 316 0 obj 868 endobj 317 0 obj <> endobj 319 0 obj <> stream xœµWKoÛF¾óW È€´æ¾IGÉ¡nô`»q”›.¬¸ŠYˆ¤Ã‡ƒ´Èï,¹$—^:²:P˜ùæÛyìûþ™ï>ó¾z_}ÜÊúÏ>óÝzç·$Eœ{ðº ØÇ”!,|)$„¿Í¼åùùÙö/‡ˆñ€Î6ñ–d]¥_²X/°aB…Y¸úýúæ“SdÈ™«²,ÊJË×8`ˆ é¯1C¬]¬ïÔ‡ËkT©ú½VûMvK†vgo´~Ð*jŒ YÕÉÅÅ}œ–›¤hþ<ªU÷y×äT#ì.è·­ˆ Ê"lDYšÕngk2D·À½À%~‰KüŸ¸$/qI—$DQÇìÜ!M}ßÔfG·ðäT6›…• ˜$#j;6Ù²áÂÍžÅfÓÚUyrì ’ D!!NÏ÷q´v0—¼·ÓîåÎlf7@„šJ•Ÿê¸V»åî =ÄÇþµF$-íÉ]dª ‰€g.úòÅDbD"n#@ý!é“ Ð!-«Ú¬Gb–d²^©}‘'NøX`'9Æèñÿ=îÃ4Ò焉O„‰_&yV˜¾—œr\*÷”ã¹Sf?žœˆž<=”#•¶œ ÂìÀ~˜†e¶‚L­OÕæj9QY‘Wu |èEI‘è¸+¾¹Õ…kQ¼›^Þ\oo>ßVc·‰ÂSÝf_*ŽQHÖóUš7iíÊ!+âLÕª+BBf‘Yû–ÖwmÛ!&ÇÒýÊtèR”YŒ_åŸ!_þ˜ØÔ“ЉÞ_ß ŒM:¶^Cq’ìÚ¦‘/Vîv-_¹ƒ&õЕ¤ÇöIZvÛk Oʠ̪•ëv¸ýñ\-&Ü×ë—2N\9”nš¥«r¤:”“ƒwBíSNä°SËwæ:±r‹P‡=¢—`øøÌ3ðC“ïë´D Öd­ÇÁ8³æŸ)ÅÑhB¬ÝAÐQŽ`Ò¿–[è2uÑtI¬û#8:Äûº(¿»“ת øG·¸ã> endobj 323 0 obj <> stream xœmTMo›@¼ó+P¤JX²Ÿ÷û#M{h›ÞZ5)G.ĬS*΂}ËïXX>`Ï{;oföa8EþŸ»&yKÞR°é±kÒ/y²}¦Á 9'i¾OÆ8ŃJ¥@ Dš7I¶Ý®ò¿ VÀ¸"®%¯’Ló$ ¸4‚»®ÝוiwÆ×„.‘޵ƒ9›ƒ‡©8‹ð¾³Kæ DãK[6f0¶_R»±Cw <Âx¡Ó fÀBuøc¾ý ½­íì7³/2Z«0… TE¦cÂ<‡Æú¡º¿?›ÝÐÙ‡ðýXÖö¡ê–§—ƒ™q19ZWÝi‰ÆVŸ,»˜ÿÍkv1?Aô?ä=³§T—8?!0œ‘Y1¢¾ÈÐÚ·H bRŒ×Ëë%¨XÅ0ˆ“"]DøµÇC79nkäÅ Ëþæ–-Þ ‘«™Ôí¯ÈÅ( ÌølÂ(i¯í1¨ÛÞØ¡ˆ¿L[Ù­K^/ö'àż֭?”pCÔUCdœ’ñ)KÄçkâ5YS·prR~å`ü 8—‡›âjwË¥hLÙ.Ñ»(kƒwÂðÌüÍq¼¯_›0ןSå]LåjíFvB (JçžBšÑ³Bµž¿]ïFóí°f8ÙvyhLs òêòÞCaûŒÅü߈ Ô­0“"öqìûóô)yJþ +.Ëendstream endobj 324 0 obj 532 endobj 325 0 obj <> endobj 327 0 obj <> stream xœµWKoÛF¾ ý<¦€µÜ÷#·8vÓ´±áÈ r(z`%Úb,Q EÁIóç;û˜•d1i}(|0<˜åÎ|Ù1%¬ þ'ýž­FŸGŸ bøk¶*Χ£r2C8S²˜ÞâV8FS¢u1]^L껺«ÛY½ýyúÉŸÒcÄ)Åý)ZŒƒÓùèÅìOŸÂ,áÜø˜¾¾._Ý^ø¸‚¢˜´)þ¦[ï6$~Ò˜ÃO G¤*å]½½þðvêó¤%RrŒó!ço‚S1ôa[w¡H¨ÈZL|³kæõY”Áìö¦KÕZnX ®C¡DX(&…î»x“¡J`SÕ*u˜÷®ù+dr@ŽS‰™Ý× ç Æ.ÕCXrM¬p˜°ÑÄ0g±ä×—“ëØ‰#n3sN„챤Œ0iŠ1—¤ðR~ éL£¶þ[µŠ è_ëÜj;]qÐC®í*ž7Ä…„~lÚ‡eÝ R*Rª]Ê\ôýæeY>>>’YhÒJ5vSw-™-ÊUÓîš~&È9=ÜgXgåS˜$ƒg˜®ªP´&Ì*,%’Cɾ8N©Œ` à ex0…Ž`Š0o|È¥¤@¢ªÝ2å ™ïO  ÈÌ ÿ¾kÿ6Á1{ŠØvYÍȶ¯Ú»uÔ/è:¬~NêĬ0OÏwå}·)ë‡rÑl6¡Zh@pù}ÑÏ»Œ k­‡Ø€~Œ•â ²pKº}÷* ˆZ¢3,ÓqqÊ>¤\¦]6Ôž/v ’<»àgqW`%†÷Ÿw»6T¾”FœhÝØ¬õ!¯Lªy½ª‚Æ ‘†ë,Þí ðIGs§‰Î.YYÉŒûë>ºÄ7Å̱K† ÃOÊc{ç¬8±…Ì!{èSw°S{HϨ;²‡zàºá¡À ß»ó? …m«¬îj9„‚%ÎØìdz8KaºæYúÜv9¤zQ¶«ÿßvÿÝÔ—;~Ïí‹9îxä"ó£'ƒ=y2B\€Ie.ÿ¢îëxÓÞ‡ásõ‹:½ˆ’gçÁ@ë›mßÌ"›Šƒç52|ÛÜ·ÍO³ vð9ð’Êw­ïâ„q™ŸüúË&5À(“ÓfUÓÃluûw¶WúMHË<3êínÙÇÞ$XŸg|§qÚìÏ{G=‹‚“*w¹G“8€éb Àɸv`ÜÀžïÛäÝ!å®Ç-ƒeµ_\”–•””@Ñ”bÓƒÃË«1­>Z:ýÜÛ,ûFEÜ84Еãß!p¥áôjnTeTõ‘`LP|0¦¨4-ò﬿MZâáJçU g;¦1Ö5Ÿªnëз=–0°Ÿß `\ΪJ Žö©x|²NuYÍÉu<ì©|º21¿bçØ•b< »š¯w˺œ ^7›½EƒdÔóHúå°åU÷‹uZ…)ÈŸõmR%ŒGÏNVeÓ¦ê¸1ØÆev‘v ƒÑE}¶©p»¹Y|Ý6³Áÿ`<0–‰7éä·ÿº^.¼)(‰ï—æLRÄOѱ„W ŽaÌp9-ÞÞþ,oûpendstream endobj 328 0 obj 1179 endobj 329 0 obj <> endobj 5 0 obj <> /Contents 6 0 R >> endobj 19 0 obj <> /Contents 20 0 R >> endobj 38 0 obj <> /Contents 39 0 R >> endobj 45 0 obj <> /Contents 46 0 R >> endobj 52 0 obj <> /Contents 53 0 R >> endobj 56 0 obj <> /Contents 57 0 R >> endobj 60 0 obj <> /Contents 61 0 R >> endobj 64 0 obj <> /Contents 65 0 R >> endobj 68 0 obj <> /Contents 69 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 91 0 obj <> /Contents 92 0 R >> endobj 95 0 obj <> /Contents 96 0 R >> endobj 99 0 obj <> /Contents 100 0 R >> endobj 106 0 obj <> /Contents 107 0 R >> endobj 110 0 obj <> /Contents 111 0 R >> endobj 117 0 obj <> /Contents 118 0 R >> endobj 124 0 obj <> /Contents 125 0 R >> endobj 131 0 obj <> /Contents 132 0 R >> endobj 135 0 obj <> /Contents 136 0 R >> endobj 139 0 obj <> /Contents 140 0 R >> endobj 143 0 obj <> /Contents 144 0 R >> endobj 147 0 obj <> /Contents 148 0 R >> endobj 151 0 obj <> /Contents 152 0 R >> endobj 155 0 obj <> /Contents 156 0 R >> endobj 159 0 obj <> /Contents 160 0 R >> endobj 173 0 obj <> /Contents 174 0 R >> endobj 181 0 obj <> /Contents 182 0 R >> endobj 185 0 obj <> /Contents 186 0 R >> endobj 189 0 obj <> /Contents 190 0 R >> endobj 193 0 obj <> /Contents 194 0 R >> endobj 197 0 obj <> /Contents 198 0 R >> endobj 204 0 obj <> /Contents 205 0 R >> endobj 208 0 obj <> /Contents 209 0 R >> endobj 212 0 obj <> /Contents 213 0 R >> endobj 216 0 obj <> /Contents 217 0 R >> endobj 220 0 obj <> /Contents 221 0 R >> endobj 224 0 obj <> /Contents 225 0 R >> endobj 228 0 obj <> /Contents 229 0 R >> endobj 232 0 obj <> /Contents 233 0 R >> endobj 236 0 obj <> /Contents 237 0 R >> endobj 240 0 obj <> /Contents 241 0 R >> endobj 244 0 obj <> /Contents 245 0 R >> endobj 248 0 obj <> /Contents 249 0 R >> endobj 252 0 obj <> /Contents 253 0 R >> endobj 256 0 obj <> /Contents 257 0 R >> endobj 260 0 obj <> /Contents 261 0 R >> endobj 264 0 obj <> /Contents 265 0 R >> endobj 268 0 obj <> /Contents 269 0 R >> endobj 272 0 obj <> /Contents 273 0 R >> endobj 276 0 obj <> /Contents 277 0 R >> endobj 286 0 obj <> /Contents 287 0 R >> endobj 290 0 obj <> /Contents 291 0 R >> endobj 294 0 obj <> /Contents 295 0 R >> endobj 298 0 obj <> /Contents 299 0 R >> endobj 302 0 obj <> /Contents 303 0 R >> endobj 306 0 obj <> /Contents 307 0 R >> endobj 310 0 obj <> /Contents 311 0 R >> endobj 314 0 obj <> /Contents 315 0 R >> endobj 318 0 obj <> /Contents 319 0 R >> endobj 322 0 obj <> /Contents 323 0 R >> endobj 326 0 obj <> /Contents 327 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 5 0 R 19 0 R 38 0 R 45 0 R 52 0 R 56 0 R 60 0 R 64 0 R 68 0 R 72 0 R 91 0 R 95 0 R 99 0 R 106 0 R 110 0 R 117 0 R 124 0 R 131 0 R 135 0 R 139 0 R 143 0 R 147 0 R 151 0 R 155 0 R 159 0 R 173 0 R 181 0 R 185 0 R 189 0 R 193 0 R 197 0 R 204 0 R 208 0 R 212 0 R 216 0 R 220 0 R 224 0 R 228 0 R 232 0 R 236 0 R 240 0 R 244 0 R 248 0 R 252 0 R 256 0 R 260 0 R 264 0 R 268 0 R 272 0 R 276 0 R 286 0 R 290 0 R 294 0 R 298 0 R 302 0 R 306 0 R 310 0 R 314 0 R 318 0 R 322 0 R 326 0 R ] /Count 61 >> endobj 1 0 obj <> endobj 4 0 obj <> endobj 9 0 obj <> endobj 8 0 obj <>stream KXIPNR+CMBX12!øøøVûsù‚³^÷°÷]÷2FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMBX12Computer Modern)LAncModCpefPrgFshRGtiHuIUwlaxmb:12'3(4)56-"OD.PE$QFG1SH'TI3(UJ)V*6XMBYNC  *B½%‹|ípáL«a-†/š9Ö  g Ú 1 r í à D Ù u ÞaØ´gÉfêø ÿ£í‹¶øì¶õ÷ù÷¢a„F{û2ûH‹ øì÷¶Z‰2‹V‹f‹û‹n`õüì!`øÅÿQ‰ ‹¶÷0¶øJŸø^ù9„‰s‹r‹‰†„yûŒüö„{‹‰oˆrˆ‡‹u‹y`¥Ç‹¨‹¦‹Ô‹¢‰¶u‹e‹o–Ž”‹À÷÷ Êû0-`«ì‹±‹«‹ñ‹¤‰¶,ûâø{÷û´û}ù‹¶ø ¬Ð÷÷^÷ø§÷Æêb¼ûC‹Mhi@Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Føˆ…¯ø¯‹÷ ÷G÷ øh÷ —€‹{‹ŠŠ†„xpH/‹û!‹÷,¸ÆŒ÷÷’Ɖ†ŠŠŠ‰Šˆˆ~|‹ra­z¤ ±˜ºÝû‘UûFEûûûê/÷'÷1ª÷’ÿ+!@‹¶øì¶õºøó÷ ø©÷û„ø®‚ ‚‹v‹ûi`õü΋uŠŠq‡y‰wŠy‹t`¢Ù‹§‹§‹Ú‹¢‰¶tp‹‰‹sŽnŠŒ‹¡øÂŒ÷¤üö€‘œ‹œ‹‘•–÷©ùŒüì!`¦ó‹­‹­‹ó‹¦‰¶!øìõ¶ûiv‹‚‹‚vÿ2€…¯ø¬‹÷ ÷—÷ ø¦÷o÷/îû1û74#ûûç-÷1÷7âî÷ûûQû‹÷ ݺ‹½ž¯¡³¸¶‹Ä‹¯pœoŸg‹W‹[8‹ûûù…¬ø¬÷U¾‹÷ ÷‘÷÷ïùB`É’‹dû^už_¨F‹û"&3û û#î6÷ºž¬²W÷F‘¶M„‹²øøûüåaNX~g‹û‹÷ͺ‹½¡±ªÃÆ‘¢‹´‹·y¬_ÿ,€¶÷WŸ÷J ÷b¶‹÷!øŒµùù4¢‹Žu@CS»H£A‹ûƒû.û%ûfûb÷)û)÷‰÷F÷÷÷ œ…Œ|‹€Š‚û,ûW1‹J‹3SÊh±k‹÷‹íšÔºÃËÖï•»‹Ö‹÷ a©ûD‚”‹—‹¢‹£ùûV¶÷%¬ø¯Ð÷÷‘÷ ÷®û+F÷T¤u·rÇ‹÷öÞ÷&÷.äûPXwkc¿ûAƒ`É’‹dü“F`¢Ó‹§‹§‹Ô‹¢‰Fø´°»À›²‹ÌÆPûû%CXK``¡ºlÿNÀ…¯÷S¨÷>¬‹÷ ÷‚çøX÷q¢‘‹¤©„Ö]ºaµS˜Q‹û06%ûû ò0÷+÷+¸õœš|‹…{Šˆ~…qJIv[‹û%Š÷è´Œ² ¯ž«®¡¶‹ö‹”û ŒYÿWÀ‹¶÷ú¶÷s¬Õóä÷÷mø%÷¶û òóÍ›¬–‹Š‘‰|‚z‹vc«y¥¡¯š·´gµD0ûeû%A`ÕûúF`¢Ö‹§‹¨‹Ü‹£‰¶4ÿ„Ћ¶÷š±÷À¶õ÷÷º÷!÷¨÷Å÷>÷;èàò÷,àû9ü,`õüì!`¨ö‹¯‹¯‹ö‹¨‰¶!÷øì÷/‹9GI‹7û/û÷ÀÿË}p‹¶ø ¬Ðóò÷÷d÷u¬’÷3÷ }€„z‹yb¬z¤¤¬œ´¾W§[<‹iF}aŠ÷û8ƒ`É’‹dûÑF`¢Ö‹§‹¨‹Ü‹£‰¶4ÿ2€û]«÷2çÖ«÷~­‹Ý÷sõ‘Ý÷÷J»qËš‹÷ÂØÑ¾n¯•¨›£œˆ†ˆ‡‹~v™x¥¥™ž £y«a`‹bvvyb£d”X‹ûT>El•bµizxyh‹g‹`¢f {s…Mt‹RPÌH÷L÷:ßÁÖ‹ãQ¨r—[£K‹3‹r‹_‹†Œ`’±‹ž‹“Œš–˜÷ ‘4‹Ð¹¹‹Ðââ‹F]]‹F4Ãû[ÔÑ~WhhQûûgñËÊ‹šÿÃ,€‹¶÷¨¶÷¨»õ÷÷3µù ù=üä`õüç!`¨÷‹°‹À‹ä‹¼‰¶û÷¨Âë“_Bµ÷©aBƒ_+T÷¨÷#÷3‹¤B™û µÿ»À…¬ø ©‹Ï÷{Ïø ø?ž‹’|…‹‰‹|‚‡ˆ€„†ˆo›f‘g‹mû*‹û"÷uª†¦†¬…‹³‚³r‹a>0‹vX‹L›oì…ŸŠŒz‹v‹ˆtûx‹„š’‹‹Ÿ›¥ž¸hÁ‹‹Â÷—÷»q¬wb­i‘U•K–O–‹»Ìä‹ ÷‹‘ErŒ~“‹—‹ ‹Ž¢ù‹¶ø ¬÷U¾Ð÷÷^÷ø§÷Æêb¼û&‹ZD}mŠ÷íûAƒ`É’‹düÅF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶FÿG°¬v¶÷°¬÷¯¶õ÷÷±÷!|ø¥÷è÷¯¬Ó‹Áï"ßûMü`õüì!`¨ó‹¯‹¯‹ô‹¨‰¶!÷°¸÷ ³‹«¡q©i‹u‹H‹H‹b¾i¿hÝŠ¡‹ñ—噜ƒŽ~xŠ„~ІYlvo‹K‹„΃ç…À„Õû¬û!Ÿû ÷¯÷ ÷7Ž9PTŠ4û;ÿtAж÷[¶ø¶‹÷!ø2÷ù÷zÙ¶s‰ ‹k‹N‹I‹N`÷!%‹v‹ocrw~la‹R‹(™MÔd¸sÈ‹÷ ‹òœÑ¸ÀËÖï•»‹Ö‹÷ a©ûD‚”‹—‹¢‹£÷n¢‹Žu@CS»H£A‹ûƒû.û%ûfûb÷)û)÷‰ÎÚšÀ´­kÄsŽ‹—‹•›ÿµ€…¯ø¶÷?ŸÜ÷÷ µ÷gø%÷$¶û$÷SaŠ([((ˆjÜûª!ÝtÓÕ·ÃÕÀaWImnlO‹Î¢ÿ8€‹¶÷ø¾ð÷$Ðó÷sù´jªdblieeªi´²¬ª´ûDûI`Æ’‹dûÑF`¢Ð‹¦‹§‹Ë‹£‰¶Mø+ÿo¡@‹¶÷¸¶÷¶õ÷÷Û÷ùsùõ¶n‰ ‹g‹g‹ ‹n`õûûÛ÷õ¶n‰ ‹g‹g‹ ‹n`õüì!`¨ö‹¯‹¯‹ö‹¨‰¶!÷¸÷Ûû¸!`¨ö‹¯‹¯‹ö‹¨‰¶!ù…¬ø¾Ð÷÷^÷÷õøN`É’‹dûX?^N=@‡¤Â÷ëûFƒ`É’‹dû'Înö£‹Õ‹¶ÜŒ:÷A‘¶M„‹²øÿ¢û‹¶øì¶÷÷÷§ù÷¶g‰'‹a‹a‹'‹g`÷üìû`¯ï‹µ‹µ‹ï‹¯‰¶ûÿ`•P¶øø¶õ÷ø"¹ùdøù‹¡ŒŒ¥ŸŒ‹¢¶t‰=‹o‹o‹=‹t`¢¦‹‹£ˆ¨‡ŒŠ‹uüû#&Qû ûC‡÷Åø8õ¶n‰ ‹g‹g‹ ‹n`õü1ûõû÷]÷Mß÷÷ÿ,€† ø¶ùdø ’œŽ’Å‹¶n‰~‹g‹b‹~‹g`”¼‹~ЋЇ"û˜û÷±Ķs‰P‹p‹X‹‰‹Y`ÆŽƒ~‚Ž…•s‹†‹‰ˆ„Šˆ?ûQû÷žĶt‰G‹p‹k‹[‹m`Æ÷-ü’y„¡‹–‹—‹“Ÿõ÷õû›”u–‹—‹¡‹Ž‘’ÿ8€‹¶øì¾Ðó÷mùJûAƒ`É’‹düÅF`¢Ò‹¦‹¦‹Ò‹¢‰¶Fÿ"à…¬÷b¦÷4¬‹÷÷b÷ø`÷¿çBÉû!Sû †7a«y¦©¨ ±‹ž„z–¬”£‹ž‹Ï´e9cû2û3_û0÷wÐØ¼µ·Ÿf‹`ð¾ “‹¡ ‚‹}LŒ‹›‹¢ûÃ-7ykZb¬¹‹æ÷ªíÿQÀ‹¶÷ú¶÷å÷‹÷÷–˜”“Þ‹¶S‰‰‹i‹n‹`‹o`ž †„‰†„‰‰4)(÷ µ¶t‰G‹p‹m‹U‹o`Ò÷0ûRûû'}„„8‹`Ç‹ª‹¨‹µ‹§‰¶xv’Œ‹Œ’“ï÷÷ûa`£Î‹§‹©‹À‹§‰¶Eÿ©€‹¶ø ¬Ð÷÷_÷÷_÷ùà÷Æçd¿û&‹\G{k{àGšK‹+‹WMv[Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Fù…¬ø¬÷U¾Ðó÷–÷ ÷dùJûAƒ`É’‹dü𵜞œž›Ÿ¾V€³‹÷õß÷%÷-åûP\xkb[®»¿µ‹÷‹ûI^‹Rsfl[\k‹G‹f»}¡ÿ8€‹÷$÷0÷$‹÷$÷xø´jªddjlbb¬l²²¬ª´ûÀ´jªddjlbb¬l²²¬ª´ÿ2€‹¶øŽ¶·Ÿ÷'÷÷îù¨‰‹kAKû‹u‹x`ž®‹À‘³˜ü¡û`µô‹º‹º‹õ‹µ‰¶ûÿ2€‹÷ ÷Ë÷¾¶‹÷÷P÷ø÷kaˆv„P|ƒ„=‹|‹û/±«æ×š–÷ÞϾ‹ë÷ Òûû*K,V¶|¢ª¯ ¹‹µl l³¹À ‹ç·@C=VCb`ûmûw‚‹‰‹yzø8ÿ8€÷ø ÷A÷$‹÷4÷gøÑ‰=jMS^‚ƒŠŠ‹‡‚—‘™ñß÷ÍjÂS_pjdg¤gº¨‹š““ÿ2€³²÷÷®ß÷µ¯ª÷÷M÷!÷™÷ß÷‹#[^‹!ûvIŽ­[¶”šª‹©´n¨banna/ïU÷÷9Úæï‹¼rêû/¦ã¦ÈÉ‹ÚÖCÊûû9P:Y²{¥¨®ž¹‹¢­\’µ´Ï‹‘‹ä‹Fmm‡]kbqiq‰e‰ŠwЇ‰…ˆ‹„‹‡z‘‹Ÿÿµ€û úTŸ‹çø ûƒ‹‹xû÷`÷D‹÷D‹÷Y¼÷6÷÷——ŒŒ‹—‹†‚‹‰‹qvû$ûGûL‹ûH‹ûLÐûG÷"û¥u‹•‹—‹—ÿ2€‹¶÷¶øJŸ÷¹÷øE÷1ì¶*øA¤Šry‹‰‹|ûìüO`÷°ûû`¨î‹¯‹­‹î‹¦‰¶*ûøoûÒû‹ÿµ€û úTŸ÷Bç÷Ü÷‹÷LF÷Gû"÷q¡‰‹‹†‹‡‹‰žy÷û¶ûD‹ûD‹ûYZû6ûûŠŠ‹‡—‹”‹‹¥ ÷$÷Ï÷L‹÷Hÿ2€³Ò÷÷-¬ð÷—Ÿ¿¹÷o÷÷.ø›­ƒ¦‹š‹£‹Ä‹Î´ªž¿¸‹¢‹—Š‹‰‹†]{Z€S‹R‹[–\œ„ˆˆ‹‹zû·x‹€Ÿ•‹Œ“•—™¯·à‹ç‹-> endobj 28 0 obj <>stream GJBXPC+CMTT12 øøøŠû~ø ùK©'ƒø9÷Š÷1FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTT12Computer ModernWLAyncXMBzodNCpeZODqfPErgQFshRGtiSHujTIvkUwlaVxmb!]8-"9.#_:/$;0%{<1&|=2}>3(~?4)@5*[6+\7,-"ZOD9.#[PE/$QF;0%RG1&SH2'TI3(UJ4)VK5*WL6XMB7YNC>@\]^ _  ! < = XZÏ^Ó3¸VÇ(lØZÍ?›üb¹(ð l Ó : ­ B ½ d îN¨OØA´[½Eª>ƒvýžS‘,‚$Ùÿ;z5ŠÚwôJ r›ßQÎ"±  m å!P!¦"*"¢#P#Ž$ $Z$•$ë%*ÿ•ÿ•‹ÅøƒÅÕÌ÷…Ì÷Aø½¿™¥‹¨¨q‹}û*}p‹nn¦‹™¬üƒj}p‹nn¦‹™ø¬’”«Ýœ‹¢kj‹uyJû…ÿ•‹Å÷Åø Ÿ‹ø`÷Èøáƒ¯w‹t‹l‹‡„kûü§jt‹nn¦‹™ë™¦‹¨¨s‹l¥÷÷6¥ûls‹nn¦‹™ë™¦‹¨¨t‹jû†÷>’©Â÷€»ŒŽt™N‹Š¾ûyÿ•ûx÷ øwÅœÚø<ø ¥™¦‹¨¨p‹}û}p‹nn¦‹™¤o9Rû;}RІ¡‡–¦.÷Š¢™¦‹¨¨p‹}û}p‹nn¦‹™¦÷ ûü‹‰‹Š‹‰q4|o…r\[ŒŽŽ‘‹–¢{›tr|zte«c½ì‹¶÷Ž“ÿ•‹Å÷ÕÅÜÌ÷TÌø6÷¹í]¹9G‹_ezx°‹™cI}q‹nn¥‹™´ûÏb}q‹nn¥‹™÷'™¥‹¨¨q‹}b÷Iì϶ÁÅ—jRû{b}q‹nn¥‹™÷'™¥‹¨¨q‹}bÿ•…Å÷ÞÅ‹Ì÷xÙø\÷¥r‹ƒt‹‡ƒ†}uTZ…s‹6CÒ辨÷÷¦ ‰Š”’‰ŒŠ‹†ŽbªŠ‘‹¡žš¦Ð&‹_û?Tû 7ûè'÷ ÷®î›ÿ•‹ÅøƒÅ÷°÷Ù÷÷x™¦‹¨¨p‹}-}p‹nn¥‹ž@û.:÷.œ¤‹¨¨q‹},}q‹nn¥‹™Ÿ÷ ûxûûŸx}q‹nn¥‹™ê™¥‹¨¨r‹wê÷\ñû\zp‹nn¦‹™ê™¥‹¨¨q‹}wÿ•‹ÅøƒÅ¾Ã÷žÃ÷¸ø~b{[…jŠƒ½4÷š‰€¢w‹z‹V}p‹nn¤‹¥üƒqr‹nn¦‹™×™¦‹¨¨r‹qøwŒ‘lŽ€—gÒûsƒ”o¨‹—‹œ““šæ÷¬‹™üuqr‹nn¦‹™×™¦‹¨¨r‹qøƒ¥¤‹¨¨p‹}Vd‹…ƒqÿ•‹Å÷{Å÷bÅÌÌ÷{ÌÍø÷}q‹nn¦‹™£üƒs}p‹nn¦‹˜÷÷ÆãÚÒZÌ<œ½›Ä»‹ÓÔPÝûûûœ÷b÷Þ£Mg\dN7ûûµ÷{÷ðŸ5iZeM2ÿ•‹Å÷ÏÅ›Ì÷´ÌøSø—–‹¬u‹xûájƒƒjcy‹t«¬‹¡ž¢÷‘ûÒûÇ€‡‡‹yj¡‹ž÷õ¬’”«¾‹¢kj‹uxiû¤ÿ•…Å÷ÞÅ‹Ì÷ Ìø\÷l÷0îûû0(ûûç+ööçë÷û[û8CM×êèËÍÑÑËI.+M@Cÿ•…Å÷ÛÅ÷Å‹Ì÷Ìø6øÎª…•iI}q‹nn¥‹™´û:{›b­N‹!/+ûûá)ò̶²¡ža‹~³Í™¥‹¨¨q‹}bJ÷S]9@CQÔåëÏÏÒ̺PWÿ•‹ÅøƒÅÉÃ÷pÃ÷OøÕ­w‹v‹J|r‹nn¥‹™¡üƒu}q‹nn¤‹šï™¦‹¨¨p‹}uøxŒŽ€”qX÷)ü8—iŸ‹¡‹©—ޱø”¡™¥‹¨¨r‹|'}p‹nn¦‹™¡üxŠˆ–‚¥y¾ÿ•Åø›Å‹Ì÷ÁÏønøÝ›‹¡oy‹†€‡„ˆƒƒyˆ„b¯]ša‹û ûûGûK÷û÷÷ Üèãªv‹}{†z‰ƒû&„z‹.6÷÷+÷+á÷æÁÆ`/™Žu”…Ÿ‹¬‹Ÿÿ•ûrÅ÷2Å÷ÕÅÜÌ÷Ì÷^ûr™¥‹¨¨q‹}b÷j£p°nËõèê÷÷7í#B]_‚¬‹šcI}q‹nn¥‹™´ü­b}q‹nn¥‹™õø|ÄÃÃÌÓÅB1+GGD@fà½ÿ•…Å÷ Â÷Å‹Ï÷žÍø4÷T ž‹°÷ Iéûû.'ûûð)÷÷ºä¥‘‰¡lx…„|…rQJ†x‹8‹Iʀ،˜à̽ʋ6Yÿ•‹ÅøƒÅ–Ì÷°Ìø^øº”˜‹‹–¬u‹xûÛjƒƒjIy‹t«¬‹¡ž¼÷˜ûÛü€‚~‹‡‹€j¡‹ž÷쬒”«ß‹¢kj‹uxHû¨ÿ•Åø›Å‹Ì÷¦Ìø_÷Å÷·v¦ûIûIvpû¶û· p÷I÷I ¦÷¶û^û—0‹u£€¹~¾‹å‹Ä‹Ë‹Ò–»™Â©˜Ý‹Ú‹«™V—\‹=‹N‹M‹>€U€Xus.‹ÿ•‹ÅøƒÅÇÌ÷œÌÉø÷}q‹nn¥‹™Ÿüƒw}q‹nn¥‹™÷[÷á÷"÷2÷48÷+ûûü½øƒê÷Àûûû Pûûÿ•ûrÅ÷2Å÷ÛÅ‹Ì÷ŸÌøJø ‹¢kj‹uxxxŸf³F‹û)-ûûã(÷Ô´¶¡ ûs^}p‹nn¦‹™÷/™¦‹¨¨p‹}^J÷÷SZ8;?MÔåéÑÑÙ×¶:Mÿ•‹Å÷ÏÅ÷Å÷ ÌñÛ÷‹ø ÷ ™¥‹¨¨q‹}û ½ÙÑ‹«‰“f¬›¢—§Ä?‹|?;`2U(}p‹nn¥‹™ïûÏ,}q‹nn¥‹™÷“™¥‹¨¨q‹},ÿ•‹Å÷RÅ÷‹ÅÏÌ÷‰Ì÷5÷Œ÷÷ÑçäèCäûûl}p‹nn¦‹™¦üƒp}p‹nn¦‹™÷ ™¦‹¨¨p‹}pøƒõë¶EVR^H-!ÿ•‹Å÷zÅ÷cÅÏÌ÷ÌÑÌ÷5÷´÷h‹x¬«‹¢ß‹¢kj‹xhû÷c÷‰Zy‹t«¬‹¡žÍª…•iûþ}p‹nn¦‹™¦üƒp}p‹nn¦‹™ø¬’”«Ü‹¢kj‹uxKûŸÿ•‹Å÷ÏÅ÷Ì÷LÙ÷l÷Q÷ ßÒà‹‘‹ŠŽg§ˆ’‹¢›œ¡¶a›YHRmS]²ª…•i&}q‹nn¥‹™×ûÏ?}q‹nn¥‹™÷Š™¥‹¨¨q‹}"ÿ•ûyÃ÷FÃÅÃ÷bòÌ÷S̲Ä÷RÈ]‹ÁžŽ“Ÿ}¬~¯‹æÑÔᤅªv¬¥™£ŽšŒ‘l¨ŠŒ‹—¤“©ž|¬Sy^‡jaj¢i“o‹0EB5ue§gxoˆm‹‹hœo“‚TmwU‹d8ðL÷÷ðÉß÷$ûE‹j\÷Y^·ÆÆ¹·¼À¶]RR`]V¨ûð)B·¹š®°¢¢š•‹Ð‹ã÷‹3]B_)ÿ•û õÅø›Å‹Ö÷œÌøŽºŸ˜³”Ò‘½‹Þ‹±÷·v¦ûIûIvpû¶û· p÷I™‹«‹—Œ˜r©M™r•{“‹¡‹›‹ž‘y­€žû÷n„™‡‹x‹„}y‹x†ŒˆŽ†´<‚‹Š‹Š‰ŠŠz{*‹~®‚¹¼‹×‹À‹Ç‹Ò•¼–Å¡¡é‹ê‹ t–Q•Z‹?‹V‹ûiw~t{ÿ•‹Å÷oÅ÷nÅÒÌ÷̺Ì÷;÷©÷h‹x¬«‹¢ß‹¢kj‹xhû÷n÷ŒZy‹t«¬‹¡žÍª…•iü}p‹nn¦‹™©üƒm}p‹nn¦‹™÷#™¥‹¨¨q‹}[ÿ•…Å÷ÞÅ‹Å÷šÅø8ø&›‹¡os…tŠc£]‹w‹û7u8ib£o­x«y¨†Ý~²„Û~‹Tfih.K‹a¤vÓ†™ˆ–r‹j‹xw${‹u§—‹”‹š´¹e¿ˆª‹÷M‹÷ •óû [’3šO•‹µ¦ª«éê‹^qwˆ—‹¬‹Ÿÿ•‹Å÷ÕÅ÷ÅÜÌ÷TÌø6÷¹í]¹9G‹_ezx÷Rª…•iI}q‹nn¥‹™´üƒb}q‹nn¥‹™÷'™¥‹¨¨q‹}b÷Iì϶ÁÅ—jRû{b}q‹nn¥‹™÷'™¥‹¨¨q‹}bÿ•Å]Å÷oÅ÷nÅÉÌ÷KÌ»Ì~÷è÷Ä«©Á‹ÁÞBßû û>|r‹nn¥‹™¡üƒu}q‹nn¤‹š÷™¦‹¨¨p‹}u÷oºÚ‹ª‹«o¢v‹t‹`‹E‹nži›q¥|ª‹͟ЯŸ‚˜sm‰s‚„ˆcyp‹·ÄÏ‹‘¤~¨sŸ”ûªB÷nÔç·OZZ_O/ÿ•Å÷:Å÷»Å‹Ì÷¥ÌøL÷hŸ¥‹¨¨p‹}û}p‹nn¦‹™´†Np"9‹:>÷÷*÷.ÛõÚ»Àe'˜Žrž‹•‹¬‹Ÿ÷%›‹¡oz‹…€ˆ†~kj©c_‹û &ûûJûMñû÷ ¶µ°­q‹x¬«‹ žÿ•…Å÷ÕÅòŸ÷Ì÷3Ì÷lø ÷6™¥‹¨¨q‹}û6Ý‹¢kj‹ty96}p‹nn¥‹™áû.ËiÓÁî¦ñŸ‹¡jk‹uvŠORt‹=‹½£ÿ•‹Å÷ÏÅæå÷/Ì÷ÂøË¤wŸrrwwrrŸw¤¤ŸŸ¤û@û}q‹nn¥‹™öûÏû}p‹nn¦‹™÷ª™¥‹¨¨q‹}(÷અ•iÿ•Åø›Å‹É÷´ÉøIøÝ›‹¡ov‹‰ƒaZ¶R’h‹!??3P®d‘…µaœ‡ôrÖzœ‡¤ou•r‹oU`O<5‹C°†ãŠšŠœm‹j‹xwû{‹u§ ‹“—µÂ`Є´‹÷ÒâäÑ`·ˆc´x&£t‘d”ƒbšj®‹¸À½¼ÐÖ‹¾c˜6Žx~§‹¬‹Ÿÿ•‹Å÷{Å÷bÅÉÌ÷hÌø@ø½¡™¥‹¨¨r‹|û}p‹nn¦‹™¡ûbûh÷b¡™¦‹¨¨p‹}û|r‹nn¥‹™¡üƒu}q‹nn¤‹š÷™¦‹¨¨p‹}u÷{÷hû{u}p‹nn¦‹™÷𤋍¨q‹}uÿ•…Å÷ÕÅÜÌ÷TÌø6øª…•iI}q‹nn¥‹™´ûm9Gu^<‹¯ª÷£ª…•iI}q‹nn¥‹™´û—/ÇoØÈ‹±¤Ÿœg£‹œÍ™¥‹¨¨q‹}bÿ•ûxÅø³Åæå‹Û÷<Ì÷üøË¤wŸrrwwrrŸw¤¤ŸŸ¤ûOû}q‹nn£‹›÷ü0‹{‹`ofpho‹s‹w‹sŒz™‹°dyt~nC틳¯‹´‹½¾••±¹‹ØøFª…•iÿ•‹ÅøƒÅ‹Ì÷Ì÷Ì÷¶ø½÷Zy‹t«¬‹¡žÍª…•iüjƒƒjIy‹t«¬‹¡ž¼÷üƒ[}q‹nn¥‹™÷5™¥‹¨¨q‹}[ÿ•‹ÅøƒÅ÷"Ì÷¶ø½ñ™¥‹¨¨q‹}û¡}q‹nn¥‹™ñüƒ%}q‹nn¥‹™÷¡™¥‹¨¨q‹}%ÿ•† ÷ùÅ‹øhø<ø ¥™¦‹¨¨p‹}û}p‹nn¦‹™¤ûûÖû÷Ö¤™¦‹¨¨p‹}û}p‹nn¦‹™¥÷ûì–i¡‹ž‹ž‹¡‹–­ÿ•‹Å÷ÏÅ÷ÅáÃ÷®÷“÷÷ ©™¥‹¨¨q‹}û&}p‹nn¦‹™®û6û.÷óª…•iN}p‹nn¦‹™¸üƒ^}p‹nn¦‹™÷&™¦‹¨¨p‹}^ßÙÕ÷ û2ks‹nn¦‹™÷™¥‹¨¨q‹}pÿ•ÅøÅÏÌ÷~ÌøKø½¦™¦‹¨¨p‹}û }p‹nn¦‹™¦ûìûJUWVKÂ÷÷즙¦‹¨¨p‹}û }p‹nn¦‹™¦ûòû Þ-îîÞé÷ ÿ•† ÷ùÅ‹øxøVø £¤‹¨¨p‹}û}p‹nn¦‹™ºYûÅŠ‡¥{ëÿ—j‹k‹‡yKwG„nˆyŠW÷Ꙧ‹¨¨p‹}û}p‹nn¤‹£Çûè‘h›ˆ¢‹²‹“ŸÐ”®›ÂަŒŒ~o >ŸH‚±‹œ‹Ÿ‹’°ÿ•‹ÅøƒÅ÷6Ì÷¶øÎª…•iû'}q‹nn¥‹™÷üƒû}q‹nn¥‹™÷É™¥‹¨¨q‹}ûÿ•…Å÷:ÅõÅ‹Ì÷xÌø2÷°×RÛûa*‹Fpž|¡‘‹¬Œµ‹ŒŒ —Œ˜‹—‹¢‹­‹¬r¯o‹o‹nP‰Q‡MwYzKg‹GDÊOè«‹É¿¯Ÿj½‰±‹££‹¨¨q‹}qw‘}JÍ‹t‹vbxhz\‹ˆ‹P`«´Æö­÷ ÿ•‚ ø±Å‹ørøNø½ª¢‹¨¨q‹}-}p‹nn£‹©:û×~XzE…bŠ…²€µ´0÷ÿ©£‹¨¨p‹}-}q‹nn¢‹©Œ÷ü¢”g ‹¡‹¡‹Ÿ‹”­ÿ•‹Å÷ÏÅ÷®÷r÷÷+®™¥‹¨¨q‹}û}q‹nn£‹£@$>ò¢£‹¨¨q‹}û}q‹nn¥‹™®÷ û+ûû8i}p‹nn¦‹™÷™¥‹¨¨t‹pá÷åûrs‹nn¥‹™÷™¥‹¨¨q‹}hÿ•‹Å÷ÕÅÁÃ÷Ã÷ÃøY÷á‹÷3h‹i{pf…šu±[‹^‹lnƒ‚Š«v‹y‹m}q‹nn¢‹ªûÏku‹nn¥‹™ß™¥‹¨¨t‹l÷L߯À·§“h\ûƒzp‹nn¦‹™Ô™¥‹¨¨t‹l÷L߯À·§“h\ûƒzp‹nn¦‹™Ô™¥‹¨¨t‹lÿ•…Å÷ÛÅ÷ÅÜÌ÷Ì÷5øÎª…•iI}q‹nn¥‹™´ü”y‹t¬«‹ ¨£p°nËõèê÷÷7í#B]_‚û ÄÃÃÌÓÅB1+GGD@fà½ÿ•‹åß ø,Ÿ‹å÷ÂøÎ½gŽ‚h‡Z‹|’û©ŒdŒSŒ‚®‹¬‹˜ŒŸŽÅ‹ÇŒÆÈŽË‹Èü¡¤wŸrrwwrrŸw¤¤ŸŸ¤ÿ•8Åù)Å÷QÌ÷ºù!ª…•iûB}q‹nn¥‹™÷)ý)û)}q‹nn¥‹™÷B¬’”«ÿ•Å÷“Å÷bÅ™Ì÷¢Ì÷à÷ÞÛ£¸À‹ÃÝ8Ùû û 8=9‹Q»WØt&keF‹S)ç4÷÷çáî‹ÂfÑ%«@¨~k‹kjª‹™Ïyû+Y~k‹kjª‹™´{û …^®‹Ž‹§‹Ž¥˜›÷÷{û …^®‹Ž‹§‹Ž¥˜û÷ê÷yû+ûÿ•.Ì‹ø(ø2.˜«‹«¬l‹}ûÎ~k‹kjª‹™ÿ•‹÷÷a÷‹÷÷Îø ¬p£nkrrkm¥q©¬£¦¨ûÒ¬p£nkrrkm¥q©¬£¦¨ÿ•8 ùtŸ‹ø$øWùŽ’Ž’‹’ z—|v‹ƒz†ûÜýLˆ„ˆ„‹„vœš ‹“›–ÿ•8 ÄÇ÷sÚ÷\ÇÄŸ‹Ç÷Å÷Ç÷²øÁÀ…±r—_‚Š|‹†p¡}¯¶‹­~÷û2›°š‹¥nn‹p}eû~L@‹A‹zŒû÷>kûJ•o­¶•“Ž˜‹“¦u™yˆe‹]‹Gµ2÷~f}‹p¨¨‹¥š±÷šÊÚ‹Û‹Ågæû¥Q—J—]²‹¼‹»»µÊ•Åû«É€¼^‹T‹YbYEÿ•û ÷ ÷÷a÷¢÷÷Îø ¬p£nkrrkm¥q©¬£¦¨Tü ‚\ptq~ƒ‡€…‹{~šz›žæ¿öÍo¦iiupn‹x–gº‰ÿ•Åø›Å‹Ì÷°Ìød÷Å÷N(÷ûû)ûûKûNîû÷÷í÷÷Kûcû—±R»½¯ÆÕ5A€x¨¸»ž¦––žn^[xp€ÿ•8Å÷ÁÆ÷ÁÅ÷<Ì÷¶ø¦‹¢‹®”œ°è¨‹•™“ ¨v‹x\û„(‚û1‹]‹€u}oxh†iŠmxŠon¡Š™ËŠÍ{`û:d‹-÷Tž ‹¨›ƒ˜yû!Ž‹®‹«÷5‹¦†¸R¦É«‹¹‹«ÿ•Ä ø\Ÿ‹ø(øJø~•’–‘‹ y—|‰ŠƒŠ‰‹€ƒûÝûd„„€‹‹y–„“†÷Üûe’‡“…”‹š— —…•€’ûº÷Nÿ•‹ÅøÅñŸ÷Ì÷ÄøÚš‹¥nz‹…‚…~x`jVV‡|Šv‰‹qz•¡˶µŽüA3}p‹nn¦‹™÷…™¦‹¨¨p‹}3ÿ•Å÷ÛÅ÷ŋ̓ÃÝÃ÷Ãø2ø ¦™¥‹¨¨q‹}4~o‹nn§‹˜g)pCs_Wä‚ ©¾Æ½Å‹ÓÈuÕFWX[,‹\“QŸMwtvtwswtwj‹VB·B׋¶±£ª«d³m¶‹ͥѺ«rŒˆ‡u‹l‰‰n‚kq‹g_ÄŽ °³š³ûR÷{ŋˌ̍£®‹?Š‹t„jPGxû±8²R…wnkli‹]ʧ¾œœ·ºÿ•8 ùtŸ‹Ì÷¶ù˜‹«kj‹l}ýC~‹k«¬‹ª™ÿ•÷YÌâÌ‹øLøF÷ñ˜©‹«¬j‹|ûì|j‹jkª‹—÷ñû,𬋬«l‹ûö~m‹kj¬‹šÿ•‹ÅøÅ‹Ü÷žÌ÷ð÷p™—ðá‹÷÷-Ûûû>47a®ˆ‘¡™¦‹ž„‘†™À¹®Å‹àÖZ4=POU\ûpûS€‚ˆˆ‹n¦‹™÷ñ¡‘‹Ÿ‹š ‹¢kj‹vsû…ÿ•8Å÷ÁÆ÷ÁÅ÷<Ì÷¶÷H‹»‹—©›¦™ª©Œ©žŒ§¨uŒ}AŒTŸ‰²÷:²‹éûUyu‹n{“~÷"ˆ‹i‹jû5‹y‹XÉmMk‹]‹kû‹t‹h‡‚zf.‰m‹‚|„un¡‹À÷”ì”ÿ•Ä ø\Ÿ‹ø(øL÷§—’’–‹—‹€’ƒûÜ÷e„ƒ‘‚‹|yvy–…•„÷¶ûLû¶ûM„€…‹yvšŒ“Œ‹–“ÿ•Å÷“É÷^ŧÜ÷’Ì÷”÷Áó¹BUIQM3'^Á™ŒŒŒ’Ž“‹” {žsvw~l4êK÷÷àåꋾoÒ3±È±¦Ç‹¿Ö@Ìûû=[Aj¤›¡™¦‹›ƒ”‹Œ©±Ðœ‹Ͻg\nx8"„f‰{‰‡‹w‰†~‹}n ‹œÿ•8 ùtŸ‹Ìø@R‹˜„}•ûêi÷#‹ì‹ê«÷$÷ 왕’‹˜•†›sr‹AQ]JS=o.‹,‹û³.µP¹KÔN§‹£œ”ÿ•ø‚÷ ‹÷êø@øÚš}™|€‹„†ƒ‚ŠŠ`bs‹ƒ‹…„“pªx—p‹i‹jqƒrxtz‹y|™}š–‹’“”ŒŒ¶´£‹“‹‘†’ƒ¦lž¦‹­‹¬¥•“¤ž¢œ‹ÿ•‹åß øÅ‹ÜËÓ÷Ì÷ª÷{‹Ï®½Ù¸·¥®‹¯¯tåûKûTKOh¨ƒ—𤗍‹›†‡™Ÿ¬¡Î‹ô¯hjor|‚†û%6ˆ8‹Xg‹}¯¯‹œ¡”û<¤wŸrrwwrrŸw¤¤ŸŸ¤ÿ•‹Å÷ÅøŸ÷±Ã±÷„‚~‹‰‹yh˜‡¦÷‰ûO}q‹nn¥‹™÷D™¥‹¨¨q‹}O÷Ö™¥‹¨¨q‹}@÷ú¬„“its‹†Šxû=ü÷n÷òûòÿ•8 ùtŸ÷UÌ÷ì÷Å‹ÙxðCìi¹AÎm‹t…z‚’†÷5¹û‹û‹1nû'û#(~‚ƒ†‹~‚‘z¢¤‹ÕŹÌÅÝ¥é‹äÿ•…ÅÂÅ÷­ÅÂÅ‹ÃâÃ÷AÃøøw~”s—p‹ø—‘””‹šžz—}„‹ƒ†…ˆûF‹§Žä‹¡œ}˜{{}y‹n‹ƒŒŠŒwŒQ‹tûÐ…Žƒ„‹}zx|”‚—…÷MûL…‚‚‹|xœ™’‹“‘Ž÷ЊK‰z‹d‹xyšš›™˜œ‹¢ˆã‹§¬v¬w¬w£{‹’‹™œ—ž—„”‚‘ršT¨b ÿ•8Åù)Å‹ÌøFù™¥‹¨¨q‹}ûBj„‚kýKl‘­÷B™¥‹¨¨q‹}û)ù)ÿ•Å÷¹Æ÷;Å‹Õ÷¡Ì÷ ÷á•÷âï틟‹¢ˆš{‡†‡†‹|x™v¥¥šž¢Àbº2ûûûû^û…÷Eêöêà÷ ÷ 4ã#X‹Rx`]÷ û³ u÷ŒŒŒ‹Ž‹‘‡˜‹—ÅÁÅÝÙÂH<4JOCÿ•à ÷;Ì÷<Ÿ÷PÌ÷¶÷¥÷"˜«‹«¬l‹}û"÷#˜‹«kj‹l}û#û#~k‹kjª‹™÷#û#~‹k«¬‹ª™ÿ•8 ùtŸ‹ø$÷ù-ƒ…–w‹|zvƒ‡Ž…÷ÝýO“z ‹šœ— “‰ˆ‘ÿ• ø´Å‹ÌÇÌø ø½ûWûl€ûƒ‹J~‹k¬ªŒª™Ž÷XÝ÷N÷÷ –•‹˜¨q‹}ûÚŒ…™tj‹uxgy‹t«¬‹ £ÿ•û ÷ ÷íÆ÷¨Ž†lweZz‚‰|†‹x~šz›¦î¼÷Àjµ_fwnpj¤sª‘‹’Œ‘—ø÷—ûT”ûy’Å Ì  yo Å Ì endstream endobj 331 0 obj 10148 endobj 26 0 obj <> endobj 25 0 obj <>stream  DZLSSK+CMR10!øøøûûŽú…ú]® Ç÷‡÷N÷0FKZCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR10Computer ModernncodNefrgFshtiuTIUwlab.:12'3ODPE/FGSH'TIUJV5*6XMBC“ôXäjÍ7¨µ;„ß@µ€ 9 v  › ¼ õ > ® ø –ÿMUPÿ+Ž0‹ªøµu¡ÙÊLÐ÷eЬ÷÷ìû ^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªW‹r‹Š©÷S‹á‹ªl¯}œjŸQ‹B‹\`oMÔôû!€lÑ“„Zÿ¼qÀ€¤÷¬ç°¤‹Þ÷Wç÷ûøbˆ…m‹~qw§¥Ÿœ©Ï?²>û/ûûûî(÷÷«÷ ••‹ˆ‚‹‰‡‰…n.Jf‹V3¶÷5÷7ݵÀ”ÊŠg®øˆ€¤ø0¡‹Þ÷©Þøk÷j÷'õû û*ûûûó+÷ ÷ ðí÷ûqû\`‹_ p¹r·‹È‹¯‹²‹Á£·¦¹º ³‹·‹¶u¥`¥`‹Q‹e‹g‹Uu_u^_nY‹ÿ+Ž0€¡uµø¡÷fµ‹Þ÷žÍ|øÂI÷'–ªEƒ’¼øóû$€lÑ“„Zûl¼¯n`¥Uû ")ûûí(÷˸­«¤÷ ûa‹y‹‰€zm[^u`‹^‹g¥s±q´ˆÄ‹´‹°Ç¨¸ ª±¬Á‹®‹µ|ª^–z‹‰‹yù‚‹ªùªò§ø9§÷|ù2‚—ŠŒx‹û>l¨š‹ŸŠšŠ¢ˆŒŠ‹xüžp‹\$l®Œ¼¬‹¬‹¼‰®Šª$‹º¦øœ†ŒŠ…ø,üì”ŒŠ’‹™‹’žø¼¦‹ºòªhŠZ‰j‹j‹ZhŒlò‹\pü?ÿ¼qÀ€¤÷m ÷B¡‹Þ÷‚Íø÷{¡Ž‹ îUìûû/$ûûô*÷÷¸÷ž•ƒ†‚‰…ƒ‰h$1‹‹Y‹c©t°m»‹Í‹¯Œ ‘÷)ߤ­‹ò•ûdÿ1Ž0‹ªøª÷4ß“¡ÚÍçâ÷Fø$÷ªû ÷ã»»·Ž‹š‹š„‡y~‹rt›w¦¨šŸ£°f¬VE6V!û_¡e¤v~|yj‹hù‹l˜eªwOzk`‹cCîT÷÷ ó¾Ù‹®}¾X§V§Q‹N‹r‹`‹„Œkvª‹«‹‹¢œŸ÷ûÿ&F¾À¹±°·ŽÆá÷‹5UDY)ÿŒÇ‹ª÷ºª÷¹­òä÷T¤÷#¤øÚù<ü¹l£Ø€gü g‰€>sl®ŽÙ‹²‹´‹æ‹¯ˆªj,‹˜®÷Šáë•k6¤÷r7j+5÷‘¬’º÷ ÷*‹¤S›û¤ÿŠqÀ€¡ø6ž‹¢t»÷{¢t»ä÷d÷V¡‡Ý{‹CXhc=7‹gÄxàˆ˜Š‹~‹„yûz‹„–‹ŒŒžž‹ž·a¸Š ‹÷¹ÎÓÀm©—j«d“a“ØS–H˜Å®¥´á÷‹1lŒ‚”‹‹˜‹žðœ‹’€†‹‰‹~ˆ‡‚‡ˆe§b‹|‹ûeHSh›o¦u«q§…Ó}ÿ+Ž0‹ªø¡÷fµÙÐ÷eÐø]÷‹á‹ªl¯}œjŸQ‹7‹_O{gŠ÷ðû$€lÑ“„Züœ^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªW‹r‹Š©ÿ„ ¤÷'Ÿ÷oª÷8ŸàÐ÷¤÷Aø$÷#ªû#÷LrŠ9m )‡uàû¨ûè¯Ò§ÒËÄrTAmefH‹æœÿÇ‹ªøµ÷ õµõEÍè÷EøNû €lÌ”…Zû¡^€‹Hl«ŒÁ£‹®‹®‰­ŠªI‡²ðø±«r olupqp¡qª§¤ «ÿ+Ž0€¡uµøµÙÐ÷eÐxøÚ1÷$–ªEƒ’¼¸÷÷û'€lÑ“„ZûF4[GB7‡º¿÷àû'€lÙ‹ˆ2û*=‹0÷,Ë·§¨ÉÿÒ8à‹ªø9 ÷A°‹¤÷“ä÷“¤ù.ù9ü÷xûu¤™÷5š¬÷+‹‹¥‹•‰ ‡‹€‹tü£i‹}"cl´Žñ‹¹‹¹‹ò‹´ˆªc"‹™­ø£‹Ÿ‹™–¦‹ž‹÷+‹šj™û5¤ÿip‹ªùª÷ä÷uøñ¯Ž–Ú¥ªhˆ<‹e‹d‹<‹hŽl¥ÚŽ€gü£gˆ€<ql®ŽÚ‹±‹²‹Ú‹®ˆªq<ˆ–¯ù‚uªùªòä÷ùªøÚ÷{û"*;,\û ¤÷Rø¯–Ø£ªhˆA‹e‹e‹@‹hŽl£Ø€gü û!÷û÷÷‹åèœ÷ŽŸ‹”‹³÷Ô¬‹¸òªgŠ[‰i‹h‹[gŒlò‹\pÿÒ8à€ øª‹ùAøÿ÷佪˜®Œªu‰nŠu‹n‹^xŒl¯Š¡y‹n‹…‹‰†~0û”(÷«‡—Š‹¦²‹ŸªnŠX‰s‹m‹nŒml°‹›‰•~…–m’x5û†,÷Ÿ†—‹‹¦²‹ŸªmŠS‰t‹‡‹VŒgl½‹—ˆ—k÷ûö}Žƒ˜‹˜‹‘™ð÷¯ñû°€Žƒ˜‹˜‹Ž”•ÿÇ‹ªùµÙÍ÷EùJû$€lÑ“„Züœ^€‹Hl¬ŒÀ¤‹¤‹¼‰°ŠªH€‹¸øˆ€¡zª÷k ¦å»¡‹Ø[ç÷7ÐÔ¤{€÷á×c¦aº‹ È™ÜÃrSQr…€j‡¸÷\‹µ‹²g°d²Y›[‹9F\ImŸz¥§Ÿ¥—†¬]Œ¦®¼–«‹¼Äd2f½€XˆEˆLm@irW‹_:ìrÊÍ‹¹³žº„÷8',Ci^Zb®½‹ÂµÞ÷9‘ÿ+Ž0€¡€Ÿø$¡÷fµÙÍ÷žÞ¼÷@ø ÷Ñû$€lÑ“„Zü褌Œ“™¦º|tšµYÕ÷ óí÷÷)îû=`\y{Žû›÷b‹ž‹Œ–›²Ã“£‹¸‹¯q£e¥bŽR‹b‹f‰On^vlejU‹^‹g£s°} ‹Ž‹ÿÇ‹õ‹õ÷TÀ¨s£nnssnn£s¨¨££¨ÿÇ‹õ÷oõ‹õ÷Tø¨s£nnssnn£s¨¨££¨ûÙ¨s£nnssnn£s¨¨££¨øˆ‹ªø°ª·Ÿ÷Õ÷ºù£‹tMK3‹k‹lŸ‹Æ‹¿¥üšgˆ1kl®Žâ‹³‹³‹â‹®ˆªk1ˆ–°øˆ‹Ø÷ôôðª‹ô÷_æøU÷Br†m„_|„ƒI‹u‹ûHõò÷0÷ÇÁ‹ï÷1ÛûûA/2S½‹Žœ®—´¥y¥hƒ‹‰‹ˆŠ¢ÌÁ°Å‹æ¶:9;Y> endobj 22 0 obj <>stream ERKWIV+CMBX12~17!øøøVûsù‚³$÷×÷l÷5FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMBX12Computer Modern5AyncMzodCpeDfPrgFshRtiSuTIvkwlaVxmbW8-{9./012'3456 7,"ZOD.[PE$QF%G1SH'TI3UJ4V5*WLXMB7YNC8om 6mÓg»‰ }è?ž÷T y" , r ½ h ¿ N ¯ J ì ¡—3œ2ºÏçeˆÈ2yð1Ì»?¾1qø ÿQ‰ ‹¶÷0¶øJŸø^ù9„‰s‹r‹‰†„yûŒüö„{‹‰oˆrˆ‡‹u‹y`¥Ç‹¨‹¦‹Ô‹¢‰¶u‹e‹o–Ž”‹À÷÷ Êû0-`«ì‹±‹«‹ñ‹¤‰¶,ûâø{÷û´û}ÿQÀû\¬øÌ¶‹÷øƒø‘™“Ë‹¶i‰‡‹b‹p‹‰‹R`Œº‹~ˆˆ…Šˆû ûû÷©¶s‰G‹o‹n‹P‹q`Ë÷Mü%†}n†v^kFE‹‡‹‹€‘Œ©—‹±¬s mlsvi\·aÇÝ‹ÁÕŸ·ù‹¶ø ¬Ð÷÷^÷ø§÷Æêb¼ûC‹Mhi@Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Føˆ…¯ø¯‹÷ ÷G÷ øh÷ —€‹{‹ŠŠ†„xpH/‹û!‹÷,¸ÆŒ÷÷’Ɖ†ŠŠŠ‰Šˆˆ~|‹ra­z¤ ±˜ºÝû‘UûFEûûûê/÷'÷1ª÷’ÿ+!@‹¶øì¶õºøó÷ ø©÷û„ø®‚ ‚‹v‹ûi`õü΋uŠŠq‡y‰wŠy‹t`¢Ù‹§‹§‹Ú‹¢‰¶tp‹‰‹sŽnŠŒ‹¡øÂŒ÷¤üö€‘œ‹œ‹‘•–÷©ùŒüì!`¦ó‹­‹­‹ó‹¦‰¶!øìõ¶ûiv‹‚‹‚vøˆ‹¯ø ¬‹ø9øLø*”–‹‹‘ž‹xûþ€û@µ‘ê¡·÷‹åûªü‚€‹‰‹„w”‹Ÿø œ÷Zaƒ!uSû‹0ÿ2€…¯ø¬‹÷ ÷—÷ ø¦÷o÷/îû1û74#ûûç-÷1÷7âî÷ûûQû‹÷ ݺ‹½ž¯¡³¸¶‹Ä‹¯pœoŸg‹W‹[8‹ûûù…¬ø¬÷U¾‹÷ ÷‘÷÷ïùB`É’‹dû^už_¨F‹û"&3û û#î6÷ºž¬²W÷F‘¶M„‹²øøûüåaNX~g‹û‹÷ͺ‹½¡±ªÃÆ‘¢‹´‹·y¬_ÿ,€¶÷WŸ÷J ÷b¶‹÷!øŒµùù4¢‹Žu@CS»H£A‹ûƒû.û%ûfûb÷)û)÷‰÷F÷÷÷ œ…Œ|‹€Š‚û,ûW1‹J‹3SÊh±k‹÷‹íšÔºÃËÖï•»‹Ö‹÷ a©ûD‚”‹—‹¢‹£ùûV¶÷%¬ø¯Ð÷÷‘÷ ÷®û+F÷T¤u·rÇ‹÷öÞ÷&÷.äûPXwkc¿ûAƒ`É’‹dü“F`¢Ó‹§‹§‹Ô‹¢‰Fø´°»À›²‹ÌÆPûû%CXK``¡ºlÿNÀ…¯÷S¨÷>¬‹÷ ÷‚çøX÷q¢‘‹¤©„Ö]ºaµS˜Q‹û06%ûû ò0÷+÷+¸õœš|‹…{Šˆ~…qJIv[‹û%Š÷è´Œ² ¯ž«®¡¶‹ö‹”û ŒYÿ^D@‹¶øì¶õ÷ø÷±ùB`õüì!`ø9÷T÷(÷÷j÷vû,÷ûPûPýøì÷*â‹Ñi°W¨bžZ‹û‹û |Wh\h]Hj1‹ÿWÀ‹¶÷ú¶÷s¬Õóä÷÷mø%÷¶û òóÍ›¬–‹Š‘‰|‚z‹vc«y¥¡¯š·´gµD0ûeû%A`ÕûúF`¢Ö‹§‹¨‹Ü‹£‰¶4ÿ„Ћ¶÷š±÷À¶õ÷÷º÷!÷¨÷Å÷>÷;èàò÷,àû9ü,`õüì!`¨ö‹¯‹¯‹ö‹¨‰¶!÷øì÷/‹9GI‹7û/û÷ÀÿË}p‹¶ø ¬Ðóò÷÷d÷u¬’÷3÷ }€„z‹yb¬z¤¤¬œ´¾W§[<‹iF}aŠ÷û8ƒ`É’‹dûÑF`¢Ö‹§‹¨‹Ü‹£‰¶4ÿ2€û]«÷2çÖ«÷~­‹Ý÷sõ‘Ý÷÷J»qËš‹÷ÂØÑ¾n¯•¨›£œˆ†ˆ‡‹~v™x¥¥™ž £y«a`‹bvvyb£d”X‹ûT>El•bµizxyh‹g‹`¢f {s…Mt‹RPÌH÷L÷:ßÁÖ‹ãQ¨r—[£K‹3‹r‹_‹†Œ`’±‹ž‹“Œš–˜÷ ‘4‹Ð¹¹‹Ðââ‹F]]‹F4Ãû[ÔÑ~WhhQûûgñËÊ‹šÿÃ,€‹¶÷¨¶÷¨»õ÷÷3µù ù=üä`õüç!`¨÷‹°‹À‹ä‹¼‰¶û÷¨Âë“_Bµ÷©aBƒ_+T÷¨÷#÷3‹¤B™û µÿ»À…¬ø ©‹Ï÷{Ïø ø?ž‹’|…‹‰‹|‚‡ˆ€„†ˆo›f‘g‹mû*‹û"÷uª†¦†¬…‹³‚³r‹a>0‹vX‹L›oì…ŸŠŒz‹v‹ˆtûx‹„š’‹‹Ÿ›¥ž¸hÁ‹‹Â÷—÷»q¬wb­i‘U•K–O–‹»Ìä‹ ÷‹‘ErŒ~“‹—‹ ‹Ž¢ù‹¶ø ¬÷U¾Ð÷÷^÷ø§÷Æêb¼û&‹ZD}mŠ÷íûAƒ`É’‹düÅF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶FÿG°¬v¶÷°¬÷¯¶õ÷÷±÷!|ø¥÷è÷¯¬Ó‹Áï"ßûMü`õüì!`¨ó‹¯‹¯‹ô‹¨‰¶!÷°¸÷ ³‹«¡q©i‹u‹H‹H‹b¾i¿hÝŠ¡‹ñ—噜ƒŽ~xŠ„~ІYlvo‹K‹„΃ç…À„Õû¬û!Ÿû ÷¯÷ ÷7Ž9PTŠ4û;ÿµ€…¯ø¶÷?ŸÜ÷÷ µ÷gø%÷$¶û$÷SaŠ([((ˆjÜûª!ÝtÓÕ·ÃÕÀaWImnlO‹Î¢ÿ8€‹¶÷ø¾ð÷$Ðó÷sù´jªdblieeªi´²¬ª´ûDûI`Æ’‹dûÑF`¢Ð‹¦‹§‹Ë‹£‰¶Mø+ù¶ù³‹å÷Ôå÷’øL(¡ˆÓ‹™¾¬Æìì‹â\ ûŽv‹Šž‹ ‹Ž¢÷Pž‹’|„‹ˆŠ‚`Zr Y²*‹û#?1ûH¯\™}¿W§…ótïu—‰¡v˜~¨o‹X`v<û3‹û©ƒ÷&Š‹Žw‹v‹ˆtûPx‹„š’‹ŒŒ•”––”˜¤¤Å]Ý~Ç‹÷0ÍõõéMåû¤ù…¬ø¾Ð÷÷^÷÷õøN`É’‹dûX?^N=@‡¤Â÷ëûFƒ`É’‹dû'Înö£‹Õ‹¶ÜŒ:÷A‘¶M„‹²øÿg°‹¶øã¿÷°÷ùdù9ý'wûµ”÷“à÷$‹Üüãû+`Ûò‹­‹È‹×‹Û‰¶û+øãÛ÷$‹“7”ûµÿ¢û‹¶øì¶÷÷÷§ù÷¶g‰'‹a‹a‹'‹g`÷üìû`¯ï‹µ‹µ‹ï‹¯‰¶ûÿQÀ† ø¶øƒø’š“Ê‹¶g‰‰‹b‹p‹‰‹R`¦¡†„ЋІû û•û÷­¶t‰E‹p‹n‹Q‹q`Ê÷Dü”x†¢‹›‹“”ŸÿQÀ‹¶÷ú¶÷[¾Ðó÷à÷¬÷ñ—•–”Ћ¶q‰w‹f‹q‹S‹t`—£ˆƒ‡…‡‰‰ûJû&ø`ûAƒ`É’‹düÅF`¢Ð‹¦‹¦‹Ð‹¢‰¶F÷›—š˜¡÷ û0’ƒ‹‰‹Šw‹}`£Í‹¦‹¾‹™‹µ‰¶{‹w‹€Œ}އހ™ÿ,€† ø¶ùdø ’œŽ’Å‹¶n‰~‹g‹b‹~‹g`”¼‹~ЋЇ"û˜û÷±Ķs‰P‹p‹X‹‰‹Y`ÆŽƒ~‚Ž…•s‹†‹‰ˆ„Šˆ?ûQû÷žĶt‰G‹p‹k‹[‹m`Æ÷-ü’y„¡‹–‹—‹“Ÿõ÷õû›”u–‹—‹¡‹Ž‘’ÿ8€‹¶øì¾Ðó÷mùJûAƒ`É’‹düÅF`¢Ò‹¦‹¦‹Ò‹¢‰¶Fÿ"à…¬÷b¦÷4¬‹÷÷b÷ø`÷¿çBÉû!Sû †7a«y¦©¨ ±‹ž„z–¬”£‹ž‹Ï´e9cû2û3_û0÷wÐØ¼µ·Ÿf‹`ð¾ “‹¡ ‚‹}LŒ‹›‹¢ûÃ-7ykZb¬¹‹æ÷ªíÿQ‰ ‚ ù ¶ùhù‘˜•Õ‹œ¶l‰C‹ƒ‹o‹D‹t`¡‹°‹§€†}ûaühûløè¶k‰+‹e‹k‹(‹r`å÷¨ý ”w”Š›‹›‹•‹” ÿQÀ‹¶÷ú¶÷å÷‹÷÷–˜”“Þ‹¶S‰‰‹i‹n‹`‹o`ž †„‰†„‰‰4)(÷ µ¶t‰G‹p‹m‹U‹o`Ò÷0ûRûû'}„„8‹`Ç‹ª‹¨‹µ‹§‰¶xv’Œ‹Œ’“ï÷÷ûa`£Î‹§‹©‹À‹§‰¶Eÿ©€‹¶ø ¬Ð÷÷_÷÷_÷ùà÷Æçd¿û&‹\G{k{àGšK‹+‹WMv[Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Fù…¬ø¬÷U¾Ðó÷–÷ ÷dùJûAƒ`É’‹dü𵜞œž›Ÿ¾V€³‹÷õß÷%÷-åûP\xkb[®»¿µ‹÷‹ûI^‹Rsfl[\k‹G‹f»}¡ÿŠ 0‚ ù ¶úªøÿ’‘ß‹¶Y‰‰‹R‹n‹B‹s`—ã‹}Š‹‰‡‚û<üRûGølê¶k‰.‹e‹l‹*‹s`ß´ûûüûFølé¶n‰)‹g‹k‹,‹r`ß÷‚ý‘zŽ„¡‹¡‹Ž’‘›÷Bøa÷Cüa‘{Ž„¡‹ž‹’žÿ2€³øä¯‹Û÷ÇÛø ø½¥Ã°‹Ùò/·ûûD?*‹U¦OÕdûYxF‹WûïS÷÷(âÛ÷‹÷5ºX§ûHòw–o¢‹¬Ûö¢à»^I‹by`Rjû 5ªyØ`©y¬x¶s‹X;;rC(SÀÚ‹Ô¸¹»¦ø ÷Dç‹÷À÷Ì÷DçûÀ/ÿ2€÷–¬‹øÅøÅ÷–¬üÅjÿ2€³£÷ ¬÷þ¯‹÷÷h÷ø÷®E‹ûLû0l‹g“v›¨‘  ‹«¯p¢kqjz_EÂXò÷÷.Þ÷–΋÷˜û{û);ûûë@÷ µ‹½š«ÒûV(‹Üíë‹â÷Ë¢R€•mM‹jEn(7ÿ8€‹÷$‹÷$÷xÓ´jªddjlbb¬l²²¬ª´ÿ2€ûŽ úSŸ‹øIø‚ùT—‹‹}•~x‹‡…}ü þ4†‹‡‹‰y™˜ž‹–‘šÿ2€¬øî¬‹÷ ÷}÷ ø™÷Óë‹÷…û€û‹û„*+‹û÷€÷€Œ÷|îû€û¾k‹s˜w r¤{›‹÷‹Ñ‹Ë“¿™îÓ’¡‹«‹É|™7”X‹:‹N‹û€|}mmwwps‹ÿ2€‹¶øŽ¶·Ÿ÷'÷÷îù¨‰‹kAKû‹u‹x`ž®‹À‘³˜ü¡û`µô‹º‹º‹õ‹µ‰¶ûÿ2€‹÷ ÷Ë÷¾¶‹÷÷P÷ø÷kaˆv„P|ƒ„=‹|‹û/±«æ×š–÷ÞϾ‹ë÷ Òûû*K,V¶|¢ª¯ ¹‹µl l³¹À ‹ç·@C=VCb`ûmûw‚‹‰‹yzø8ÿ8€÷ø ÷A÷$‹÷4÷gøÑ‰=jMS^‚ƒŠŠ‹‡‚—‘™ñß÷ÍjÂS_pjdg¤gº¨‹š““ÿ2€³²÷÷®ß÷µ¯ª÷÷M÷!÷™÷ß÷‹#[^‹!ûvIŽ­[¶”šª‹©´n¨banna/ïU÷÷9Úæï‹¼rêû/¦ã¦ÈÉ‹ÚÖCÊûû9P:Y²{¥¨®ž¹‹¢­\’µ´Ï‹‘‹ä‹Fmm‡]kbqiq‰e‰ŠwЇ‰…ˆ‹„‹‡z‘‹Ÿÿ2€‹¶÷¶øJŸ÷¹÷øE÷1ì¶*øA¤Šry‹‰‹|ûìüO`÷°ûû`¨î‹¯‹­‹î‹¦‰¶*ûøoûÒû‹ÿ2€³Ò÷÷-¬ð÷—Ÿ¿¹÷o÷÷.ø›­ƒ¦‹š‹£‹Ä‹Î´ªž¿¸‹¢‹—Š‹‰‹†]{Z€S‹R‹[–\œ„ˆˆ‹‹zû·x‹€Ÿ•‹Œ“•—™¯·à‹ç‹-> endobj 14 0 obj <>stream  QRNYHB+CMR12 øøøiûúpù‚®'Üø%÷‚÷/FKZCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR12Computer ModernQLAyncXMBzodNCpeODqfPErgFshRGtiSHujTIvkUJwlaVKxmbW ]8-{9.:/;01|=2'\3(4)@5"[6+ 7, -"ZOD9.#[PE/$QF0%RG1&SH'TI3(UJ4)VK5*WL6+XMB7,YNC8n>o‰i  !w< m   RZÞqóO­%yß\æZâB˜wß L ¾ (  { ) ¯ vT©adÆ3„ú¡k$aëbè£Øx˜6NÚû4tËL˜°õhª´fà ‘!9!®!Î"V"¤#C#ž#ç$¬%£ÿFbpÿcÌ@‹¨ù¨êÜøÎ÷”u'~ûûC‹4_‰’¬ø­¯—⩨n‰3‹h‹m‹2‹snŸÓŽfü§fˆCwnø‹ÿÞà‹¨÷`¨øDŸøùL‡—‰‘}‹}‹‰ˆ†{ûeüê}boqKŠnÈ‹¬‹§‹»‹¥‰¨aŒr ‹§‹‘‹˜¹÷÷Âû1‹‰‹ˆmX‹rn¢Ú‹§‹§‹Ó‹¢‰¨J‹y‹}´ûžø¡÷ûáû|ÿÆ`û`Ÿ×ø€¨ŒÖø)÷â¦ÎºŒž‹¨n‰}‹k‹t‹‰‹Sn°‰”t‹y‹‚‰†‡%ûû÷¤…™‹‘‹Œ¥®‹Ÿ¨q‰Z‹o‹e‹‰‹RnÅ‹“†˜l÷)ü_!‹‰‡ƒzmpe^‹lx‹‹®®£x˜yzvne°fÀô¼Ê¥ÿùP‹¨øŸ×Ì÷cÌøQ÷‡‹è‹§t«n²\‘i‹*‹e8ƒwŠòû€nÏ“„Zû£^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨K‹¸÷NôÐÃÉÉ™XNû^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨Y‹r‹Š©ÿ³-À¡÷¨ÝÁ¡‹×÷^Þ÷þøf‹bsœz£¢ž™¨ÎE»:û .#ûûë)÷÷©÷ ””„‹ˆ‚ŠˆˆuDUmU‹N:À÷,÷:à´½±Â|d¢ÿÞà‹¨ù¨‹ùEøø÷÷]œ£¨·êŒ¨`‰€‹X‹p‹K‹tn´ˆ˜s‹z‹€‡……‚û ûDû÷\ˆ‡’‹™ ›¯¨s‰<‹n‹o‹E‹snÖ‹•† k÷Oû©û<û‰zrkc1Šn¶–‹¾‹¦‹Ì‹¢‰¨a~¤‹œ‹–’‘”÷'÷k÷6û†‘‚ŒŠ‹‡‹yzdŠn£Ù‹¨‹§‹Ò‹£‰¨P‹s‹t®ÿ6@‹¨ù¨ê£øœÕ÷zù,„žŠ‹t‹û/nŸÓŽfüŒp‹\,n¥À‹§‹§‹À‹¥‰¨,‹º¦ø¶Œ÷…ý €Žƒ•‹”‹‘š÷‡ùŒüÖfˆCwn¢Û‹¨‹¨‹Û‹¢‰¨wCˆ•°ø§°Ž•ÓŸ¨û/u‹ŠŠƒxûnüÍÿµe ‹¨÷П÷µ¨ê×÷áæ¶ù?nŸÓŽfü§fˆCwnø ÷åâëÜBÛû ˜êÐË‹Öá4ÞûûFûÒ÷¬’·÷ï¯5UIW8û(ûä_‰’¬÷¨÷Oë½7>:NA)ÿ³-À‹¡øŸ‹øøø'”–‹‹–„‹zû΀û3¡‘ñž°÷‹÷û²üy‹¡÷Ú›÷Lu‚ûz[û ‹û ÿé“p¡ø2Ÿ‹×÷©×ø_÷j÷)òûû ,!ûûï+÷÷ ìí÷ûjû^f‹^›n¼p¸ŠÆ‹µ‹±‹Èª¸§¶·›®‹²‹µy¦dª]‹L‹f‹h‹Mq\o[]xe‹ÿùPŸø/Ÿ÷i³‹×÷Ê÷Àù?nÏ“„Zûqv¨`®N‹û')ûûê)÷×·½ž™F÷!•¨Gƒ’¼øõJüÕ‹y‹ˆ}ushbnY‹qû•÷VÓ—³¡¬Ÿª³ª½‹É‹®^•{—z‹‰‹yÿÞà‹¨ù¨ê£ø1£÷vù1‚˜ŠŒu‹û-n¶‹¤‹¦„ü²n‹\,n¥À‹§‹§‹À‹¥‰¨,‹º¨ø¢“ƒ‹‰”÷ûZ÷ûZ÷ûZ•}ŒŠ’‹”‹ŒøÐ¨‹ºê¨q‰V‹o‹o‹V‹qnê‹\nüIÿÃ* v¨ù/¨‹èøs¥ù ù=‹…‹Š‰…Z<^ÃG®C‹ûKû2û2û`ûc÷4û0÷I÷8è÷#÷–‹‘€Š†„‚û3ûE*‹EûSµ÷¸÷µ÷P·Óôç2û*Ÿ‹ˆ—‹™‹ŽŸÿùPûV¨÷/Ÿø-¡×Ì÷›×÷‰û9K‹¸÷Br´dË‹÷ðì÷÷-íû3\L‡ˆÎû€nÑ‘„_üj^€‹Jn¥Á‹§‹¨‹Á‹¥‰?ø•‹ž‹Œ–›©¸¼ž±‹ÖÇ0ûû G4>ln˜žwt¢|Ÿ‹§ÿ³-À¡÷pž÷CŸ‹×÷ƒÉø÷|¡‹žðUéû û3$ûûñ*÷÷ ¸÷ ‘†…ƒ‰††‰q7Hta‹a&§÷AžŒž“÷1ã§‹ö‹‘û!Œiÿù`v¢ù<¡‹èøgèùW÷ç÷cû,÷2ûBûFû)û4ûaû_÷+û1÷C÷G÷(÷3÷]ûÚûå%ûë÷”÷‰÷Þéî÷5û†û˜û/*ÿëÊÀ‹¨ù¨êÚøæµù?nŸÓŽfü§fˆCwn÷ò÷;÷÷*÷M÷Uû÷/û:ûý"_‰’¬øµ¬’·ôÞ‹Íc´I¸D‹&‹c‹SŠ-RAjaOb7‹ÿÆ`ûV¨÷/Ÿø-¡‹×÷›ÌøKøMwf.y±dÂ?‹û#-ûûë)÷Á·¤½¯ûM^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨K‹¸L÷’‹kynttgfeˆ|‹?Pé÷÷ ÑßÕÚµ5Wÿ+/`‹¨ø ¨÷‘ŸÙÊæÚ÷@ø&÷¨û÷ å¹¹´“‹š‰—…‡Šr‚‹nt›{¢£››£°g¨[ER®f•‚|yn‹d‹Q®r“†]~]g‹WFéR÷÷ îÀÖ‹¤„ÆOªX¥Y‹5‹N‹„‹yž•‚ž‹ ‹œ‘œ•™î3‹ð¢‹´œ¦ž¨©• ‹ã‹&ty‹bzpxnmv‹¦û÷+B¼Ä“²±¥¡™”‹Ñ‹Þ÷‹4P?\/ù‹¨÷½¨÷½ªêÜ÷T¡øÏù=ü¦nŸÓŽfü¥fˆCwn£ä‹©‹®‹ã‹¨‰¨m4‰—¯÷ãé•j7¡÷›u7j-3÷•¬’·÷÷$‹¨V™û!¡ÿ‚8Ÿø6‹¸÷y¸÷Üø;‹ƒ‹xu„‚l¤l‘k‹û gIT€‹h±h«o­„¹‚€˜ˆ¤w|˜u‹o`r[3I‹[±uŒŠŒ‰‡‹ˆ‹€‹†yûy‹†•‹ŒŒœ ’‹š›±\Á‹œ‹ô¿ÅÚÁj«‚”gªp‘I—m‘B™‹Çª ¹å÷‹‘.lŒƒ’‹Ž‹–‹ÿùP‹¨øŸ÷i³×Ì÷cÌøQ÷‡‹è‹§t«n²\‘i‹5‹cJ}lŠ÷ñû€nÏ“„Zü ^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨K‹¸÷NôÐÃÉÉ™XNû^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨Y‹r‹Š©ÿЗÐv ‹¨÷ß÷¨êÚ÷µèí ~ø:÷èî¢ØÊ‹ØìûÞû$û¿nŸÓŽfü§fˆCwn¢Ý‹¨‹¨‹Þ‹¢‰¨wCˆ•°÷”º÷²‹°€¦o­e‹v‹F‹<‹q·`š|µtË٘⠑‹”€‹…ІOnpk‹]‹ºƒÀŠ’…¶ˆ¤„½‡«mª€–q¦Tš-—û÷š‹¢‹— ”Œ©‹Ÿ‹Ü÷‹û+4\KûÿGv¨÷~¨ø(¨‹èø;Üù÷Z²Ë¨q‰F‹m‹k‹4‹pnªãŽgKûûƒq<ûO»÷²÷µ÷Q·Ñâ‹óL¥ûE€‹ˆ—‹™‹ŽŸ÷‹…‹Š‰…Z<n¯NÂ,‹ûIû3û1ûaûc÷3û0÷JÒܢ˰k¬j“‹“‹‘›ÿ|Çà¡ø¨÷8ŸàÌ÷¡÷<ø&÷!¨û!÷LuŠ-g+0ˆwàûªûÕtÀʬÉÓÄuTCnadG‹èœÿü`‹¨ø³÷ì×Ê÷Bøü¥v¢oquvpm£x£ª¥¡ûûNnË”…Zû¤^€‹Jn§»‹¨‹–‹Å‹­‰¨J‡²øÿùPv¨ù1¦‹Å÷ÓÅ÷dø5X˜^½‹ËÑÃÊÙ÷8‹¡û6‘`‹‡•‹–‹÷^‹ˆ‹‡‹„~jN[ÉI—_‹û:2%[œ_°c®d®‚Òy®ƒÂ}™…ºtªU‹S@VD8^‹M–Z¶Q¿‡ÓЬГƒ‹‰‹€‹†yû^y‹†•‘‹Œ’—“ °“š¯cÊiá‹÷Üê÷Èt¸p¬f¸^–d•ÿÞà‹¨÷̨÷°¨êÜ÷¿Üøéøó°Ž•ÓŸ¨s‰9‹n‹m‹9‹snŸÓŽfûû¿÷°Ž•ÓŸ¨s‰9‹n‹m‹9‹snŸÓŽfü§fˆCwn£Ý‹¨‹©‹Ý‹£‰¨wCˆ•°÷÷¿ûfˆCwn£Ý‹¨‹©‹Ý‹£‰¨wCˆ•°ÿùPŸø³×Ì÷cÌ÷ÄøBnÏ“„ZûG6^D@9†ºÀ÷ßû!€n׋ˆ2û*‹M‹g©j£q´¾‹œ‹«‹­¨¨¢›±‹‹1÷•¨Gƒ’¼÷øÿ+/`û`Ÿ›Ûø}³÷ì‹ÞæÊ÷_øü©sžsovupq¡u¥©ž££û'ûNnÖ”„Zü$T€AQ‰‹l‹t™¥“ž‹œ¢zsrzys[Áq¿ÓÆÉæø€ÿÃ* ‹¨ù­÷ªÜù!ù:üìyûs¡™÷2”¯÷2‹‹§‹“‰ŸˆŒ‹tü¨i‹})gn«ò‹²‹²‹ó‹«‰¨g)‹™­ø¨‹¤”›“¨‹ž‹÷2‹”g™û2¡ÿa<`‹¨ù¨ïÜ÷møó°Ž•Ö¡¨s‰5‹m‹m‹4‹sn¡ÖŽfü§fˆ@un£á‹©‹©‹â‹£‰¨u@ˆ•°ÿÆ` ø¨‹øtø,÷䔡œ¶ËŒ¨n‰}‹l‹v‹|‹]nµ‰m‹€‹‚‰††%û–û÷®†™Š‹‹¥±‹¨r‰W‹p‹j‹‰‹NnË•‡—l÷#ûú}†—‹’‹‘’œÿÆ`‹¨ø«÷s³×Ê÷¬÷‹Œ„“‹Œ‹ŽÊÁ““ÐÇ·Œ Œ¨w‰q‹m‹q‹X‹tnœŠ—‚‹{wwyŠû#ûøvû€nÏ“„Zü ^€‹Jn§»‹©‹©‹»‹§‰¨K‹¸õËÃÄ;žnŸnšv’€‹}y}†vn¤¼‹¦‹¶‹‹¶‰¨p‹l‹o´ÿÞàv¨ù¨êÜ÷õ¦øÎ÷zû ,9-O#³÷Cø°Ž•ÓŸ¨s‰9‹n‹m‹9‹snŸÓŽfüû%÷"÷÷Ú÷ïøÈØ‹¨q‰U‹o‹n‹U‹qnê‹\pø‹vŸÈòø¨‹î÷+Úøøö²Î¨r‰C‹n‹j‹4‹pnªäŽgü_2\PUv‹P“mÅ©†©‹¯£{¤itq}fDÌMâßèÇ÷ÿÃ*  ø¨‹ù2øñ÷ä¡Ê·œŒ¨r‰y‹l‹n‹‰‹Un¸‰—p‹x‹Š‹„‡/ûš'÷¯†—‹‹Ž§°‹ ¨o‰b‹n‹k‹‰‹Sn±‹˜‰–~…—j’w6ûˆ+÷¤†˜‹‹¦²‹ž¨r‰Y‹p‹o‹‰‹Ln¾‹•‡–k÷ûú€Ž„–‹”‹Ž›ï÷±ïû±{ˆ”‹–‹Ž’–ÿü`‹¨ù³×Ê÷@ùJû€nÏ“„Zü ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸ÿé“pŸ÷zž¤ÝÇŸ‹Ò÷bÌסø÷Ÿ‹Á‹³_²h«^™_‹9LUJnž}¢£œœ£´g‹|¢µ»³‹¹Æe1cû]ˆ?7‹><çrÈÍ‹¸³ž»\ªg¶‹ Å™ÛÃuSRsƒ}e‹ÀšJ¼)Bj`Zb¯»‹÷÷>—¯ÿÞàv ù"¨‹ùMø÷øÜ”¤œ·ÙŒ¨X‰‰‹d‹p‹Y‹rn¾Ššo‹w‹…‹‰…}ûOüûYøœ†–‹‹¨½‹¤¨s‰?‹n‹o‹G‹snÉ‹›‹šc÷~üü}†™‹™‹ŒŽ’œÿù7À‹¨ù¨êÜøø7𛲰›š÷÷§§Ú¨n‰‹^‹q‹P‹tn Š‚‹u‹|„‚uvûÅû»÷×¼–‹ß¨s‰9‹n‹m‹9‹snß–‹Zü£Z€‹7n£Ý‹¨‹©‹Ý‹£‰¨7€‹¼÷B÷ ÷÷Mû©…„†‡Œ†‹…og‹{n£Ô‹¨‹¥‹½‹®‰¨U‹zk»ÿÆ`‹¨ø ¨‹ø„÷¬÷€¨±µÁž ´¹º’«‹¨`‰‰‹d‹e‹‰‹Yn˜‰›…‹t‹z‚€…ƒK:=òˆ…”‹’‹‘©Œ¨r‰X‹p‹j‹‰‹Nn¾‹ž‰ p÷ û-‰…‹ˆ‹ˆ=)~_U_€`Šn±‹¶‹±‹‹½‰¨sŽ‡š‹™‹›’“•˜š ¬´£ª§h¦g¦gœu‹‰‹…‹ƒƒ{pŠn¥¼‹§‹¬‹‹Ç‰¨V‹ys«ÿ/ö@‹¨øŸ×Ì÷cÌ÷cÌùa÷‡‹è‹§t«n²\‘i‹8‹aO{d}ØU¡L‹*‹e8ƒwŠòû€nÏ“„Zû£^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨K‹¸÷NôÐÃÉÉ™XNû^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨K‹¸÷NôÐÃÉÉ™XNû^€‹Jn¥Á‹§‹¨‹Á‹¥‰¨Y‹r‹Š©ÿùPŸø/Ÿ÷i³×Ê÷×÷;ùJû€nÏ“„Züê¡“§½’¢f¶eË‹÷ðì÷÷-íûT\raiU‹‹–›£¯·¨¼‹©ôûTHasgwlclY‹U‹h®z¦~ ‹‹œÿî€v ù"¨‹ú_úøÝ›»¨Ÿ½Œ¨`‰‰‹_‹q‹U‹snÈŠk‹w‹†ˆƒ‰„û,ünû6ø‹ŠŽ‰“‹Ž©À‹£¨s‰A‹n‹n‹N‹qnÀ‹™ˆ–y’~’l˜gû#üRû4ø††™‹‹Ž©¾‹¥¨t‰?‹o‹n‹N‹qnÁ‹ž‹—e÷Züþ|‡”‹“‹Žš÷:ø›÷;ü›|ˆ“‹”‹šÿùP‹¨ø ¨÷”œÙÊ÷eÊøKùJ„Šv†…‹‰‹‰‹†Ži˜l‹{‹# T$û=nÙûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸÷Ü÷eûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸û¦÷ù÷ê׸Ô®‹‹£„‹‹Œ‡ŠŠ€‚ƒ‹{‹ƒŽzœ‚û@ÿü`ûްú2°ì°÷/ù‚ûfìþ2*f÷ÿé“pv¦ù£‹¹÷¹´÷¾÷ý½¦Ô¹‹ßâ7Ç/(=B0‹i•i§i–~ŒŠÑZ*^YH‹B!ðIñ÷èÝô‹ñC¸=»ûå~”c¥‹¼ÌÏ´ÎÓËWC‹N_ZQkFV¦yÎ`¦y¥z¹l‹N?>W;6BÉÞ‹ÙÄÊÌ©ÿFbp÷QÁ‹÷˜÷£÷QÁû˜Uÿé“p÷”Ÿ‹ø}ø}÷”Ÿü}wÿé“pv¦±ÝèŸø&£‹Ý÷‡Ýø÷·û€"ZOs‹VŽr®‘’‰¯‘‹°¡|žqq{zqM½aâ÷÷ ÷÷m÷¡ûÎ3û*/ûûè1ïÕ‹±ÁŸ¾û6L‹p¾‚ž{±‹»‹¸‹Ã‹»¥´¦¦¨Á‹Ä‹¨Y•tŸZ‹6‹|7e+3ÿü`‹ì‹ì÷L¼¦t rnwtrm¤x¢¦¡ §ÿü`‹ì÷ì‹ì÷Lø¦t rnwtrm¤x¢¦¡ §ûâ¦t rnwtrm¤x¢¦¡ §ÿé“pûŽ úSŸ‹øøBù^˜‹‹˜‘ƒ~‹ˆ‚†~ûåþB†~‹‰‹‰€“ƒ–˜‹Ž•–ÿü`ûU ÷@ì÷ì‹ï÷Lø¦t rnwtrm¤x¢¦¡ §zü ‹h‹DN@…ƒ‹‰‹‰††’ÑÕ÷ °ˆÉZnxuqpžu©ž‹’‘ÿé“pvŸùŸ‹×÷“×øT÷Ô‹Þ†Üg×bÞC¡Z‹Q‹Dnf8oLM‹û‹*’B¯D²?Ðs¿‹â‹½¿¨Å¯Öí‹Åû`ûÕk‹Jx÷€Ç‹×‹Ñ‹Ý‹Õ›ÆœÎ¾ª¶‹±‹Åtž5˜R‹<‹G‹H‹?€NxûLxh‹ÿé“p‹¨ø³¨·Ÿ÷Ð÷´ù¢‹ŒwspYf$‹n¢‹½‹Â¥ügˆ3ln¦ì‹¬‹¬‹ë‹¦‰¨l3ˆ—¯ÿÓ' ÷”Ÿ‹úfúf÷”Ÿþfwÿù`÷°÷)°‹ù!ù7÷Ø™‹žz‹|üá}y‹yxœ‹šøáûN™‹žz‹|üá}y‹yxœ‹šÿé“p‹Ò÷úé÷¨‹é÷jÞøL÷<uˆzƒT{„‚R‹m‹ûM¦¢ÈË¥£÷,÷ ÿ‹î÷0ØûûG(5X·‹Ž ¥š«§xžo‚‹‰‹ˆŠžÏÁ¹Ì‹à¿D/6ZARKû^ûvsøÿü`ø( ÷@ìæŸ÷DøýŒ„Œ†‹~‹}‹:FF‚‚‹‰‹ˆ††”ÚÕ÷Ét³cnxuqpžu©¦˜žŒÿé“pø'ì÷AŸ‹Ÿ÷>Ÿ÷EøtŠ’Š‹˜‹™‹ÜÐД”‹‹Ž††‚Ÿ÷øýŒ„Œ†‹~‹}‹:FF‚‚‹‰‹ˆ††”ÚÕ÷Ét³cnxuqpžu©¦˜žŒ÷RŒ„Œ†‹~‹}‹:FF‚‚‹‰‹ˆ††”ÚÕ÷Ét³cnxuqpžu©¦˜žŒÿü`ûްú2°‹°÷Žûް*ú2ì°ûþ|ÿé“pv¦ø$ŸçÝ´£‹Ý÷‡Ý÷÷ð÷‘÷³Á¯‹¯€žme‹bušx¥¤œš¨¿e¾4ûûûûpû§÷ Mà÷èê÷÷.ä'2j>o÷ûÏL‹m ‚¥¼‹ÑÚ¯î勨fši›f‹Y‹`‹X‹^xer[gzc‹ÿù`> ÷³°÷´Ÿ÷Ȱø#÷{÷¨™‹žz‹|û¨÷¨™‹yx‹z|û¨û¨}y‹yxœ‹š÷¨û¨}‹yž‹œšÿùP‹¨ø ³÷ß®ŸÙÊ÷eÊ÷ÒøF…‹Š‰Š‰Š‰‹}‹û ÷ñâ±Æ•‹»Š©iaˆl€n£~œ£—ª¾\¸>0û Yûû=nÙûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸÷Ü÷1¹‘~bû¦^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸øÿé“pv øÑÒ—Ÿ÷Þøoù¢û…û ‹‰˜‡žulû\¡Ž”ɘ–“‘Ö‹™‹÷h!û,pd&û8‹ûP€‹c´µ‹²˜½‹÷)£÷ºÎÿü`ûU ÷@ìãŸ÷W‡Év²dnxuqpžu©š‹–’‘ŽŽŒ‹Œ‹‹}†KqO_]‡ˆŠ‰‹‡††”×Õ÷ÿ;,@‹¨ø ¨÷‘ŸÙÊ÷dÊçÚøJø&÷¨û÷ á·½·š‹™†‘ˆ‡Šr‚‹nt›{¢£››£¯h©Yc‹eyrsq°Sp‹+ûW!û=nÙûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸÷Ü÷dûÜ^€‹Jn§Â‹©‹¦‹Ò‹¢‰¨wB‰–¯û¥÷÷÷ñà±Ç’‹·‹¨vp†ƒx‹|‹z”}š…‡|‹~‹€û ÿ/ö@‹¨ø ³÷ß®ŸÙÊ÷eÊ÷eÊøâøF…‹Š‰Š‰Š‰‹}‹û ÷ñâ±Æ•‹»Š©iaˆl€n£~œ£—ª¾\¸>BSpokw®aŸY‹.ûX û=nÙûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸÷Ü÷eûÜ^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸÷Ü÷1¹‘~bû¦^€‹Jn§¼‹©‹©‹½‹§‰¨K‹¸øü¶€÷óå¯Áª‹°Ÿr_‰iƒz•{›…Š„‹‰‹~ûv ù? û¥š÷o•ûa–¨ Ì  7Ÿ Ÿ” Ì› endstream endobj 334 0 obj 10242 endobj 12 0 obj <> endobj 11 0 obj <>stream NHYTKJ+CMBX10!øøøûÁûŽŒúF³ù÷A÷8÷2FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMBX10Computer ModernNTIU/5*6žð1±ÿUPú‹ºøäº÷Àø‡À÷Áù5€—ŠŒv‹ûy\÷üÇ‹uŠŠoˆsˆ‰‹o‹r\±ŽÄ‹²‹µ‹¿‹´ˆºry‹zŒynŽŠŒ‹¡øŸø†üÞ•ŒŠ›‹¦‹”¢øÖ‹¡ŒŒ§Ž£Ž‹§‹¤ºeˆR‹d‹a‹W‹bŽ\¤‹œŠ‰¨ˆŒŠ‹uü)ù´‹ºøÙÅ‹º÷„÷"÷ƒºùtù7ý5vû…º”÷•Ü÷$‹ØüÙû-\ÁŽ÷‹Æ‹Æ‹÷‹Áˆºû-øÙ×÷#‹•;•ûºÿ´ ‹ºøäº÷÷"÷µù÷ºbˆ)‹]‹]‹)‹bŽ\÷üäû\´Ží‹¹‹¹‹í‹´ˆºûÿt¶Ð€ºøïº÷÷"øÀùuøö‹¡ŒŒ§Ž£Ž‹§‹¤ºeˆR‹d‹a‹W‹bŽ\¤‹œŠ‰¨ˆŒŠ‹uü û(ûZûûC‰÷Ãø4÷ºeˆ)‹`‹`‹)‹eŽ\÷ü,û÷û÷c÷Rà÷ ÷€–ùB–û‘”÷^ û]’º ÷  7Ÿ ³’ ÷§ Œ  endstream endobj 335 0 obj 663 endobj 76 0 obj <> endobj 75 0 obj <>stream RBMUEL+CMTI12 øøøgûúãù‚ª=÷Á÷b÷1FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTI12Computer Modern/LyncModNpeDfPErgshRGtiSujTIvkUwlaxmb{.:/0\5"6 ,-ZOD.PE/QF%G1&SHTI3(UJ4VK5*WL6XMBYNCoiwm 07áEoÇyÙRìzjí ‚  ® Š F ¼ FÁGwóÌs8®?ÿéuš¸ð-Œû •o¬÷òÿenP‹¨ù¨ø øô”°’”׋’œ•‹–ƒ‹ƒca‰‹cd‹ce‹ƒ€‹x’‹ž¤§‹{…‹ˆ‰…ûü»‚h…ƒN‹y‚‹x“‹›ø1 ‹Œ‹‘œ×÷mŒŽ‘‹Ž’…Ž„€‹ŠŠ‚rn9`û û/‹9nŠŒ–““’øoû`Ÿ¾Ô½Ÿø/ŸÑÄž¿ø‰ø™‹‹š”~o‹„r‡}Bû»ƒlcSS‹^‚¸¬Ç®ê¢Ë“¢˜‹Ÿ³s±Z0iû'…‚”‹—‹ŒŽ™“©¥êÅ‹—–†srqvQk2~X‹d1Æs¼¶‹©¡››_XhXk^gvh‹p‹o˜„°»Œ´‹š€™w„c‰QX²j¾ó‹âõ£êøºŸø/Ÿ÷¹¿¡Ä÷Œ÷£‘¡Á÷당‹YzM_û zZ‚r‡‚‹v[ªm´è«÷)”‚‹‡‹Šˆ‡|‚ip1S‹|ƒ’¢£–ª“Ÿ¥Ô­è‹ÅÀt¼>M‹\gj^ˆ¸l¯]‹t‹qv`xf~O‹‰ƒ‰”–‹ŒŒ‘¢šÆžÆ­‹¥‹nx‡u‡}Bû¸‡}‹Š‹‡“¢‹•œøVŸ÷µÖºŸ‹Ë÷eÙøBø rŠux‹sr¡†”•°‘¿ºa°Nûûû!û(%ÈOÛ÷Ýð™’ƒ“…ˆ‹ŠŠƒ‚VC@oX‹Xp¸Æ¹£÷¬Ä­Ç¼­¶‹‘‹À‹™[ÿlÜ ‹¨ù¨ùþøø”­‘“É‹œ”‹–„‹zû v‹ˆ‹{ûèüÑUøÊ‰¡ŠŒs‹û y‚‹x’‹ž¤§‹{…‹ˆ‰…ûüŸzH[‰m‰†Šy‚“Чª‹¨©‹ª‰¨‹‘–‹ž”ƒŒ…mŒo’‹­‹”™‹Œ÷ø±ŒÅüúxˆ—‹—‹Ž“˜øùŒû"ü΂h…ƒN‹y‚‹x•‹Ž­¯‹®¯‹°‰®‹’–‹ž•ƒ‹|S‹“”“ŒŒøˆŸø/Ÿ‹Ë÷—Ëø…÷«óKÅ@ûûû!û(ûÎUÓ÷÷÷#÷&û‹û¡ai¯Ï¹£÷¬Ä°Ë¾©°‹¾¥\R`sûkTbDXrh‹øˆŸø/Ÿ÷i©‹Éø·ù3Œ‘‹Ž‹”„Œ{Š'‚}ЂЋy“‹™½‹‚‹†‰ƒŠ‡Pû‚}«r¨`‹ûûû-û&2ºLÏ´´¥¸±–N¸¢‹²‹Ÿ¨˜¨œ®—ċޔ‚‹‡‹ŠŠ…tw8xho‹u† ž˜§Ž˜Tž„pO5Q‹V‰Ù—½«÷ ›³¥É¸¾¶‹È‘.ˆˆ}ÿÖÛ`‹¨ù¨ùeøÛ›Éµ’°–Œœ–‚‹‡om‰‹nm‹ln‹„€‹x‚“Š’°ŠŸ€‹m‹‚ˆŠ…ûüTûJø¦†šŠŒv‹ûy‚‹x’‹ž”¦‹…¡ûü¸zH[‰m‰†Šy‚“Чª‹¨©‹ª‰¨‹‘–‹ž”ƒŒ…mŒo’‹­‹”™‹Œ÷ø£÷dü󌈗‹–‹ŽŒœøˆûV¨÷/Ÿø/Ÿø:Êãûƒl„…e‹€‹xƒ’‰¥¨‹¦©‹«‰¨‹‘—‹–…‹yuq‹š”Œ’º÷L•r¤hº‹÷÷÷.÷%â]ÌFLWK„†‚¼g¡i‹t‹qv`xf~O‹‰ƒ‰”–‹ŒŒ‘¢šÆžÆ­‹¥‹nx‡v‡|Ãz“ªÈÝ‹¯žfVSiûwahEbol‹M…錎ŒŽ“øVŸ÷rŸ÷=Ÿ‹Ê÷†­÷z÷|®÷P‹÷¸f±P#û%ûD&¿Cà÷Ýð™’ƒ“…ˆŠŠ‚ƒVC@oX‹I‚Ú«·’§•²‘Ÿ³÷3í•‹³¢oi û:‹kÿân‹¨ù¨øýÖ÷•ù?y‚‹x’‹ž¤§‹{…‹ˆ‰…ûü»‚h…ƒN‹y‚‹x“‹›÷º÷M÷Q÷h÷x÷(9êûûEH”±‘‹­‹í÷½;*Qoû5L+X>;S.‹$nŠŒ–““’÷Àû`ŸÖø¨÷4Ò¡Ÿ‹Ø÷ÓØ÷¤ø&Ùœ•‹–„‹z?”¶‘¯œÛ”·–½°‹Ž‹¤‹šxi„…p‹€x™œ¢¢¬²d¢b+‹rû„ivûLz‚‹x“‹›ÆDüO‰‚{N€a\g‹‡‹rŒ~°’©‹“ž}•zttyjd°t´Ü‹º÷ª÷5ÿ—n‹¨÷µ£÷̨øÌÜ÷Æ÷Ò÷-÷÷ð÷ ÞIÊ û²y‚‹x’‹ž¤§‹{…‹ˆ‰…ûü»‚h…ƒN‹y‚‹x•‹®°‹¯¯‹²‰®‹“–‹ž•ƒ‹|S‹“”š÷ø¿”±’‹¬‹âݲjOy‚-XS‡ˆ_[0‹ûÿ—n‹¨÷ʨ÷°ªù1÷~”‹‹Œ•‹ˆ†‹ˆ‹ˆˆ‰‰ƒw†€TûbRû)‹ûnŠŒ–‹™Ð÷ªâΓ{oy„o‰ƒ‹‰‰‡‹ˆ•‹—‹ŒŽ˜Ã÷rŒŒ‘‹•‹ˆ‹Šˆˆ}w?ys9‹8É÷Œ”®’Œ«‹÷÷ –bN‚‹w†k‹†‰‹†€”‹—‹‹ŽŽ£÷E‹Ž“‹Ž–ƒ‹züWz‚‹x“‹›Â‹ƒˆ‹‰‡}ûü³‚h…ƒN‹y‚‹x“‹›ødŸ‹ŒŒ‘šÿœ€ ÷×Ô™Ÿ÷Ö×÷÷²Ž—¸÷ß‹‹§‹¡}|‡x|‹rv›ƒš¦˜¯¾G’o]‹eufW‚Æ`šp‹t‹qv`xf~O‹‰ƒ‰”–‹ŒŒ‘¢šÆžÆ­‹¥‹nx‡u‡}Bû¸‡}‹Š‹‡“¢‹•ž›øVû`Ÿ–ÓðŸø%ŸÅÉøoøŽ–‹Ž‹–ƒ˜yt‹~v‰zŠ¢r­]‹!ûû%û&/½QÍÀ¸¹’’kû€le?:‹€‹i‹q–¡””Ÿ‹™˜‚›twrzke²{Øñ‹ÖÌŸÚ}÷RƒjN>U‹U‰Ø—»©÷›±¤É¸¾·‹Ç“5…‰Š†‰‚ø$ŸÈÕ÷4Ë¿Ÿ‹Ù÷K¼øøg‡‰m‹‡€’}Ÿ¢œ­¹c±Kû h%`‹fžv”œ{ž†¶¤†¾‹Tps3ûg‹Y™€º»‹´‹ y“~ƒd‡TNÄhÐ÷ ·÷Á‹áD›[–p‘g“‹¸¥¡ÏÜ´‹¨v’køˆŸø/Ÿ÷i©÷¿¡Ä÷¾ù3‘Œ‹Ž‹”„Œ{Š'‚}ЂЋy“‹™½‹‚‹‡‰Š‡û&ü܈~Љ‹ˆ~”œ§‹‘¥’É÷Œ‘¢Á÷당‹YzM_û zZ‚r‡‚‹v[ªm´è«÷)”‚‹‡‹Šˆ‡|‚ip1S‹|ƒ’¢£–ª“Ÿ¥Ô­è‹ÅÀt¼>K‹afoiÿÉnPv ‹¨÷ß÷¨øPÒ³Ý|ø„÷è÷¨ßÞ‹ßÛAÎûûy‚‹x’‹ž¤§‹{…‹ˆ‰…ûü»‚h…ƒN‹y‚‹x•‹­±‹®¯‹±‰®‹“–‹ž•ƒ‹|S‹“”šÏ÷£¸÷ÚœVf{ƒi„r„o‚f‹w=ÊrÁÛ©ó”•‹‡€‹Š‰‡}{Wohj‹k‰¨§©’Àª‹°‹™‹Ëb®^9—%Í÷œ“«’Ž”Œ’©‹ž‹Éñ‹+y†ûPû_ÿô¸Pv¨÷~¨ø(¨‹Ûù3÷P˜¿ŒŒ¿Œ•“–“„†kh‰‹jd‹be‹‚€‹x“‹›’±­‹w‡w)|pp[HfE‹B#·÷2Ú¬÷5ÞñÑàá±Ð‹÷—û_|‰tˆ|‚‚“‹•‹Œ›È÷ˆŒŽŒ“‹”„‹‰‰‹‡‹„‚J;kÆX©J‹û^ûhûtûû;õ*÷¸å™ÒÆ“pŸg•‹‹ŒŒ÷ÙŸø¨÷BŸ§Â÷”ø&Þœ•‹–„‹z<³÷1ŒŒ”‹”„šxr‹‚u‡|dû16y‚‹x“‹›ÜCû´†w‹‹‡]¦aÂí½÷(”‚‹‡€‹Š‰†€ld)J‹|}’¬š¢š÷ÀŸø/Ÿ÷Õ·¾½¿÷Óùž}–zyq{ou›ƒšŸ£¥ûLü’ƒu‹~‹‚Q²v¬ç«÷)”‚‹‡‹Šˆ‡|‚iq1R‹€£¥™¯¼ŸÁŸÁžÁ”¤“‹¾j¦d/jû(†‚”‹—‹ŒŽ™“«¥èÅ‹¡‹x€q…z„yøºv¨ù1¦÷É÷aÈùù=ŒŽ“‹Ž”ƒ‹‰ˆ‹ˆ‹ƒ€^OfÒA‹y‹û ûûû ub¯d t†Ðw—‡´“‰µ}d‹^0=$0>D²ñ‹•¦‘£Œ“”ƒ‹†€‹‰Š‡{WûdŠˆ‰ƒ‹ˆ‚“‹‹ŒŒ•—¸Ç¦b¸kÚ‹÷ ÷÷÷Úc¸Y›ƒE x‘k”\™‹ÖáÚâß÷ ‹ûl‹~‹z‡n‰…‹‰‹Š’‹’–‹Œ›ø¡Ÿø/ŸÑÄž¿ø‰ø™‹‹š”~o‹ƒrˆ}Cûµ‹Š‹‰†wafh]‹^‚¸¬Ç®ê¢Ë“¢˜‹Ÿ³s±Z0iû'…‚”‹—‹ŒŽ™“©¥êÅ‹—–†srqvQk2~X‹d1Æs¼µ‹®Ÿ«³–dªv®‹²‹Ÿ¨˜¨œ®—ċޔ‚‹‡‹ŠŠ…tw8xho‹u† žš¢š÷Àû`Ÿ•ÔøžŸ÷Õ‹Ø÷mÃ÷óù™›vtuvt|–|Ÿ¢¡¡¡ûYý>€`e9M‹„‹{Œ}”©•¤‹”˜‚›tutxng¯x¶Û‹ÕÒžØèø ‹Œž‹š¹oµU)Xû'…ƒ“Š‘–‹ŒŒ’£Ë³Æ½‹¤ŽxuŠ|…tùP‹¨ù­ø°øø’§‘“’¨‹‹â´…FmƒXˆ{‹‰‰„‹‰€•‹—‹ŒŽŽ›©÷I•‹Œ‹Œ–„‹züŠv‹‰‹†{NûLŠˆ‰„‹ˆ•‹Ž•‹ŒŒ“Ÿ½÷)¡£÷‹­¢‹‡„…ˆ~Љûü±‚fƒ6‹y‚‹x”‹“¹¼‹º»‹½‰º‹•–‹–„‹zz‹{Œ{xŒ‹›‹‹•ÿxÚà‹¨ù¨‹ø;øøù“­•’Ç‹ “‹ž•‹‡fd‰‹fe‹df‹ƒ€‹y€’‹œÆ‹„€‰‹…‡{ûü°‚g…„G‹}‹x•‹¯²‹°±‹³‰°‹“–‹ž•„‹xon‹œ‘‹”øVŸø/ŸÒÄ¿÷ Ýøxø ¾w˜yxrxt‹‚†”¢pŽf‹{q]û—û X}·³‹Å­è¢È“£˜‹Ÿ³s±Z0iû'…‚”‹—‹ŒŽ™“©¥êÅ‹—–†srqvQcû‡g‹o%×{µ÷:¹÷ý¥øVŸ÷ØÕ˜Ÿ÷i©÷kÇÏØ÷¾ù3‘Œ‹Ž‹”„Œ{Š'‚}ЂЋy“‹™½‹‚‹‡‰Š‡û&ü܈~Љ‹ˆ~”œ§‹‘¥’¿÷c£ˆØ{‹H‹†‹†‰†w‹†‹}D·s°°‹£¥œ«ž­˜Ã‹”‚‹‡‹ŠŠ…t}RxN`‹y–ª¡‹”®ž‹‹–‹Ö6 ]“¨›Ÿ¢³º¯·³µ¹‹Ÿ‹”€Œ‰i†ƒr‹|v›ƒš¢¢ž«¥x©_P‹_Vd]SHwƒyƒÿÖÛ`v¨ù¨‹ÏùeøÛ›Êµ‘°–Œœ–‚‹‡pl‰‹oP‹oŠ‹„€‹x‚“Š’°ŠŸ€‹m‹‚‰‰…2ûúnû'#&‹RY³á¢«‘¡ïø%”­‘“É‹œ”‹–‚‹†hf‰‹gf‹eg‹ƒ€‹x’‹ž¤§‹{…‹ˆ‰…)üƒk‹x‹|û ÜIå÷ ‹÷÷¨÷ ùŸø/ŸÒÅœ¿àÄ÷GÝø ÷>„mŠs‹ƒ}l7UQ€À­‹·œÆ¬çš´•‹Ÿ³s±Z0iû'…‚”‹—‹ŒŽ™“©¥êÅ‹—–†srqvQj1€\‹g)Õu¾¥‹­‘¯Ç¡OÈ…¦‹×‹²Î¦Óš´µ÷'‹Ç¾w˜yxrxt‹‚†”¢pŽf‹{‹dk |fvUk[X‹X}·³§’¦˜¿’©Ô“¨‘¤–·‹š”~o‹„r‡}÷ŽŸù©‹Â÷¾ù3Œ‘‹Ž‹”„Œ{Š'‚}ЂЋy“‹™½‹‚‹‡‰Š‡ûüŒ‰‚ˆ€‹|V­h¹­‹Ÿ¢™§¬™Ì‹Ž•ƒ‹†‡‹„‹‰…Šˆ‡|ˆ‚~ZzOi‹u† ž˜§Ž˜øˆŸø/Ÿ‹ÉøoøŽ–‹Ž‹–ƒ˜yk„d‹ŠŠxºi—p‹ûûû-û&2ºLÏ´´¥¸±–N¸¢‹²‹Ÿ¨˜¨œ®—ċޔ‚‹‡‹ŠŠ…tw8xho‹u† žš¢šS…qO6Q‹V‰Ù—½«÷ ›³¥É¸¾¶‹Ç’2„Šˆ€‹‰øVŸšÓ÷Ö—Ÿ‹Ø÷Á×ødø+u…~y‹wv›ƒš¦˜¯ºT–nY‹lb|p€¬l®Y‹'Yûw‚”‹–Œ›¢×»»¹‹¢¢{[tcƒl†uiû‰ƒ€irU^‹†‹u‹y™¨“’£‹—ž}•zqwupc·y³´‹«¦¡µ“s¥^Ç‹í¾÷Ÿ”‚‹‡‹‰z†vG\TZ‹a…¹ “«—¼‘¡•´’§žØŸØÇ‹‹ ‹}ù´Ÿø/Ÿø³¿¡Äø†÷£‘¢Á÷당‹YzM_û zZ‚r‡‚‹v[ªm´è«÷)”‚‹‡‹Šˆ‡|‚ip1S‹|ƒ’¢£–ª“Ÿ¥Ô­è‹ÅÀt¼>M‹YggT…Ï\¢[‹Q‹ZlgYˆ¸l¯]‹t‹qv`xf~O‹‰ƒ‰”–‹ŒŒ‘¢šÆžÆ­‹¥‹nx‡u‡}Bû¸‡}‹Š‹‡“—‹›’’Ÿ•±÷*‘¤¡‘ ¡•°Â÷ 苹‹X{w‡u‡yIûœˆ€‹ˆ‹‰€“~¢‹•œøVŸø/Ÿ÷i©‹¿÷pÊ÷¾ù3’ŒŽ‹Ž‹”„Œ{Š'‚}ЂЋy“‹™½‹‚‹†‰„І&ü)‚g‹q‹€,»TÉ÷÷÷0÷#â]ÌFY‹bc{{‰ü ^}Áµ²–³¡åŽ••Ž••²ÈØÀ‹¯žfVSiûwahEbol‹øˆ÷”Ÿ‹øTø˜÷”𔋕•ƒ‹{ü$|‚‹“‹›÷À‹ì‹î÷gÅ©t”zolplu›z£¦«¤¬÷À‹ì÷ì‹÷K÷»ø |rkomox˜w¦¬¦ª¦7ûâ©t”zolplu›z£¦«¤¬øˆûŽ úSŸ‹øâøìù^Ž’‹”ƒ•€‹†„†ü´þGˆ†‡„‹†‚“–•‹’•øˆvŸùŸ‹Æ÷ËÄø³ø…§‹÷ ûûLüTCP› ÷Ü‹ÙÄÆ÷«Ñ»÷@‹êûºü†`l¯ÉÚÕ÷ȶׯɻ¢­‹¦¼}8.?û—…x|`_û+‹øˆø'ì÷AŸ‹óÒó÷ÁøwœêÈÉ©¤š™ŒŒ‹Ž‡‘†zû û ût‘g²«¦§ª§v•xq‹‚„„÷CœêÈÉ©¤š™ŒŒ‹Ž‡‘†zû û ût‘g²«¦§ª§v•xq‹‚„„øˆv¦÷ Ù÷VŸ÷%ЖŸ‹á÷|Ì÷´ø×®|¨‹š‹÷ÞÙ™’†Œˆ‰Š‹ˆ‚^waƒd‹d‹c”k†‡ˆ‹…‹‰ˆˆ~?ûÃЇЅ‹‡ˆŒ„•’‹Œ‘™›»ÁÕ‹Ã’Kp^rûpZbARqb‹F‹iÈǰ…Ÿª‹ ªmŒˆV‹Dy?¸NÜ÷÷÷÷*Ý_Ò9F‹X_†‡øˆø( ÷@ìµóÒó÷½øúy(LNkp‚ŠŠ‹ˆ††™÷÷÷ –‹º_ftkpu™{¥¥‹””’“÷Cy(LNkp‚ŠŠ‹ˆ††™÷÷÷ –‹º_ftkpu™{¥¥‹””’“øˆv¦ø$ŸðÓµ£‹È÷ÁÙ÷t÷âÐ÷³÷Ÿ¬‹©‹¨‚“lZ‰‹b‹‰x™œµ‹ÉÉV™bQ‹/l0û5ûxû@‹WJû÷÷÷ ÷)÷$²u÷ûH‹_Zo`¦ûÜWwººã¼÷n÷Ó‹>~enûrV…€a9>‹øºû`ŸÖÜŸø¨÷*Ô©Ÿ‹Ø÷êÂÈÙ÷¤ø&÷YCû´†w‹‹‡V­h¹²‹Ÿ¨˜¨œ®—ċޔ‚‹‡‹ŠŠ…tw8xho‹u† žœÚ÷Ó”…‹{û“°Œ–”¸Ÿì˜Ê÷ ‹š‹Ç‹¤nl†p‹~~”{¢¢¢ž¬Òû‹sû‹Dcpûx)Lz‚‹x“‹›ÆBü L~Z…uƒl[g‹‡‹rŒ~°’©‹“ž}•zttyjd°t´Ü‹º÷ª÷5÷ÀûU ÷@ìµñ÷Sšz9^O]cŠŠ‹ˆ‡…œ÷ ÷ ÷¡…¬fkpolo ž¢‹š™ŒŒv ù? û¥•÷sû`•¨ Ê  7Ÿ Ÿ” endstream endobj 336 0 obj 7263 endobj 49 0 obj <> endobj 48 0 obj <>stream CVTESN+CMMI12 øøømûŽú–ù‚© i÷”÷i÷RFL[fkorwCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMMI12Computer ModernpartialdiffalphabetachisigmanofPrFwaxmb:=<>;@ OPG1S'XBYNC Š‹ŒŽÐ'È\Õ±Y+Éê*}Ï  ž 5  Ü 9ÿMUPÿH{`Ÿø/Ÿ÷Æ÷bÆ÷b÷¹‘¤½°«¥£­›²‹³™mcRbûwU‚s†~‹y^ªg»è®÷'‘‡…‚‹Šˆ†zt9ecd‹{Œ«¤–©‘™ŸÂµ÷‹ÄÇh¸?2‹\LyrˆÄbª_‹k‹uxziyg}O‹‡‡†’“‹ŒŒ‘¢›Èij‹¢“{mud„l‚gg‚g‡x€^†y„q€\‹†}–€š—‹™‘“š”®Ÿ’©“©’©ÿÖµ Ÿø/Ÿ‹Î÷­Îø\÷§êMÒ0ûûû$û!,ÉDæ÷÷÷$÷!û™ûYf³Ñ¹£ñ§½¸ØÃ¥´‹¼±cEcv eNbHTqd‹ÿâ¢Pû`ŸŸÛøz¨÷-ÜžŸ‹ß÷ÛßøRø&Ÿ“‹ž•ƒ‹y:žò™Ò“«‘£ ¢¥‹ ‹ ‚•‚d‡n‹zwšžŸ©œ±µa¢_`‹akwdyhgtûHx‹y€‘‹ŸËy.bûvt z4|BY‹ˆ‹n‹yž¾‹·‹ŒŸ|—xwmze`·u²ñ‹µ÷K–½Ø¼÷ž©ÿw Ћ¨÷µ£÷̨øõß÷¼÷Ò÷<÷÷ñ÷ÙIÒûûÉx‚‹x”‹šÈ‹ƒ€‰‹…‡|ûü®‚h‰E‹x‹y€”‹‘žŸ‹ž÷ ž‹ ‰ž‹“–‹ž•‚‹|OŠ’•Œ’Œ÷ø¼”°²‹îÖÉs@q~6]]zy[e0‹û!ÿ¹Ap ÷ÐÛ™Ÿ÷Ç÷ßøø-l…{u‹usžƒ™§¢£©«l§Yc‹]yaN„Àc¥c‹d‹wmuzg|O‹†‡†’“‹ŒŒ‘¢šÇžÅ³‹£’znud„l‚gg‚g‡x€^†y„q€\‹†}–€š–‹ž’‘ŸŽ“°÷+‘¢¡‘ ¡™›Ž˜Ž”¦¼¤¡—–¥¢´‹›‹›ˆ˜‚ÿyÙ‹¨÷½¨÷½ª‹ùG÷½÷Úëבzn~‰}†u‰‡Š†‹‰„‡’“‹Œ›Å÷}ˆ‘„‚‹Š‡‡zv@wv4‹0Ì÷—”®Ž´‹÷÷fD…‹uˆqЇ‰~‹‡ƒˆ‘’‹ ÷C‹Ž•‹–‚‹yünx‹y€’‹œÉ‹„€†Š‡ˆ€ûü°‚h‰E‹x‹y€”‹‘žŸ‹ž÷¡‹£‰¡‹”—‹–…‹u<‰’š“’ÿ»îàŸø%ŸŸÚǘÃñÆ÷„²¾÷ìÈ¡OÉ€±‹×‹¸Í§Ð¢Å°÷‹ÆÈl‘‚susw‹’„‡”‚¥p‹W‹io-v\oNfcW‹ÞSyµ¹¨”®œµ÷<Ÿ”®‹š•|n‹„r…sdaû=‡u‡z‹€‹u‹skeЉ€€{zl‹¾<‹Öœ«’·¸÷ —ª˜‹Ÿµm±Z/fû%ƒ‡†’”‹Œ™¤ã²¯°‹•›Šk†‹vz_\ûb‹e"áx¾œ‹¸‹³Òø–ŸøŸŠŸ‹Ì÷SƸ÷Á÷ †z‹‰}xuo_`\‹bt°ÆÂª÷žµ­Ñº¯²‹͘9ƒŠˆ~ЉšÇ€¥p³W‹ûûû&û((ÅQϺ¶¬§ØP•ºz©©‹£¯›­™È‹‡…‚‹Š†‡||PxLb‹n‰¥Ÿ¢Ž–”²’¤¡“¨°÷*”¯‹‘™€–|k‹ƒh‰ÿ,j Ÿ›Ù÷sܘŸ‹ß÷Òßønø,k…s‹xsžƒ™© ¥¦µ[žaN‹iO‚xtÖMy‹%Uûu‡†’“‘­÷Π¨‹¸”asu…t[{K‡|}Q|OnTV‹†‹r‹v˜¯’“©‹—Ÿ|—xsqvkaºx¶»‹­± ´›P½w°‹ñÁ÷¡‡…‚Іƒˆp3Qb^‹hx¥´¡››Í—¹˜À•°šÇ­·¹‹‹§‹ ~ÿXxpŸø/Ÿ÷Æ÷aÆ÷iÆ÷b÷¹‘¤½°«¥£­›²‹³™mc…‹w\~W‹ˆ[ƒmxA‰€‡|…q‹‡}–€š©‹¢”¯žÖ¥òšÈ“¿÷÷‹³™mcSdûuO‚s†~‹y^ªg»è®÷'‘‡…‚‹Šˆ†zt;fac‹{Œ«¥—«–»¸÷ ‹ÅÇh¸?H‹UecPˆÁj¶@‹2‹\LyrˆÄbª_‹n‹t}xeyg}N‹‡‡†’“‹ŒŒ‘¢šÆžÆ³‹¢“{mud„l‚gg‚g‡x€^†y„q€\‹†}–€š—‹™‘“š”®Ÿ’©“©’©ÿ PŸø/Ÿ÷i³ŒÂ÷Ì÷{ù1Œ‘‹•‹‰Š‹gˆy‰zŠ|‰yŠs‰„Š‹y•‹•¾‹‚‹„ƒn‡ys+cRûw‡y†r‹z‹~%ÄVÌ÷÷ ÷)÷%çWÌ@W‹\`xw•ükh£Ù¬ŽžÑŽ˜›Ë˜“ÆäÏ‹·Ÿ_W[oûrWrU][]‹ÿü`‹ì‹ì÷L»¨sŸsnwssn£w£¨Ÿ££ÿé“`ûŽ úSŸ‹øøAù]‹Œ‘š‹—’ƒ†‹‚‹ƒuûãþA‹Š…|‹‰•„“‘‹”Œ’ ÿù`o ø–Ÿ‹øéù'ø{“’‹‘–ƒ“€‰‹ŠŠ}…ü±ûyƒ‰„‹…‹„Œ…ž‚ø±û˜…Š‹–““–‘‰’y“ü—÷ÿù`o ø–Ÿ‹øéù'÷xž”Œ‘‹’‹‘‰’y“ü±÷~‘‰Œ‰‹„ƒ“‡˜…ø–ûü—û‚w‚‹„‹…ƒ’—‹ŒŒ™‘ÿü`ûU ÷@ìãŸ÷W‡Åx¶bk{quušp­˜‹–””Œ‹Œ‹‹}†j…JQJ€‹‰‹‰††“ØÕ÷ÿäv¦øCŸÔÛÜ£‹Òºß÷ˆÐøZ÷â…ÃhÎ1‹û!û$û#û3Nµû÷÷€ð÷ì÷÷$:÷ûû%`ûp‚‘u§®š«œªl‹~´Õ×’¦‹ãÃEûKxAfû€ûÜ-{Õµ·§òš°˜©Äðó‹æ h{7hQgPUj^‹v ù? û¥•––û`•¡ Ì  7Ÿ ¡’ endstream endobj 337 0 obj 3466 endobj 42 0 obj <> endobj 41 0 obj <>stream FYFOUY+CMBX12~2a!øøøVûsù‚³Ë÷ï÷t÷5FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMBX12Computer Modern=LAyncMzodNCpeODqfPrgFshRGtiSHuTIvUwlaVxmbW8{9.:0123(4)56 7, -"ZOD.[PE/$QF0%RG1SH'TI3(UJ4)V5*W6XMB7YNC8o  m   >B½C«¥ùVÇ_âS¾.…îM¦Ï ( Ñ < Û x ¾ ´ ' ~ Ì né‹¿@¡6Ò;ÑYqïN¸ÿvrÄ&ÃGÆ9y%ðø ÿ£í‹¶øì¶õ÷ù÷¢a„F{û2ûH‹ øì÷¶Z‰2‹V‹f‹û‹n`õüì!`øÅÿQ‰ ‹¶÷0¶øJŸø^ù9„‰s‹r‹‰†„yûŒüö„{‹‰oˆrˆ‡‹u‹y`¥Ç‹¨‹¦‹Ô‹¢‰¶u‹e‹o–Ž”‹À÷÷ Êû0-`«ì‹±‹«‹ñ‹¤‰¶,ûâø{÷û´û}ÿQÀû\¬øÌ¶‹÷øƒø‘™“Ë‹¶i‰‡‹b‹p‹‰‹R`Œº‹~ˆˆ…Šˆû ûû÷©¶s‰G‹o‹n‹P‹q`Ë÷Mü%†}n†v^kFE‹‡‹‹€‘Œ©—‹±¬s mlsvi\·aÇÝ‹ÁÕŸ·ù‹¶ø ¬Ð÷÷^÷ø§÷Æêb¼ûC‹Mhi@Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Føˆ…¯ø¯‹÷ ÷G÷ øh÷ —€‹{‹ŠŠ†„xpH/‹û!‹÷,¸ÆŒ÷÷’Ɖ†ŠŠŠ‰Šˆˆ~|‹ra­z¤ ±˜ºÝû‘UûFEûûûê/÷'÷1ª÷’ÿ+!@‹¶øì¶õºøó÷ ø©÷û„ø®‚ ‚‹v‹ûi`õü΋uŠŠq‡y‰wŠy‹t`¢Ù‹§‹§‹Ú‹¢‰¶tp‹‰‹sŽnŠŒ‹¡øÂŒ÷¤üö€‘œ‹œ‹‘•–÷©ùŒüì!`¦ó‹­‹­‹ó‹¦‰¶!øìõ¶ûiv‹‚‹‚vøˆ‹¯ø ¬‹ø9øLø*”–‹‹‘ž‹xûþ€û@µ‘ê¡·÷‹åûªü‚€‹‰‹„w”‹Ÿø œ÷Zaƒ!uSû‹0ÿ2€…¯ø¬‹÷ ÷—÷ ø¦÷o÷/îû1û74#ûûç-÷1÷7âî÷ûûQû‹÷ ݺ‹½ž¯¡³¸¶‹Ä‹¯pœoŸg‹W‹[8‹ûûù…¬ø¬÷U¾‹÷ ÷‘÷÷ïùB`É’‹dû^už_¨F‹û"&3û û#î6÷ºž¬²W÷F‘¶M„‹²øøûüåaNX~g‹û‹÷ͺ‹½¡±ªÃÆ‘¢‹´‹·y¬_ÿo¡@‹¶øì¶õºø…º÷¶ù6–ŠŒw‹ûq`õü΋uŠŠq‡y‰wŠy‹t`¢Ù‹§‹§‹Ú‹¢‰¶tp‹‰‹sŽnŠŒ‹¡ø¬øƒüè–ŒŠ˜‹£‹‘¢øÜ‹¡ŒŒ¥ŸŒ‹¢¶t‰=‹o‹o‹<‹t`¢¦‹‹£ˆ¨‡ŒŠ‹uü6ÿ,€¶÷WŸ÷J ÷b¶‹÷!øŒµùù4¢‹Žu@CS»H£A‹ûƒû.û%ûfûb÷)û)÷‰÷F÷÷÷ œ…Œ|‹€Š‚û,ûW1‹J‹3SÊh±k‹÷‹íšÔºÃËÖï•»‹Ö‹÷ a©ûD‚”‹—‹¢‹£ùûV¶÷%¬ø¯Ð÷÷‘÷ ÷®û+F÷T¤u·rÇ‹÷öÞ÷&÷.äûPXwkc¿ûAƒ`É’‹dü“F`¢Ó‹§‹§‹Ô‹¢‰Fø´°»À›²‹ÌÆPûû%CXK``¡ºlÿNÀ…¯÷S¨÷>¬‹÷ ÷‚çøX÷q¢‘‹¤©„Ö]ºaµS˜Q‹û06%ûû ò0÷+÷+¸õœš|‹…{Šˆ~…qJIv[‹û%Š÷è´Œ² ¯ž«®¡¶‹ö‹”û ŒYÿLç±ù¯‹÷!øJ÷!ù¢÷è÷hû÷&ûrûsûû'ûgûg÷ û!÷p÷p÷ ÷!÷gûüûÎJ‹LªeÄ[Ô†é‹Ô‹ÈŽß´Ï·ÑӤƋ܋Ç`¨^°Q—M‹'‹(€8YFriT`=‹ÿ^D@‹¶øì¶õ÷ø÷±ùB`õüì!`ø9÷T÷(÷÷j÷vû,÷ûPûPýøì÷*â‹Ñi°W¨bžZ‹û‹û |Wh\h]Hj1‹ÿQÀûV¶÷%¬ø¯‹÷ ÷‘÷øœøVfV8h¾Z«I‹û#5û"û#ï6÷±¾“¼¿û^F`¢Ó‹§‹§‹Ô‹¢‰¶F#÷¢a÷;èàò÷,àû9ü,`õüì!`¨ö‹¯‹¯‹ö‹¨‰¶!÷øì÷/‹9GI‹7û/û÷ÀÿË}p‹¶ø ¬Ðóò÷÷d÷u¬’÷3÷ }€„z‹yb¬z¤¤¬œ´¾W§[<‹iF}aŠ÷û8ƒ`É’‹dûÑF`¢Ö‹§‹¨‹Ü‹£‰¶4ÿ2€û]«÷2çÖ«÷~­‹Ý÷sõ‘Ý÷÷J»qËš‹÷ÂØÑ¾n¯•¨›£œˆ†ˆ‡‹~v™x¥¥™ž £y«a`‹bvvyb£d”X‹ûT>El•bµizxyh‹g‹`¢f {s…Mt‹RPÌH÷L÷:ßÁÖ‹ãQ¨r—[£K‹3‹r‹_‹†Œ`’±‹ž‹“Œš–˜÷ ‘4‹Ð¹¹‹Ðââ‹F]]‹F4Ãû[ÔÑ~WhhQûûgñËÊ‹šÿÃ,€‹¶÷¨¶÷¨»õ÷÷3µù ù=üä`õüç!`¨÷‹°‹À‹ä‹¼‰¶û÷¨Âë“_Bµ÷©aBƒ_+T÷¨÷#÷3‹¤B™û µÿ»À…¬ø ©‹Ï÷{Ïø ø?ž‹’|…‹‰‹|‚‡ˆ€„†ˆo›f‘g‹mû*‹û"÷uª†¦†¬…‹³‚³r‹a>0‹vX‹L›oì…ŸŠŒz‹v‹ˆtûx‹„š’‹‹Ÿ›¥ž¸hÁ‹‹Â÷—÷»q¬wb­i‘U•K–O–‹»Ìä‹ ÷‹‘ErŒ~“‹—‹ ‹Ž¢ù‹¶ø ¬÷U¾Ð÷÷^÷ø§÷Æêb¼û&‹ZD}mŠ÷íûAƒ`É’‹düÅF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ÛÀ˰ s?û¦F`¢Ó‹§‹§‹Ô‹¢‰¶FÿG°¬v¶÷°¬÷¯¶õ÷÷±÷!|ø¥÷è÷¯¬Ó‹Áï"ßûMü`õüì!`¨ó‹¯‹¯‹ô‹¨‰¶!÷°¸÷ ³‹«¡q©i‹u‹H‹H‹b¾i¿hÝŠ¡‹ñ—噜ƒŽ~xŠ„~ІYlvo‹K‹„΃ç…À„Õû¬û!Ÿû ÷¯÷ ÷7Ž9PTŠ4û;ÿtAж÷[¶ø¶‹÷!ø2÷ù÷zÙ¶s‰ ‹k‹N‹I‹N`÷!%‹v‹ocrw~la‹R‹(™MÔd¸sÈ‹÷ ‹òœÑ¸ÀËÖï•»‹Ö‹÷ a©ûD‚”‹—‹¢‹£÷n¢‹Žu@CS»H£A‹ûƒû.û%ûfûb÷)û)÷‰ÎÚšÀ´­kÄsŽ‹—‹•›ÿµ€…¯ø¶÷?ŸÜ÷÷ µ÷gø%÷$¶û$÷SaŠ([((ˆjÜûª!ÝtÓÕ·ÃÕÀaWImnlO‹Î¢ÿ8€‹¶÷ø¾ð÷$Ðó÷sù´jªdblieeªi´²¬ª´ûDûI`Æ’‹dûÑF`¢Ð‹¦‹§‹Ë‹£‰¶Mø+ù¶ù³‹å÷Ôå÷’øL(¡ˆÓ‹™¾¬Æìì‹â\ ûŽv‹Šž‹ ‹Ž¢÷Pž‹’|„‹ˆŠ‚`Zr Y²*‹û#?1ûH¯\™}¿W§…ótïu—‰¡v˜~¨o‹X`v<û3‹û©ƒ÷&Š‹Žw‹v‹ˆtûPx‹„š’‹ŒŒ•”––”˜¤¤Å]Ý~Ç‹÷0ÍõõéMåû¤ÿo¡@‹¶÷¸¶÷¶õ÷÷Û÷ùsùõ¶n‰ ‹g‹g‹ ‹n`õûûÛ÷õ¶n‰ ‹g‹g‹ ‹n`õüì!`¨ö‹¯‹¯‹ö‹¨‰¶!÷¸÷Ûû¸!`¨ö‹¯‹¯‹ö‹¨‰¶!ù…¬ø¾Ð÷÷^÷÷õøN`É’‹dûX?^N=@‡¤Â÷ëûFƒ`É’‹dû'Înö£‹Õ‹¶ÜŒ:÷A‘¶M„‹²øÿg°‹¶øã¿÷°÷ùdù9ý'wûµ”÷“à÷$‹Üüãû+`Ûò‹­‹È‹×‹Û‰¶û+øãÛ÷$‹“7”ûµÿ¢û‹¶øì¶÷÷÷§ù÷¶g‰'‹a‹a‹'‹g`÷üìû`¯ï‹µ‹µ‹ï‹¯‰¶ûÿQÀ† ø¶øƒø’š“Ê‹¶g‰‰‹b‹p‹‰‹R`¦¡†„ЋІû û•û÷­¶t‰E‹p‹n‹Q‹q`Ê÷Dü”x†¢‹›‹“”Ÿÿ`•P¶øø¶õ÷ø"¹ùdøù‹¡ŒŒ¥ŸŒ‹¢¶t‰=‹o‹o‹=‹t`¢¦‹‹£ˆ¨‡ŒŠ‹uüû#&Qû ûC‡÷Åø8õ¶n‰ ‹g‹g‹ ‹n`õü1ûõû÷]÷Mß÷÷ÿ,€† ø¶ùdø ’œŽ’Å‹¶n‰~‹g‹b‹~‹g`”¼‹~ЋЇ"û˜û÷±Ķs‰P‹p‹X‹‰‹Y`ÆŽƒ~‚Ž…•s‹†‹‰ˆ„Šˆ?ûQû÷žĶt‰G‹p‹k‹[‹m`Æ÷-ü’y„¡‹–‹—‹“Ÿõ÷õû›”u–‹—‹¡‹Ž‘’ÿ8€‹¶øì¾Ðó÷mùJûAƒ`É’‹düÅF`¢Ò‹¦‹¦‹Ò‹¢‰¶Fÿ"à…¬÷b¦÷4¬‹÷÷b÷ø`÷¿çBÉû!Sû †7a«y¦©¨ ±‹ž„z–¬”£‹ž‹Ï´e9cû2û3_û0÷wÐØ¼µ·Ÿf‹`ð¾ “‹¡ ‚‹}LŒ‹›‹¢ûÃ-7ykZb¬¹‹æ÷ªíÿQ‰ ‚ ù ¶ùhù‘˜•Õ‹œ¶l‰C‹ƒ‹o‹D‹t`¡‹°‹§€†}ûaühûløè¶k‰+‹e‹k‹(‹r`å÷¨ý ”w”Š›‹›‹•‹” ÿQÀ‹¶÷ú¶÷å÷‹÷÷–˜”“Þ‹¶S‰‰‹i‹n‹`‹o`ž †„‰†„‰‰4)(÷ µ¶t‰G‹p‹m‹U‹o`Ò÷0ûRûû'}„„8‹`Ç‹ª‹¨‹µ‹§‰¶xv’Œ‹Œ’“ï÷÷ûa`£Î‹§‹©‹À‹§‰¶Eÿ©€‹¶ø ¬Ð÷÷_÷÷_÷ùà÷Æçd¿û&‹\G{k{àGšK‹+‹WMv[Š÷û=ƒ`É’‹dûÑF`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶F÷i÷ܿʰ¡u=û¦F`¢Ó‹§‹§‹Ô‹¢‰¶Fù…¬ø¬÷U¾Ðó÷–÷ ÷dùJûAƒ`É’‹dü𵜞œž›Ÿ¾V€³‹÷õß÷%÷-åûP\xkb[®»¿µ‹÷‹ûI^‹Rsfl[\k‹G‹f»}¡ÿŠ 0‚ ù ¶úªøÿ’‘ß‹¶Y‰‰‹R‹n‹B‹s`—ã‹}Š‹‰‡‚û<üRûGølê¶k‰.‹e‹l‹*‹s`ß´ûûüûFølé¶n‰)‹g‹k‹,‹r`ß÷‚ý‘zŽ„¡‹¡‹Ž’‘›÷Bøa÷Cüa‘{Ž„¡‹ž‹’žÿ2€³øä¯‹Û÷ÇÛø ø½¥Ã°‹Ùò/·ûûD?*‹U¦OÕdûYxF‹WûïS÷÷(âÛ÷‹÷5ºX§ûHòw–o¢‹¬Ûö¢à»^I‹by`Rjû 5ªyØ`©y¬x¶s‹X;;rC(SÀÚ‹Ô¸¹»¦ÿ2€÷–¬‹øÅøÅ÷–¬üÅjÿ2€³£÷ ¬÷þ¯‹÷÷h÷ø÷®E‹ûLû0l‹g“v›¨‘  ‹«¯p¢kqjz_EÂXò÷÷.Þ÷–΋÷˜û{û);ûûë@÷ µ‹½š«ÒûV(‹Üíë‹â÷Ë¢R€•mM‹jEn(7ÿ8€‹÷$‹÷$÷xÓ´jªddjlbb¬l²²¬ª´ÿ8€‹÷$÷0÷$‹÷$÷xø´jªddjlbb¬l²²¬ª´ûÀ´jªddjlbb¬l²²¬ª´ÿ2€¬øî¬‹÷ ÷}÷ ø™÷Óë‹÷…û€û‹û„*+‹û÷€÷€Œ÷|îû€û¾k‹s˜w r¤{›‹÷‹Ñ‹Ë“¿™îÓ’¡‹«‹É|™7”X‹:‹N‹û€|}mmwwps‹ÿ2€‹¶øŽ¶·Ÿ÷'÷÷îù¨‰‹kAKû‹u‹x`ž®‹À‘³˜ü¡û`µô‹º‹º‹õ‹µ‰¶ûÿ2€‹÷ ÷Ë÷¾¶‹÷÷P÷ø÷kaˆv„P|ƒ„=‹|‹û/±«æ×š–÷ÞϾ‹ë÷ Òûû*K,V¶|¢ª¯ ¹‹µl l³¹À ‹ç·@C=VCb`ûmûw‚‹‰‹yzø8ÿ2€³²÷÷®ß÷µ¯ª÷÷M÷!÷™÷ß÷‹#[^‹!ûvIŽ­[¶”šª‹©´n¨banna/ïU÷÷9Úæï‹¼rêû/¦ã¦ÈÉ‹ÚÖCÊûû9P:Y²{¥¨®ž¹‹¢­\’µ´Ï‹‘‹ä‹Fmm‡]kbqiq‰e‰ŠwЇ‰…ˆ‹„‹‡z‘‹Ÿÿµ€û úTŸ‹çø ûƒ‹‹xû÷`÷D‹÷D‹÷Y¼÷6÷÷——ŒŒ‹—‹†‚‹‰‹qvû$ûGûL‹ûH‹ûLÐûG÷"û¥u‹•‹—‹—ÿ2€‹¶÷¶øJŸ÷¹÷øE÷1ì¶*øA¤Šry‹‰‹|ûìüO`÷°ûû`¨î‹¯‹­‹î‹¦‰¶*ûøoûÒû‹ÿµ€û úTŸ÷Bç÷Ü÷‹÷LF÷Gû"÷q¡‰‹‹†‹‡‹‰žy÷û¶ûD‹ûD‹ûYZû6ûûŠŠ‹‡—‹”‹‹¥ ÷$÷Ï÷L‹÷Hÿ2€³Ò÷÷-¬ð÷—Ÿ¿¹÷o÷÷.ø›­ƒ¦‹š‹£‹Ä‹Î´ªž¿¸‹¢‹—Š‹‰‹†]{Z€S‹R‹[–\œ„ˆˆ‹‹zû·x‹€Ÿ•‹Œ“•—™¯·à‹ç‹-> endobj 34 0 obj <>stream IBSXWJ+CMSS12 øøøMûúfùŠ®"÷Ó÷h÷1FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMSS12Computer Modern5LAyncMBzodNCpefPErgFshGtiSHuvkUwlaVxmb-.>:0&=2()<* , -"ZOD.#[PE/$QFG1&SH'TI(UJ4)VWL6XMB7YNC{ ` m  6+f¶ï;–õ/yÌ W®P’Ñû³äT‘í-QÍú3n Ü D ] Ê  @ — ð   t ” ¸ ý R ” × þæsÿFbpÿí‹ÉøøŸ‹á÷DùJ5ýJø!Ë3‰4‹3‹[ÿ†û‹ ÷JÃø3Ÿ‹øäøùJ3ûýJÕÔ÷_÷®Õû_äûÄù÷ ûÿûƒÿ¿è°û`ÅøÎŸøEøP@]û >ûX‡CІÆV÷ƒŸD÷C<÷NüPh0uY|†y‹}‹kŽl—‘J‘Ь„«‹£‹º‹¶÷ÿöN‹ ø Ç‹×÷W×ø<÷ÁÈ~çû S‹[re[ÏDüU×÷É¢Þ×èŽJhûº×ÿ³-ÀÉ÷íɋ׸%÷]fXxS‹8UÕìÞ³æïΧ{n¶—ÌQ­j“P‹û=ûûûç"÷ ¼Ã—³Â‹ŽˆªŠÿQ†°‹ ù!Ÿ‹ØøØ÷eùJûýJØøýŒ™G÷6ü@±'Ô¬á÷9øHÖŒüþØùJûsHrMJûGWû d"]Šˆœ~°~²yÁ‹{´ÿ‰à‹Ã÷§Ç÷‹Ã‹Ü÷êÚèùJýJ÷–÷!òåíã4Ò$›÷ «¸Î‹Åå%ßû!û*ûÃ÷‹÷öáVIE5Q!ûûã÷§÷÷ÛCEE:Lûÿ¨Ã‹È÷ØÆ‹øøø)²ûñP÷—‹—Œ—‹×û™ûîcøÈû#‹Š‹6ÿé“pÉ÷ïÇ‹×÷©×ø_÷p÷(óûû *!ûûï(÷÷ ìð÷ûjû<CHÇ÷ ÷ Ö»ÊÐÑWû ûDTHÿöNÇ÷ìÇ÷pŸ‹×÷‚Õø;ùJAû¸]±W™`‹,=%ûûÕ$ê°Ã—¼½X×?÷ s`hr_‹NCº÷÷à³Å²«wj¡ÿ®UP‹ ù!Ÿ‹Ø÷ñØ÷jùJûýJØùŒ”w¿ûŸc÷qüX÷ùJ>ýŠ‚ŸW÷w³ÿq’@vÉøøÉ‹áøÉù<H¥V”P‹ûOûû@ûXûU÷ûC÷SÙ³–¸Ò…ÐL\d{;‹û(3÷+÷/÷;î÷÷¯É‡YÏÿöNûV ÷7Ç÷êÉ‹×÷€×÷.¸­lµsÁ‹ëáì÷÷ K÷.bK~_WºAý×ø¦¢­±¡´‹ÕÇ@,'FCAox•™yr¡ˆ‹›ÿ³-ÀÇ÷CÁ÷ Ç‹Ö÷„Æø+÷u‹¶‡ÈkÀbÐE“n‹û1#ûûë$÷¹Â˜³Â‹ˆª‹ŠŒ‰¡‹PYP„m‹>‹IЉõ‘ÁœÎºÀÆ‹ª‹Ð}œ!ÿ+/`‹ øÅ÷\ÇÔÕ÷AøöÅû÷ ÏÄ—¬®‹ª€—†Í„j“f‹,GB*1BQÔüÕÿn­‹ ÷ Å÷·Ã‹ß÷ÎÚ÷ã÷µ÷êîóõ*ëûûˆýJá÷µ÷÷ñ÷ ÅE@†qtz|fiorbf‹E4Ô<öª‹ÙàÁÐV†®‹•‹¶‹Æ›Íd}`…n‹}‹c‹Z²öð½÷ ¢æü'™wÆ…Ä‹¬Ô±©¬¾“Fr‹RXZVWiû¿+ÇC³`mySvP‹Cjȼä¡ÔÉÿù`÷°÷/°‹ù!ù7÷Û™‹žz‹|üá}y‹yxœ‹šøáûT™‹žz‹|üá}y‹yxœ‹šÿé“p‹Ïø¶É÷ÓÛ¼ÊLøÏûF‹Š‹ ¥¦èçÌÅÕÌÊÉ‹ç÷>ñûû‹TDp.«c‹‰”¤ö°¼Õ‹áÃH5WvQHIÿ|Çàû úTŸ‹×÷žù‚û*ûeû_‹û7‹ûD¶ûX÷%ûÇd¯NÙh÷päè‹æ‹÷»ô÷$ÎÉÿ|Çàû úTŸ÷@×÷û÷*÷±÷_‹÷7‹÷D`÷Xû%÷O²gÈ=®û¦2•.‹0‹û»"û$HMÿ7V€ûV øtŸçÜ‹Ü÷Xøˆ::Ü:üù܃øJÿé“p÷Æ ø'Ÿ÷(Î÷¢øuîD—‚”‹Ž‹ž™œœ•ˆ—y•ûÈ÷È•Ž—‹•œ}œx‹†ˆƒ…'D“÷!¢y–|y{u“û!(Ò”‚‹ˆ‹x}zzŽ÷NûNyˆ‹z™zž•‹Ž“‘ïÒƒû!t€š›—¡Š”ÿ $‹ øÅ÷>ÜÔÕ÷YÕøSùK::܈û>AüPÕû£ø÷Åû ÷Ç«¦¡‹¡ƒ™Ïw“„l‹ARD*/BQÔüÕÿü`û óÜ‹Ü÷DŒÛ::¤rû³ÿ;,@‹ øÅ÷\ÇÔÕ÷YÕ÷Aø÷Åû÷ ÑÈ•¨¯‹©€˜†ÍŽl’h‹0CF&1BQÔüÕ÷£ø÷Åû÷ ÑÈ•¨¯‹©€˜†ÍŽl’h‹0CF&üªÕv ùJ û£š÷X ûa–Ç ×  7Ÿ Á‘ ו endstream endobj 339 0 obj 4424 endobj 32 0 obj <> endobj 31 0 obj <>stream JTQBNU+CMSS10 øøøNûŽú{ù‹®¶÷g÷D÷1FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMSS10Computer ModernnBodNCerFsGtia-+7O#PE/$FS'T(UJB @Ÿç@{É"L}óO³5ƒ»ÿMUPÿª ‹ ø È‹Ù÷ZÙøG÷¾Í|æû1‹ZG…ƒÒCüVÙ÷‰ͤÞ×ëŒDkû·Ùÿšª ‹Ã÷¦È÷‹Ã‹Þ÷ñÜìùJýJ÷œ÷$ôåíâ4Ò!œæ¢ÖÅ‹×ç Ýû"û.ûÃ÷‹÷÷ãVIODGûûûã÷¦÷%õíN;@3Qûøˆ€Ë÷ïÈ‹Ù÷¯Ùøi÷p÷'öû û*ûûûñ(÷ ÷ ïð÷ûpû;FCÃ÷ ÷ ×¼ÌÑÓWû û GPAÿª €È÷ìÈ÷oŸ‹Ù÷‰ÖøFùJ@ûºV·S–f‹(=#ûûØ%ê¬Æ”ÁÃWÙ=÷‹}Šykntwrƒq‹MBº÷÷á´Æ¸©tk¡ÿÄUP‹ ù!Ÿ‹Ù÷ûÙ÷pùJûýJÙùŒžbµ6‘€÷‰üz÷ùJ=ýŠx´aà…–ÿ~ã€uËøöË‹äøÕù=L£U–I‹ûTûûAûXûU÷ûD÷WÞ²˜¶Ò…ÐCX^F‹û+2÷,÷-÷7í÷"÷Ú»rpµÿ¼qÀ€È÷=Â÷È‹Ö÷‹Äø2÷o‹­ŠÖdÇbÉN–g‹û1!ûûë"÷ ÊÄ£§²…ÌLWI‡t‹;‹KÒˆí›×À½Ä‹¿‹Ãi˜/ÿUª ‹ ø2Ÿ‹Ö÷1÷j‹ïÓÓíÎ2ŠTZl]æEüVÖÿ9qÀ‹ ÷ºÈ÷ŽÏ‹äøy÷ÏÈûÂ÷÷—‹—Š—‹÷DÌüDýGä÷ÏÿUP€Ê÷òÆÒ÷MÒ÷ëøAW£b“X‹rû!‹ûZ¨k¤xªu¡‡Â€¯„Å‹VF<‹|:‹S°y—G«{ÂoÜ‹‹Â‹¶«ª£œ³‹¶‹Âf­‰Žd®p‘Y”T–]•‹¼ÉÓ‹˜«‹À‡Äiÿšª uË÷XÈ÷õË‹äøÙøë÷¿ûfN÷ûDSz[ˆr‹û'÷÷:÷:ï÷÷ËÅ|XÉšÜU¤Y£-‹ûPûû>û[û`÷#û9÷IíÚ­šªÿip€Ë÷áÅöŸßÓ÷Cø÷!Åû!÷Fû4QßûŸO™EÐÑ‹¾¤¤˜{Æqvkk‹f}©Àÿî》 ø'Ÿ÷'ä’Ö÷7ù<22ä„û'@üPÖÿàŽ0€È÷$À÷/Æ‹Ó÷aÙø#÷µñBÑ/J‹^{\p‘I¿°½˜¼‹º³cA`û*‰ûa‹3`¦:♋éŸgÖ=÷‹x‹rixnyeŠ€‹[^¢µÑ÷6’¶ÿMUP÷UÅ‹÷÷¨÷UÅûQÿ Ç8 ÷¸³÷¹Ÿ÷ͳø-÷z÷«™ž‹ŸŸx‹}û«÷¬™‹žww‹x}û¬û¬}x‹wwž‹™÷¬û¬}‹xŸŸ‹ž™øˆ€ øÓÒ÷ß÷|øÝ—‹—Œ—‹÷ û(û72û\‹û~ß‹÷À÷#÷jÙãÌü3Du¡ùJ¡û¤œ÷W¡ûb—È Ù  7Ÿ ÈŽ Ù– endstream endobj 340 0 obj 1500 endobj 103 0 obj <> endobj 102 0 obj <>stream GIEKRI+CMEX10!øøøsôp®ù˜¦ùš÷ˆ÷}÷vFL[hv†šCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMEX10Computer ModernparenleftbiggparenrightbiggsummationdisplayradicalbigradicalBigXpqŠ‹ŒŽø€ÁÿMUPÿàpöÉ  6Ÿ‹ÞùPöÓ‹‰‰Žf°HÎH÷û5÷–B÷Ù‹ø‹÷¡¯÷ï÷9÷¾Ú÷"ÝÝ··ŽŽ‹‹Ž•„‹}}‹‰‹||ûãûÅ"ü^‹ü9‹üåü ÷’û¿Ÿt±b´g—‹™‹™’‹•ÿàpöÉ  6Ÿø-Þø£ûx‹ø1ø û’÷¿w¢e´b¯—‰‹}‹‚‹‡‡‰®gÎHÎû÷5û–ÔûÙ‹ü‹û¡gûïû9û¾<û"88aa‰ˆ‰ˆ‹ˆ”‹—™‹‹šš÷ã÷Åôø^‹ø9ÿ¤qÀúˆâñ»òúˆ÷ ÷Ôrd#!Gûmv†)qûT‹üïø‘øé’“Ž‹‹‹Ž„•üfùø¸÷‹æ}”‰ÁƒâzÚY¤{Ï^­:¤û ÷­ûbt‹ŠŠˆ…Šˆ‹x‹€ø¥ýhüšü󋆋Ѐ”‹ú|ûx ‡Ÿø<ûxª‹ŒŒ•žø·v’˜‹‹Ž–ƒ”~‹‡‚†€ü˜þÈûiø„û š{ÒÁú|ù  ߟødù¶ûkù‚ûû7›|ÏÛ÷zý¶¬‹Œ‹“£ø¹Èš‹‹Œ–ƒ”|‹‡~‡~wŸûyŸº º  yo ³’ ³’ endstream endobj 341 0 obj 804 endobj 88 0 obj <> endobj 87 0 obj <>stream ZNHEGC+CMR10~58!øøøûûŽú…ú]®*÷Ÿ÷X÷3FKZCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR10Computer Modern#yncModpeOfrgFshRtiHuTvwlaxmb].;4[, ZOD.PEQF0GSH'TI3UJ)V5WXMBYNC><  $Ÿ+Œ%‰VÀ1Š>ÄƒÌ ' à $ ™  È  ¡ c(±ÑòO­ÍÓÿMUPÿÇûa¡ßøuª‹ßø3÷ä¥Ê¾Œ›‹ªt‰nŠt‹y‹\uŒlªŠ›z‹r‹Š‰†&ûŠû÷¡‡•‰‹¥°‹žªqŠI‰z‹p‹cŒml»‹ž‹™h÷*ü†~}j…~uToFK‹†‹t‹xª“¡‹›¥x›twu~m^µg½Ê‹´Ä£Äÿ+Ž0‹ªøµu¡ÙÊLÐ÷eЬ÷÷ìû ^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªW‹r‹Š©÷S‹á‹ªl¯}œjŸQ‹B‹\`oMÔôû!€lÑ“„Zÿ¼qÀ€¤÷¬ç°¤‹Þ÷Wç÷ûøbˆ…m‹~qw§¥Ÿœ©Ï?²>û/ûûûî(÷÷«÷ ••‹ˆ‚‹‰‡‰…n.Jf‹V3¶÷5÷7ݵÀ”ÊŠg®ÿ”ª ‹ªùªò§ø£Ü÷…ù)‚¡ˆ‹t‹û=l£Ø€güˆp‹\$l®Œ¼¬‹¬‹¼‰®Šª$‹º¦ø¯Œ÷…ý~‚•‹–‹Ž“–÷Šù ŒüÒg‰€>sl°ŽÏ‹²‹²‹Î‹°ˆªs>‰–¯ø£¯–Ø£ªû=q‹‹Š„yûoüÇøˆ€¤ø0¡‹Þ÷©Þøk÷j÷'õû û*ûûûó+÷ ÷ ðí÷ûqû\`‹_ p¹r·‹È‹¯‹²‹Á£·¦¹º ³‹·‹¶u¥`¥`‹Q‹e‹g‹Uu_u^_nY‹ÿ+Ž0€¡uµø¡÷fµ‹Þ÷žÍ|øÂI÷'–ªEƒ’¼øóû$€lÑ“„Zûl¼¯n`¥Uû ")ûûí(÷˸­«¤÷ ûa‹y‹‰€zm[^u`‹^‹g¥s±q´ˆÄ‹´‹°Ç¨¸ ª±¬Á‹®‹µ|ª^–z‹‰‹yÿ+Ž0ûVª÷,¡øµr¤ÙÐ÷›ÞÜ÷C÷娾¼¨¾‹ÔÈ3ûû E7AceŸ´p} ‹Œ‹ŸT{µU׋÷ óí÷÷*îû=a_uwìÍû$€lÒ’…_üh^€‹Hl­Œ¿¥‹¦‹¾‰®ŠªH€‹¸÷<ÿ¼qÀ€¤÷m ÷B¡‹Þ÷‚Íø÷{¡Ž‹ îUìûû/$ûûô*÷÷¸÷ž•ƒ†‚‰…ƒ‰h$1‹‹Y‹c©t°m»‹Í‹¯Œ ‘÷)ߤ­‹ò•ûdÿ Çu¥ù8¤‹òø_òùe÷ç÷`û+÷6ûJûGû-û4ûbûa÷.û0÷F÷J÷+÷3÷^ûàûã+ûã÷™÷—÷&ÏÞâ÷#Dû”ûû7/ÿ1Ž0‹ªøª÷4ß“¡ÚÍçâ÷Fø$÷ªû ÷ã»»·Ž‹š‹š„‡y~‹rt›w¦¨šŸ£°f¬VE6V!û_¡e¤v~|yj‹hù‹l˜eªwOzk`‹cCîT÷÷ ó¾Ù‹®}¾X§V§Q‹N‹r‹`‹„Œkvª‹«‹‹¢œŸ÷ûÿ&F¾À¹±°·ŽÆá÷‹5UDY)ÿŒÇ‹ª÷ºª÷¹­òä÷T¤÷#¤øÚù<ü¹l£Ø€gü g‰€>sl®ŽÙ‹²‹´‹æ‹¯ˆªj,‹˜®÷Šáë•k6¤÷r7j+5÷‘¬’º÷ ÷*‹¤S›û¤ÿŠqÀ€¡ø6ž‹¢t»÷{¢t»ä÷d÷V¡‡Ý{‹CXhc=7‹gÄxàˆ˜Š‹~‹„yûz‹„–‹ŒŒžž‹ž·a¸Š ‹÷¹ÎÓÀm©—j«d“a“ØS–H˜Å®¥´á÷‹1lŒ‚”‹‹˜‹žðœ‹’€†‹‰‹~ˆ‡‚‡ˆe§b‹|‹ûeHSh›o¦u«q§…Ó}ÿ+Ž0‹ªø¡÷fµÙÐ÷eÐø]÷‹á‹ªl¯}œjŸQ‹7‹_O{gŠ÷ðû$€lÑ“„Züœ^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªW‹r‹Š©ÿàpu¡‹ª÷À¡÷¿ªòá÷Š÷?òë¥z÷t÷õ÷—‹¢‹—¡Ž•¨‹Ÿ‹å÷‡û%Fs:û(ï~ì£ÙÈ‹Ùëûßû'ûÎl£Ø€gü£g‰€>sl¯ŽÒ‹²‹²‹Ò‹¯ˆªs>‰–¯÷‘½÷›‹µ‹®i±g‹l‹H‹J‹c´e´gÂ…©‹ٜݧ‘‹–~€‹‚„Š…Dhyr‹Z‹ƒ¾}è~ÛyËZ¬Tžÿ„ ¤÷'Ÿ÷oª÷8ŸàÐ÷¤÷Aø$÷#ªû#÷LrŠ9m )‡uàû¨ûè¯Ò§ÒËÄrTAmefH‹æœÿÇ‹ªøµ÷ õµõEÍè÷EøNû €lÌ”…Zû¡^€‹Hl«ŒÁ£‹®‹®‰­ŠªI‡²ðø±«r olupqp¡qª§¤ «ù‚‹ª÷ɪ÷­ªòä÷¿äøùøñ¯–Ø£ªhˆA‹e‹e‹@‹hŽl£Ø€gû~û¿÷~¯–Ø£ªhˆA‹e‹e‹@‹hŽl£Ø€gü£g‰€>sl®ŽÕ‹±‹±‹Ö‹®ˆªs>‰–¯÷š÷¿ûšg‰€>sl®ŽÕ‹±‹±‹Ö‹®ˆªs>‰–¯ÿ+Ž0€¡uµøµÙÐ÷eÐxøÚ1÷$–ªEƒ’¼¸÷÷û'€lÑ“„ZûF4[GB7‡º¿÷àû'€lÙ‹ˆ2û*=‹0÷,Ë·§¨ÉÿÒ8à‹ªø9 ÷A°‹¤÷“ä÷“¤ù.ù9ü÷xûu¤™÷5š¬÷+‹‹¥‹•‰ ‡‹€‹tü£i‹}"cl´Žñ‹¹‹¹‹ò‹´ˆªc"‹™­ø£‹Ÿ‹™–¦‹ž‹÷+‹šj™û5¤ÿÇ€ øª‹ø}ø4÷ᔢœ¶ÍŒªt‰nŠt‹s‹]zŒl°Š–t‹x‹‚‰‡‡€%û“û÷«…˜‹‹¥²‹ªmŠS‰t‹p‹cŒmlÊ‹…˜l÷$û÷‘}†˜‹˜‹”•ÿÒ8à€ øª‹ùAøÿ÷佪˜®Œªu‰nŠu‹n‹^xŒl¯Š¡y‹n‹…‹‰†~0û”(÷«‡—Š‹¦²‹ŸªnŠX‰s‹m‹nŒml°‹›‰•~…–m’x5û†,÷Ÿ†—‹‹¦²‹ŸªmŠS‰t‹‡‹VŒgl½‹—ˆ—k÷ûö}Žƒ˜‹˜‹‘™ð÷¯ñû°€Žƒ˜‹˜‹Ž”•ÿÇ‹ªùµÙÍ÷EùJû$€lÑ“„Züœ^€‹Hl¬ŒÀ¤‹¤‹¼‰°ŠªH€‹¸øˆ€¡zª÷k ¦å»¡‹Ø[ç÷7ÐÔ¤{€÷á×c¦aº‹ È™ÜÃrSQr…€j‡¸÷\‹µ‹²g°d²Y›[‹9F\ImŸz¥§Ÿ¥—†¬]Œ¦®¼–«‹¼Äd2f½€XˆEˆLm@irW‹_:ìrÊÍ‹¹³žº„÷8',Ci^Zb®½‹ÂµÞ÷9‘ÿÇ‹ªøª‹øŒ÷³÷©±±¼£¥ª¯´šºŒªq‰mŠq‹m‹V~Œl ‰“~‹{‹{~†…M==ð‚•‹‹‘‹šš”ŸŒªqŠI‰{‹v‹\ŒplÑ‹ŒŠºOîû\O‹‰\R[QP‰v‹l¥ªŒ¥‹¨‹µ‰£ŠªuŽ„˜‹š‹¡¨¬ÈÓ¨d“€²Y“€˜{‹…‹‚‚|pŠl©ŒÃ¡‹¦‹²Š©‰ªU‹yt¨ÿAUP‹ªøµu¡ÙÊLÐ÷eÐ÷eЮ÷÷ìû ^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªH€‹¸÷LóÒÃËÊ–URû}^€‹Hl®Œ¾¦‹¥‹¿‰­ŠªW‹r‹Š©÷S‹á‹ªl¯}œjŸQ‹7‹_Oze}âA–^‹B‹\`oMÖôû!€lÑ“„Zÿ+Ž0€¡€Ÿø$¡÷fµÙÍ÷žÞ¼÷@ø ÷Ñû$€lÑ“„Zü褌Œ“™¦º|tšµYÕ÷ óí÷÷)îû=`\y{Žû›÷b‹ž‹Œ–›²Ã“£‹¸‹¯q£e¥bŽR‹b‹f‰On^vlejU‹^‹g£s°} ‹Ž‹ÿÇû޳ú,³ì³÷3ù‚ûcìþ,*c÷ÿÇ‹õ‹õ÷TÀ¨s£nnssnn£s¨¨££¨ÿÇûU ÷@õ÷oõ‹õ÷Tø¨s£nnssnn£s¨¨££¨xü‹o‹=KA„ƒ‹‰‹ˆ„‡–ÓÛ÷¨‰ÕUhypqqœp¯‹‹ŒŒ’Œ–“’øˆ‹ª÷ªøaŸ÷žØDÒð§÷9÷ž4g‰€Avl´Ž¿‹µ‹µ‹À‹´ˆªvA‰–¯âïèª'ø[Ÿ‹‘{‚‹ˆ‹ƒûÇüi÷¤ûˆ÷ˆø ÿÇû޳ú,³‹³÷“û޳*ú,ì³ûþ|ÿÇûU ÷@õê¡÷G›ŒŒŠ}KoN_\……ŠŠ‹‡„‡—ÚÚ÷Ës´chypqqœp¯›‹—‘•“ÿGUP‹ªøª÷¡ÚÍ÷fÍèâøTø$÷ªû ÷仺¸Ž‹š‹š„‡y~‹rt›w¦¨šŸ£¯h­SP‹_e†‡n°Sp‹,ûWûû> endobj 84 0 obj <>stream  WDSZIK+CMR7øøøpûŽúöù‚®øž÷8÷1÷,FJYCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR7Computer Modern123UÄZÿ€ëÀÿ9qÀ‹¯ø¤¯·Ÿ÷%Ü÷ãù¦‰ŒoKL0Šb‹g£‹Í‹Â§ü’j‹~'egŒ÷ް‹ª‹÷ˆ¡Š¯e'‹˜¬ÿ9qÀ‹à÷ìõ诋õ÷ƒìø÷JiˆuP~ƒ…>‹}‹ûLôè®§ÇºÕÆÐÉ‹ê÷ !Õûû74/X¶†•£¨œ¯„®WªÒÏ¡º‹ï¿=:4MFkgû…û‚‚‹‰‹oø0ÿ9qÀw«Ñ÷÷!§÷ò¨ªò÷oö÷¥÷âÙÃU ûCfQc3–Æaº–¬‹ «s¢loozb-óN÷ ÷ëèï‹ÙKÙû¢ô±±Ö‹ÈÚ0Æûû6U;i¡x©ªŸ¢§‹¨w l®·Ð–°‹¸Êu4a}]qljeo‰Yˆr‰‰‹†Š‰ƒ‰€}”‹œwŸù?Ÿû¤š÷n•ûa–¯ Ú  7Ÿ §“ Ú› endstream endobj 343 0 obj 560 endobj 82 0 obj <> endobj 81 0 obj <>stream TTCVLS+CMSY10øøønþTúðù›¤ùÍ÷f÷Y÷QFL[fmyCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMSY10Computer Modernapproxequalradicalasteriskmathptœ¦Š‹Œ'†®O·UøˆÃ ÷øøO÷Žö3â"û62" ã4ô÷àäôÿ Ç‹³÷¥³÷¹Ÿ÷ͳø-÷Í÷«™ž‹ŸŸx‹}û«÷©š‹ ww‹y}û­û¬}x‹wwž‹™÷¬û¥û¬}x‹wwž‹™øë™ž‹ŸŸx‹}û«ÿ Ç÷z³‹ø÷ù)÷z™ž‹ŸŸx‹}üµ}x‹wwž‹™ÿ ÇÃÃÝòÃÝËù-ùeøX „”„‹ˆzЇGEaK‹O‹^©G¸`§V®K‹/AE.u’ƒ’–ŽßÞ©½‹Ç‹¸mÏ^¶oÀhË‹çÕÑèû~ „•„€‹‰zŠ|†RM[D‹O‹^©G¸`§V®K‹/AE.u’ƒ’–ŽßÞ©½‹Ç‹¸mÏ^¶oÀhË‹éÓÔäÿAUPþT úSŸ‹ù øýëûFø‡“‰‘„‹ˆ‹‰‹‚ƒ(@€‚ŠŠ‹‡„‡‘Ž‹‹”“¿²÷ZüG‘}Š–‹›‹’šø\úD–ŒŒ‹–ƒ”‹ˆ„…øˆ­ øŸ÷0½÷™÷y¯q¯p°q—‚~’‹˜™—›“‡•}’û%Ï÷"Ï”—‘‹››}—~‡‹†Š€ƒû.™÷4Œ˜Š¢r‹{‹~~Ž~€™û3ûç~”‹Œ„‹~}{{—…”‡÷!Hû!G‚‡…‹{{™˜‹Œ–“÷è}û8†ˆ|™™‹¦‹‹¢Š™u¡ù?¡û³ à  7Ÿ ³š endstream endobj 344 0 obj 853 endobj 79 0 obj <> endobj 78 0 obj <>stream  QJNQOA+CMR8 øøøgûŽúÂù‚®l÷Z÷=÷-FJYCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR8Computer Modernnehtixm01=2345OFIUJYN€åb¨þÄwöB‡ü„Ü„ÿb* ÿNH°‹¬ø§××÷m×øz÷ÃßeÁ"(‹^CsŠëû%€jÏ“„Zû›^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸÷IôÛ¼ÈÈš`Lûy^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸ÿØ8àª÷c¥÷8§‹ä÷’Ïø1÷x¡‘‹¢äZõû!û*$ûû÷'÷÷½ö¢ˆ•~€‰„…‰g*5ˆy‹^‹] m¹m¹‹Ë‹©Œ¥”÷ ࣰ‹÷ ‹û!ŒtÿNH°‹¬ø§÷e·××÷m×øz÷ÃßeÁ"3‹]SykŠ÷éû)€jÏ“„Zü˜^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸÷IôÛ¼ÈÈš`Lûy^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸ÿ30ªø ¬÷8Ÿå×÷ª÷Nø"÷)¬û)÷LlŠ0b,.ˆoåû¥û åy¹Î³ÇÖÃlUFlfeH‹á›ÿ'$‹¬ø·÷ ÷×Ô÷Wøü¨t¦jnqtkh¨v¥® ¨¥û*ûNjË”…Zûœ^‹Kj²ŽÃ‹š‹˜‹Ç‹®ˆ¬J‡²øÿ0Å‹¬ø¬÷È÷~§®¨­©¬¬®®¥ÊŒ¬dˆ‰‹^‹†‹P‹lŽjž‰‹~‹~†}LA<陋’‹‹’‘š¤Œ¬cˆS‹€‹y‹X‹mŽjÏ‹ŒŠ¿N­a®b­amgmglhrofb?‰j°Ž’‹µ‹‹È‹«ˆ¬~€’‹‹—™Ž¤©¦©¥¨¦j§k¦jŸt‹‰‹„‹ƒ„}sŠj¶Ž¸‹ž‹‹¾‹©ˆ¬M‹qªÿum@‹¬ø§××÷n×÷n×ù¡÷ÃÜhÄû/‹]L{nyÓRŸJ‹*‹]F~pŠëû%€jÏ“„Zû›^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸÷IôÚ¼ÊÌ–XTûy^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸÷IôÚ¼ÊÌ–XTûy^‹Kj¶Ž·‹¦‹¨‹µ‹¶ˆ¬K‹¸ÿ@v§ù §‹ä÷¢äø}÷Ó‹ö€ÌjË_ã:¡T‹û‹]-}ogB‰(‹W‹IŽ&»;¹AÕxÀ‹»‹áš½î°ÓŽä‹ÌûtûÌi‹F›vô€Ä‹é‹¿‹Ð‹Ñ– ñÙ•¤‹­‹ÐzŸ0—T‹@‹G‹P‹1Sv"F}j‹ÿ@‹¬ø«¬·Ÿ÷Ú÷Îù¦‰ŒpbcVs,‹j¦‹Á‹Å¦ü•fˆ,hj´Žá‹¸‹¸‹â‹´ˆ¬h,ˆ—°ÿ:f`÷ ¹÷:¹‹ùWùo÷᚟‹¢¢s‹|ý |s‹ttŸ‹šù ûh𣋢¢w‹|ý|w‹tt£‹šÿ@‹Ý÷ïôí¬‹ô÷tê÷®÷`›šµ¬›™ÉÄÆÂ‹æ÷ 'Øûû <02Z²„™ ªš±¿Y‹¨ÔΤ¼‹è»<7#B?û û ûû€‹‰‹rø¨÷GlˆwƒYx…ƒ?‹{‹ûFÿ@v©Ô÷÷±òÅ¥©ñ÷bó÷‘÷âÚ½Q"ûDfVT@ŸÀh¯¤¢¬«t¢kpozc,ñM÷÷èçïÞI×%¡Ú§ÆÏ‹ÛÛ1Ä# :Q?f¤{¥ªŸ¡¨‹°k™uŒµÂØŽ‹¥×ƒ$Ena}{mlt‰N‡xŠƒŠ‹~}”‹œÿ@‹¬÷¬ø^Ÿ÷µÖøùŸ‹“v~‹ŠŠ}ûÓücj÷®8fˆ€>tjàŽ‹Ä‹Ä‹‹àˆ¬t>ˆ–°Þõ¬!@øüû’ÿ@v©ôî÷F§÷à—ŸÁ¬÷‰ç÷ øÆ˜‡³µ‹÷×ãš–„ކ‰‰‹†‚d|]U‹P‹Zšl—‰‹Š‹~‹€yû¹y‹›“‹Ž“—š±¾à‹Ã‹¦]”xœg]‹d‹fŠUo_xmclV‹J‹K´tÌŽŠ‘‹Œ‹§¡ª°n˜wyk`1Ù0÷÷õì÷÷7òû Y\{iev ù? û¥š÷o•ûa–¬ ×  7Ÿ § ×› endstream endobj 345 0 obj 1938 endobj 170 0 obj <> endobj 169 0 obj <>stream JKTGVZ+CMTT12~aa øøøŠû~ø ùK©(÷R÷?÷4FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTT12Computer Modern AMNCDFRGI"./$%'3(* |œfÙ€ Rÿ•ÿ•‹Å÷Åø Ÿ‹ø`÷Èøáƒ¯w‹t‹l‹‡„kûü§jt‹nn¦‹™ë™¦‹¨¨s‹l¥÷÷6¥ûls‹nn¦‹™ë™¦‹¨¨t‹jû†÷>’©Â÷€»ŒŽt™N‹Š¾ûyÿ•‹ÅøƒÅ¾Ã÷žÃ÷¸ø~b{[…jŠƒ½4÷š‰€¢w‹z‹V}p‹nn¤‹¥üƒqr‹nn¦‹™×™¦‹¨¨r‹qøwŒ‘lŽ€—gÒûsƒ”o¨‹—‹œ““šæ÷¬‹™üuqr‹nn¦‹™×™¦‹¨¨r‹qøƒ¥¤‹¨¨p‹}Vd‹…ƒqÿ•‹ÅøƒÅÉÃ÷pÃ÷OøÕ­w‹v‹J|r‹nn¥‹™¡üƒu}q‹nn¤‹šï™¦‹¨¨p‹}uøxŒŽ€”qX÷)ü8—iŸ‹¡‹©—ޱø”¡™¥‹¨¨r‹|'}p‹nn¦‹™¡üxŠˆ–‚¥y¾ÿ•Åø›Å‹Ì÷ÁÏønøÝ›‹¡oy‹†€‡„ˆƒƒyˆ„b¯]ša‹û ûûGûK÷û÷÷ Üèãªv‹}{†z‰ƒû&„z‹.6÷÷+÷+á÷æÁÆ`/™Žu”…Ÿ‹¬‹Ÿÿ•‹ÅøƒÅÇÌ÷œÌÉø÷}q‹nn¥‹™Ÿüƒw}q‹nn¥‹™÷[÷á÷"÷2÷48÷+ûûü½øƒê÷Àûûû Pûûÿ•‹Å÷oÅ÷nÅÒÌ÷̺Ì÷;÷©÷h‹x¬«‹¢ß‹¢kj‹xhû÷n÷ŒZy‹t«¬‹¡žÍª…•iü}p‹nn¦‹™©üƒm}p‹nn¦‹™÷#™¥‹¨¨q‹}[ÿ•Å]Å÷oÅ÷nÅÉÌ÷KÌ»Ì~÷è÷Ä«©Á‹ÁÞBßû û>|r‹nn¥‹™¡üƒu}q‹nn¤‹š÷™¦‹¨¨p‹}u÷oºÚ‹ª‹«o¢v‹t‹`‹E‹nži›q¥|ª‹͟ЯŸ‚˜sm‰s‚„ˆcyp‹·ÄÏ‹‘¤~¨sŸ”ûªB÷nÔç·OZZ_O/ÿ•Å÷:Å÷»Å‹Ì÷¥ÌøL÷hŸ¥‹¨¨p‹}û}p‹nn¦‹™´†Np"9‹:>÷÷*÷.ÛõÚ»Àe'˜Žrž‹•‹¬‹Ÿ÷%›‹¡oz‹…€ˆ†~kj©c_‹û &ûûJûMñû÷ ¶µ°­q‹x¬«‹ žÿ•‹ÅøƒÅ÷"Ì÷¶ø½ñ™¥‹¨¨q‹}û¡}q‹nn¥‹™ñüƒ%}q‹nn¥‹™÷¡™¥‹¨¨q‹}%—ø÷—ûT”ûy’Å Ì  yo Å Ì endstream endobj 346 0 obj 1353 endobj 167 0 obj <> endobj 166 0 obj <>stream KCSKLK+CMTT10øøø‡ûùoù´©ø›÷<÷5÷0FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTT10Computer ModernNCF/$'uãSø¡ø¡‹Èø}ÈÌÃ÷vÃ÷RøÓ¬|Žp‹G|r‹ml£‹›¤ü}r|r‹ml£‹›õ𤋩ªs‹{røoŒ÷Lüˆ˜h›Š¥‹©—ޱø‘¤𤋩ªs‹{!{s‹lm¤‹š¤üoŠø¡€Èø“È‹Ð÷ÏÇøxøÙ›‹¤my‹††„‰‡‹‰~rj§]ŸX‹ûûûûJûK÷û÷÷áäå¬s‹€‚t‹n‰„):sb‹05õ÷*÷)âõäÇÂ]:™Žz{©‹®‹ Ÿø¡‹È÷jÈ÷jÈÕÐ÷иÐ÷?÷§÷b‹{®­‹¡žèž‹¡ih‹{bû÷j÷ŽVx‹u­®‹ ŸÔª…•iü{r‹lm¥‹š¬ü}j{r‹lm¥‹š÷.𤋩ªs‹{W€–ø÷–ûS”ûy’È Ð  yo È Ð endstream endobj 347 0 obj 552 endobj 128 0 obj <> endobj 127 0 obj <>stream  NJELXV+CMSY8 øøømþO¡ùŸ÷­÷>÷9÷5FKZ_Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMSY8Computer Modernprime0¦Š*iÿ:f`÷w¹‹ùùP÷w™¡‹¢¢u‹}üÓ}u‹tt¡‹™ÿ 1`´ øqŸ‹÷‡÷Ÿør–‹–©o£mc‹jˆûüFЉ‡}‹Š~ª‚’‘‹–s£ù? û“¹ ä ¹š endstream endobj 348 0 obj 302 endobj 121 0 obj <> endobj 120 0 obj <>stream QMQUZG+CMTI10"øøøû7ûŽzú]ªo÷]÷B÷3FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTI10Computer Modern ncoderstilaxmODPEFSTUJMBYNÀ#{7Ÿ"¡¹5É‹†ÿeÆ0ÿ27Ѐ¡ø-¡÷ÀÃÈ÷z÷C¡‘ ¡˜¾‹Œœ¨™£¸Ö׋·^vM_û }c~iˆ‚‹v_§g»è­÷)•ƒ‹„~‹‹‰‡|ƒpp)Q‹vŠš™¤•¥“£ŸÀ´÷‹ÅÝT¡Z9‹[O~x„¼i©`‹g‹wt{mxc~P‹‰•‹˜‹ŒŒ¡Ñž¼ª‹¥‹n€{ˆx‡{@ûÀ‰…І‹ˆ€“|Ÿ—‹œ’’žø`€¡÷±Ú¸¡‹Ñ÷aàøGø Y…‹b‹‰{–{¢¦£¡±¼`°Kûûû"û&(ÆIã÷Þ–ƒ‡‹ŠŠƒA-2‡z‹Ur¸ÅÀ¦ô¥»¯Ì½®¸‹–‹¸‰šbÿÿp€¡ø-¡‹Ñ÷—Ñø‘÷ªêPÐ4ûûû"û&$ÊMÞ÷÷÷"÷'û‘ûŸdfªÓ½¥÷«Á°È»©²‹¼§_P`u$kOnTX^Z‹ÿÿp€¡ø-¡÷fµ‹ÏøÁù1ŒŽ“‹”…Žƒˆ‹ŠˆŠ(ƒЀЋx€•‹™»„‹ˆˆ~‹ŠQû~|ªp¦a‹ûû û,û&6¹EÖ¯· ¼³–Z°v®‹°‹ ¤šª±—Å‹•ƒ‹„‹ŠŠ…u}SxLi‹q‹¦™’‹š‘£P£ƒlN;T‹\ƒÆ©½ª÷ µ¤È¹½´‹“‹¢Šo•{•n‹x‹ˆŠ‡‰…ø`€¡÷p¡÷;¡‹Ð÷†±÷ƒ÷{©‹ÎŽ»žÚ«‹Ì‹’¹f²K"û#&ûE1»6ê÷Þ–ƒ‡‹ŠŠƒA-2‡z‹J€Ò²±•¸’¦‘¡¶÷8òŽ•‹³¢pi!û9‹jÿ¥©p€ ÷ÐÚš¡÷Öß÷–÷´ŒŽ¸÷á‹‹§‹Ÿ}h€ˆk‹†~”x¥ª™²¿J–jF‹gY{u€Àdžj‹g‹wt{mxc~P‹‰•‹˜‹ŒŒ¡Ñž¼ª‹¥‹n€{ˆx‡{@ûÀ‰…І‹ˆ€“|Ÿ©‹’¨“ÿ˜âp€¡ÄÛ÷.Ͻ¡ÙÃ÷Äøøk‡ƒp‹€‘z£œ¥—¶¹b²Iû b+W‹>Ì}§…·¸‹Ukp;$u‹Q{¾¾‹µ‹ž~˜vtoz^NÅgÒ÷*±÷¹‹â=b”o‘g“‹¶£ ÏÛ¦‹°–dÿL7À€¡øª÷CŸ§Ç÷˜ø$àœ–‹ž—‚‹{;°÷(™‹‹ zr‹v‡|dû36z€‹x”‹›ÛCû³Š‡‡{‹}Y¬c¿ð¾÷)•ƒ‹„‹‹Šƒyy[c@R‹p‹¤›’‹›’§ÿ2ª €¡ø-¡÷ܸúÂaÝø÷ß÷#•ƒ‹„~‹‹‰‡|ƒnp+Q‹ƒ}Œ¦¥˜¬˜°¡Ä Ä Ä•¨“‹žÂe¤f-iû)†•‹˜‹Œ™”¬¥èÅ‹––†ts€n„x€l€nƒt~jjj}e‡€‹wd£b¿é¬÷*ô†øt¤w“}vpworŸƒ™Ÿ§ž¨ÿÿ0€¡ùµ‹Ç÷Ãù1ŒŽ“‹”…Žƒˆ‹ŠˆŠ(ƒЀЋx€•‹™»„‹ˆˆ~‹ŠûüˆЇ†w‹|V¯f»±‹Ÿ¦˜¤œ®™Ë‹Ž•ƒ‹„†‹…‹ˆ†„rzExao‹q‹¦™’‹š‘£ÿÿp€¡ø-¡‹Ïøwø ™‹‹ zk‹„iІx¶k›k‹ûû û,û&6¹EÖ¯· ¼³–Z°v®‹°‹ ¤šª±—Å‹•ƒ‹„‹ŠŠ…u}SxLi‹q‹¦™’‹›’§P ƒkM:T‹\ƒÆ©½ª÷ µ¤È¹½´‹·¤Wa‰Š†‰…ÿÏâp€¡›Ù÷qÛ™¡‹ß÷½ßønø*c‹f‹Š~”x¥ª™²¾Q—nT‹jZxuÇZ“r‹'Uût•‹˜‹Œ›¦á¿²³‹¨žtcsZ‚f€bЇ€]{Jv;O‹ˆ‹s‹z™©“”¤‹š¥v‘~rrvjdµt¹»‹¬±œ©ŸR¼€¥‹ò¾÷Ÿ•ƒ‹„ŠŠ{†p5Yda‹wp—¿£–¶“­–µšÉ“¬™¿¦Âº‹Ž‹¤‹›}ÿ1ÅЀ¡ø-¡øÀÃÈ÷z÷C¡‘ ¡˜¼‹— ¨½¶ÅЋ¹‹X|p„n‰‚Jû˜‰…І‹ˆ€“|Ÿ—‹œ’’ž³÷4¡‘ ¡˜¼‹— ¨½¶ÅЋ¹‹X|M_û }c~iˆ‚‹v_§g»è­÷)•ƒ‹„~‹‹‰‡|ƒpp)Q‹vŠš™¤•¥“£ŸÀ´÷‹ÅßQŸ\E‹Y_m_ƒÐWž^‹O‹Zji]„¼i©`‹g‹wt{mxc~P‹‰•‹˜‹ŒŒ¡Ñž¼ª‹¥‹n€{ˆx‡{@ûÀ‰…І‹ˆ€“|Ÿ—‹œ’’žu¡ù?¡û¦–÷sûa–ª Ï  7Ÿ ¡” endstream endobj 349 0 obj 2193 endobj 114 0 obj <> endobj 113 0 obj <>stream  TPCECS+CMMI8øøøsûŽúêù‚©ùF÷=÷6÷1FKZ\Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMMI8Computer ModernpiniOJŠÏhýÿMUPÿ„®€§ø§÷õÐÓ÷\÷8Žš•±Žš™Á‹Œ¢¬¬¼º·Î‹¯ v\TaûxZ~j‹…‹~Rºo¶í´÷ ˜•ƒŽ„‹‰„ˆs9ade‹{ƒ•¢¢“¡•¤š±·÷‹ÃÖW¯C:‹WZne„Â_«X‹g‹rt{ls\Y‹‰‚’‡“˜‹Œ’¥—¼Æµ‹¥‘ruy†xƒj‰ƒ|P‡}{I„q}Q‡|…r‹‡tžƒ˜‹š—’—Ž‘“­ ÿi½à§ø§÷çÅЬÑ÷¾ù¡{›tqnsmu›{¢¥¨£©û&üpI‹‰pE†|†‹zZ±gÀì´÷ ˜•ƒŽ„‹‰„ˆt;bbc‹¦£’˜ª•¦•¦–¦•¦–¦•¦”¢—ª‹œ½c®X*aû ~‚’‡“˜‹Œ‘Ž•§ê¹¦©‹™•†oŠ}mÿb"  ÷öÍ÷ßÂ÷°ø÷v0yA‹A‹„‹`–g˜a•ƒ‹¡¢ž£’Ї”v¹|»‹Ý‹¢‹µšÔ÷ ›‹–‹•“—–Ž˜‹‘§r‹zûýv‹e‹Z[ggo]‹„‚’ˆ“•‹Ž‘“¼ÓÆ‹¢‹Ån!Vû fB„|w‹‚vœ›±‹•± Ýv ù? û¥•––û`•« Ù  7Ÿ § endstream endobj 350 0 obj 723 endobj 283 0 obj <> endobj 282 0 obj <>stream GCKTKU+CMSS10~11bøøøNûŽú{ù‹®ù÷I÷<÷4FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMSS10Computer ModernodeulbPEFVMCO¨:S¥ÿMUPøˆ€Ë÷ïÈ‹Ù÷¯Ùøi÷p÷'öû û*ûûûñ(÷ ÷ ïð÷ûpû;FCÃ÷ ÷ ×¼ÌÑÓWû û GPAÿª €È÷ìÈ÷oŸ‹Ù÷‰ÖøFùJ@ûºV·S–f‹(=#ûûØ%ê¬Æ”ÁÃWÙ=÷‹}Šykntwrƒq‹MBº÷÷á´Æ¸©tk¡ÿ¼qÀ€È÷=Â÷È‹Ö÷‹Äø2÷o‹­ŠÖdÇbÉN–g‹û1!ûûë"÷ ÊÄ£§²…ÌLWI‡t‹;‹KÒˆí›×À½Ä‹¿‹Ãi˜/ÿª €ÂøŸ‹Ù÷ZÙøGøP=û¶@ShKD„¥¶÷ß=ûãC¢[ÞÀ‹Ò›¼¶[Öÿî》 ù!Ÿ‹Ö÷0ùJ@ýJÖÿª €È÷ìÈ÷oŸ‹Ö÷‰Ù÷1ùJ@ýJÙ¹£u¶h΋ïáï÷÷G÷-dMZOŽN›£¯®Â‹Æ×`ûû7`Ndj¹ru¡ùJ¡û¤œ÷W¡ûb—È Ù  7Ÿ ÈŽ Ù– endstream endobj 351 0 obj 658 endobj 280 0 obj <> endobj 279 0 obj <>stream HUIXAF+CMTT10~118øøø‡ûùoù´©ú¼÷O÷>÷4FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMTT10Computer Modernab/=23*+BC ‘û7xäw Wø¡ø¡…ÈTÈ÷1ÈïÈ‹Ð`ä÷MÐvø«¡l»Š±‹§¡‹ª©r‹|aŽƒ÷lÒUßû$`%‹Bm {£š‹§”Œ°‹“ŒŒŸ™Œ˜‹”‹׿lDºûEˆûY+FÊJñ°‹É’ºª€÷N7‹t‹vdygz^‹ƒ‹Mb­²¼á°÷%ø¡…ÈT ÷÷È÷ÈàÐ÷‘Ð|÷:ø÷Jª…•iB{r‹lm¥‹™¸ü‘w‹v®­‹Ÿ¤¼a´¶‚«÷ìê÷÷2í![^yliûYÔÆÅÀÊÕÅB4+EJE=hã»ø¡8 ùtŸ‹ø,ø^ù’›Œ‹‹“|œwu‹„|…~ûÞýF„{Š‹‹ƒyšzŸ¡‹’š‘˜ø¡÷WÑÝÑ‹øTøM÷ï—¬‹®®f‹}ûî}f‹hh¬‹—÷ôû,™°‹®®j‹ûúj‹hh°‹™ø¡‹ÈøˆÈ‹ä÷šÐÎÅ‚ƒ…†‹}l¤‹›÷笒”«¥ž‹¡ih‹xoû‚ƾëÖ¶³ÊùˋÛ÷ &Öûû <96f§€œ ¢œ§‹—†˜‚’š¹ºªÂ‹ÝØ]3EZQITø¡€È÷Ç÷^È‹äOä÷pÐcÐìø÷âï§Ä‹ÁÕBÎûû E[Fj¤}Ÿ ¢œ§‹™…•ˆŽªªÒ‹”‹Ͻg^m|hpukqr‰g‰R‡|‹‹nòl£‹›¹î¾HQNSL0c>–ºq’‘‹Ÿ£xŸrtu|k2ìQ÷÷àçè‹Ò\ÆI©ø¡å øŸ÷8ÇøCø—’˜’‹ž‹¨cûC¥ŒÍ‹¨”‹¬jj‹j‚‹nŒIqûÊ}”‰‹„‹w~y|x–…˜„÷PûP„~…‹w‡‹n³÷Ó‰qŠI‹n‚‹j¬¬‹¬”‹¨ŠÍ‰¥ÈifŸÑa¦{‹“‹Ÿ˜šœ”‰ŒrœG¬q™ø¡Ü ÷=Ñ÷>Ÿ÷QÑ÷½÷£÷"—®‹®®h‹û"÷#—‹®hh‹hû#û"h‹hh®‹—÷"û#‹h®®‹®—€–ø÷–ûS”ûy’È Ð  yo È Ð endstream endobj 352 0 obj 1097 endobj 201 0 obj <> endobj 200 0 obj <>stream SDKIIU+CMSS12~c9 øøøMûúfùŠ® þ÷‘÷T÷4FL[Copyright (C) 1997 American Mathematical Society. All Rights ReservedCMSS12Computer ModernyncMzodCpePErgFshtiSHuvUlaVxmbZOD.[PE$QF1&SH'TIUJ4)VW6MB7YNCWÜ7q»\³W–Àx©V–º6cœ×,™Òf¿ÿFbpÿ¿è°û`ÅøÎŸøEøP@]û >ûX‡CІÆV÷ƒŸD÷C<÷NüPh0uY|†y‹}‹kŽl—‘J‘Ь„«‹£‹º‹¶÷ÿöN‹ ø Ç‹×÷W×ø<÷ÁÈ~çû S‹[re[ÏDüU×÷É¢Þ×èŽJhûº×ÿ³-ÀÉ÷íɋ׸%÷]fXxS‹8UÕìÞ³æïΧ{n¶—ÌQ­j“P‹û=ûûûç"÷ ¼Ã—³Â‹ŽˆªŠÿQ†°‹ ù!Ÿ‹ØøØ÷eùJûýJØøýŒ™G÷6ü@±'Ô¬á÷9øHÖŒüþØùJûsHrMJûGWû d"]Šˆœ~°~²yÁ‹{´ÿ¨Ã‹È÷ØÆ‹øøø)²ûñP÷—‹—Œ—‹×û™ûîcøÈû#‹Š‹6ÿé“pÉ÷ïÇ‹×÷©×ø_÷p÷(óûû *!ûûï(÷÷ ìð÷ûjû<CHÇ÷ ÷ Ö»ÊÐÑWû ûDTHÿöNÇ÷ìÇ÷pŸ‹×÷‚Õø;ùJAû¸]±W™`‹,=%ûûÕ$ê°Ã—¼½X×?÷ s`hr_‹NCº÷÷à³Å²«wj¡ÿq’@vÉøøÉ‹áøÉù<H¥V”P‹ûOûû@ûXûU÷ûC÷SÙ³–¸Ò…ÐL\d{;‹û(3÷+÷/÷;î÷÷¯É‡YÏÿöNûV ÷7Ç÷êÉ‹×÷€×÷.¸­lµsÁ‹ëáì÷÷ K÷.bK~_WºAý×ø¦¢­±¡´‹ÕÇ@,'FCAox•™yr¡ˆ‹›ÿ³-ÀÇ÷CÁ÷ Ç‹Ö÷„Æø+÷u‹¶‡ÈkÀbÐE“n‹û1#ûûë$÷¹Â˜³Â‹ˆª‹ŠŒ‰¡‹PYP„m‹>‹IЉõ‘ÁœÎºÀÆ‹ª‹Ð}œ!ÿn­‹ ÷ Å÷·Ã‹ß÷ÎÚ÷ã÷µ÷êîóõ*ëûûˆýJá÷µ÷÷ñ÷ ÅE@> endobj 115 0 obj <> endobj 10 0 obj <> endobj 104 0 obj <> endobj 89 0 obj <> endobj 178 0 obj <> endobj 164 0 obj <> endobj 86 0 obj <> endobj 165 0 obj <> endobj 176 0 obj <> endobj 162 0 obj <> endobj 83 0 obj <> endobj 163 0 obj <> endobj 80 0 obj <> endobj 77 0 obj <> endobj 50 0 obj <> endobj 179 0 obj <> endobj 43 0 obj <> endobj 284 0 obj <> endobj 36 0 obj <> endobj 281 0 obj <> endobj 33 0 obj <> endobj 202 0 obj <> endobj 30 0 obj <> endobj 171 0 obj <> endobj 27 0 obj <> endobj 168 0 obj <> endobj 24 0 obj <> endobj 129 0 obj <> endobj 177 0 obj <> endobj 16 0 obj <> endobj 122 0 obj <> endobj 2 0 obj <>endobj xref 0 354 0000000000 65535 f 0000153095 00000 n 0000252858 00000 n 0000152567 00000 n 0000153143 00000 n 0000143557 00000 n 0000000015 00000 n 0000000383 00000 n 0000153536 00000 n 0000153198 00000 n 0000241814 00000 n 0000191249 00000 n 0000191031 00000 n 0000241147 00000 n 0000180685 00000 n 0000180158 00000 n 0000252033 00000 n 0000000402 00000 n 0000000432 00000 n 0000143717 00000 n 0000000486 00000 n 0000003227 00000 n 0000173833 00000 n 0000173449 00000 n 0000251117 00000 n 0000169782 00000 n 0000169489 00000 n 0000250174 00000 n 0000159237 00000 n 0000158638 00000 n 0000249146 00000 n 0000216707 00000 n 0000216451 00000 n 0000248122 00000 n 0000211925 00000 n 0000211527 00000 n 0000247170 00000 n 0000003248 00000 n 0000143861 00000 n 0000003357 00000 n 0000005158 00000 n 0000204011 00000 n 0000203605 00000 n 0000246136 00000 n 0000005179 00000 n 0000144005 00000 n 0000005277 00000 n 0000007195 00000 n 0000200037 00000 n 0000199738 00000 n 0000245480 00000 n 0000007216 00000 n 0000144149 00000 n 0000007314 00000 n 0000008727 00000 n 0000008748 00000 n 0000144293 00000 n 0000008802 00000 n 0000010430 00000 n 0000010451 00000 n 0000144437 00000 n 0000010505 00000 n 0000012121 00000 n 0000012142 00000 n 0000144581 00000 n 0000012229 00000 n 0000013432 00000 n 0000013453 00000 n 0000144725 00000 n 0000013518 00000 n 0000013977 00000 n 0000013997 00000 n 0000144869 00000 n 0000014062 00000 n 0000018115 00000 n 0000192373 00000 n 0000192012 00000 n 0000244897 00000 n 0000226952 00000 n 0000226695 00000 n 0000244472 00000 n 0000225742 00000 n 0000225493 00000 n 0000244013 00000 n 0000224833 00000 n 0000224612 00000 n 0000243642 00000 n 0000219822 00000 n 0000219496 00000 n 0000242927 00000 n 0000018136 00000 n 0000145021 00000 n 0000018311 00000 n 0000020539 00000 n 0000020560 00000 n 0000145165 00000 n 0000020658 00000 n 0000023189 00000 n 0000023210 00000 n 0000145309 00000 n 0000023286 00000 n 0000027315 00000 n 0000218591 00000 n 0000218309 00000 n 0000242402 00000 n 0000027337 00000 n 0000145463 00000 n 0000027449 00000 n 0000031297 00000 n 0000031319 00000 n 0000145618 00000 n 0000031453 00000 n 0000035667 00000 n 0000234906 00000 n 0000234689 00000 n 0000241333 00000 n 0000035689 00000 n 0000145773 00000 n 0000035847 00000 n 0000040358 00000 n 0000232393 00000 n 0000232155 00000 n 0000252624 00000 n 0000040380 00000 n 0000145928 00000 n 0000040527 00000 n 0000045065 00000 n 0000231752 00000 n 0000231552 00000 n 0000251709 00000 n 0000045087 00000 n 0000146075 00000 n 0000045210 00000 n 0000046027 00000 n 0000046048 00000 n 0000146222 00000 n 0000046114 00000 n 0000048501 00000 n 0000048523 00000 n 0000146369 00000 n 0000048633 00000 n 0000049719 00000 n 0000049741 00000 n 0000146516 00000 n 0000049785 00000 n 0000051425 00000 n 0000051447 00000 n 0000146671 00000 n 0000051513 00000 n 0000053183 00000 n 0000053205 00000 n 0000146818 00000 n 0000053315 00000 n 0000057047 00000 n 0000057069 00000 n 0000146965 00000 n 0000057201 00000 n 0000058068 00000 n 0000058089 00000 n 0000147112 00000 n 0000058166 00000 n 0000061088 00000 n 0000243940 00000 n 0000244385 00000 n 0000243575 00000 n 0000243786 00000 n 0000230899 00000 n 0000230682 00000 n 0000250752 00000 n 0000229226 00000 n 0000228992 00000 n 0000249657 00000 n 0000061110 00000 n 0000147259 00000 n 0000061294 00000 n 0000064014 00000 n 0000243867 00000 n 0000251946 00000 n 0000243508 00000 n 0000246055 00000 n 0000064036 00000 n 0000147406 00000 n 0000064207 00000 n 0000066244 00000 n 0000066266 00000 n 0000147553 00000 n 0000066376 00000 n 0000069607 00000 n 0000069629 00000 n 0000147700 00000 n 0000069750 00000 n 0000072155 00000 n 0000072177 00000 n 0000147847 00000 n 0000072298 00000 n 0000073606 00000 n 0000073628 00000 n 0000147994 00000 n 0000073705 00000 n 0000076033 00000 n 0000238448 00000 n 0000238172 00000 n 0000248557 00000 n 0000076055 00000 n 0000148141 00000 n 0000076178 00000 n 0000078758 00000 n 0000078780 00000 n 0000148288 00000 n 0000078892 00000 n 0000081663 00000 n 0000081685 00000 n 0000148435 00000 n 0000081821 00000 n 0000084345 00000 n 0000084367 00000 n 0000148582 00000 n 0000084455 00000 n 0000087232 00000 n 0000087254 00000 n 0000148729 00000 n 0000087355 00000 n 0000090089 00000 n 0000090111 00000 n 0000148876 00000 n 0000090212 00000 n 0000092716 00000 n 0000092738 00000 n 0000149023 00000 n 0000092839 00000 n 0000095319 00000 n 0000095341 00000 n 0000149170 00000 n 0000095442 00000 n 0000098120 00000 n 0000098142 00000 n 0000149317 00000 n 0000098243 00000 n 0000100578 00000 n 0000100600 00000 n 0000149464 00000 n 0000100699 00000 n 0000102667 00000 n 0000102689 00000 n 0000149611 00000 n 0000102755 00000 n 0000104258 00000 n 0000104280 00000 n 0000149758 00000 n 0000104381 00000 n 0000106015 00000 n 0000106037 00000 n 0000149905 00000 n 0000106125 00000 n 0000106945 00000 n 0000106966 00000 n 0000150052 00000 n 0000107032 00000 n 0000110813 00000 n 0000110835 00000 n 0000150199 00000 n 0000110945 00000 n 0000114170 00000 n 0000114192 00000 n 0000150346 00000 n 0000114280 00000 n 0000118764 00000 n 0000118786 00000 n 0000150501 00000 n 0000118920 00000 n 0000121535 00000 n 0000121557 00000 n 0000150648 00000 n 0000121667 00000 n 0000125771 00000 n 0000125793 00000 n 0000150795 00000 n 0000125894 00000 n 0000130285 00000 n 0000236972 00000 n 0000236717 00000 n 0000247753 00000 n 0000235958 00000 n 0000235730 00000 n 0000246728 00000 n 0000130307 00000 n 0000150950 00000 n 0000130476 00000 n 0000132674 00000 n 0000132696 00000 n 0000151097 00000 n 0000132784 00000 n 0000133943 00000 n 0000133965 00000 n 0000151244 00000 n 0000134066 00000 n 0000135101 00000 n 0000135122 00000 n 0000151391 00000 n 0000135210 00000 n 0000136272 00000 n 0000136293 00000 n 0000151538 00000 n 0000136370 00000 n 0000137457 00000 n 0000137479 00000 n 0000151685 00000 n 0000137523 00000 n 0000138425 00000 n 0000138446 00000 n 0000151832 00000 n 0000138490 00000 n 0000139351 00000 n 0000139372 00000 n 0000151979 00000 n 0000139416 00000 n 0000140358 00000 n 0000140379 00000 n 0000152126 00000 n 0000140423 00000 n 0000141491 00000 n 0000141512 00000 n 0000152273 00000 n 0000141556 00000 n 0000142162 00000 n 0000142183 00000 n 0000152420 00000 n 0000142227 00000 n 0000143480 00000 n 0000143502 00000 n 0000158616 00000 n 0000169466 00000 n 0000173427 00000 n 0000180136 00000 n 0000191008 00000 n 0000191991 00000 n 0000199716 00000 n 0000203583 00000 n 0000211505 00000 n 0000216429 00000 n 0000218287 00000 n 0000219475 00000 n 0000224590 00000 n 0000225472 00000 n 0000226674 00000 n 0000228970 00000 n 0000230660 00000 n 0000231531 00000 n 0000232134 00000 n 0000234667 00000 n 0000235709 00000 n 0000236696 00000 n 0000238150 00000 n 0000241125 00000 n trailer << /Size 354 /Root 1 0 R /Info 2 0 R >> startxref 252910 %%EOF iminuit-2.30.1/doc/notebooks/automatic_differentiation.ipynb0000644000000000000000000052235014332717401021245 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Automatic differentiation with JAX\n", "\n", "Here we look into automatic differentiation, which can speed up fits with very many parameters.\n", "\n", "iminuit's minimization algorithm MIGRAD uses a mix of gradient descent and Newton's method to find the minimum. Both require a first derivative, which MIGRAD usually computes numerically from finite differences. This requires many function evaluations and the gradient may not be accurate. As an alternative, iminuit also allows the user to compute the gradient and pass it to MIGRAD.\n", "\n", "Although computing derivatives is often straight-forward, it is usually too much hassle to do manually. Automatic differentiation (AD) is an interesting alternative, it allows one to compute exact derivatives efficiently for pure Python/numpy functions. We demonstrate automatic differentiation with the JAX module, which can not only compute derivatives, but also accelerates the computation of Python code (including the gradient code) with a just-in-time compiler.\n", "\n", "[Recommended read: Gentle introduction to AD](https://www.kaggle.com/borisettinger/gentle-introduction-to-automatic-differentiation)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Fit of a gaussian model to a histogram\n", "\n", "We fit a gaussian to a histogram using a maximum-likelihood approach based on Poisson statistics. This example is used to investigate how automatic differentiation can accelerate a typical fit in a counting experiment.\n", "\n", "To compare fits with and without passing an analytic gradient fairly, we use `Minuit.strategy = 0`, which prevents Minuit from automatically computing the Hesse matrix after the fit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "JAX version 0.4.31\n", "numba version 0.60.0\n" ] } ], "source": [ "# !pip install jax jaxlib matplotlib numpy iminuit numba-stats\n", "%config InlineBackend.figure_formats = ['svg']\n", "import jax\n", "from jax import numpy as jnp # replacement for normal numpy\n", "from jax.scipy.special import erf # replacement for scipy.special.erf\n", "from iminuit import Minuit\n", "import numba as nb\n", "import numpy as np # original numpy still needed, since jax does not cover full API\n", "\n", "jax.config.update(\n", " \"jax_enable_x64\", True\n", ") # enable float64 precision, default is float32\n", "\n", "print(f\"JAX version {jax.__version__}\")\n", "print(f\"numba version {nb.__version__}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We generate some toy data and write the negative log-likelihood (nll) for a fit to binned data, assuming Poisson-distributed counts.\n", "\n", "**Note:** We write all statistical functions in pure Python code, to demonstrate Jax's ability to automatically differentiate and JIT compile this code. In practice, one should import JIT-able statistical distributions from jax.scipy.stats. The library versions can be expected to have fewer bugs and to be faster and more accurate than hand-written code." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# generate some toy data\n", "rng = np.random.default_rng(seed=1)\n", "n, xe = np.histogram(rng.normal(size=10000), bins=1000)\n", "\n", "\n", "def cdf(x, mu, sigma):\n", " # cdf of a normal distribution, needed to compute the expected counts per bin\n", " # better alternative for real code: from jax.scipy.stats.norm import cdf\n", " z = (x - mu) / sigma\n", " return 0.5 * (1 + erf(z / np.sqrt(2)))\n", "\n", "\n", "def nll(par): # negative log-likelihood with constants stripped\n", " amp = par[0]\n", " mu, sigma = par[1:]\n", " p = cdf(xe, mu, sigma)\n", " mu = amp * jnp.diff(p)\n", " result = jnp.sum(mu - n + n * jnp.log(n / (mu + 1e-100) + 1e-100))\n", " return result" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Let's check results from all combinations of using JIT and gradient and then compare the execution times." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "start_values = (1.5 * np.sum(n), 1.0, 2.0)\n", "limits = ((0, None), (None, None), (0, None))\n", "\n", "\n", "def make_and_run_minuit(fcn, grad=None):\n", " m = Minuit(fcn, start_values, grad=grad, name=(\"amp\", \"mu\", \"sigma\"))\n", " m.errordef = Minuit.LIKELIHOOD\n", " m.limits = limits\n", " m.strategy = 0 # do not explicitly compute hessian after minimisation\n", " m.migrad()\n", " return m" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 496.2 Nfcn = 66
EDM = 1.84e-08 (Goal: 0.0001) time = 0.4 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance APPROXIMATE
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 496.2 │ Nfcn = 66 │\n", "│ EDM = 1.84e-08 (Goal: 0.0001) │ time = 0.4 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance APPROXIMATE │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m1 = make_and_run_minuit(nll)\n", "m1.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 496.2 Nfcn = 26, Ngrad = 6
EDM = 1.84e-08 (Goal: 0.0001) time = 1.2 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance APPROXIMATE
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 496.2 │ Nfcn = 26, Ngrad = 6 │\n", "│ EDM = 1.84e-08 (Goal: 0.0001) │ time = 1.2 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance APPROXIMATE │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m2 = make_and_run_minuit(nll, grad=jax.grad(nll))\n", "m2.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 496.2 Nfcn = 66
EDM = 1.84e-08 (Goal: 0.0001) time = 0.1 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance APPROXIMATE
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 496.2 │ Nfcn = 66 │\n", "│ EDM = 1.84e-08 (Goal: 0.0001) │ time = 0.1 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance APPROXIMATE │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m3 = make_and_run_minuit(jax.jit(nll))\n", "m3.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 496.2 Nfcn = 26, Ngrad = 6
EDM = 1.84e-08 (Goal: 0.0001) time = 0.3 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance APPROXIMATE
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 496.2 │ Nfcn = 26, Ngrad = 6 │\n", "│ EDM = 1.84e-08 (Goal: 0.0001) │ time = 0.3 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance APPROXIMATE │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m4 = make_and_run_minuit(jax.jit(nll), grad=jax.jit(jax.grad(nll)))\n", "m4.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 496.2 Nfcn = 82
EDM = 5.31e-05 (Goal: 0.0001) time = 2.0 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance APPROXIMATE
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 496.2 │ Nfcn = 82 │\n", "│ EDM = 5.31e-05 (Goal: 0.0001) │ time = 2.0 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance APPROXIMATE │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from numba_stats import norm # numba jit-able version of norm\n", "\n", "\n", "@nb.njit\n", "def nb_nll(par):\n", " amp = par[0]\n", " mu, sigma = par[1:]\n", " p = norm.cdf(xe, mu, sigma)\n", " mu = amp * np.diff(p)\n", " result = np.sum(mu - n + n * np.log(n / (mu + 1e-323) + 1e-323))\n", " return result\n", "\n", "\n", "m5 = make_and_run_minuit(nb_nll)\n", "m5.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from timeit import timeit\n", "\n", "times = {\n", " \"no JIT, no grad\": \"m1\",\n", " \"no JIT, grad\": \"m2\",\n", " \"jax JIT, no grad\": \"m3\",\n", " \"jax JIT, grad\": \"m4\",\n", " \"numba JIT, no grad\": \"m5\",\n", "}\n", "for k, v in times.items():\n", " t = timeit(\n", " f\"{v}.values = start_values; {v}.migrad()\",\n", " f\"from __main__ import {v}, start_values\",\n", " number=1,\n", " )\n", " times[k] = t" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:48:38.246537\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib import pyplot as plt\n", "\n", "x = np.fromiter(times.values(), dtype=float)\n", "xmin = np.min(x)\n", "\n", "y = -np.arange(len(times))\n", "plt.barh(y, x)\n", "for yi, k, v in zip(y, times, x):\n", " plt.text(v, yi, f\"{v/xmin:.1f}x\")\n", "plt.yticks(y, times.keys())\n", "for loc in (\"top\", \"right\"):\n", " plt.gca().spines[loc].set_visible(False)\n", "plt.xlabel(\"execution time / s\");" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Conclusions:\n", "\n", "1. As expected, the best results with JAX are obtained by JIT compiling function and gradient and using the gradient in the minimization. However, the performance of the Numba JIT compiled function is comparable even without computing the gradient.\n", "\n", "1. JIT compiling the cost function with JAX but not using the gradient also gives good performance, but worse than using Numba for the same.\n", "\n", "3. Combining the JAX JIT with the JAX gradient calculation is very important. Using only the Python-computed gradient even reduces performance in this example.\n", "\n", "In general, the gain from using a gradient is larger for functions with hundreds of parameters, as is common in machine learning. Human-made models often have less than 10 parameters, and then the gain is not so dramatic." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Computing covariance matrices with JAX\n", "\n", "Automatic differentiation gives us another way to compute uncertainties of fitted parameters. MINUIT compute the uncertainties with the HESSE algorithm by default, which computes the matrix of second derivates approximately using finite differences and inverts this.\n", "\n", "Let's compare the output of HESSE with the exact (within floating point precision) computation using automatic differentiation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "sigma[amp] : HESSE = 100.0, JAX = 100.0\n", "sigma[mu] : HESSE = 0.0100, JAX = 0.0100\n", "sigma[sigma]: HESSE = 0.0071, JAX = 0.0071\n" ] } ], "source": [ "m4.hesse()\n", "cov_hesse = m4.covariance\n", "\n", "\n", "def jax_covariance(par):\n", " return jnp.linalg.inv(jax.hessian(nll)(par))\n", "\n", "\n", "par = np.array(m4.values)\n", "cov_jax = jax_covariance(par)\n", "\n", "print(\n", " f\"sigma[amp] : HESSE = {cov_hesse[0, 0] ** 0.5:6.1f}, JAX = {cov_jax[0, 0] ** 0.5:6.1f}\"\n", ")\n", "print(\n", " f\"sigma[mu] : HESSE = {cov_hesse[1, 1] ** 0.5:6.4f}, JAX = {cov_jax[1, 1] ** 0.5:6.4f}\"\n", ")\n", "print(\n", " f\"sigma[sigma]: HESSE = {cov_hesse[2, 2] ** 0.5:6.4f}, JAX = {cov_jax[2, 2] ** 0.5:6.4f}\"\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Success, HESSE and JAX give the same answer within the relevant precision.\n", "\n", "**Note:** If you compute the covariance matrix in this way from a least-squares cost function instead of a negative log-likelihood, you must multiply it by 2.\n", "\n", "Let us compare the performance of HESSE with Jax." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "22.9 ms ± 2.51 ms per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -n 1 -r 3\n", "m = Minuit(nll, par)\n", "m.errordef = Minuit.LIKELIHOOD\n", "m.hesse()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "35 ms ± 4.11 ms per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -n 1 -r 3\n", "jax_covariance(par)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The computation with Jax is slower, but it is also more accurate (although the added precision is not relevant).\n", "\n", "Minuit's HESSE algorithm still makes sense today. It has the advantage that it can process any function, while Jax cannot. Jax cannot differentiate a function that calls into C/C++ code or Cython code, for example.\n", "\n", "Final note: If we JIT compile `jax_covariance`, it greatly outperforms Minuit's HESSE algorithm, but that only makes sense if you need to compute the hessian at different parameter values, so that the extra time spend to compile is balanced by the time saved over many invocations. This is not what happens here, the Hessian in only needed at the best fit point." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "107 μs ± 10.3 μs per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -n 1 -r 3 jit_jax_covariance = jax.jit(jax_covariance); jit_jax_covariance(par)\n", "jit_jax_covariance(par)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "It is much faster... but only because the compilation cost is excluded here." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "429 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" ] } ], "source": [ "%%timeit -n 1 -r 1\n", "\n", "\n", "# if we include the JIT compilation cost, the performance drops dramatically\n", "@jax.jit\n", "def jax_covariance(par):\n", " return jnp.linalg.inv(jax.hessian(nll)(par))\n", "\n", "\n", "jax_covariance(par)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "With compilation cost included, it is much slower.\n", "\n", "Conclusion: Using the JIT compiler makes a lot of sense if the covariance matrix has to be computed repeatedly for the same cost function but different parameters, but this is not the case when we use it to compute parameter errors." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Fit data points with uncertainties in x and y\n", "\n", "Let's say we have some data points $(x_i \\pm \\sigma_{x,i}, y_i \\pm \\sigma_{y,i})$ and we have a model $y=f(x)$ that we want to adapt to this data. If $\\sigma_{x,i}$ was zero, we could use the usual least-squares method, minimizing the sum of squared residuals $r^2_i = (y_i - f(x_i))^2 / \\sigma^2_{y,i}$. Here, we don't know where to evaluate $f(x)$, since the exact $x$-location is only known up to $\\sigma_{x,i}$.\n", "\n", "We can approximately extend the standard least-squares method to handle this case. We use that the uncertainty along the $x$-axis can be converted into an additional uncertainty along the $y$-axis with error propagation,\n", "\n", "$$\n", "f(x_i \\pm \\sigma_{x,i}) \\simeq f(x_i) \\pm f'(x_i)\\,\\sigma_{x,i}.\n", "$$\n", "\n", "Using this, we obtain modified squared residuals\n", "\n", "$$\n", "r^2_i = \\frac{(y_i - f(x_i))^2}{\\sigma^2_{y,i} + (f'(x_i) \\,\\sigma_{x,i})^2}.\n", "$$\n", "\n", "We demonstrate this with a fit of a polynomial." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# polynomial model\n", "def f(x, par):\n", " return jnp.polyval(par, x)\n", "\n", "\n", "# true polynomial f(x) = x^2 + 2 x + 3\n", "par_true = np.array((1, 2, 3))\n", "\n", "\n", "# grad computes derivative with respect to the first argument\n", "f_prime = jax.jit(jax.grad(f))\n", "\n", "\n", "# checking first derivative f'(x) = 2 x + 2\n", "assert f_prime(0.0, par_true) == 2\n", "assert f_prime(1.0, par_true) == 4\n", "assert f_prime(2.0, par_true) == 6\n", "# ok!\n", "\n", "# generate toy data\n", "n = 30\n", "data_x = np.linspace(-4, 7, n)\n", "data_y = f(data_x, par_true)\n", "\n", "rng = np.random.default_rng(seed=1)\n", "sigma_x = 0.5\n", "sigma_y = 5\n", "data_x += rng.normal(0, sigma_x, n)\n", "data_y += rng.normal(0, sigma_y, n)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:48:42.025913\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.errorbar(data_x, data_y, sigma_y, sigma_x, fmt=\"o\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Array(876.49545695, dtype=float64)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# define the cost function\n", "@jax.jit\n", "def cost(par):\n", " result = 0.0\n", " for xi, yi in zip(data_x, data_y):\n", " y_var = sigma_y**2 + (f_prime(xi, par) * sigma_x) ** 2\n", " result += (yi - f(xi, par)) ** 2 / y_var\n", " return result\n", "\n", "\n", "cost.errordef = Minuit.LEAST_SQUARES\n", "\n", "# test the jit-ed function\n", "cost(np.zeros(3))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 23.14 Nfcn = 91
EDM = 3.12e-05 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 1.25 0.15
1 x1 1.5 0.5
2 x2 1.6 1.5
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1 x2
x0 0.0223 -0.039 (-0.530) -0.150 (-0.657)
x1 -0.039 (-0.530) 0.24 0.17 (0.230)
x2 -0.150 (-0.657) 0.17 (0.230) 2.32
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 23.14 │ Nfcn = 91 │\n", "│ EDM = 3.12e-05 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 1.25 │ 0.15 │ │ │ │ │ │\n", "│ 1 │ x1 │ 1.5 │ 0.5 │ │ │ │ │ │\n", "│ 2 │ x2 │ 1.6 │ 1.5 │ │ │ │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬──────────────────────â”\n", "│ │ x0 x1 x2 │\n", "├────┼──────────────────────┤\n", "│ x0 │ 0.0223 -0.039 -0.150 │\n", "│ x1 │ -0.039 0.24 0.17 │\n", "│ x2 │ -0.150 0.17 2.32 │\n", "└────┴──────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Minuit(cost, np.zeros(3))\n", "m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:48:42.979909\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.errorbar(data_x, data_y, sigma_y, sigma_x, fmt=\"o\", label=\"data\")\n", "x = np.linspace(data_x[0], data_x[-1], 200)\n", "par = np.array(m.values)\n", "plt.plot(x, f(x, par), label=\"fit\")\n", "plt.legend()\n", "\n", "# check fit quality\n", "chi2 = m.fval\n", "ndof = len(data_y) - 3\n", "plt.title(f\"$\\\\chi^2 / n_\\\\mathrm{{dof}} = {chi2:.2f} / {ndof} = {chi2/ndof:.2f}$\");" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We obtained a good fit." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/basic.ipynb0000644000000000000000000017040514332717401015106 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Basics\n", "\n", "You will learn basic usage of iminuit and how to approach standard fitting problems with `iminuit`.\n", "\n", "`iminuit` is a Python frontend to the `Minuit2` library in C++, an integrated software that combines a local minimizer (called MIGRAD) and two error calculators (called HESSE and MINOS). You provide it an analytical function, which accepts one or several parameters, and an initial guess of the parameter values. It will then find a local minimum of this function starting from the initial guess. In that regard, iminuit minimizer is like other local minimizers, like those in `scipy.optimize`.\n", "\n", "In addition, iminuit has the ability to compute **uncertainty estimates** for model parameters. `iminuit` was designed to solve statistics problems, where uncertainty estimates are an essential part of the result. The two ways of computing uncertainty estimates, HESSE and MINOS, have different advantages and disadvantages.\n", "\n", "`iminuit` is the successor of `pyminuit`. If you used `pyminuit` before, you will find iminuit very familiar. An important feature of `iminuit` (and `pyminuit`) is that it uses introspection to detect the parameter names of your function. This is very convenient, especially when you work interactively in a Jupyter notebook. It also provides special output routines for Jupyter notebooks to pretty print the fit results, as you will see below." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# basic setup of the notebook\n", "%config InlineBackend.figure_formats = ['svg']\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "\n", "# everything in iminuit is done through the Minuit object, so we import it\n", "from iminuit import Minuit\n", "\n", "# we also need a cost function to fit and import the LeastSquares function\n", "from iminuit.cost import LeastSquares\n", "\n", "# display iminuit version\n", "import iminuit\n", "\n", "print(\"iminuit version:\", iminuit.__version__)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Quick start\n", "\n", "In this first section, we look at a simple case where line should be fitted to scattered $(x, y)$ data. A line has two parameters $(\\alpha, \\beta)$. We go through the full fit, showing all basic steps to get you started quickly. In the following sections we will revisit the steps in more detail." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# our line model, unicode parameter names are supported :)\n", "def line(x, α, β):\n", " return α + x * β\n", "\n", "\n", "# generate random toy data with random offsets in y\n", "rng = np.random.default_rng(1)\n", "data_x = np.linspace(0, 1, 10)\n", "data_yerr = 0.1 # could also be an array\n", "data_y = rng.normal(line(data_x, 1, 2), data_yerr)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "To recover the parameters α and β of the line model from this data, we need to minimize a suitable cost function. The cost function must be twice differentiable and have a minimum at the optimal parameters. We use the method of least-squares here, whose cost function computes the sum of squared residuals between the model and the data. The task of iminuit is to find the minimum of that function.\n", "\n", "The iminuit module provides the `LeastSquares` class to conveniently generate a least-squares cost function.\n", "We will revisit how to write one by hand in a later section. Using a built-in cost function comes with some perks, for example, the fit (if data are 1D) is automatically visualized in a Jupyter notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "least_squares = LeastSquares(data_x, data_y, data_yerr, line)\n", "\n", "m = Minuit(least_squares, α=0, β=0) # starting values for α and β\n", "\n", "m.migrad() # finds minimum of least_squares function\n", "m.hesse() # accurately computes uncertainties" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "And that is all for a basic fit. The fit result is immediately visible here in the notebook, since calls to `m.migrad()` and `m.hesse()` return the `Minuit` object, which then automatically renders its state in a Jupyter notebook.\n", "\n", "The automatically generated plot of the fitted function is intentionally very basic. You can make a nicer plot by hand with `matplotlib`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# draw data and fitted line\n", "plt.errorbar(data_x, data_y, data_yerr, fmt=\"ok\", label=\"data\")\n", "plt.plot(data_x, line(data_x, *m.values), label=\"fit\")\n", "\n", "# display legend with some fit info\n", "fit_info = [\n", " f\"$\\\\chi^2$/$n_\\\\mathrm{{dof}}$ = {m.fval:.1f} / {m.ndof:.0f} = {m.fmin.reduced_chi2:.1f}\",\n", "]\n", "for p, v, e in zip(m.parameters, m.values, m.errors):\n", " fit_info.append(f\"{p} = ${v:.3f} \\\\pm {e:.3f}$\")\n", "\n", "plt.legend(title=\"\\n\".join(fit_info), frameon=False)\n", "plt.xlabel(\"x\")\n", "plt.ylabel(\"y\");" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In the following, we dive into details step by step; how the Minuit object is initialized, how to run the algorithms, and how to get the results.\n", "\n", "`iminuit` was designed to make it easy to fit cost functions like `least_squares(...)`, where the parameters are individual arguments of the function. There is an alternative function signature that Minuit supports, which is more convenient when you explore models that have a not-yet-defined number of parameters, for example, a polynomial. Here, the parameters are passed as a NumPy array. We will discuss both in the following, but focus on the first.\n", "\n", "## Initialize the Minuit object\n", "\n", "To minimize a function, one has to create an instance of the Minuit class and pass the function and a starting value for each parameter. This does not start the minimization yet, this will come later.\n", "\n", "The `Minuit` object uses introspection to get the number and names of the function parameters automatically, so that they can be initialized with keywords." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = Minuit(least_squares, α=0, β=0)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "If we forget a parameter or mistype them, Minuit will raise an error. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " Minuit(least_squares)\n", "except RuntimeError:\n", " import traceback\n", "\n", " traceback.print_exc()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " Minuit(least_squares, a=0, b=0)\n", "except RuntimeError:\n", " import traceback\n", "\n", " traceback.print_exc()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Initial parameter values\n", "\n", "The main algorithm MIGRAD is a local minimizer. It searches for a local minimum by a doing a mix of Newton steps and gradient-descents from a starting point. If your function has several minima, the minimum found will depend on the starting point. Even if it has only one minimum, iminuit will converge to it faster if you start in the proximity of the minimum.\n", "\n", "You can set the starting point using the parameter names as keywords, ` = `." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(least_squares, α=5, β=5) # pass starting values for α and β" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, the starting values can also be passed as positional arguments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(least_squares, 5, 5) # another way of passing starting values for α and β" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "You can also use iminuit with functions that accept NumPy arrays. This has pros and cons.\n", "\n", "**Pros**\n", "\n", "- Easy to change number of fitted parameters\n", "- Sometimes simpler function body that's easier to read\n", "- Technically this is more efficient, but this is hardly going to be noticeable\n", "\n", "**Cons**\n", "\n", "- iminuit cannot figure out names for each parameter\n", "\n", "To demonstrate, use a version of the line model which accepts the parameters as a NumPy array." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def line_np(x, par):\n", " return np.polyval(par, x) # for len(par) == 2, this is a line" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Calling `line_np` with more or less arguments is easy and will use a polynomial of the corresponding order to predict the behavior of the data.\n", "\n", "The built-in cost functions support such a model. For it to be detected properly, you need to pass the starting values in form a single sequence of numbers. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "least_squares_np = LeastSquares(data_x, data_y, data_yerr, line_np)\n", "\n", "Minuit(least_squares_np, (5, 5)) # pass starting values as a sequence" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Any sequence will work for initialization, you can also pass a list or a NumPy array here. `iminuit` uses the length of the sequence to detect how many parameters the model has. By default, the parameters are named automatically `x0` to `xN`. One can override this with the keyword `name`, passing a sequence of parameter names." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(least_squares_np, (5, 5), name=(\"a\", \"b\"))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Since `least_squares_np` works for parameter arrays of any length, one can easily change the number of fitted parameters." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# fit a forth order polynomial\n", "Minuit(least_squares_np, (5, 5, 5, 5))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "It is often useful to try different orders of a polynomial model. If the order is too small, the polynomial will not follow the data. If it is too large, it will overfit the data and pick up random fluctuations and not the underlying trend. One can figure out the right order by experimenting or using an algorithm like cross-validation.\n", "\n", "### Inspecting current parameters\n", "\n", "You can check the current parameter values and settings with the method `Minuit.params` at any time. It returns a special list of `Param` objects which pretty-prints in Jupyter and in the terminal." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This produces a nice table with numbers rounded according to the rules of the *Particle Data Group*. The table will be updated once you run the actual minimization. To look at the initial conditions later, use `Minuit.init_params`. We will come back to the meaning of *Hesse Error* and *Minos Error* later.\n", "\n", "`Minuit.params` returns a tuple-like container of `Param` objects, which are data objects with attributes that one can query. Use `repr()` to get a detailed representation of the data object." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for p in m.params:\n", " print(repr(p), \"\\n\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Parameters with limits\n", "\n", "`iminuit` allows you to set parameter limits. Often a parameter is limited mathematically or physically to a certain range. For example, if your function contains `sqrt(x)`, then $x$ must be non-negative, $x \\ge 0$. You can set upper-, lower-, or two-sided limits for each parameter individually with the `limits` property.\n", "\n", "- Lower limit: use `Minuit.limits[] = (, None)` or `(, float(\"infinity\"))`\n", "- Upper limit: use `Minuit.limits[] = (None, )` or `(-float(\"infinity\"), )`\n", "- Two-sided limit: use `Minuit.limits[] = (, )`\n", "- Remove limits: use `Minuit.limits[] = None` or `(-float(\"infinity\"), float(\"infinity\")`\n", "\n", "You can also set limits for several parameters at once with a sequence. To impose the limits $α \\ge 0$ and $0 \\le β \\le 10$ in our example, we use:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.limits = [(0, None), (0, 10)]\n", "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible for the cost function to declare limits on its parameters. For this you need the `Annotated` type, which is available in Python-3.9 or later, and from the package `typing-extensions` in Python-3.8. The restrictions should be imported from the external package `annotated-types`. The built-in cost functions propagate such annotations of model parameters. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Annotated and Gt are imported from iminuit.typing here for universal compatibility,\n", "# but users should in general import them from external packages `typing-extensions` and\n", "# `annotated-types` to decouple models from the `iminuit` package\n", "from iminuit.typing import Annotated, Gt\n", "\n", "\n", "def line_with_positive_slope(x, slope: Annotated[float, Gt(0)], offset):\n", " return slope * x + offset\n", "\n", "\n", "lsq = LeastSquares(data_x, data_y, data_yerr, line_with_positive_slope)\n", "\n", "Minuit(lsq, 1, 0)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "You can reset the limit automatically set by such an annotation by calling `minuit_instance.limit[\"slope\"] = None` before fitting, if you wish.\n", "\n", "### Fixing and releasing parameters\n", "\n", "Sometimes you have a parameter which you want to set to a fixed value temporarily. Perhaps you have a guess for its value, and you want to see how the other parameters adapt when this parameter is fixed to that value.\n", "\n", "Or you have a complex function with many parameters that do not all affect the function at the same scale. Then you can manually help the minimizer to find the minimum faster by first fixing the less important parameters to initial guesses and fit only the important parameters. Once the minimum is found under these conditions, you can release the fixed parameters and optimize all parameters together. Minuit remembers the last state of the minimization and starts from there. The minimization time roughly scales with the square of the number of parameters. Iterated minimization over subspaces of the parameters can reduce that time.\n", "\n", "To fix an individual parameter, use `minuit_instance.fixed[] = True`. In our example, we fix α:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.fixed[\"α\"] = True\n", "m.params" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# migrad will not vary α, only β\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now we release α and fix β and minimize again, you can also use the parameter index instead of its name." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.fixed[0] = False\n", "m.fixed[1] = True\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We could iterate this and would slowly approach the minimum, but that's silly; instead we release both parameters and run again. The array-like views support broadcasting to enable this shortcut notation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.fixed = False\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to fix a parameter and set a value with one convenient call, using `Minuit.fixto`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.fixto(\"α\", 3)\n", "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Varying starting points for minimization\n", "\n", "It is sometimes useful to change the values of some fixed parameters by hand and fit the others or to restart the fit from another starting point. For example, if the cost function has several minima, changing the starting value can be used to find the other minimum." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def cost_function_with_two_minima(x):\n", " return x**4 - x**2 + 1\n", "\n", "\n", "x = np.linspace(-1.5, 1.5)\n", "plt.plot(x, cost_function_with_two_minima(x));" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# starting at -0.1 gives the left minimum\n", "m = Minuit(cost_function_with_two_minima, x=-0.1)\n", "m.migrad()\n", "print(\"starting value -0.1, minimum at\", m.values[\"x\"])\n", "\n", "# changing the starting value to 0.1 gives the right minimum\n", "m.values[\"x\"] = 0.1 # m.values[0] = 0.1 also works\n", "m.migrad()\n", "print(\"starting value +0.1, minimum at\", m.values[\"x\"])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced: Simplex and Scan minimizers \n", "\n", "`iminuit` also offers two other minimizers which are less powerful than MIGRAD, but may be useful in special cases.\n", "\n", "#### SIMPLEX\n", "\n", "The Nelder-Mead method (aka SIMPLEX) is well described on [Wikipedia](https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method). It is a gradient-free minimization method that usually converges more slowly, but may be more robust. For some problems it can help to start the minimization with SIMPLEX and then finish with MIGRAD. Since the default stopping criterion for SIMPLEX is much more lax than MIGRAD, either running MIGRAD after SIMPLEX or reducing the tolerance with `Minuit.tol` is strongly recommended." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(cost_function_with_two_minima, x=10).simplex()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Let's run MIGRAD after SIMPLEX to finish the minimization." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(cost_function_with_two_minima, x=10).simplex().migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This combination uses slightly fewer function evaluations and produced a more accurate result than just running MIGRAD alone in this case (for another problem this may not be true)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(cost_function_with_two_minima, x=10).migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Scan\n", "\n", "Scan is a last resort. It does an N-dimensional grid scan over the parameter space. The number of function evaluations scale like $n^k$, where $k$ is the number of parameters and $n$ the number of steps along one dimension. Using scan for high-dimensional problems is unfeasible, but it can be useful in low-dimensional problems and when all but a few parameters are fixed. The scan needs bounds, which are best set with `Minuit.limits`. The number of scan points is set with the `ncall` keyword." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = Minuit(cost_function_with_two_minima, x=10)\n", "m.limits = (-10, 10)\n", "m.scan(ncall=50)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The scan brought us in proximity of the minimum.\n", "\n", "In this case, the minimum is considered valid, because the EDM value is smaller than the EDM goal, but the scan may also end up in an invalid minimum, which is also ok. The scan minimizes the cost function using a finite number of steps, regardless of the EDM value (which is only computed after the scan for the minimum).\n", "\n", "One should always run MIGRAD or SIMPLEX after a SCAN." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced: Errordef\n", "\n", "If you do not use one of the cost functions from the `iminuit.cost` module, you may need to pass an additional parameter to Minuit.\n", "\n", "Minuit by default assumes that the function scales like a chi-square function when one of the parameters is moved away from the minimum. If your cost function is constructed as a log-likelihood, it scales differently, and you must indicate that to Minuit wit the `errordef` parameter. Setting this is not needed for the cost functions in `iminuit.cost`.\n", "\n", "The `errordef` parameter is required to compute correct uncertainties. If you don't care about uncertainty estimates (but why are you using Minuit then?), you can ignore it. Minuit supports two kinds of cost functions, the *negative log-likelihood* and the *least-squares* function. Each has a corresponding value for `errordef`:\n", "\n", " - `0.5` or the constant `Minuit.LIKELIHOOD` for negative log-likelihood functions \n", " - `1` or the constant `Minuit.LEAST_SQUARES` for least-squares functions (the default)\n", "\n", "If you like to understand the origin of these numbers, have a look into the study **Hesse and Minos**, which explains in depth how uncertainties are computed.\n", "\n", "For our custom cost function, we could set `m.errordef=1` or `m.errordef=Minuit.LEAST_SQUARES`, which is more readable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# a simple least-squares cost function looks like this...\n", "def custom_least_squares(a, b):\n", " ym = line(data_x, a, b)\n", " z = (data_y - ym) / data_yerr\n", " return np.sum(z**2)\n", "\n", "\n", "m = Minuit(custom_least_squares, 1, 2)\n", "m.migrad() # standard errordef, correct in this case" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.errordef = Minuit.LIKELIHOOD # errordef for negative log-likelihoods, wrong here\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reported errors are now by a factor `sqrt(2)` smaller than they really are.\n", "\n", "An even better way is to add an attribute called `errordef` to the cost function. If such an attribute is present, Minuit uses it. Since this cost function has the default scaling, we do not need to set anything, but keep it in mind for negative log-likelihoods." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# artificial cost function that scales like a negative log-likelihood\n", "def custom_least_squares_2(a, b):\n", " return 0.5 * custom_least_squares(a, b)\n", "\n", "\n", "# Instead of calling Minuit.errordef, we assign an errordef attribute to the cost\n", "# function. Minuit will automatically use this value.\n", "custom_least_squares_2.errordef = Minuit.LIKELIHOOD\n", "\n", "m = Minuit(custom_least_squares_2, 1, 2)\n", "m.migrad() # uses the correct errordef automatically" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We get the correct errors. The built-in cost functions from the module `iminuit.cost` all define the `errordef` attribute, so you don't need to worry about that.\n", "\n", "If the cost function defines the `errordef`, it should not be necessary to set it to another value, so `Minuit` warns you if you try to set it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# raises a warning\n", "m.errordef = 1" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced: Initial step sizes\n", "\n", "Minuit uses a gradient-descent method to find the minimum, and the gradient is computed numerically using finite differences. The initial step size is used to compute the first gradient. A good step size is small compared to the curvature of the function, but large compared to numerical resolution. Using a good step size can slightly accelerate the convergence, but Minuit is not very sensitive to the choice. If you don't provide a value, iminuit will guess a step size based on a heuristic.\n", "\n", "You can set initial step sizes with the `errors` property, `Minuit.errors[] = `. Using an appropriate step size is important when you have you a parameter which has physical bounds. Varying the initial parameter value by the step size may not create a situation where the parameter goes outside its bounds. For example, a parameter $x$ with $x > 0$ and initial value $0.1$ may not have a step size of $0.2$.\n", "\n", "In our example, we could use an initial step size of $\\Delta α = 0.1$ and $\\Delta β = 0.2$. Setting both can be done conveniently by assigning a sequence:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = Minuit(least_squares, α=5, β=5)\n", "m.errors = (0.1, 0.2) # assigning sequences works\n", "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Broadcasting is also supported." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.errors = 0.3 # broadcasting\n", "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Only positive step sizes are allowed. Non-positive values are replaced with the heuristic and a warning is emitted." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.errors[\"β\"] = -0.3\n", "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced: Override parameter name detection\n", "\n", "`iminuit` tries hard to detect the parameter names correctly. It works for a large variety of cases. For example, if you pass a functor instead of a function, it will use the arguments of the `__call__` method, automatically skipping `self`. It even tries to parse the docstring if all else fails.\n", "\n", "You can check which parameter names iminuit finds for your function with the `describe` function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iminuit import describe\n", "\n", "\n", "def foo(x, y, z):\n", " pass\n", "\n", "\n", "assert describe(foo) == [\"x\", \"y\", \"z\"]\n", "\n", "\n", "class Foo:\n", " def __call__(self, a, b):\n", " pass\n", "\n", "\n", "assert describe(Foo()) == [\"a\", \"b\"]" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Sometimes parameter names cannot be determined, for example, when a function accepts a variable number of arguments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def func_varargs(*args): # function with variable number of arguments\n", " return np.sum((np.array(args) - 1) ** 2)\n", "\n", "\n", "assert describe(func_varargs) == []" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "`describe` cannot detect the number and names of the parameters in this case and returns an empty list. If you work with functions that accept a variable number of arguments a lot, it is better to use a cost function which accepts a parameter array (this is explained in the next section).\n", "\n", "When iminuit cannot detect the arguments, but you know how many arguments there are, or if you simply want to override the names found by `iminuit`, you can do that with the keyword `name`, like so:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Minuit(func_varargs, name=(\"a\", \"b\"), a=1, b=2).migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Alternative interface: `iminuit.minimize`\n", "\n", "Those familiar with `scipy` may find the `minimize` function useful. It exactly mimics the function interface of `scipy.optimize.minimize`, but uses `Minuit` for the actual minimization. The `scipy` package must be installed to use it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iminuit import minimize # has same interface as scipy.optimize.minimize\n", "\n", "minimize(least_squares_np, (5, 5))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This interface is handy if you want to be able to switch between iminuit and `scipy.optimize.minimize`, but we recommend the standard interface instead. It is an advantage of Minuit that you can interact and manually steer the minimization process. This is not as convenient with a functional interface like `minimize`." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Investigating the fit status\n", "\n", "Calling `Minuit.migrad()` runs the actual minimization with the MIGRAD algorithm. MIGRAD essentially tries a Newton-step and if that does not produce a smaller function value, it tries a line search along the direction of the gradient. So far so ordinary. The clever bits in MIGRAD are how various pathological cases are handled.\n", "\n", "Let's look again at the output of `Minuit.migrad()`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = Minuit(least_squares, α=5, β=5)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The `Minuit.migrad` method returns the Minuit instance so that one can chain method calls. The instance also pretty prints the latest state of the minimization.\n", "\n", "The first block in this output is showing information about the function minimum. This is good for a quick check:\n", "\n", "- All blocks should be green.\n", "- Purple means something bad. \n", "- Yellow may be bad or not. Be careful.\n", "\n", "Let's see how it looks when the function is bad." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m_bad = Minuit(lambda x: 0, x=1) # a constant function has no minimum\n", "m_bad.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Coming back to our previous good example, the info about the function minimum can be directly accessed with `Minuit.fmin`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.fmin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# print(repr(...)) to see a detailed representation of the data object\n", "print(repr(m.fmin))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The most important one here is `is_valid`. If this is false, the fit did not converge and the result is useless. Since this is so often queried, a shortcut is provided with `Minuit.valid`.\n", "\n", "If the fit fails, there is usually a numerical or logical issue.\n", "\n", "- The fit function is not analytical everywhere in the parameter space or does not have a local minimum (the minimum may be at infinity, the extremum may be a saddle point or maximum). Indicators for this are `is_above_max_edm=True`, `hesse_failed=True`, `has_posdef_covar=False`, or `has_made_posdef_covar=True`. A non-analytical function is one with a discrete step, for example.\n", "- MIGRAD reached the call limit before the convergence so that `has_reached_call_limit=True`. The number of function calls is given by `nfcn`, and the call limit can be changed with the keyword argument `ncall` in the method `Minuit.migrad`. Note that `nfcn` can be slightly larger than `ncall`, because MIGRAD internally only checks this condition after a full iteration, in which several function calls can happen.\n", "\n", "MIGRAD detects convergence by a small `edm` value, the *estimated distance to minimum*. This is the difference between the current minimum value of the minimized function and the prediction based on the current local quadratic approximation of the function (something that MIGRAD computes as part of its algorithm). If the fit did not converge, `is_above_max_edm` is true.\n", "\n", "If you are interested in parameter uncertainties, you should make sure that:\n", "\n", "- `has_covariance`, `has_accurate_covar`, and `has_posdef_covar` are true.\n", "- `has_made_posdef_covar` and `hesse_failed` are false.\n", "\n", "The second object of interest after the fit is the parameter list, which can be directly accessed with `Minuit.params`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.params" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for p in m.params:\n", " print(repr(p))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "`m.params` is a tuple-like container of `Param` data objects which contain information about the fitted parameters. Important fields are:\n", "\n", "- `number`: parameter index.\n", "- `name`: parameter name.\n", "- `value`: value of the parameter at the minimum.\n", "- `error`: uncertainty estimate for the parameter value.\n", "\n", "Whether the uncertainty estimate is accurate depends on the correct mathematical modeling of your fitting problem and using the right `errordef` value for Minuit. What do we mean by correct mathematical modelling? If you look into the function `simple_least_squares(a, b)`, you see that each squared residual is divided by the expected variance of the residual. This is necessary to get accurate uncertainty estimates for the parameters.\n", "\n", "Sometimes the expected variance of the residual is not well known. If the cost function to minimize satisfies certain conditions, there is a simple test to check whether the residual variances are ok. One should look at the function value at the minimum, given by `Minuit.fmin.fval`, and divide it by the so-called degrees of freedom, which is difference of the number of residuals and the number of fitted parameters, and can be queried with the attribute `Minuit.ndof`. This is called reduced chi2, it can be directly queried with `Minuit.fmin.reduced_chi2`.\n", "\n", "The reduced chi2 is available for all built-in binned cost functions and the `LeastSquares` cost function in `iminuit.cost`. It cannot be automatically provided for unbinned cost functions, since that requires binning the data, which has to be defined by the user. For unbinned cost functions, you can still compute a reduced chi2 yourself, but it is not possible to do automatically. Querying `Minuit.fmin.reduced_chi2` is safe, it either returns a valid value or `nan` if the chi2 cannot be computed automatically for the current cost function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f\"𜒲/ndof = {m.fval:.2f} / {m.ndof} = {m.fmin.reduced_chi2:.2f}\"" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This value should be around 1. The more data points one has, the closer. If the value is much larger than 1, then the data variance is underestimated or the model does not describe the data. If the value is much smaller than 1, then the data variance is overestimated (perhaps because of positive correlations between the fluctuations of the data values).\n", "\n", "The last block shows the covariance matrix, this is useful to check for large correlations which are usually a sign of trouble." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.covariance" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We will discuss this matrix in more detail in the next section.\n", "\n", "## Parameter uncertainties, covariance, and confidence intervals/regions\n", "\n", "You saw how to get the uncertainty of each individual parameter and how to access the full covariance matrix of all parameters together, which includes the correlations. Correlations are essential additional information if you want to work with parameter uncertainties seriously.\n", "\n", "Minuit offers two ways to compute the parameter uncertainties, Hesse and Minos. Both have pros and cons.\n", "\n", "### Hesse for covariance and correlation matrices\n", "\n", "The Hesse algorithm numerically computes the matrix of second derivatives at the function minimum (called the Hesse matrix) and inverts it. The Hesse matrix is symmetric by construction. In the limit of infinite data samples to fit, the result of this computation converges to the true covariance matrix of the parameters. It is often a good and sometimes even an unbiased estimate for finite samples. These errors obtained from this method are sometimes called *parabolic errors*, because the Hesse matrix method is exact if the function is a hyperparabola (third and higher-order derivatives are all zero). The errors are also by construction symmetric in positive and negative direction.\n", "\n", "**Pros**\n", "\n", "- (Comparably) fast computation.\n", "- Provides covariance matrix for error propagation.\n", "- Provides symmetric errors which are easy to work with.\n", "\n", "**Cons**\n", "\n", "- May not have good coverage probability when sample size is small.\n", "\n", "The MIGRAD algorithm computes an approximation of the Hesse matrix automatically during minimization. When the default strategy is used, Minuit does a check whether this approximation is sufficiently accurate and if not, it computes the Hesse matrix automatically.\n", "\n", "All this happens inside the C++ Minuit2 code and is a bit intransparent, so to be on the safe side, we recommend to call `Minuit.hesse` explicitly after the minimization, if exact errors are important." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# let's mess up the current errors a bit so that hesse has something to do\n", "m.errors = (0.16, 0.2)\n", "m.params" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.hesse().params # note the change in \"Hesse Error\"" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Covariance and correlation Matrix\n", "\n", "To see the covariance matrix of the parameters, you do:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "inputHidden": false, "outputHidden": false }, "outputs": [], "source": [ "m.covariance" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The parameters α and β are strongly anti-correlated, the numerical value of the correlation is shown in parentheses. The correlation is also highlighted by the blue color of the off-diagonal elements." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(repr(m.covariance)) # use print(repr(...) to skip pretty printing" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "To get the correlation matrix, use:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.covariance.correlation() # returns a newly created correlation matrix" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Nonzero correlation is not necessarily a bad thing, but if you have freedom in redefining the parameters of the fit function, it is good to chose parameters which are not strongly correlated.\n", "\n", "**Warning:** Minuit cannot accurately minimize the function if two parameters are (almost) perfectly (anti-)correlated. It also means that one of two parameters is superfluous, it doesn't add new information. You should rethink the cost function in this case and try to remove one of the parameters from the fit, either by fixing its value or by expressing it as a function of the other parameters.\n", "\n", "Both matrices are subclasses of `numpy.ndarray`, so you can use them everywhere you would use a NumPy array. In addition, these matrices support value access via parameter names:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.covariance[\"α\", \"β\"]" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### MINOS for non-parabolic minima\n", "\n", "Minuit has another algorithm to compute uncertainties: MINOS. It implements the so-called profile likelihood method, where the neighborhood around the function minimum is scanned until the contour is found where the function increase by the value of `errordef`. The contour defines a confidence region that covers the true parameter point with a certain probability. The probability is exactly known in the limit of infinitely large data samples, but approximate for the finite case. Please consult a textbook about statistics about the mathematical details or look at the tutorial \"Error computation with HESSE and MINOS\".\n", "\n", "**Pros**\n", "\n", "- Produces asymmetric errors, which may better visualize the uncertainty in the parameter.\n", "- Produces pretty two-dimensional confidence regions for scientific plots.\n", "\n", "**Cons**\n", "\n", "- Computationally expensive.\n", "- Asymmetric errors are difficult to error-propagate, see [Barlow 2004](https://arxiv.org/pdf/physics/0406120.pdf).\n", "\n", "MINOS is not automatically called during minimization, it needs to be called explicitly afterwards, like so:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.minos()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "By now you are probably used to seeing green colors, which indicate that Minos ran successful. Be careful when these are red instead, Minos can fail. The fields in the new Minos table mean the following:\n", "\n", "- Valid: Whether Minos considers the scan result valid.\n", "- At Limit: True if Minos hit a parameter limit before the finishing the contour, which would be bad.\n", "- Max FCN: True if Minos reached the maximum number of allowed calls before finishing the contour, also bad.\n", "- New Min: True if Minos discovered a deeper local minimum in the neighborhood of the current one. Not necessarily bad, but should not happen.\n", "\n", "The errors computed by Minos are now also shown in the parameter list." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.params" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "**Note:** If the absolute values of the Minos errors are very close to the Hesse Error, the function is well approximated by a hyperparabola around the minimum. You can use this as a check instead of explicitly plotting the function around the minimum (for which we provide tools, see below).\n", "\n", "### Coverage probability of intervals/regions constructed with Hesse and Minos algorithms\n", "\n", "It is important to construct confidence intervals (and confidence regions in multiple dimensions) which have a well-defined coverage probability. How confidence intervals are correctly interpreted is [explained in the Wikipedia](https://en.wikipedia.org/wiki/Confidence_interval), [this Stackoverflow article](https://stats.stackexchange.com/questions/26450/why-does-a-95-confidence-interval-ci-not-imply-a-95-chance-of-containing-the/26457#26457), and in good introductory text books on statistics. The slightly unintuitive interpretation is the price to pay in the frequentist framework of statistics to avoid subjective priors.\n", "\n", "Standard one-dimensional confidence intervals should have 68 % coverage probability. As previously mentioned, the coverage probability of the intervals constructed from the uncertainties reported by Hesse and Minos are not necessarily the standard 68 %.\n", "\n", "Whether Hesse or Minos produce an interval with a coverage probability closer to the desired level in finite samples depends on the case. There are theoretical results which suggest that Hesse may be slightly better, but we also found special cases where Minos intervals performed better.\n", "\n", "Some sources claim that Minos gives better coverage when the cost function is not parabolic around the minimum; that is not generally true, in fact Hesse intervals may have better coverage.\n", "\n", "As a rule-of-thumb, use Hesse as the default and try both algorithms if accurate coverage probability matters.\n", "\n", "## Quick access to fit results\n", "\n", "You get the main fit results with properties and methods from the `Minuit` object. We used several of them already. Here is a summary:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(m.values) # array-like view of the parameter values" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# access values by name or index\n", "print(\"by name \", m.values[\"α\"])\n", "print(\"by index\", m.values[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iterate over values\n", "for key, value in zip(m.parameters, m.values):\n", " print(f\"{key} = {value}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# slicing works\n", "print(m.values[:1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(m.errors) # array-like view of symmetric uncertainties" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "`Minuit.errors` supports the same access as `Minuit.values`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(m.params) # parameter info (using str(m.params))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(repr(m.params)) # parameter info (using repr(m.params))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# asymmetric uncertainties (using str(m.merrors))\n", "print(m.merrors)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# asymmetric uncertainties (using repr(m.merrors))\n", "print(repr(m.merrors))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(m.covariance) # covariance matrix computed by Hesse (using str(m.covariance))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\n", " repr(m.covariance)\n", ") # covariance matrix computed by Hesse (using repr(m.covariance))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "As already mentioned, you can play around with iminuit by assigning new values to `m.values` and `m.errors` and then run `m.migrad()` again. The values will be used as a starting point.\n", "\n", "## Plotting\n", "\n", "`iminuit` comes with built-in methods to draw the likelihood around the minimum. These can be used to draw confidence regions with a defined confidence level or for debugging the likelihood.\n", "\n", "### Drawing confidence regions\n", "\n", "To get a generic overview, use the method `Minuit.draw_mnmatrix`. It shows scans over the likelihood where all other parameters than the ones scanned are minimized, in other words, it is using the Minos algorithm. The regions and intervals found in this way correspond to uncertainty intervals. It is also a great way to see whether the likelihood is sane around the minimum. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# find the minimum again after messing around with the parameters\n", "m.migrad()\n", "\n", "# draw matrix of likelihood contours for all pairs of parameters at 1, 2, 3 sigma\n", "m.draw_mnmatrix();" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The diagonal cells show the 1D profile around each parameter. The points were the horizontal lines cross the profile correspond to confidence intervals with confidence level `cl` (a probability). The off-diagonal cells show confidence regions with confidence level `cl`. Asymptotically (in large samples), the `cl` is equal to the probability that the region contains the true value. In finite samples, this is usually only approximately so.\n", "\n", "For convenience, the drawing functions interpret `cl >= 1` as the number of standard deviations with a confidence level that corresponds to a standard normal distribution:\n", "\n", "- cl = 1: 68.3 %\n", "- cl = 2: 95.4 %\n", "- cl = 3: 99.7 %\n", "\n", "Drawing all profiles and regions can be time-consuming. The following commands show how to draw only individual contours or profiles." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# draw three confidence regions with 68%, 90%, 99% confidence level\n", "m.draw_mncontour(\"α\", \"β\", cl=(0.68, 0.9, 0.99));" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# get individual contours to plot them yourself\n", "pts = m.mncontour(\"α\", \"β\", cl=0.68, size=20)\n", "x, y = np.transpose(pts)\n", "plt.plot(x, y, \"o-\");" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "To make the contour look nicer, you can increase the `size` parameter or use the `interpolated` parameter to do cubic spline interpolation or use the `experimental` algorithm." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# draw original points\n", "plt.plot(x, y, \".\", label=\"size=20\")\n", "\n", "# draw interpolated points\n", "pts2 = m.mncontour(\"α\", \"β\", cl=0.68, size=20, interpolated=100)\n", "x2, y2 = np.transpose(pts2)\n", "plt.plot(x2, y2, label=\"size=20, interpolated\")\n", "\n", "# actual curve at higher resolution\n", "pts = m.mncontour(\"α\", \"β\", cl=0.68, size=100)\n", "x3, y3 = np.transpose(pts)\n", "plt.plot(x3, y3, \"-\", label=\"size=100\")\n", "\n", "plt.legend();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# with experimental algorithm\n", "pts = m.mncontour(\"α\", \"β\", cl=0.68, size=50, experimental=True)\n", "x4, y4 = np.transpose(pts)\n", "plt.plot(x4, y4, \"-\", label=\"size=50 experimental\");" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The experimental algorithm takes more time but produces a smoother contour.\n", "\n", "To draw the 1D profile, call `Minuit.draw_mnprofile`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.draw_mnprofile(\"α\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# or use this to plot the result of the scan yourself\n", "a, fa, ok = m.mnprofile(\"α\")\n", "plt.plot(a, fa);" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Likelihood debugging\n", "\n", "`mnmatrix`, `mnprofile`, and `mncontour` do Minos scans. If you have trouble with Minos or with the minimization, you should check how the likelihood looks like where you are. The following functions perform no minimization, they just draw the likelihood function as it is at certain coordinates." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# draw 1D scan over likelihood, the minimum value is subtracted by default\n", "m.draw_profile(\"α\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# or draw it yourself, the minimum value is not subtracted here\n", "x, y = m.profile(\"α\")\n", "plt.plot(x, y);" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# draw 2D scan over likelihood\n", "m.draw_contour(\"α\", \"β\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# or use this to plot the result of the scan yourself\n", "x, y, z = m.contour(\"α\", \"β\", subtract_min=True)\n", "cs = plt.contour(x, y, z, (1, 2, 3, 4)) # these are not sigmas, just the contour values\n", "plt.clabel(cs);" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Interactive fit\n", "\n", "In Jupyter notebooks, it is possible to fit a model to data interactively, by calling `Minuit.interactive`. This functionality requires optional extra packages. If they are not there, you will get a friendly error message telling you what you need to install." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "You can change the parameter values with the sliders. Clicking the \"Fit\" button runs `Minuit.migrad` with these as starting values.\n", "\n", "**Note:** If you see this notebook on ReadTheDocs or otherwise statically rendered, changing the sliders won't change the plot. This requires a running Jupyter kernel.\n", "\n", "Interactive fits are useful to find starting values and to debug the fit. The following issues are easy to detect:\n", "\n", "- Starting values are way off.\n", "- You forgot to set limits on some parameters.\n", "- Some parameters are strongly correlated.\n", "- Your model is not analytical.\n", "\n", "Strong correlations are caused when a change to one parameter can be almost perfectly undone by a changing one or more other parameters. If the model suddenly jumps when you move the sliders, this may indicate that the model is not analytical, but also note that the sliders have finite resolution and the model curve is also only drawn with finite resolution. Set tighter limits on the affected parameter or investigate the root cause with numerical experiments.\n", "\n", "`Minuit.interactive` uses the `visualize` method on the cost function, if it is available. All built-in cost functions provide this method, but it only works for 1D distributions, since there is no obvious general way to visualize data-model agreement in higher dimensions. You can provide your visualization though, see the documentation of `Minuit.interactive`. This can also be useful to draw the model in more detail, for example, if you want to give different components in an additive model different colors (e.g. signal and background)." ] } ], "metadata": { "kernel_info": { "name": "python3" }, "kernelspec": { "display_name": "Python 3.8.13 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "nteract": { "version": "0.12.3" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/binned_vs_unbinned.ipynb0000644000000000000000000226552314332717401017666 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Binned vs. unbinned fits\n", "\n", "We compare binned with unbinned fit applied to a toy example of a gaussian signal peak over exponential background.\n", "\n", "For one-dimensional data, binned fit are preferred. They are usually considerably faster than an unbinned fit and more numerically stable. For multi-dimensional data, however, an unbinned fit can be faster.\n", "\n", "It is a common misconception that binned fits are inherently biased. This idea originates from the past when it was common (at least in particle physics) to fit binned data with the least-squares method, which is indeed biased, see [Dembinski, Schmelling, Waldi, *Application of the Iterated Weighted Least-Squares Fit to counting experiments*, NIM A 940 (2019) 135-141](https://doi.org/10.1016/j.nima.2019.05.086). That bias can be completely avoided, however, if the fit uses the maximum-likelihood method and a Poisson distribution to describe the observed bin contents as a function of the predicted ones, and if the model prediction for a bin content is properly computed by integrating over the model density, instead of computing it from the density at the bin center times the bin width. The cost functions `BinnedNLL` and `ExtendedBinnedNLL` from `iminuit.cost` use the correct calculation.\n", "\n", "So there is no need to worry bias, but some information is lost in the binning process - the densities of events inside each bin. This loss can be made negligible by making the bin width small enough. How small the bins have to be depends on the sensitivity of the model parameter on this particular loss of information. In this tutorial we demonstrate this and also demonstrate the difference in run-time of unbinned and binned fits.\n", "\n", "**Conclusions:** With only 20 bins, the binned fit reached an accuracy for the signal yield that is comparable to the unbinned fit. With 50 bins, also all shape parameters have uncertainties that are less than 5 % larger than those in the unbinned fit. At the same time, the binned fit is much faster. Even with 200 bins, the binned fit is two orders of magnitude faster than the unbinned fit. In practice, this is a huge difference, 3 seconds vs. 5 minutes.\n", "\n", "You can try to run this notebook with a data sample contains less points, then the difference will not be as dramatic." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "from numba_stats import norm, expon\n", "import matplotlib.pyplot as plt\n", "from iminuit import Minuit\n", "from iminuit.cost import ExtendedUnbinnedNLL, ExtendedBinnedNLL\n", "import joblib\n", "from IPython.display import display" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# sample size, change this to see how the results of the comparison change\n", "n = 100_000\n", "truth = np.array((1.0, 1.0, 1.0, 0.1, 1.0))\n", "\n", "rng = np.random.default_rng(1)\n", "s = rng.normal(truth[2], truth[3], size=int(n * truth[0]))\n", "b = rng.exponential(truth[4], size=int(n * truth[1]))\n", "pts = np.append(s, b)\n", "pts = pts[(pts > 0) & (pts < 2)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def fit(c):\n", " m = Minuit(c, s=1, b=1, mu=1, sigma=0.1, tau=1)\n", " m.limits[\"s\", \"b\", \"sigma\", \"tau\"] = (0, None)\n", " m.limits[\"mu\"] = (0, 2)\n", " m.migrad()\n", " assert m.valid\n", " return m" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = -4.08e+06 Nfcn = 120
EDM = 1.25e-05 (Goal: 0.0002) time = 2.2 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 s 0.995 0.004 0
1 b 1.008 0.005 0
2 mu 999.3e-3 0.4e-3 0 2
3 sigma 99.21e-3 0.34e-3 0
4 tau 1.002 0.007 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
s b mu sigma tau
s 1.32e-05 -0.005e-3 (-0.281) -0.04e-6 (-0.029) 0.30e-6 (0.246) -0.004e-3 (-0.159)
b -0.005e-3 (-0.281) 2.36e-05 0 -0.46e-6 (-0.283) 0.020e-3 (0.586)
mu -0.04e-6 (-0.029) 0 1.46e-07 -0.01e-6 (-0.044) -0.14e-6 (-0.054)
sigma 0.30e-6 (0.246) -0.46e-6 (-0.283) -0.01e-6 (-0.044) 1.12e-07 -0.36e-6 (-0.157)
tau -0.004e-3 (-0.159) 0.020e-3 (0.586) -0.14e-6 (-0.054) -0.36e-6 (-0.157) 4.76e-05
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:58:24.216166\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = -4.08e+06 │ Nfcn = 120 │\n", "│ EDM = 1.25e-05 (Goal: 0.0002) │ time = 2.2 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ s │ 0.995 │ 0.004 │ │ │ 0 │ │ │\n", "│ 1 │ b │ 1.008 │ 0.005 │ │ │ 0 │ │ │\n", "│ 2 │ mu │ 999.3e-3 │ 0.4e-3 │ │ │ 0 │ 2 │ │\n", "│ 3 │ sigma │ 99.21e-3 │ 0.34e-3 │ │ │ 0 │ │ │\n", "│ 4 │ tau │ 1.002 │ 0.007 │ │ │ 0 │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬───────────────────────────────────────────────────â”\n", "│ │ s b mu sigma tau │\n", "├───────┼───────────────────────────────────────────────────┤\n", "│ s │ 1.32e-05 -0.005e-3 -0.04e-6 0.30e-6 -0.004e-3 │\n", "│ b │ -0.005e-3 2.36e-05 0 -0.46e-6 0.020e-3 │\n", "│ mu │ -0.04e-6 0 1.46e-07 -0.01e-6 -0.14e-6 │\n", "│ sigma │ 0.30e-6 -0.46e-6 -0.01e-6 1.12e-07 -0.36e-6 │\n", "│ tau │ -0.004e-3 0.020e-3 -0.14e-6 -0.36e-6 4.76e-05 │\n", "└───────┴───────────────────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def density(x, s, b, mu, sigma, tau):\n", " xrange = (0, 2)\n", " s1 = s * n * np.diff(norm.cdf(xrange, mu, sigma))\n", " b1 = b * n * np.diff(expon.cdf(xrange, 0, tau))\n", " return s1 + b1, (s * n * norm.pdf(x, mu, sigma) + b * n * expon.pdf(x, 0, tau))\n", "\n", "\n", "m = fit(ExtendedUnbinnedNLL(pts, density))\n", "par_names = [m.params[i].name for i in range(m.npar)]\n", "results = {np.inf: (np.array(m.values), np.array(m.errors), m.fmin.time)}\n", "m" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:58:24.536331\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "xm = np.linspace(np.min(pts), np.max(pts), 1000)\n", "_, ym = density(xm, *m.values)\n", "plt.hist(pts, bins=100, range=(0, 2), label=\"data\")\n", "dx = 2 / 100\n", "plt.plot(xm, ym * dx, label=\"fit\")\n", "plt.legend()\n", "plt.xlabel(\"x\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This fit is unbinned, the observed sample is binned here only for visualisation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 190.9 (χ²/ndof = 1.0) Nfcn = 110
EDM = 2.17e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 190.9 (χ²/ndof = 1.0) │ Nfcn = 110 │\n", "│ EDM = 2.17e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 87.19 (χ²/ndof = 0.9) Nfcn = 110
EDM = 2.41e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 87.19 (χ²/ndof = 0.9) │ Nfcn = 110 │\n", "│ EDM = 2.41e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 36.34 (χ²/ndof = 0.8) Nfcn = 110
EDM = 1.7e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 36.34 (χ²/ndof = 0.8) │ Nfcn = 110 │\n", "│ EDM = 1.7e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 7.555 (χ²/ndof = 0.5) Nfcn = 102
EDM = 5.22e-05 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 7.555 (χ²/ndof = 0.5) │ Nfcn = 102 │\n", "│ EDM = 5.22e-05 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 2.084 (χ²/ndof = 0.4) Nfcn = 114
EDM = 4.66e-08 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 2.084 (χ²/ndof = 0.4) │ Nfcn = 114 │\n", "│ EDM = 4.66e-08 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 2.677e-06 Nfcn = 112
EDM = 2.67e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 2.677e-06 │ Nfcn = 112 │\n", "│ EDM = 2.67e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:58:25.591219\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def integral(xe, s, b, mu, sigma, tau):\n", " return s * n * norm.cdf(xe, mu, sigma) + b * n * expon.cdf(xe, 0, tau)\n", "\n", "\n", "fig, ax = plt.subplots(3, 2, figsize=(10, 8), sharex=True, constrained_layout=True)\n", "for axi, bins in zip(ax.flat, (200, 100, 50, 20, 10, 5)):\n", " w, xe = np.histogram(pts, bins=bins, range=(0, 2))\n", " c = ExtendedBinnedNLL(w, xe, integral)\n", " m = fit(c)\n", " display(m.fmin)\n", " axi.stairs(w, xe, fill=True, label=\"data\")\n", " axi.stairs(np.diff(integral(xe, *m.values)), xe, label=\"fit\")\n", " axi.legend(title=f\"bins = {len(w)}\")\n", " results[bins] = (np.array(m.values), np.array(m.errors), m.fmin.time)\n", "fig.supxlabel(\"x\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:58:26.271725\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "npar = len(results[np.inf][0])\n", "\n", "fig, ax = plt.subplots(npar, 2, sharex=True, figsize=(10, 10))\n", "for j, (k, (v, e, _)) in enumerate(results.items()):\n", " for i, (vi, ei) in enumerate(zip(v, e)):\n", " c = f\"C{i}\"\n", " ax[i, 0].errorbar(j, vi, ei, color=c, fmt=\"o\")\n", " ax[i, 0].set_ylabel(par_names[i])\n", " einf = results[np.inf][1][i]\n", " ax[i, 1].plot(j, ei / einf, \"o\", color=c)\n", "for i in range(npar):\n", " ax[i, 1].set_ylim(0.95, 1.2)\n", " ax[i, 1].axhline(1.05, ls=\"--\", color=\"0.5\")\n", "plt.xticks(np.arange(7), [f\"{x}\" for x in results.keys()]);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Shown on the left is the fitted value and its uncertainty estimate. Shown of the right is the relative size of the error bar of the binned fit compared to the unbinned fit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T10:58:26.797669\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "x = np.arange(7)\n", "y = [v[2] for v in results.values()]\n", "plt.plot(x, y, \"o\")\n", "for xi, yi in zip(x[1:], y[1:]):\n", " plt.text(xi, yi * 1.2, f\"{y[0]/yi:.0f}x\", ha=\"center\")\n", "plt.xticks(x, [f\"{x}\" for x in results.keys()])\n", "plt.ylabel(\"time / sec\")\n", "plt.semilogy();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now demonstrate that the binned fits and the unbinned fit are unbiased. We repeat the fit many times with independent random samples, the mean of the results minus the truth is the bias. In each iteration, the binned fits use the same data that the unbinned fit uses." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@joblib.delayed\n", "def run(seed):\n", " rng = np.random.default_rng(seed)\n", " s = rng.normal(truth[2], truth[3], size=int(n * truth[0]))\n", " b = rng.exponential(truth[4], size=int(n * truth[1]))\n", " pts = np.append(s, b)\n", " pts = pts[(pts > 0) & (pts < 2)]\n", "\n", " if bins == np.inf:\n", " m = fit(ExtendedUnbinnedNLL(pts, density))\n", " assert m.valid\n", " else:\n", " w, xe = np.histogram(pts, bins=bins, range=(0, 2))\n", " m = fit(ExtendedBinnedNLL(w, xe, integral))\n", " assert m.valid\n", " return np.array(m.values)\n", "\n", "\n", "results = {}\n", "for bins in (np.inf, 200, 100, 50, 20, 10, 5):\n", " results[bins] = joblib.Parallel(-1)(run(seed) for seed in range(100))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:24.676343\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:24.732845\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:24.852060\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:24.912010\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:24.982423\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:25.152378\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:00:25.360993\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ref = None\n", "for bin, values in results.items():\n", " plt.figure(figsize=(5, 3))\n", " m = np.mean(values, axis=0) - truth\n", " s = np.std(values, axis=0, ddof=1)\n", " plt.title(f\"{bin=}\")\n", " plt.errorbar(np.arange(len(m)), m / s, 1, fmt=\"o\", label=f\"{bin=}\")\n", " plt.axhline(0, ls=\"--\", color=\"0.5\")\n", " plt.xticks(np.arange(len(m)), [\"s\", \"b\", \"mu\", \"sigma\", \"tau\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The plots show the bias relative to the standard deviation for each parameter. All results are unbiased, whatever the binning. The bias is not exactly zero, since we used only 100 repetitions, it shrinks further with more. One can observe that the residual bias that is coming from the finite sampling is the same for the unbinned fit and the fits with 100 and 200 bins, which are essentially equivalent." ] } ], "metadata": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" }, "keep_output": true, "kernelspec": { "display_name": "Python 3.8.12 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/conditional_variable.ipynb0000644000000000000000000077356314332717401020213 0ustar00{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Fit PDF with conditional variable\n", "\n", "In this example, we show an unusual fit where the total sample is not drawn form a single probability distribution, but each individual sample $x$ is drawn from a different distribution, whose parameters are determined by a conditional variable $y$.\n", "\n", "In our example, we are drawing samples $x$ from varying Gaussian distributions. The location of each Gaussian is a function of the conditional variable $y$, but all share the same width parameter $\\sigma$. We fit the shared parameter $\\sigma$, but also the parameters $a$ and $b$ which determine how the location of each gaussian depends on $y$, assuming a line function $\\mu = a + b y$.\n", "\n", "This tutorial reproduces a [corresponding one from RooFit](https://root.cern.ch/doc/master/rf303__conditional_8C.html)." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "iminuit version 2.28.0\n" ] } ], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import iminuit\n", "from iminuit.cost import UnbinnedNLL\n", "from iminuit import Minuit\n", "import numpy as np\n", "import numba as nb\n", "import boost_histogram as bh\n", "import matplotlib.pyplot as plt\n", "from scipy.stats import norm\n", "from numba_stats import norm as norm_nb\n", "\n", "print(\"iminuit version\", iminuit.__version__)" ] }, { "cell_type": "code", "execution_count": null, "id": "2", "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1)\n", "\n", "# conditional variable: each sample is paired with a random y parameter\n", "y = rng.normal(0, 10, size=10000)\n", "y = y[np.abs(y) < 10] # truncate at 10\n", "\n", "\n", "# location of each gaussian is a function of y\n", "def mu(y, a, b):\n", " return a + b * y\n", "\n", "\n", "# draw samples from Gaussians whose locations depend on y\n", "truth = {\"a\": 0, \"b\": 0.5, \"sigma\": 1.0}\n", "x = rng.normal(mu(y, truth[\"a\"], truth[\"b\"]), truth[\"sigma\"])" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "The distribution in $x$ is more broad than the usual Gaussian because it is a convolution of many Gaussian distributions with varying means. We can visualise this by binning the data in $x$ and $y$." ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:01:08.429955\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ax_x = bh.axis.Regular(100, -10, 10)\n", "ax_y = bh.axis.Regular(5, -10, 10)\n", "h = bh.Histogram(ax_x, ax_y)\n", "h.fill(x, y)\n", "for i, (a, b) in enumerate(ax_y):\n", " plt.stairs(h.values()[:, i], ax_x.edges, label=f\"[{a}, {b})\", fill=True, alpha=0.2)\n", "h1 = h[:, sum]\n", "plt.stairs(h1.values(), ax_x.edges, color=\"k\", label=\"total\")\n", "plt.xlabel(\"x\")\n", "plt.ylabel(\"events\")\n", "plt.legend(title=\"y interval\", frameon=False, handlelength=1.2);" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "## Fit with conditional variable\n", "\n", "The random distribution of $x$ depends on the value of $y$. We can exploit that information in the likelihood function to obtain a more accurate estimate of the parameters." ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 1.93e+04 Nfcn = 130
EDM = 2.25e-06 (Goal: 0.0002) time = 0.1 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 a -0.010 0.012
1 b 0.4993 0.0022
2 sigma 0.986 0.008 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
a b sigma
a 0.000142 0e-6 0
b 0e-6 4.76e-06 0e-6
sigma 0 0e-6 7.08e-05
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 1.93e+04 │ Nfcn = 130 │\n", "│ EDM = 2.25e-06 (Goal: 0.0002) │ time = 0.1 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ a │ -0.010 │ 0.012 │ │ │ │ │ │\n", "│ 1 │ b │ 0.4993 │ 0.0022 │ │ │ │ │ │\n", "│ 2 │ sigma │ 0.986 │ 0.008 │ │ │ 0 │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬────────────────────────────â”\n", "│ │ a b sigma │\n", "├───────┼────────────────────────────┤\n", "│ a │ 0.000142 0e-6 0 │\n", "│ b │ 0e-6 4.76e-06 0e-6 │\n", "│ sigma │ 0 0e-6 7.08e-05 │\n", "└───────┴────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def model(xy, a, b, sigma):\n", " x, y = xy\n", " mu = a + b * y\n", " # cannot use norm.pdf from numba_stats here, because it is not vectorized in mu\n", " return norm.pdf(x, mu, sigma)\n", "\n", "\n", "nll = UnbinnedNLL((x, y), model)\n", "\n", "m = Minuit(nll, 0.0, 0.0, 2.0)\n", "m.limits[\"sigma\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:01:08.931729\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# construct model representation for comparison with data histogram\n", "a, b, sigma = m.values\n", "\n", "# get expected content per bin from cdf, sum over the individual cdfs\n", "v = np.diff(np.sum(norm.cdf(ax_x.edges[:, np.newaxis], mu(y, a, b), sigma), axis=1))\n", "\n", "plt.stairs(v, ax_x.edges, label=\"model\", zorder=5, lw=2)\n", "plt.errorbar(ax_x.centers, h1.values(), h1.variances() ** 0.5, fmt=\"ok\", label=\"data\")\n", "plt.xlabel(\"x\")\n", "plt.ylabel(\"events\")\n", "plt.legend(frameon=False);" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "## Fit without conditional variable\n", "\n", "We can also ignore the dependence of $x$ and $y$ and just fit the total $x$ distribution with a model built from the distribution of $y$ values. This also works in this case, but information is lost and therefore the parameter uncertainties become larger than in the previous case.\n", "\n", "On top of that, the calculation is much slower, because building the pdf is more expensive. We parallelise the computation with numba." ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = -8.774e+04 Nfcn = 95
EDM = 1.33e-06 (Goal: 0.0002) time = 12.5 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 a 0.002 0.029
1 b 0.500 0.005
2 sigma 0.98 0.04 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
a b sigma
a 0.000839 0.004e-3 (0.030) -0 (-0.027)
b 0.004e-3 (0.030) 2.43e-05 -0.141e-3 (-0.718)
sigma -0 (-0.027) -0.141e-3 (-0.718) 0.0016
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:01:21.558091\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = -8.774e+04 │ Nfcn = 95 │\n", "│ EDM = 1.33e-06 (Goal: 0.0002) │ time = 12.5 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ a │ 0.002 │ 0.029 │ │ │ │ │ │\n", "│ 1 │ b │ 0.500 │ 0.005 │ │ │ │ │ │\n", "│ 2 │ sigma │ 0.98 │ 0.04 │ │ │ 0 │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬───────────────────────────────â”\n", "│ │ a b sigma │\n", "├───────┼───────────────────────────────┤\n", "│ a │ 0.000839 0.004e-3 -0 │\n", "│ b │ 0.004e-3 2.43e-05 -0.141e-3 │\n", "│ sigma │ -0 -0.141e-3 0.0016 │\n", "└───────┴───────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nb.config.THREADING_LAYER = \"workqueue\"\n", "\n", "\n", "@nb.njit(parallel=True, fastmath=True)\n", "def model(x, a, b, sigma):\n", " mu = a + b * y\n", " total = np.zeros_like(x)\n", " for i in nb.prange(len(mu)):\n", " total += norm_nb.pdf(x, mu[i], sigma)\n", " return total\n", "\n", "\n", "nll = UnbinnedNLL(x, model)\n", "m2 = Minuit(nll, 0.0, 0.0, 2.0)\n", "m2.limits[\"sigma\"] = (0, None)\n", "m2.migrad()" ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:01:22.050500\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 3, figsize=(8, 2), constrained_layout=True)\n", "for par, axi in zip(m.parameters, ax):\n", " axi.set_title(par)\n", " t = truth[par]\n", " axi.axhline(t, ls=\"--\", color=\"0.5\")\n", " axi.errorbar([\"with\\n conditional\"], m.values[par], m.errors[par], fmt=\"ok\")\n", " axi.errorbar([\"without\\n conditional\"], m2.values[par], m2.errors[par], fmt=\"or\")\n", " axi.set_xlim(-0.5, 1.5)\n", " dt = 2 * m2.errors[par]\n", " axi.set_ylim(t - dt, t + dt)" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 5 } iminuit-2.30.1/doc/notebooks/correlated_data.ipynb0000644000000000000000000001646414332717401017146 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Fitting data with correlated uncertainties\n", "\n", "We sometimes want to combine results from different studies. If these results have independent uncertainties and can be expected to have the same mean, then the optimal combination (minimum variance) is given by a weighted mean, where the weight is inversely proportional to the variance (uncertainty squared) of each individual input value. [This is a well-known result](https://en.wikipedia.org/wiki/Inverse-variance_weighting).\n", "\n", "If the uncertainties of the results are correlated, it is more complicated to compute an optimally weighted mean. Instead of deriving analytical formulas, we use a fit here to obtain the mixing weight, which is equivalent. It serves to demonstrate how fits to correlated data values can be carried out. A whole project built on this approach is [GammaCombo](https://gammacombo.github.io/).\n", "\n", "We consider a toy example where two measurements should be combined which have strongly correlated systematic uncertainties." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here are the results we want to comine. The statistical uncertainties are assumed to be uncorrelated, the systematic uncertainties are assumed to be perfectly correlated (represented by thick bars in the plot)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "value = [1.2, 1.5]\n", "error_sta = [0.3, 0.3]\n", "error_sys = [0.1, 0.2]\n", "correlation_sys = 1.0\n", "\n", "plt.errorbar((\"result 1\", \"result 2\"), value, error_sta, fmt=\"o\")\n", "plt.errorbar((\"result 1\", \"result 2\"), value, error_sys, lw=3, fmt=\"none\")\n", "plt.xlim(-0.5, 1.5);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We formulate the combination as a fitting problem. We assume that both results originate from a common true value, which we can estimate in the usual way. Our objective function is derived from the log-probability of a multivariate normal distribution (in the derivation we dropped constants and scaled the result). We predict the constant mean of this distribution, which is matched to the two observed values while taking their covariance into account. The covariance matrix of the multivariate normal distribution captures the correlated uncertainties of the individual results.\n", "\n", "The combined result obtained in this way is unbiased (assuming all inputs are unbiased) and also happens to minimize the variance, so this approach is optimal (unbiased and has minimum variance) even if the input results are not distributed like a multivariate normal.\n", "\n", "The simpler special case for uncorrelated observations is handled in `iminuit.cost.LeastSquares`, but for the general case there is no ready-made cost function yet, so we write it here." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# construct covariance matrices\n", "cov_sta = np.diag(np.square(error_sta))\n", "cov_sys = np.diag(np.square(error_sys))\n", "cov_sys[0, 1] = error_sys[0] * error_sys[1] * correlation_sys\n", "cov_sys[1, 0] = cov_sys[0, 1]\n", "\n", "# total covariance is sum of individual contributions\n", "cov = cov_sta + cov_sys\n", "inv_cov = np.linalg.inv(cov)\n", "\n", "\n", "def model(x, z):\n", " \"\"\"Return combined value based on input x and mixing parameter z.\"\"\"\n", " return z * x[1] + (1 - z) * x[0]\n", "\n", "\n", "def cost(z):\n", " \"\"\"Chi-square distributed cost function.\"\"\"\n", " xp = model(value, z)\n", " delta = value - xp\n", " return np.einsum(\"i,j,ij\", delta, delta, inv_cov)\n", "\n", "\n", "# with this extra information, iminuit will also print the chi2/ndof gof statistic\n", "cost.errordef = Minuit.LEAST_SQUARES\n", "cost.ndata = len(value)\n", "\n", "m = Minuit(cost, 0.5)\n", "m.limits[\"z\"] = (0, 1)\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our fit gives more weight to the more accurate measurement, as expected. In order to find the statistical and systematic uncertainty of the combined result, we do error propagation. We compute the trivial Jacobian for our model analytically." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "z = m.values[0]\n", "jac = np.array([z, (1 - z)])\n", "total = model(value, z)\n", "total_err_sta = np.einsum(\"i,j,ij\", jac, jac, cov_sta) ** 0.5\n", "total_err_sys = np.einsum(\"i,j,ij\", jac, jac, cov_sys) ** 0.5\n", "\n", "print(f\"total = {total:.2f} +/- {total_err_sta:.2f}(sta) + {total_err_sys:.2f}(sys)\")\n", "\n", "plt.errorbar(\n", " (\"result 1\", \"result 2\", \"combined\"),\n", " value + [total],\n", " error_sta + [total_err_sta],\n", " fmt=\"o\",\n", ")\n", "plt.errorbar(\n", " (\"result 1\", \"result 2\", \"combined\"),\n", " value + [total],\n", " error_sys + [total_err_sys],\n", " lw=3,\n", " fmt=\"none\",\n", ")\n", "plt.xlim(-1, 3);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note how the systematic uncertainty gets barely reduced by the combination, a consequence of the strong correlation. Try running this example with zero correlation to see how the uncertainty becomes smaller.\n", "\n", "## Further reading\n", "\n", "[Schmelling (2000)](https://arxiv.org/abs/hep-ex/0006004) argues that a combination may ignore data correlations if they are not well-known, because a result of a combination that ignores correlations is still unbiased, it merely does not have minimum possible variance. Depending on the situation, this may be preferable over the result shown here which takes the correlation into account, since one then has to propagate the uncertainty of correlation into the combined result.\n", "\n", "[Cowan (2018)](https://inspirehep.net/literature/1694207) demonstrates that it is techniqually feasible and beneficial to include uncertainties on uncertainties explicitly in the likelihood when combining measurements.\n", "\n", "[Barlow (2022)](https://inspirehep.net/literature/1509024) discusses two commonly used techniques to combine measurements with correlated systematic uncertainties, and shows under which conditions they are equivalent." ] } ], "metadata": { "kernelspec": { "display_name": "py311", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/cost_function_benchmarks.ipynb0000644000000000000000000107722114332717401021102 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Performance of cost functions\n", "\n", "This is not really a tutorial, but more of a benchmark of the builtin cost functions.\n", "\n", "We test the performance of the cost functions shipped with iminuit. We check that they produce unbiased results with proper variance. To do that, we generate normal distributed data many times and fit a normal distribution to each independent data set. The bias is computed from the averages of these reconstructed parameters. We also compute the mean of the estimated variance for each data set, which should converge to 1.\n", "\n", "Since we do the fit many times, we do not use implementations of the pdf and cdf of a normal distribution from `scipy.stats`, but Numba-accelerated versions from the `numba-stats` package. For the binned fits, we compute histograms of the data with $3 + n/10$ equidistant bins, where $n$ is the sample size.\n", "\n", "Disclaimer: This tutorial is targeted at experts, please read the code to understand what is going on." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Maximum-likelihood fits\n", "\n", "Here we check that the different maximum-likelihood cost functions produce asymptotically unbiased results with the expected variance." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from iminuit import Minuit\n", "from iminuit.cost import (\n", " UnbinnedNLL,\n", " BinnedNLL,\n", " ExtendedUnbinnedNLL,\n", " ExtendedBinnedNLL,\n", " LeastSquares,\n", ")\n", "from argparse import Namespace\n", "from numba_stats import norm\n", "import joblib" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 2 need to re-try [(True, True), (True, True), (True, True), (False, False)]\n", "10 9 need to re-try [(True, True), (True, True), (True, True), (False, False)]\n", "10 57 need to re-try [(True, True), (True, True), (False, False), (False, False)]\n", "10 85 need to re-try [(True, True), (True, True), (True, True), (False, True)]\n" ] } ], "source": [ "n_tries = 100 # increase this to get less scattering\n", "\n", "n_pts = np.array((10, 30, 100, 300, 1000, 3000, 10000))\n", "\n", "truth = Namespace(mu=0, sigma=1)\n", "\n", "\n", "# function that runs random experiments with sample size n\n", "@joblib.delayed\n", "def compute(n):\n", " rng = np.random.default_rng(n)\n", " np.random.seed(n)\n", " u_nll = []\n", " b_nll = []\n", " e_u_nll = []\n", " e_b_nll = []\n", " for i_try in range(n_tries):\n", " while True:\n", " k = 2 * rng.poisson(n)\n", " x = rng.normal(truth.mu, truth.sigma, size=k)\n", " x = x[np.abs(x) < 2]\n", " x = x[:k]\n", " xrange = np.array((-2.0, 2.0))\n", " nh, xe = np.histogram(x, bins=3 + n // 10, range=xrange)\n", " m = [\n", " # model must be a normalized pdf\n", " Minuit(\n", " UnbinnedNLL(\n", " x,\n", " lambda x, mu, sigma: (\n", " norm.pdf(x, mu, sigma)\n", " / np.diff(norm.cdf(xrange, mu, sigma))\n", " ),\n", " ),\n", " mu=truth.mu,\n", " sigma=truth.sigma,\n", " ),\n", " # model must be a function that returns the integral over the scaled pdf and the scaled pdf\n", " Minuit(\n", " ExtendedUnbinnedNLL(\n", " x,\n", " lambda x, n, mu, sigma: (\n", " n * np.diff(norm.cdf(xrange, mu, sigma)),\n", " n * norm.pdf(x, mu, sigma),\n", " ),\n", " ),\n", " n=n,\n", " mu=truth.mu,\n", " sigma=truth.sigma,\n", " ),\n", " # model must be a normalized cdf up to an arbitrary additive constant (only differences are used)\n", " Minuit(\n", " BinnedNLL(\n", " nh,\n", " xe,\n", " lambda x, mu, sigma: (\n", " norm.cdf(x, mu, sigma)\n", " / np.diff(norm.cdf(xrange, mu, sigma))\n", " ),\n", " ),\n", " mu=truth.mu,\n", " sigma=truth.sigma,\n", " ),\n", " # model must be a scaled cdf up to an arbitrary additive constant (only differences are used)\n", " Minuit(\n", " ExtendedBinnedNLL(\n", " nh, xe, lambda x, n, mu, sigma: n * norm.cdf(x, mu, sigma)\n", " ),\n", " n=n,\n", " mu=truth.mu,\n", " sigma=truth.sigma,\n", " ),\n", " ]\n", " for mi in m:\n", " mi.limits[\"sigma\"] = (1e-3, None)\n", " mi.limits[\"mu\"] = (-2, 2)\n", " if \"n\" in mi.parameters:\n", " mi.limits[\"n\"] = (0, None)\n", "\n", " # only accept a random data set when all fits converged ok\n", " all_good = True\n", " for mi in m:\n", " mi.migrad()\n", " mi.hesse()\n", " if not mi.valid or not mi.accurate:\n", " all_good = False\n", " break\n", " if all_good:\n", " break\n", " print(f\"{n} {i_try} need to re-try {[(mi.valid, mi.accurate) for mi in m]}\")\n", "\n", " # store parameter deviations and estimated variances for each pseudo-experiment\n", " u_nll.append(\n", " (\n", " m[0].values[\"mu\"] - truth.mu,\n", " m[0].errors[\"mu\"] ** 2,\n", " m[0].values[\"sigma\"] - truth.sigma,\n", " m[0].errors[\"sigma\"] ** 2,\n", " )\n", " )\n", " e_u_nll.append(\n", " (\n", " m[1].values[\"n\"] - n,\n", " m[1].errors[\"n\"] ** 2,\n", " m[1].values[\"mu\"] - truth.mu,\n", " m[1].errors[\"mu\"] ** 2,\n", " m[1].values[\"sigma\"] - truth.sigma,\n", " m[1].errors[\"sigma\"] ** 2,\n", " )\n", " )\n", " b_nll.append(\n", " (\n", " m[2].values[\"mu\"] - truth.mu,\n", " m[2].errors[\"mu\"] ** 2,\n", " m[2].values[\"sigma\"] - truth.sigma,\n", " m[2].errors[\"sigma\"] ** 2,\n", " )\n", " )\n", " e_b_nll.append(\n", " (\n", " m[3].values[\"n\"] - n,\n", " m[3].errors[\"n\"] ** 2,\n", " m[3].values[\"mu\"] - truth.mu,\n", " m[3].errors[\"mu\"] ** 2,\n", " m[3].values[\"sigma\"] - truth.sigma,\n", " m[3].errors[\"sigma\"] ** 2,\n", " )\n", " )\n", "\n", " # means over pseudo-experiments are computed here\n", " return (\n", " np.mean(u_nll, axis=0),\n", " np.mean(e_u_nll, axis=0),\n", " np.mean(b_nll, axis=0),\n", " np.mean(e_b_nll, axis=0),\n", " )\n", "\n", "\n", "unbinned_nll = []\n", "extended_unbinned_nll = []\n", "binned_nll = []\n", "extended_binned_nll = []\n", "\n", "result = joblib.Parallel(-1)(compute(n) for n in n_pts)\n", "\n", "for a, b, c, d in result:\n", " unbinned_nll.append(a)\n", " extended_unbinned_nll.append(b)\n", " binned_nll.append(c)\n", " extended_binned_nll.append(d)\n", "\n", "unbinned_nll = np.transpose(unbinned_nll)\n", "extended_unbinned_nll = np.transpose(extended_unbinned_nll)\n", "binned_nll = np.transpose(binned_nll)\n", "extended_binned_nll = np.transpose(extended_binned_nll)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We plot the measured bias as a point and the mean variance as an error bar. The deviations go down with $n^{-{1/2}}$, where $n$ is the sample size. We undo this for the plots by multiplying deviations with $n^{1/2}$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:07:22.278782\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(2, 2, figsize=(9, 8), sharex=True, sharey=True)\n", "\n", "plt.sca(ax[0, 0])\n", "plt.title(\"Unbinned NLL\")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * unbinned_nll[0],\n", " np.sqrt(n_pts * unbinned_nll[1]),\n", " fmt=\"o\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\mu$\",\n", ")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * unbinned_nll[2],\n", " np.sqrt(n_pts * unbinned_nll[3]),\n", " fmt=\"s\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\sigma$\",\n", ")\n", "\n", "plt.sca(ax[0, 1])\n", "plt.title(\"Binned NLL\")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * binned_nll[0],\n", " np.sqrt(n_pts * binned_nll[1]),\n", " fmt=\"o\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\mu$\",\n", ")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * binned_nll[2],\n", " np.sqrt(n_pts * binned_nll[3]),\n", " fmt=\"s\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\sigma$\",\n", ")\n", "\n", "plt.sca(ax[1, 0])\n", "plt.title(\"Extended Unbinned NLL\")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * extended_unbinned_nll[2],\n", " np.sqrt(n_pts * extended_unbinned_nll[3]),\n", " fmt=\"o\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\mu$\",\n", ")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * extended_unbinned_nll[4],\n", " np.sqrt(n_pts * extended_unbinned_nll[5]),\n", " fmt=\"s\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\sigma$\",\n", ")\n", "\n", "plt.sca(ax[1, 1])\n", "plt.title(\"Extended binned NLL\")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * extended_binned_nll[2],\n", " np.sqrt(n_pts * extended_binned_nll[3]),\n", " fmt=\"o\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\mu$\",\n", ")\n", "plt.errorbar(\n", " n_pts,\n", " n_pts**0.5 * extended_binned_nll[4],\n", " np.sqrt(n_pts * extended_binned_nll[5]),\n", " fmt=\"s\",\n", " label=r\"$\\sqrt{n}\\,\\Delta\\sigma$\",\n", ")\n", "\n", "plt.ylim(-5, 5)\n", "plt.legend()\n", "plt.semilogx()\n", "for i in (0, 1):\n", " ax[1, i].set_xlabel(r\"$n_\\mathrm{pts}$\")\n", "for axi in ax.flat:\n", " for y in (-1, 1):\n", " axi.axhline(y, ls=\":\", color=\"0.5\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Least-squares fits\n", "\n", "We do the same as before, but this time we use a least-squares fit of $x,y$ scattered data and vary the residual function. Other functions than the identity can be used to reduce the pull of large outliers, turning the ordinary least-squares fit into a robust fit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n_tries = 100 # increase this to 500 to get less scattering\n", "\n", "truth = Namespace(a=1, b=2)\n", "\n", "n_pts = np.array((10, 30, 100, 300, 1000, 3000, 10000))\n", "\n", "\n", "@joblib.delayed\n", "def compute(n):\n", " rng = np.random.default_rng(n)\n", " x = np.linspace(0, 1, n)\n", "\n", " linear = []\n", " soft_l1 = []\n", " arctan = []\n", " for i_try in range(n_tries):\n", "\n", " def model(x, a, b):\n", " return a + b * x\n", "\n", " while True:\n", " y = model(x, 1, 2)\n", " ye = 0.1\n", " y += rng.normal(0, ye, len(y))\n", "\n", " m = [\n", " Minuit(LeastSquares(x, y, ye, model), a=0, b=0),\n", " Minuit(LeastSquares(x, y, ye, model, loss=\"soft_l1\"), a=0, b=0),\n", " Minuit(LeastSquares(x, y, ye, model, loss=np.arctan), a=0, b=0),\n", " ]\n", "\n", " all_good = True\n", " for mi in m:\n", " mi.migrad()\n", " mi.hesse()\n", " if not mi.valid or not mi.accurate:\n", " all_good = False\n", " break\n", " if all_good:\n", " break\n", " print(f\"{n} {i_try} need to re-try {[(mi.valid, mi.accurate) for mi in m]}\")\n", "\n", " linear.append(\n", " (\n", " m[0].values[\"a\"] - truth.a,\n", " m[0].values[\"b\"] - truth.b,\n", " m[0].errors[\"a\"] ** 2,\n", " m[0].errors[\"b\"] ** 2,\n", " )\n", " )\n", " soft_l1.append(\n", " (\n", " m[1].values[\"a\"] - truth.a,\n", " m[1].values[\"b\"] - truth.b,\n", " m[1].errors[\"a\"] ** 2,\n", " m[1].errors[\"b\"] ** 2,\n", " )\n", " )\n", " arctan.append(\n", " (\n", " m[2].values[\"a\"] - truth.a,\n", " m[2].values[\"b\"] - truth.b,\n", " m[2].errors[\"a\"] ** 2,\n", " m[2].errors[\"b\"] ** 2,\n", " )\n", " )\n", "\n", " return [\n", " (*np.mean(t, axis=0), *np.var(np.array(t)[:, :2], axis=0))\n", " for t in (linear, soft_l1, arctan)\n", " ]\n", "\n", "\n", "linear = []\n", "soft_l1 = []\n", "arctan = []\n", "\n", "for li, so, ar in joblib.Parallel(-1)(compute(n) for n in n_pts):\n", " linear.append(li)\n", " soft_l1.append(so)\n", " arctan.append(ar)\n", "\n", "linear = np.transpose(linear)\n", "soft_l1 = np.transpose(soft_l1)\n", "arctan = np.transpose(arctan)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:07:00.399877\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(2, 3, figsize=(9, 8), sharex=True, sharey=False)\n", "\n", "for k, (title, func) in enumerate(\n", " (\n", " (\"Least-squares\", linear),\n", " (\"Least-squares\\nwith soft L1 norm\", soft_l1),\n", " (\"Least-squares\\nwith arctan norm\", arctan),\n", " )\n", "):\n", " ax[0, k].set_title(title)\n", " for i, x in enumerate(\"ab\"):\n", " ax[0, k].errorbar(\n", " n_pts * 0.95 + 0.1 * i,\n", " np.sqrt(n_pts) * func[0 + i],\n", " np.sqrt(n_pts * func[4 + i]),\n", " fmt=\"so\"[i],\n", " label=rf\"$\\sqrt{{n}}\\,\\Delta {x}$\",\n", " )\n", " ax[1, k].plot(\n", " n_pts * 0.95 + 0.1 * i,\n", " func[2 + i] / func[4 + i],\n", " \"so\"[i],\n", " label=rf\"$\\sqrt{{n}}\\,\\Delta {x}$\",\n", " )\n", " ax[0, k].legend()\n", "plt.semilogx()\n", "for i in range(3):\n", " ax[1, i].axhline(1, ls=\"--\", color=\"0.5\")\n", " ax[0, i].set_ylim(-2, 2)\n", " ax[1, i].set_ylim(0.7, 3)\n", "ax[0, 0].set_ylabel(\"bias and variance\")\n", "ax[1, 0].set_ylabel(\"estimated variance / true variance\")\n", "fig.supxlabel(r\"$n_\\mathrm{pts}$\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The normal least-squares fit has a smallest variance, which is equal to the minimum variance for this problem given by the Cramer-Rao bound. The robust fits use less information to achieve robustness, hence the variance is larger. The loss from the soft L1 norm in this case is nearly negligible, but for the arctan norm it is noticable.\n", "\n", "**Beware**: The variance estimate obtained from the fit is wrong for robust least-squares, since the robust least-squares is not even asymptotically a maximum-likelihood estimator. The estimate is significantly larger than the actual variance for the soft_l1 and arctan norms in this case." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/cost_functions.ipynb0000644000000000000000000007560314332717401017071 0ustar00{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Cost functions\n", "\n", "We give an in-depth guide on how to use the built-in cost functions.\n", "\n", "The iminuit package comes with a couple of common cost functions that you can import from `iminuit.cost` for convenience. Of course, you can write your own cost functions to use with iminuit, but most of the cost function is always the same. What really varies is the statistical model which predicts the probability density as a function of the parameter values. This you still have to provide yourself and the iminuit package will not include machinery to build statistical models (that is out of scope).\n", "\n", "Using the built-in cost functions is not only convenient, they also have some extra features.\n", "\n", "* Support of fitted weighted histograms.\n", "* Technical tricks improve numerical stability.\n", "* Optional numba acceleration (if numba is installed).\n", "* Cost functions can be added to fit data sets with shared parameters.\n", "* Temporarily mask data.\n", "\n", "We demonstrate each cost function on a standard example from high-energy physics, the fit of a peak over some smooth background (here taken to be constant)." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import cost, Minuit\n", "\n", "# faster than scipy.stats functions\n", "from numba_stats import truncnorm, truncexpon, norm, expon\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "\n", "# accurate numerical derivatives\n", "from jacobi import jacobi" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "We generate our data by sampling from a Gaussian peak and from exponential background in the range 0 to 2. The original data is then binned. One can fit the original or the binned data." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": {}, "outputs": [], "source": [ "xr = (0, 2) # xrange\n", "\n", "rng = np.random.default_rng(1)\n", "\n", "xdata = rng.normal(1, 0.1, size=1000)\n", "ydata = rng.exponential(size=len(xdata))\n", "xmix = np.append(xdata, ydata)\n", "xmix = xmix[(xr[0] < xmix) & (xmix < xr[1])]\n", "\n", "n, xe = np.histogram(xmix, bins=20, range=xr)\n", "cx = 0.5 * (xe[1:] + xe[:-1])\n", "dx = np.diff(xe)\n", "\n", "plt.errorbar(cx, n, n**0.5, fmt=\"ok\")\n", "plt.plot(xmix, np.zeros_like(xmix), \"|\", alpha=0.1);" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "We also generate some 2D data to demonstrate multivariate fits. In this case, a Gaussian along axis 1 and independently an exponential along axis 2. In this case, the distributions are not restricted to some range in x and y." ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "n2, _, ye = np.histogram2d(xdata, ydata, bins=(20, 5), range=(xr, (0, np.max(ydata))))\n", "\n", "plt.pcolormesh(xe, ye, n2.T)\n", "plt.scatter(xdata, ydata, marker=\".\", color=\"w\", s=1);" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "## Maximum-likelihood fits\n", "\n", "Maximum-likelihood fits are the state-of-the-art when it comes to fitting models to data. They can be applied to unbinned and binned data (histograms).\n", "\n", "* Unbinned fits are the easiest to use, because no data binning is needed. They become slow when the sample size is large.\n", "* Binned fits require you to appropriately bin the data. The binning has to be fine enough to retain all essential information. Binned fits are much faster when the sample size is large.\n", "\n", "### Unbinned fit\n", "\n", "Unbinned fits are ideal when the data samples are not too large or very high dimensional. There is no need to worry about the appropriate binning of the data. Unbinned fits are inefficient when the samples are very large and can become numerically unstable, too. Binned fits are a better choice then.\n", "\n", "The cost function for an unbinned maximum-likelihood fit is really simple, it is the sum of the logarithm of the pdf evaluated at each sample point (times -1 to turn maximization into minimization). You can easily write this yourself, but a naive implementation will suffer from instabilities when the pdf becomes locally zero. Our implementation mitigates the instabilities to some extent.\n", "\n", "To perform the unbinned fit you need to provide the pdf of the model, which must be vectorized (a Numpy ufunc). The pdf must be normalized, which means that the integral over the sample value range must be a constant for any combination of model parameters.\n", "\n", "The model pdf in this case is a linear combination of the normal and the exponential pdfs. The parameters are $z$ (the weight), $\\mu$ and $\\sigma$ of the normal distribution and $\\tau$ of the exponential. The cost function detects the parameter names.\n", "\n", "It is important to put appropriate limits on the parameters, so that the problem does not become mathematically undefined.\n", "* $0 < z < 1$,\n", "* $\\sigma > 0$,\n", "* $\\tau > 0$.\n", "\n", "In addition, it can be beneficial to use $0 < \\mu < 2$, but it is not required. We use `truncnorm` and `truncexpon`, which are normalized inside the data range (0, 2)." ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": {}, "outputs": [], "source": [ "def pdf(x, z, mu, sigma, tau):\n", " return z * truncnorm.pdf(x, *xr, mu, sigma) + (1 - z) * truncexpon.pdf(\n", " x, *xr, 0.0, tau\n", " )\n", "\n", "\n", "c = cost.UnbinnedNLL(xmix, pdf)\n", "\n", "m = Minuit(c, z=0.4, mu=1, sigma=0.2, tau=1)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"mu\"] = (0, 2)\n", "m.limits[\"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "If the gradient of the model is available, it can be passed to the cost function to enable the computation of its gradient, which Minuit then uses to potentially improve the minimization. We use a numerically computed gradient here obtained from the `jacobi` library. This is for demonstration purpose only and generally not recommended, since `jacobi` computes the gradient much more accurately than what is required for Minuit." ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": {}, "outputs": [], "source": [ "def grad(x, *par):\n", " return jacobi(lambda par: pdf(x, *par), par)[0].T\n", "\n", "\n", "c = cost.UnbinnedNLL(xmix, pdf, grad=grad)\n", "\n", "m = Minuit(c, z=0.4, mu=1, sigma=0.2, tau=1)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"mu\"] = (0, 2)\n", "m.limits[\"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "We can also fit a multivariate model to multivariate data. We pass model as a logpdf this time, which works well because the pdfs factorize." ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": {}, "outputs": [], "source": [ "def logpdf(xy, mu, sigma, tau):\n", " x, y = xy\n", " return norm.logpdf(x, mu, sigma) + expon.logpdf(y, 0, tau)\n", "\n", "\n", "c = cost.UnbinnedNLL((xdata, ydata), logpdf, log=True)\n", "m = Minuit(c, mu=1, sigma=2, tau=2)\n", "m.limits[\"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "12", "metadata": {}, "source": [ "And we can also use a gradient as before." ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": {}, "outputs": [], "source": [ "def grad(xy, *par):\n", " return jacobi(lambda p: logpdf(xy, *p), par)[0].T\n", "\n", "\n", "c = cost.UnbinnedNLL((xdata, ydata), logpdf, log=True, grad=grad)\n", "m = Minuit(c, mu=1, sigma=2, tau=2)\n", "m.limits[\"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "### Extended unbinned fit\n", "\n", "An important variant of the unbinned ML fit is described by [Roger Barlow, Nucl.Instrum.Meth.A 297 (1990) 496-506](https://inspirehep.net/literature/297773). Use this if both the shape and the integral of the density are of interest. In practice, this is often the case, for example, if you want to estimate a cross-section or yield.\n", "\n", "The model in this case has to return the integral of the density and the density itself (which must be vectorized). The parameters in this case are those already discussed in the previous section and in addition $s$ (integral of the signal density), $b$ (integral of the uniform density). The additional limits are:\n", "\n", "* $s > 0$,\n", "* $b > 0$.\n", "\n", "Compared to the previous case, we have one more parameter to fit." ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "def density(x, s, b, mu, sigma, tau):\n", " return s + b, (\n", " s * truncnorm.pdf(x, *xr, mu, sigma) + b * truncexpon.pdf(x, *xr, 0, tau)\n", " )\n", "\n", "\n", "c = cost.ExtendedUnbinnedNLL(xmix, density)\n", "\n", "m = Minuit(c, s=300, b=1500, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"s\", \"b\", \"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "The fitted values and the uncertainty estimates for the shape parameters are identical to the previous fit." ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "m.visualize()" ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "Once again, we fit 2D data, using the log-density mode." ] }, { "cell_type": "code", "execution_count": null, "id": "19", "metadata": {}, "outputs": [], "source": [ "def logdensity(xy, n, mu, sigma, tau):\n", " x, y = xy\n", " return n, np.log(n) + norm.logpdf(x, mu, sigma) + expon.logpdf(y, 0, tau)\n", "\n", "\n", "c = cost.ExtendedUnbinnedNLL((xdata, ydata), logdensity, log=True)\n", "m = Minuit(c, n=1, mu=1, sigma=2, tau=2)\n", "m.limits[\"n\", \"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ "### Binned Fit\n", "\n", "Binned fits are computationally more efficient and numerically more stable when samples are large. The caveat is that one has to choose an appropriate binning. The binning should be fine enough so that the essential information in the original is retained. Using large bins does not introduce a bias, but the parameters have a larger-than-minimal variance.\n", "\n", "In this case, 50 bins are fine enough to retain all information. Using many bins is safe, since the maximum-likelihood method correctly takes Poisson statistics into account, which works even if bins have zero entries. Using more bins than necessary just increases the computational cost.\n", "\n", "Instead of a pdf, you need to provide a cdf for a binned fit (which must be vectorized). " ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": {}, "outputs": [], "source": [ "def cdf(xe, z, mu, sigma, tau):\n", " return z * truncnorm.cdf(xe, *xr, mu, sigma) + (1 - z) * truncexpon.cdf(\n", " xe, *xr, 0, tau\n", " )\n", "\n", "\n", "c = cost.BinnedNLL(n, xe, cdf)\n", "m = Minuit(c, z=0.4, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"sigma\", \"tau\"] = (0.01, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "iminuit also shows the chi-square goodness-of-fit test statistic when the data are binned. It is calculated for free in the binned case.\n", "\n", "Sometimes the cdf is expensive to calculate. In this case, you can approximate it via the cumulated sum of \"bin-width times pdf evaluated at center\". This approxmiation may lead to a bias. Using an accurate cdf avoids this bias.\n", "\n", "Here is the same example fitted with an approximate cdf." ] }, { "cell_type": "code", "execution_count": null, "id": "23", "metadata": {}, "outputs": [], "source": [ "def pdf(x, z, mu, sigma, tau):\n", " return z * truncnorm.pdf(x, *xr, mu, sigma) + (1 - z) * truncexpon.pdf(\n", " x, *xr, 0, tau\n", " )\n", "\n", "\n", "def approximate_cdf(xe, z, mu, sigma, tau):\n", " dx = np.diff(xe)\n", " cx = xe[:-1] + 0.5 * dx\n", " p = pdf(cx, z, mu, sigma, tau)\n", " return np.append([0], np.cumsum(p * dx))\n", "\n", "\n", "c = cost.BinnedNLL(n, xe, approximate_cdf)\n", "m = Minuit(c, z=0.4, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"sigma\", \"tau\"] = (0.01, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "The fitted values and the uncertainty estimates for $\\mu$ and $\\sigma$ are not identical to the unbinned fit, but very close. For practical purposes, the results are equivalent. This shows that the binning is fine enough to retain the essential information in the original data.\n", "\n", "Since this approximation is useful in practice, the `BinnedNLL` computes it automatically if you pass the keyword `use_pdf=\"approximate\"`." ] }, { "cell_type": "code", "execution_count": null, "id": "25", "metadata": {}, "outputs": [], "source": [ "c = cost.BinnedNLL(n, xe, pdf, use_pdf=\"approximate\")\n", "m = Minuit(c, z=0.4, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"sigma\", \"tau\"] = (0.01, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "26", "metadata": {}, "source": [ "Another option is to compute the cdf numerically with `use_pdf=\"numerical\"`, but this tends to be expensive and is only supported for 1D histograms." ] }, { "cell_type": "code", "execution_count": null, "id": "27", "metadata": {}, "outputs": [], "source": [ "c = cost.BinnedNLL(n, xe, pdf, use_pdf=\"numerical\")\n", "m = Minuit(c, z=0.4, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"z\"] = (0, 1)\n", "m.limits[\"sigma\", \"tau\"] = (0.01, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "28", "metadata": {}, "source": [ "Fitting a multidimensional histogram is equally easy. Since the pdfs in this example factorise, the cdf of the 2D model is the product of the cdfs along each axis." ] }, { "cell_type": "code", "execution_count": null, "id": "29", "metadata": {}, "outputs": [], "source": [ "def cdf(xe_ye, mu, sigma, tau):\n", " xe, ye = xe_ye\n", " return norm.cdf(xe, mu, sigma) * expon.cdf(ye, 0, tau)\n", "\n", "\n", "c = cost.BinnedNLL(n2, (xe, ye), cdf)\n", "m = Minuit(c, mu=0.1, sigma=0.2, tau=2)\n", "m.limits[\"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "30", "metadata": {}, "source": [ "The automatically provided visualization for multidimensional data set is often not very pretty, but still helps to judge whether the fit is reasonable. There is no obvious way to draw higher dimensional data with error bars in comparison to a model, and so the automatic visualization shows all data bins as a single sequence. You can override the default visualization by calling `Minuit.visualize` with your own plotting function, or by assigning a plot function to the cost function `BinnedNLL` (monkey patching), or by deriving your own class from `BinnedNLL`." ] }, { "cell_type": "markdown", "id": "31", "metadata": {}, "source": [ "### Extended binned maximum-likelihood fit\n", "\n", "As in the unbinned case, the binned extended maximum-likelihood fit should be used when also the amplitudes of the pdfs are of interest.\n", "\n", "Instead of a density, you need to provide the integrated density in this case (which must be vectorized). There is no need to separately return the total integral of the density, like in the unbinned case. The parameters are the same as in the unbinned extended fit." ] }, { "cell_type": "code", "execution_count": null, "id": "32", "metadata": {}, "outputs": [], "source": [ "def integral(xe, s, b, mu, sigma, tau):\n", " return s * truncnorm.cdf(xe, *xr, mu, sigma) + b * truncexpon.cdf(xe, *xr, 0, tau)\n", "\n", "\n", "c = cost.ExtendedBinnedNLL(n, xe, integral)\n", "m = Minuit(c, s=300, b=1500, mu=0, sigma=0.2, tau=2)\n", "m.limits[\"s\", \"b\", \"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "33", "metadata": {}, "source": [ "Again, we can also fit multivariate data." ] }, { "cell_type": "code", "execution_count": null, "id": "34", "metadata": {}, "outputs": [], "source": [ "def integral(xe_ye, n, mu, sigma, tau):\n", " xe, ye = xe_ye\n", " return n * norm.cdf(xe, mu, sigma) * expon.cdf(ye, 0, tau)\n", "\n", "\n", "c = cost.ExtendedBinnedNLL(n2, (xe, ye), integral)\n", "m = Minuit(c, n=1500, mu=0.1, sigma=0.2, tau=2)\n", "m.limits[\"n\", \"sigma\", \"tau\"] = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "35", "metadata": {}, "source": [ "### Temporary masking\n", "\n", "In complicated binned fits with peak and background, it is sometimes useful to fit in several stages. One typically starts by masking the signal region, to fit only the background region.\n", "\n", "The cost functions have a mask attribute to that end. We demonstrate the use of the mask with an extended binned fit." ] }, { "cell_type": "code", "execution_count": null, "id": "36", "metadata": {}, "outputs": [], "source": [ "def integral(xe, s, b, mu, sigma, tau):\n", " return s * truncnorm.cdf(xe, *xr, mu, sigma) + b * truncexpon.cdf(xe, *xr, 0, tau)\n", "\n", "\n", "c = cost.ExtendedBinnedNLL(n, xe, integral)\n", "\n", "# we set the signal amplitude to zero and fix all signal parameters\n", "m = Minuit(c, s=0, b=1500, mu=1, sigma=0.2, tau=2)\n", "\n", "m.limits[\"s\", \"b\", \"sigma\", \"tau\"] = (0, None)\n", "m.fixed[\"s\", \"mu\", \"sigma\"] = True\n", "\n", "# we temporarily mask out the signal\n", "c.mask = (cx < 0.5) | (1.5 < cx)\n", "\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "37", "metadata": {}, "source": [ "We plot the intermediate result. Points which have been masked out are shown with open markers." ] }, { "cell_type": "code", "execution_count": null, "id": "38", "metadata": {}, "outputs": [], "source": [ "for ma, co in ((c.mask, \"k\"), (~c.mask, \"w\")):\n", " plt.errorbar(cx[ma], n[ma], n[ma] ** 0.5, fmt=\"o\", color=co, mec=\"k\", ecolor=\"k\")\n", "plt.stairs(\n", " np.diff(integral(xe, *[p.value for p in m.init_params])), xe, ls=\":\", label=\"init\"\n", ")\n", "plt.stairs(np.diff(integral(xe, *m.values)), xe, label=\"fit\")\n", "plt.legend();" ] }, { "cell_type": "markdown", "id": "39", "metadata": {}, "source": [ "Now we fix the background and fit only the signal parameters." ] }, { "cell_type": "code", "execution_count": null, "id": "40", "metadata": {}, "outputs": [], "source": [ "c.mask = None # remove mask\n", "m.fixed = False # release all parameters\n", "m.fixed[\"b\"] = True # fix background amplitude\n", "m.values[\"s\"] = 100 # do not start at the limit\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "41", "metadata": {}, "source": [ "Finally, we release all parameters and fit again to get the correct uncertainty estimates." ] }, { "cell_type": "code", "execution_count": null, "id": "42", "metadata": {}, "outputs": [], "source": [ "m.fixed = None\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "43", "metadata": {}, "source": [ "We get the same result as before. Since this was an easy problem, we did not need these extra steps, but doing this can be helpful to fit lots of histograms without adjusting each fit manually." ] }, { "cell_type": "markdown", "id": "44", "metadata": {}, "source": [ "### Weighted histograms\n", "\n", "The cost functions for binned data also support weighted histograms. Just pass an array with the shape `(n, 2)` instead of `(n,)` as the first argument, where the first number of each pair is the sum of weights and the second is the sum of weights squared (an estimate of the variance of that bin value)." ] }, { "cell_type": "markdown", "id": "45", "metadata": {}, "source": [ "## Least-squares fits\n", "\n", "A cost function for a general weighted least-squares fit (aka chi-square fit) is also included. In statistics this is called non-linear regression.\n", "\n", "In this case you need to provide a model that predicts the y-values as a function of the x-values and the parameters. The fit needs estimates of the y-errors. If those are wrong, the fit may be biased. If your data has errors on the x-values as well, checkout the tutorial about automatic differentiation, which includes an application of that to such fits." ] }, { "cell_type": "code", "execution_count": null, "id": "46", "metadata": {}, "outputs": [], "source": [ "def model(x, a, b):\n", " return a + b * x**2\n", "\n", "\n", "rng = np.random.default_rng(4)\n", "\n", "truth = 1, 2\n", "x = np.linspace(0, 1, 20)\n", "yt = model(x, *truth)\n", "ye = 0.4 * x**5 + 0.1\n", "y = rng.normal(yt, ye)\n", "\n", "plt.plot(x, yt, ls=\"--\", label=\"truth\")\n", "plt.errorbar(x, y, ye, fmt=\"ok\", label=\"data\")\n", "plt.legend(loc=\"upper left\");" ] }, { "cell_type": "code", "execution_count": null, "id": "47", "metadata": {}, "outputs": [], "source": [ "c = cost.LeastSquares(x, y, ye, model)\n", "m1 = Minuit(c, a=0, b=0)\n", "m1.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "48", "metadata": {}, "source": [ "We can also plot the standard visualization manually and add further graphs to the figure." ] }, { "cell_type": "code", "execution_count": null, "id": "49", "metadata": {}, "outputs": [], "source": [ "m1.visualize()\n", "plt.plot(c.x, model(c.x, *truth), ls=\"--\", label=\"truth\");" ] }, { "cell_type": "markdown", "id": "50", "metadata": {}, "source": [ "We can also fit a multivariate model, in this case we fit a plane in 2D." ] }, { "cell_type": "code", "execution_count": null, "id": "51", "metadata": {}, "outputs": [], "source": [ "def model2(x_y, a, bx, by):\n", " x, y = x_y\n", " return a + bx * x + by * y\n", "\n", "\n", "# generate a regular grid in x and y\n", "x = np.linspace(-1, 1, 10)\n", "y = np.linspace(-1, 1, 10)\n", "X, Y = np.meshgrid(x, y)\n", "x = X.flatten()\n", "y = Y.flatten()\n", "\n", "# model truth\n", "Z = model2((x, y), 1, 2, 3)\n", "\n", "# add some noise\n", "rng = np.random.default_rng(1)\n", "Zerr = 1\n", "Z = rng.normal(Z, Zerr)\n", "\n", "plt.scatter(x, y, c=Z)\n", "plt.colorbar();" ] }, { "cell_type": "code", "execution_count": null, "id": "52", "metadata": {}, "outputs": [], "source": [ "c2 = cost.LeastSquares((x, y), Z, Zerr, model2)\n", "m2 = Minuit(c2, 0, 0, 0)\n", "m2.migrad()" ] }, { "cell_type": "markdown", "id": "53", "metadata": {}, "source": [ "Multivariate fits are difficult to check by eye. Here we use color to indicate the function value.\n", "\n", "To guarantee that plot of the function and the plot of the data use the same color scale, we use the same normalising function for pyplot.pcolormesh and pyplot.scatter." ] }, { "cell_type": "code", "execution_count": null, "id": "54", "metadata": {}, "outputs": [], "source": [ "xm = np.linspace(-1, 1, 100)\n", "ym = np.linspace(-1, 1, 100)\n", "Xm, Ym = np.meshgrid(xm, ym)\n", "xm = Xm.flatten()\n", "ym = Ym.flatten()\n", "\n", "qm = plt.pcolormesh(Xm, Ym, model2((xm, ym), *m2.values).reshape(Xm.shape))\n", "plt.scatter(c2.x[0], c2.x[1], c=c2.y, edgecolors=\"w\", norm=qm.norm)\n", "plt.colorbar();" ] }, { "cell_type": "markdown", "id": "55", "metadata": {}, "source": [ "### Robust least-squares\n", "\n", "The built-in least-squares function also supports robust fitting with an alternative loss functions. See the documentation of `iminuit.cost.LeastSquares` for details. Users can pass their own loss functions. Builtin loss functions are:\n", "\n", "* `linear` (default): gives ordinary weighted least-squares\n", "* `soft_l1`: quadratic ordinary loss for small deviations ($\\ll 1\\sigma$), linear loss for large deviations ($\\gg 1\\sigma$), and smooth interpolation in between\n", "\n", "Let's create one outlier and see what happens with ordinary loss." ] }, { "cell_type": "code", "execution_count": null, "id": "56", "metadata": {}, "outputs": [], "source": [ "c.y[3] = 3 # generate an outlier\n", "\n", "m3 = Minuit(c, a=0, b=0)\n", "m3.migrad()" ] }, { "cell_type": "code", "execution_count": null, "id": "57", "metadata": {}, "outputs": [], "source": [ "m3.visualize()\n", "plt.plot(c.x, model(c.x, 1, 2), ls=\"--\", label=\"truth\");" ] }, { "cell_type": "markdown", "id": "58", "metadata": {}, "source": [ "The result is distorted by the outlier. Note that the error did not increase! The size of the error computed by Minuit does **not** include mismodelling.\n", "\n", "We can repair this with by switching to \"soft_l1\" loss." ] }, { "cell_type": "code", "execution_count": null, "id": "59", "metadata": {}, "outputs": [], "source": [ "c.loss = \"soft_l1\"\n", "m3.migrad()" ] }, { "cell_type": "code", "execution_count": null, "id": "60", "metadata": {}, "outputs": [], "source": [ "m3.visualize()\n", "plt.plot(c.x, model(c.x, *truth), ls=\"--\", label=\"truth\");" ] }, { "cell_type": "markdown", "id": "61", "metadata": {}, "source": [ "The result is almost identical as in the previous case without an outlier.\n", "\n", "Robust fitting is very useful if the data are contaminated with small amounts of outliers. It comes with a price, however, the uncertainties are in general larger and the errors computed by Minuit are not correct anymore.\n", "\n", "Calculating the parameter uncertainty properly for this case requires a so-called sandwich estimator, which is currently not implemented. As an alternative, one can use the bootstrap to compute parameter uncertainties. We use the `resample` library to do this." ] }, { "cell_type": "code", "execution_count": null, "id": "62", "metadata": {}, "outputs": [], "source": [ "from resample.bootstrap import variance as bvar\n", "\n", "\n", "def fit(x, y, ye):\n", " c = cost.LeastSquares(x, y, ye, model, loss=\"soft_l1\")\n", " m = Minuit(c, a=0, b=0)\n", " m.migrad()\n", " return m.values\n", "\n", "\n", "berr = bvar(fit, c.x, c.y, c.yerror, size=1000, random_state=1) ** 0.5\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(9, 4))\n", "for i, axi in enumerate(ax):\n", " axi.errorbar(0, m1.values[i], m1.errors[i], fmt=\"o\")\n", " axi.errorbar(1, m3.values[i], m3.errors[i], fmt=\"o\")\n", " axi.errorbar(2, m3.values[i], berr[i], fmt=\"o\")\n", " axi.set_xticks(np.arange(3), (\"no outlier\", \"Minuit, soft_l1\", \"bootstrap\"))" ] }, { "cell_type": "markdown", "id": "63", "metadata": {}, "source": [ "In this case, Minuit's estimate is similar to the bootstrap estimate, but that is not generally true when the \"soft_l1\" loss is used.\n", "\n", "Robust fits are very powerful when the outliers cannot be removed by other means. If one can identify outliers by other means, it is better to remove them. We manually remove the point (using the mask attribute) and switch back to ordinary loss." ] }, { "cell_type": "code", "execution_count": null, "id": "64", "metadata": {}, "outputs": [], "source": [ "c.mask = np.arange(len(c.x)) != 3\n", "c.loss = \"linear\"\n", "m4 = Minuit(c, a=0, b=0)\n", "m4.migrad()" ] }, { "cell_type": "markdown", "id": "65", "metadata": {}, "source": [ "Now the uncertainties are essentially the same as before adding the outlier." ] }, { "cell_type": "code", "execution_count": null, "id": "66", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(9, 4))\n", "for i, axi in enumerate(ax):\n", " axi.errorbar(0, m1.values[i], m1.errors[i], fmt=\"o\")\n", " axi.errorbar(1, m3.values[i], m3.errors[i], fmt=\"o\")\n", " axi.errorbar(2, m3.values[i], berr[i], fmt=\"o\")\n", " axi.errorbar(3, m4.values[i], m4.errors[i], fmt=\"o\")\n", " axi.set_xticks(\n", " np.arange(4), (\"no outlier\", \"Minuit, soft_l1\", \"bootstrap\", \"outlier removed\")\n", " )" ] } ], "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.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 5 } iminuit-2.30.1/doc/notebooks/cython.ipynb0000644000000000000000000004603514332717401015332 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using Cython\n", "\n", "We show how to use Cython to accelerate the computation of a cost function and how to avoid some pitfalls.\n", "\n", "**Disclaimer:** If you do not care specifically about [Cython](https://cython.org) and just want to make your code faster, prefer [Numba](https://numba.pydata.org) (see the corresponding Numba tutorial for more details), or try to run iminuit in the PyPy interpreter. Numba is more powerful and easier to use, and you don't have to learn the awkward Cython dialect. Cython is a good choice when you have to call into C code from Python, but it is not a good choice to call into C++ code, for this [pybind11](https://pybind11.readthedocs.io/en/stable/) is the ideal choice. Cython does not fully support the C++ language, it was designed for C.\n", "\n", "With that out of the way, let's see how to use iminuit with a Cython-compiled function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# setup of the notebook\n", "%load_ext Cython\n", "from iminuit import Minuit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following cell is Cython code and will be compiled to machine code behind the scenes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "\n", "def cython_func(double x, double y, double z):\n", " return (x - 1.) ** 2 + (y - 2.) ** 2 + (z - 3.) ** 2 + 1." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Minuit can work with this compiled function like it was a native Python function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 1 Nfcn = 36
EDM = 2.38e-18 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x 1 1
1 y 2 1
2 z 3 1
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x y z
x 1 0 0
y 0 1 0
z 0 0 1
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 1 │ Nfcn = 36 │\n", "│ EDM = 2.38e-18 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x │ 1 │ 1 │ │ │ │ │ │\n", "│ 1 │ y │ 2 │ 1 │ │ │ │ │ │\n", "│ 2 │ z │ 3 │ 1 │ │ │ │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───┬───────â”\n", "│ │ x y z │\n", "├───┼───────┤\n", "│ x │ 1 0 0 │\n", "│ y │ 0 1 0 │\n", "│ z │ 0 0 1 │\n", "└───┴───────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Minuit(cython_func, 1, 1, 1)\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the past, Cython would not create a proper signature for the function by default, which iminuit uses need to get the parameter names. This was improved at some point.\n", "\n", "If you encouter a function without a signature, you can tell Minuit explicitly about the names of the parameters with the keyword `name`. This can also be used to override the automatic detection and use other names." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 1 Nfcn = 36
EDM = 9.78e-20 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 a 1 1
1 b 2 1
2 c 3 1
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
a b c
a 1 0 0
b 0 1 0
c 0 0 1
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 1 │ Nfcn = 36 │\n", "│ EDM = 9.78e-20 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ a │ 1 │ 1 │ │ │ │ │ │\n", "│ 1 │ b │ 2 │ 1 │ │ │ │ │ │\n", "│ 2 │ c │ 3 │ 1 │ │ │ │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───┬───────â”\n", "│ │ a b c │\n", "├───┼───────┤\n", "│ a │ 1 0 0 │\n", "│ b │ 0 1 0 │\n", "│ c │ 0 0 1 │\n", "└───┴───────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Minuit(cython_func, 1, 1, 1, name=(\"a\", \"b\", \"c\"))\n", "m.migrad()" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.13 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/error_bands.ipynb0000644000000000000000000002736714332717401016335 0ustar00{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# How to draw error bands\n", "\n", "We show two ways to compute 1-sigma bands around a fitted curve.\n", "\n", "Whether the curve describes a probability density (from a maximum-likelihood fit) or an expectation (from a least-squares fit) does not matter, the procedure is the same. We demonstrate this on an unbinned extended maximum-likelihood fit of a Gaussian." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "from numba_stats import norm\n", "from iminuit import Minuit\n", "from iminuit.cost import ExtendedUnbinnedNLL\n", "import matplotlib.pyplot as plt\n", "\n", "# generate toy sample\n", "rng = np.random.default_rng(1)\n", "x = rng.normal(size=100)\n", "\n", "# bin it\n", "w, xe = np.histogram(x, bins=100, range=(-5, 5))\n", "\n", "# compute bin-wise density estimates\n", "werr = w**0.5\n", "cx = 0.5 * (xe[1:] + xe[:-1])\n", "dx = np.diff(xe)\n", "d = w / dx\n", "derr = werr / dx\n", "\n", "\n", "# define model and cost function\n", "def model(x, par):\n", " return par[0], par[0] * norm.pdf(x, par[1], par[2])\n", "\n", "\n", "cost = ExtendedUnbinnedNLL(x, model)\n", "\n", "# fit the model\n", "m = Minuit(cost, (1, 0, 1))\n", "m.migrad()\n", "m.hesse()\n", "\n", "# plot everything\n", "plt.errorbar(cx, d, derr, fmt=\"o\", label=\"data\", zorder=0)\n", "\n", "plt.plot(cx, model(cx, m.values)[1], lw=3, label=\"fit\")\n", "plt.legend(\n", " frameon=False,\n", " title=f\"$n = {m.values[0]:.2f} +/- {m.errors[0]:.2f}$\\n\"\n", " f\"$\\\\mu = {m.values[1]:.2f} +/- {m.errors[1]:.2f}$\\n\"\n", " f\"$\\\\sigma = {m.values[2]:.2f} +/- {m.errors[2]:.2f}$\",\n", ");" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "We want to understand how uncertain the Gaussian curve is. Thus we want to draw a 1-sigma error band around the curve, which approximates the 68 % confidence interval." ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "## With error propagation\n", "\n", "The uncertainty is quantified in form of the covariance matrix of the fitted parameters. We can use [error propagation](https://en.wikipedia.org/wiki/Propagation_of_uncertainty) to obtain the uncertainty of the curve,\n", "\n", "$$\n", "C' = J \\, C \\, J^T,\n", "$$\n", "\n", "where $C$ is the covariance matrix of the input vector, $C'$ is the covariance matrix of the output vector and $J$ is the matrix of first derivatives of the mapping function between input and output. The mapping in this case is the curve, $\\vec y = f(\\vec{x}; \\vec{p})$, regarded as a function of $\\vec{p}$ and not of $\\vec{x}$, which is fixed. The function maps from $\\vec{p}$ to $\\vec{y}$ and the Jacobi matrix is made from elements\n", "\n", "$$\n", "J_{ik} = \\frac{\\partial y_i}{\\partial p_k}.\n", "$$\n", "\n", "To compute the derivatives one can sometimes use [Sympy](https://www.sympy.org/en/index.html) or an auto-differentiation tool like [JAX](https://jax.readthedocs.io/en/latest/) if the function permits it, but in general they need to be computed numerically. The library [Jacobi](https://github.com/hDembinski/jacobi) provides a fast and robust calculator for numerical derivatives and a function for error propagation." ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "from jacobi import propagate\n", "\n", "# run error propagation\n", "y, ycov = propagate(lambda p: model(cx, p)[1], m.values, m.covariance)\n", "\n", "# plot everything\n", "plt.errorbar(cx, d, derr, fmt=\"o\", label=\"data\", zorder=0)\n", "\n", "plt.plot(cx, y, lw=3, label=\"fit\")\n", "\n", "# draw 1 sigma error band\n", "yerr_prop = np.diag(ycov) ** 0.5\n", "plt.fill_between(cx, y - yerr_prop, y + yerr_prop, facecolor=\"C1\", alpha=0.5)\n", "\n", "plt.legend(\n", " frameon=False,\n", " title=f\"$n = {m.values[0]:.2f} +/- {m.errors[0]:.2f}$\\n\"\n", " f\"$\\\\mu = {m.values[1]:.2f} +/- {m.errors[1]:.2f}$\\n\"\n", " f\"$\\\\sigma = {m.values[2]:.2f} +/- {m.errors[2]:.2f}$\",\n", ");" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "Error propagation is relatively fast." ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [], "source": [ "%%timeit -r 1 -n 1000\n", "propagate(lambda p: model(cx, p)[1], m.values, m.covariance)" ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "## With the bootstrap\n", "\n", "Another generic way to compute uncertainties is bootstrapping. We know that the parameters asymptotically follow a multivariate normal distribution, so we can simulate new experiments with varied parameter values." ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1)\n", "\n", "par_b = rng.multivariate_normal(m.values, m.covariance, size=1000)\n", "\n", "# standard deviation of bootstrapped curves\n", "y_b = [model(cx, p)[1] for p in par_b]\n", "yerr_boot = np.std(y_b, axis=0)\n", "\n", "# plot everything\n", "plt.errorbar(cx, d, derr, fmt=\"o\", label=\"data\", zorder=0)\n", "\n", "plt.plot(cx, y, lw=3, label=\"fit\")\n", "\n", "# draw 1 sigma error band\n", "plt.fill_between(cx, y - yerr_boot, y + yerr_boot, facecolor=\"C1\", alpha=0.5)\n", "\n", "plt.legend(\n", " frameon=False,\n", " title=f\"$n = {m.values[0]:.2f} +/- {m.errors[0]:.2f}$\\n\"\n", " f\"$\\\\mu = {m.values[1]:.2f} +/- {m.errors[1]:.2f}$\\n\"\n", " f\"$\\\\sigma = {m.values[2]:.2f} +/- {m.errors[2]:.2f}$\",\n", ");" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "The result is visually indistinguishable from before, as it should be. If you worry about deviations between the two methods, read on." ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "In this example, computing the band from 1000 samples is slower than error propagation." ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": {}, "outputs": [], "source": [ "%%timeit -r 1 -n 100\n", "par_b = rng.multivariate_normal(m.values, m.covariance, size=1000)\n", "y_b = [model(cx, p)[1] for p in par_b]\n", "np.std(y_b, axis=0)" ] }, { "cell_type": "markdown", "id": "12", "metadata": {}, "source": [ "However, the calculation time scales linearly with the number of samples. One can simply draw fewer samples if the additional uncertainty is acceptable. If we draw only 50 samples, bootstrapping wins over numerical error propagation." ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": {}, "outputs": [], "source": [ "%%timeit -r 1 -n 1000\n", "rng = np.random.default_rng(1)\n", "par_b = rng.multivariate_normal(m.values, m.covariance, size=50)\n", "y_b = [model(cx, p)[1] for p in par_b]\n", "np.std(y_b, axis=0)" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "Let's see how the result looks, whether it deviates noticably." ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "# compute bootstrapped curves with 50 samples\n", "par_b = rng.multivariate_normal(m.values, m.covariance, size=50)\n", "y_b = [model(cx, p)[1] for p in par_b]\n", "yerr_boot_50 = np.std(y_b, axis=0)\n", "\n", "# plot everything\n", "plt.errorbar(cx, d, derr, fmt=\"o\", label=\"data\", zorder=0)\n", "\n", "plt.plot(cx, y, lw=3, label=\"fit\")\n", "\n", "# draw 1 sigma error band\n", "plt.fill_between(cx, y - yerr_boot_50, y + yerr_boot_50, facecolor=\"C1\", alpha=0.5)\n", "\n", "plt.legend(\n", " frameon=False,\n", " title=f\"$n = {m.values[0]:.2f} +/- {m.errors[0]:.2f}$\\n\"\n", " f\"$\\\\mu = {m.values[1]:.2f} +/- {m.errors[1]:.2f}$\\n\"\n", " f\"$\\\\sigma = {m.values[2]:.2f} +/- {m.errors[2]:.2f}$\",\n", ");" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "No, the result is still visually indistinguishable. This suggests that 50 samples can be enough for plotting.\n", "\n", "Numerically, the three error bands differ at the 10 % level in the central region (expected relative error is $50^{-1/2} \\approx 0.14$). The eye cannot pickup these differences, but they are there. The curves differ more in the tails, which is not visible in linear scale, but noticable in log-scale." ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(12, 5))\n", "\n", "plt.sca(ax[0])\n", "plt.plot(cx, y - yerr_prop, \"-C0\", label=\"prop\")\n", "plt.plot(cx, y + yerr_prop, \"-C0\", label=\"prop\")\n", "plt.plot(cx, y - yerr_boot, \"--C1\", label=\"boot[1000]\")\n", "plt.plot(cx, y + yerr_boot, \"--C1\", label=\"boot[1000]\")\n", "plt.plot(cx, y - yerr_boot_50, \":C2\", label=\"boot[50]\")\n", "plt.plot(cx, y + yerr_boot_50, \":C2\", label=\"boot[50]\")\n", "plt.legend()\n", "plt.semilogy()\n", "\n", "plt.sca(ax[1])\n", "plt.plot(cx, yerr_boot / yerr_prop, label=\"boot[1000] / prop\")\n", "plt.plot(cx, yerr_boot_50 / yerr_prop, label=\"boot[50] / prop\")\n", "plt.legend()\n", "plt.axhline(1, ls=\"--\", color=\"0.5\", zorder=0)\n", "for delta in (-0.1, 0.1):\n", " plt.axhline(1 + delta, ls=\":\", color=\"0.5\", zorder=0)\n", "plt.ylim(0.5, 1.5);" ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "We see that the bootstrapped bands are a bit wider in the tails. This is caused by non-linearities that are neglected in error propagation." ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "## Which is better? Error propagation or bootstrap?\n", "\n", "There is no clear-cut answer. At the visual level, both methods are usually fine (even with a small number of bootstrap samples). Which calculation is more accurate depends on details of the problem. Fortunately, the sources of error are orthogonal for both methods, so each method can be used to check the other.\n", "\n", "* The bootstrap error is caused by sampling. It can be reduced by drawing more samples, the relative error is proportional to $N^{-1/2}$.\n", "* The propagation error is caused by using a truncated Taylor series in the computation." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.13 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 5 } iminuit-2.30.1/doc/notebooks/external_minimizer.ipynb0000644000000000000000000000716314332717401017732 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using external minimizers\n", "\n", "We show how to use an external minimizer to find the minimum of a function and then use iminuit to compute the parameter uncertainties.\n", "\n", "We will demonstrate this with a maximum-likelihood fit of a normal distribution, which is carried out with `scipy.optimize.minimize`. iminuit is then used to compute the parameter uncertainties.\n", "\n", "Note: iminuit can call the scipy minimizers directly with `Minuit.scipy`, so `scipy.optimize.minimize` is only used here to demonstrate the general approach." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iminuit import Minuit\n", "import numpy as np\n", "from scipy.stats import norm\n", "from scipy.optimize import minimize" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# normally distributed data\n", "rng = np.random.default_rng(1)\n", "x = rng.normal(size=1000)\n", "\n", "\n", "# negative log-likelihood for a normal distribution\n", "def nll(par):\n", " return -np.sum(norm.logpdf(x, par[0], par[1]))\n", "\n", "\n", "nll.errordef = Minuit.LIKELIHOOD\n", "\n", "# minimize nll with scipy.optimize.minimize\n", "result = minimize(nll, np.ones(2))\n", "result" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# initialize Minuit with the fit result from scipy.optimize.minimize\n", "m = Minuit(nll, result.x)\n", "m.hesse() # this also works without calling MIGRAD before" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also compute the \"Hesse errors\" at any other point than the minimum. These cannot be interpreted as parameter uncertainties, they are just some numbers related to the second derivative of the cost function at that point." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.values = (1.0, 0.5)\n", "m.hesse()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Minuit now reports that the minimum is invalid, which is correct, but it does not matter for the Hesse errors, which are computed anyway.\n", "\n", "Likewise, it one can also run MINOS to get MINOS estimates. Note that MINOS can fail if the starting point is not actually a minimum. So here we reset the values to the solution found by scipy.optimize." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.values = result.x\n", "m.minos()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that MINOS ran successfully. The Hesse Errors were also updated, because MINOS needs HESSE to run first. HESSE is called automatically in this case." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/generic_least_squares.ipynb0000644000000000000000000001673514332717401020401 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Generic least-squares function\n", "\n", "This tutorial shows how to write a basic generic least-squares cost function that works well with iminuit.\n", "\n", "We have seen in the basic tutorial how to make a least-squares function with an explicit signature that iminuit could read to find the parameter names automatically. Part of the structure of a least-squares function is always the same. What changes is the model that predicts the y-values and its parameters. Here, we show how to make a generic [weighted least-squares](https://en.wikipedia.org/wiki/Weighted_least_squares) that extracts the parameters from the model which the user provides.\n", "\n", "Note: **Cost functions for common use-cases can be imported from `iminuit.cost`**, including a better version of a generic least-squares function that we build here. The built-in cost functions come with extra features and use some insights to make them work better than naive implementations, so prefer the built-in cost functions if you can." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Derive parameters from model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from iminuit import Minuit\n", "from iminuit.util import describe\n", "from typing import Annotated" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class LeastSquares:\n", " \"\"\"\n", " Generic least-squares cost function with error.\n", " \"\"\"\n", "\n", " errordef = Minuit.LEAST_SQUARES # for Minuit to compute errors correctly\n", "\n", " def __init__(self, model, x, y, err):\n", " self.model = model # model predicts y for given x\n", " self.x = np.asarray(x)\n", " self.y = np.asarray(y)\n", " self.err = np.asarray(err)\n", "\n", " def __call__(self, *par): # we must accept a variable number of model parameters\n", " ym = self.model(self.x, *par)\n", " return np.sum((self.y - ym) ** 2 / self.err**2)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Let's try it out with iminuit. We use a straight-line model which is only allowed to have positive slopes, and use an annotation with a slice to declare that, see `iminuit.util.describe` for details." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def line(x, a: float, b: Annotated[float, 0:]):\n", " return a + b * x\n", "\n", "\n", "rng = np.random.default_rng(1)\n", "x_data = np.arange(1, 6, dtype=float)\n", "y_err = np.ones_like(x_data)\n", "y_data = line(x_data, 1, 2) + rng.normal(0, y_err)\n", "\n", "lsq = LeastSquares(line, x_data, y_data, y_err)\n", "\n", "# this fails\n", "try:\n", " m = Minuit(lsq, a=0, b=0)\n", " m.errordef = Minuit.LEAST_SQUARES\n", "except RuntimeError:\n", " import traceback\n", "\n", " traceback.print_exc()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happened? iminuit uses introspection to detect the parameter names and the number of parameters. It uses the `describe` utility for that, but it fails, since the generic method signature `LeastSquares.__call__(self, *par)`, does not reveal the number and names of the parameters.\n", "\n", "The information could be extracted from the model signature, but iminuit knows nothing about the signature of `line(x, a, b)` here. We can fix this by generating a function signature for the `LeastSquares` class from the signature of the model." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# get the args from line\n", "describe(line, annotations=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# we inject that into the lsq object with the special attribute\n", "# `_parameters` that iminuit recognizes\n", "pars = describe(line, annotations=True)\n", "model_args = iter(pars)\n", "next(model_args) # we skip the first argument which is not a model parameter\n", "lsq._parameters = {k: pars[k] for k in model_args}\n", "\n", "# now we get the right answer\n", "describe(lsq, annotations=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can put this code into the init function of our generic least-squares class to obtain a generic least-squares class which works with iminuit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class BetterLeastSquares(LeastSquares):\n", " def __init__(self, model, x, y, err):\n", " super().__init__(model, x, y, err)\n", " pars = describe(model, annotations=True)\n", " model_args = iter(pars)\n", " next(model_args)\n", " self._parameters = {k: pars[k] for k in model_args}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lsq = BetterLeastSquares(line, x_data, y_data, y_err)\n", "\n", "m = Minuit(lsq, a=0, b=1)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Report number of data points\n", "\n", "The minimum value of our least-squares function is asymptotically chi2-distributed. This is useful, because it allows us to judge the quality of the fit. iminuit automatically reports the reduced chi2 value $\\chi^2/n_\\text{dof}$ if the cost function has `errordef` equal to `Minuit.LEAST_SQUARES` and reports the number of data points." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class EvenBetterLeastSquares(BetterLeastSquares):\n", " @property\n", " def ndata(self):\n", " return len(self.x)\n", "\n", "\n", "lsq = EvenBetterLeastSquares(line, x_data, y_data, y_err)\n", "\n", "m = Minuit(lsq, a=0, b=0)\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a developer of a cost function, you have to make sure that its minimum value is chi2-distributed if you add the property `ndata` to your cost function, `Minuit` has no way of knowing that.\n", "\n", "For binned likelihoods, one can make the minimum value asymptotically chi2-distributed by applying transformations, see [Baker and Cousins, Nucl.Instrum.Meth. 221 (1984) 437-442](https://doi.org/10.1016/0167-5087(84)90016-4).\n" ] } ], "metadata": { "kernelspec": { "display_name": "py310", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "27d7f7c882b6255fd802da382767366ff09de66c661617e6bcea60578475bec2" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/gof.ipynb0000644000000000000000000001060614332717401014574 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# GoF from binned cost functions\n", "\n", "The builtin cost functions for binned data, `BinnedNLL` and `ExtendedBinnedNLL` have a minimum value which is asymptotically chi2-distributed and thus can be used as a goodness-of-fit statistic. This example shows, that one still needs a large number of entries in each bin to reach the asymptotic regime." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "from iminuit.cost import BinnedNLL, ExtendedBinnedNLL\n", "import numpy as np\n", "from numba_stats import norm, expon\n", "import matplotlib.pyplot as plt\n", "import joblib\n", "from scipy.stats import chi2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def generate(n, seed):\n", " rng = np.random.default_rng(seed)\n", " s = rng.normal(1, 0.1, size=rng.poisson(n))\n", " b = rng.exponential(size=rng.poisson(n))\n", " x = np.append(s, b)\n", " return x[(x > 0) & (x < 2)]\n", "\n", "\n", "x = generate(1000, 1)\n", "plt.hist(x, bins=20, range=(0, 2));" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@joblib.delayed\n", "def run(n, seed):\n", " x = generate(n, seed)\n", " xrange = (0, 2)\n", " w, xe = np.histogram(x, bins=20, range=xrange)\n", "\n", " def model1(x, z, mu, sigma, tau):\n", " return z * norm.cdf(x, mu, sigma) / np.diff(norm.cdf(xrange, mu, sigma)) + (\n", " 1 - z\n", " ) * expon.cdf(x, 0, tau) / np.diff(expon.cdf(xrange, 0, tau))\n", "\n", " def model2(x, s, b, mu, sigma, tau):\n", " return s * n * norm.cdf(x, mu, sigma) + b * n * expon.cdf(x, 0, tau)\n", "\n", " m = [\n", " Minuit(BinnedNLL(w, xe, model1), z=0.5, mu=0.5, sigma=0.5, tau=0.5),\n", " Minuit(ExtendedBinnedNLL(w, xe, model2), s=1, b=1, mu=0.5, sigma=0.5, tau=0.5),\n", " ]\n", " for mi in m:\n", " mi.limits[\"mu\"] = (0, 2)\n", " mi.limits[\"sigma\", \"tau\"] = (0.1, None)\n", " m[0].limits[\"z\"] = (0, 1)\n", " m[1].limits[\"s\", \"b\"] = (0, None)\n", " r = []\n", " for mi in m:\n", " mi.migrad()\n", " if mi.valid:\n", " pvalue = chi2(mi.fcn._fcn.ndata - mi.nfit).sf(mi.fval)\n", " r.append(pvalue)\n", " else:\n", " r.append(np.nan)\n", " return r\n", "\n", "\n", "pvalues = {}\n", "for n in (20, 100, 1000, 10000):\n", " pvalues[n] = np.array(joblib.Parallel(-1)(run(n, i) for i in range(500)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(2, 4, figsize=(8, 4), constrained_layout=True)\n", "for i, (ni, vi) in enumerate(pvalues.items()):\n", " ax[0, i].hist(vi[:, 0])\n", " ax[1, i].hist(vi[:, 1])\n", " ax[0, i].set_title(\n", " f\"n = {ni}, failed fits = {np.sum(np.isnan(vi[:, 0]))}\", fontsize=\"small\"\n", " )\n", " ax[1, i].set_title(\n", " f\"n = {ni}, failed fits = {np.sum(np.isnan(vi[:, 1]))}\", fontsize=\"small\"\n", " )\n", "fig.supxlabel(\"pvalue\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The top row shows the p-values of the test statistic for `BinnedNLL` and the bottom row for `ExtendedBinnedNLL`. If the test statistic was perfectly chi-square-distributed, the p-value distribution should be uniform." ] } ], "metadata": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" }, "kernelspec": { "display_name": "Python 3.8.12 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/hesse_and_minos.ipynb0000644000000000000000000071053414332717401017166 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Hesse and Minos\n", "\n", "We discuss how uncertainty computation with Hesse and Minos works and how the two approaches differ.\n", "\n", "iminuit (and C++ MINUIT) offers two major ways of computing parameter uncertainties from the cost function (which must be of least-squares form or negative log-likelihood), HESSE and MINOS. These have different pros and cons, on which we already touched in the basic tutorial. Here we want to go a bit deeper into the pros and cons and also try to reveal a bit of the math behind the two approaches.\n", "\n", "There are several sources which explain what HESSE and MINOS do, in particular the MINUIT User's Guide (linked from the [iminuit documentation](https://scikit-hep.org/iminuit/about.html)). The mathematical details are covered in F. James, \"Statistical Methods in Experimental Physics\", 2nd edition, World Scientific (2006)." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We need to use a couple of technical terms from mathematical statistics when talk about proven properties. We also use recurring variable names with the same meaning throughout.\n", "\n", "* $n$ number of [observations](https://en.wikipedia.org/wiki/Sample_%28statistics%29)\n", "* $x$ observation from data distribution $f(x; \\theta)$ with parameter $\\theta$ (not an angle!)\n", "* $\\hat \\theta$ estimate of $\\theta$ obtained from a sample (the parameter value obtained from the fit)\n", "* $\\mathcal L$ likelihood function\n", "* $\\mathcal I$ [Fisher information](https://en.wikipedia.org/wiki/Fisher_information)\n", "* $E[\\dots]$ expectation value of $\\dots$ over distribution of $x$\n", "* $V[\\dots]$ variance of $\\dots$\n", "\n", "The terms **asymptotic** and **asymptotic limit** refer to inference from an infinite data sample. Mathematical properties of statistical methods are most commonly computed in this limit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HESSE\n", "\n", "HESSE in a nutshell:\n", "\n", "* Computes approximate covariance matrix $C_{ij}$ for all fitted parameters\n", "* Square-root of diagonal elements of $C_{ij}$ corresponds to one standard deviation; to obtain $k$ standard deviations, multiply covariance matrix $C$ by $k^2$\n", "* Can be used to form confidence intervals $\\hat \\theta_i \\pm C_{ii}^{1/2}$\n", "* Only way to obtain parameter correlations\n", "* Comparably fast, requires:\n", " * Numerical computation of all second derivatives of the cost function (Hessian matrix)\n", " * Inverting this matrix\n", "* Cannot compute uncertainty for only one parameter if there are several\n", "* Approximately computed as by-product of MIGRAD algorithm (usually accurate enough when `strategy` >= 1 is used)\n", "\n", "The algorithm derives its name from the Hessian matrix of second derivatives which is computed to obtain the uncertainties.\n", "\n", "### How does it work?\n", "\n", "The matrix of second derivatives of the cost function is computed for all free parameters and multiplied by 2. The result is inverted and multiplied by `errordef`.\n", "\n", "MINUIT implements parameter limits by applying a variable transformation and therefore distinguishes internal and external parameter space. The Hessian matrix is computed in the internal parameter space and transformed using the chain rule to external space.\n", "\n", "### Why does it work?\n", "\n", "One can prove under general conditions in the asymptotic limit that a parameter estimate $\\hat\\theta$ obtained from the least-squares and the maximum-likelihood methods is normally distributed with minimum variance, given by the [Cramer-Rao lower bound](https://en.wikipedia.org/wiki/Cram%C3%A9r%E2%80%93Rao_bound), which is the minimum for any unbiased estimator (these methods are asymptotically unbiased).\n", "\n", "$$\n", "V(\\hat \\theta) \\underset{n\\rightarrow \\infty}{\\longrightarrow} \\left\\{ n E\\left[\\left( \\frac{\\partial \\ln\\! f(x;\\theta)}{\\partial \\theta} \\right)^2 \\right]_{\\theta = \\hat\\theta} \\right\\}^{-1} = \\left\\{ -n E\\left[\\frac{\\partial^2 \\ln\\! f(x;\\theta)}{\\partial \\theta^2} \\right]_{\\theta = \\hat\\theta} \\right\\}^{-1}\n", "$$\n", "\n", "The expectation here is taken over the data distribution. Since the expectation value is constant, we see that the variance of $\\hat\\theta$ scales goes down with $n^{-1}$ in the asymptotic limit.\n", "\n", "If the data range is independent of $\\theta$, which we usually assume (but see F. James book for a counter example), we can swap integration over $x$ and differentiation with respect to $\\theta$. Doing this and replacing the expectation with its plug-in estimate, the arithmetic average, we obtain:\n", "\n", "$$\n", "-n E\\left[\\frac{\\partial^2 \\ln\\! f(x;\\theta)}{\\partial \\theta^2} \\right]_{\\theta = \\hat \\theta} = -n \\frac{1}{n} \\sum_i \\frac{\\partial^2 \\ln\\! f(x_i; \\theta)}{\\partial \\theta^2}\\Big\\vert_{\\theta = \\hat \\theta} = \\frac{\\partial^2 \\big(-\\sum_i \\ln\\! f(x_i; \\theta)\\big)}{\\partial \\theta^2}\\Big\\vert_{\\theta = \\hat \\theta}\n", "$$\n", "\n", "We now see that the numerator contains the negative log-likelihood function that we often plug into iminuit. If there is a vector of parameters $\\hat{\\vec \\theta}$, then this turns into the Hessian matrix of second derivatives.\n", "\n", "#### A bit of history\n", "\n", "So what about these factors of $2$ and `errordef` in MINUIT that were mentioned above? These don't appear here. There are historical reasons for those. In the asymptotic limit, the least-squares cost function that corresponds to the log-likelihood is $Q = -2 \\ln\\! \\mathcal{L} - \\text{constants}$. MINUIT was originally developed with least-squares fits in mind, therefore its internal math assumes the $Q$ form. If the second derivatives are computed from $Q$, the constants are removed but the Hessian must be multiplied by a factor of two to get the right variance. Correspondingly, if the user puts in a negative log-likelihood function, the same procedure now introduces an extra factor of two $2$, which must be compensated by the `errordef` value of 0.5 for the negative log-likelihood.\n", "\n", "### Why is HESSE approximate\n", "\n", "We started out from Cramer-Rao bound, the asymptotic limit for the parameter variance. How fast the finite sample approaches the limit depends on the problem at hand. For normal distributed data, the bound is exact.\n", "\n", "We further approximated the computation of the bound by replacing the expectation over the likelihood with the sample mean of the likelihood. \n", "\n", "## MINOS\n", "\n", "MINOS in a nutshell:\n", "\n", "* Approximate confidence intervals (intervals are wrongly claimed to be \"exact\" in some sources, including the MINUIT paper from 1975)\n", "* Cannot compute parameter correlations\n", "* Some (unverified) sources claim better coverage probability than intervals based on HESSE\n", "* In general slower than HESSE (requiring more function evaluations):\n", " * Iteratively computes the value pair $\\theta^d, \\theta^u$ which increases the cost function by `errordef` over the minimum\n", " * If the cost function has several parameters, it is minimised with respect to all other parameters during this scan\n", "* Can be used to compute uncertainty for only one parameter - but this is not more efficient than HESSE, since the computation requires at least one evaluation of HESSE\n", "\n", "The MINOS algorithm computes [profile-likelihood based](https://en.wikipedia.org/wiki/Likelihood_function#Profile_likelihood) confidence intervals.\n", "\n", "### How does it work?\n", "\n", "MINOS scans the likelihood along one parameter $\\theta_i$, while minimizing the likelihood with respect to all other parameters $\\theta_k$ with $k \\ne i$. This is effectively the same as expressing the other parameter estimates as a function of $\\theta_i$, $\\hat \\theta_k(\\theta_i)$, and scanning the now one-dimensional negative log-likelihood $-\\ln \\mathcal{L}(\\theta_i; \\theta_k = \\hat \\theta_k(\\theta_i) , k\\ne i)$. This is called the [profile likelihood](https://en.wikipedia.org/wiki/Likelihood_function#Profile_likelihood) for parameter $\\theta_i$.\n", "\n", "One follows this curve until $-\\ln \\mathcal{L}$ increases by `errordef` with respect to its minimum and stores the two corresponding values $\\theta^d_i$ and $\\theta^u_i$. The interval $(\\theta^d_i, \\theta^u_i)$ has $68\\,\\%$ coverage probability in the asymptotic limit. In multi-dimensional parameter space, the computation is comparably expensive due to the iterative steps of scanning and minimization.\n", "\n", "An efficient algorithm to compute the interval is described by Venzon and Moolgavkar in *A Method for Computing Profile-Likelihood-Based Confidence Intervals*, Journal of the Royal Statistical Society C37 (1988) 87–94 [DOI](https://doi.org/10.2307%2F2347496).\n", "\n", "### Why does it work?\n", "\n", "We define the likelihood ratio $\\ell(\\vec\\theta) = \\mathcal{L}(\\vec\\theta) / \\mathcal{L}(\\hat{\\vec\\theta})$. In the asymptotic limit, $-2 \\ln \\ell(\\vec\\theta)$ is $\\chi^2(k)$ distributed, where $k$ is the number of fitted parameters. For $k = 1$, the $\\chi^2$-interval $[0, 1)$ contains $68\\,\\%$ probability. For a single parameter fit therefore a corresponding interval is found by the two values $\\theta^d$ and $\\theta^u$ which solve\n", "\n", "$$\n", "-2\\ln\\ell(\\theta) = 1 \\Leftrightarrow -\\ln\\ell(\\theta) = 1/2\n", "$$\n", "\n", "We recognize the difference in the negative log-likelihood on the left-hand side and our `errordef = 0.5` on the right-hand side. Confidence intervals with other coverage probability can be constructed by finding the corresponding upper value of the $\\chi^2$-interval with that integrated probability. In a least-squares fit, we have\n", "\n", "$$\n", "\\Delta Q(\\theta) = -2 \\ln \\ell(\\theta) = 1\n", "$$\n", "\n", "therefore `errordef = 1` is the crossing value for a least-squares cost function.\n", "\n", "In the multi-parameter case, when we search for the interval for $\\theta_i$, the other parameters are effectively fixed to their best-fit values for the current value $\\theta_i$ in the scan, $\\theta_k = \\hat\\theta_k(\\theta_i)$. Therefore, during the scan they are not free. The profile likelihood is effectively a likelihood for a single parameter. Thus, $68\\,\\%$-intervals are also here obtained when the negative log-likelihood crosses the value $1/2$ above the minimum. \n", "\n", "### Why is MINOS approximate\n", "\n", "In some sources, the MINOS intervals are wrongly described as *exact*. They are not exact, because for finite samples the intervals do not necessarily have $68\\,\\%$ coverage probability, only in the asymptotic limit.\n", "\n", "Some sources claim that two approximations are involved in the HESSE calculation of an interval, but only one in the MINOS calculation and conclude that MINOS intervals therefore approach the asymptotic limit more rapidly. This claim is disputed by others." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Coverage probability\n", "\n", "We compute the coverage probability of HESSE and MINOS intervals in toy experiments.\n", "\n", "### Poisson distributed data\n", "\n", "We construct HESSE and MINOS intervals for a counting experiment. We consider the extreme case of a single observation $k$ drawn from a Poisson distribution $P(k;\\lambda)$. We use the maximum-likelihood method to find the best estimate for $\\lambda$ for each $k$ under the constraint $\\lambda > 0$, which is trivially just $\\hat \\lambda = k$, and construct intervals with the HESSE and MINOS algorithms to check their coverage.\n", "\n", "This case can be fully handled analytically, but here we use iminuit's HESSE and MINOS algorithms to compute the intervals." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from scipy.stats import multivariate_normal, poisson\n", "from argparse import Namespace\n", "from iminuit import Minuit\n", "from functools import lru_cache\n", "import joblib" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:25:35.063905\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@lru_cache(10000)\n", "def run(k):\n", " m = Minuit(lambda lambd: -poisson.logpmf(k, lambd), lambd=k + 1)\n", " m.limits[\"lambd\"] = (0, None)\n", " m.errordef = Minuit.LIKELIHOOD\n", " m.migrad()\n", " m.hesse()\n", " m.minos()\n", " assert m.valid\n", "\n", " p = m.values[\"lambd\"]\n", " dp = m.errors[\"lambd\"]\n", " pm = max(p + m.merrors[\"lambd\"].lower, 0.0), p + m.merrors[\"lambd\"].upper\n", "\n", " r = p, dp, *pm\n", " return r\n", "\n", "\n", "rng = np.random.default_rng(seed=1)\n", "nmc = 5000\n", "mu = 10 ** np.linspace(-1, 2, 100)\n", "\n", "pcov = {\n", " \"HESSE\": np.empty_like(mu),\n", " \"MINOS\": np.empty_like(mu),\n", "}\n", "\n", "for i, mui in enumerate(mu):\n", " nh = 0\n", " nm = 0\n", " for imc in range(nmc):\n", " k = rng.poisson(mui)\n", "\n", " p, dp, pd, pu = run(k)\n", "\n", " if p - dp < mui < p + dp:\n", " nh += 1\n", " if pd < mui < pu:\n", " nm += 1\n", "\n", " pcov[\"HESSE\"][i] = nh / nmc\n", " pcov[\"MINOS\"][i] = nm / nmc\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(9, 4))\n", "\n", "plt.sca(ax[0])\n", "n = np.arange(101)\n", "interval = {\n", " \"HESSE\": np.empty((len(n), 2)),\n", " \"MINOS\": np.empty((len(n), 2)),\n", "}\n", "for i, k in enumerate(n):\n", " p, dp, pd, pu = run(k)\n", " interval[\"HESSE\"][i] = (p - dp, p + dp)\n", " interval[\"MINOS\"][i] = (pd, pu)\n", "\n", "for algo, vals in interval.items():\n", " plt.plot(n, vals[:, 0] - n, color=\"C0\" if algo == \"HESSE\" else \"C1\", label=algo)\n", " plt.plot(n, vals[:, 1] - n, color=\"C0\" if algo == \"HESSE\" else \"C1\", label=algo)\n", "plt.xlabel(\"$k$\")\n", "plt.ylabel(r\"$\\lambda^d - \\hat\\lambda$, $\\lambda^u - \\hat\\lambda$\")\n", "\n", "plt.sca(ax[1])\n", "for algo, vals in pcov.items():\n", " plt.plot(mu, vals, label=algo)\n", "\n", "plt.axhline(0.68, ls=\":\", color=\"0.5\", zorder=0)\n", "plt.xlabel(r\"$\\lambda$\")\n", "plt.ylabel(\"coverage probability\")\n", "plt.legend()\n", "plt.semilogx();" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In this special case, the intervals found by both methods are very close. The MINOS interval is identical to the HESSE interval up to a small almost constant shift. Visually, the rate of converge to the asymptotic coverage probability of 68% seems to be equal for both methods." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can speak about the rate of convergence although we have drawn only a single observation from the Poisson pdf. The log-likelihood for $n$ observations with the same expectation is identical to the log-likelihood for one observation with an $n$-times higher expectation up to additive constants.\n", "\n", "$$\n", "\\ln L = \\sum_i^n (\\lambda_i - k_i \\ln \\lambda_i)\n", "= \\lambda - \\sum_i k_i (\\ln \\lambda - \\ln n)\n", "= \\lambda - k \\ln \\lambda + k \\ln n\n", "$$\n", "\n", "with $\\sum_i^n \\lambda_i = \\lambda$, $\\sum_i^n k_i = k$, and $\\lambda_i = \\lambda / n$. Therefore, the test cases with large values of $\\lambda$ correspond to large observation samples with a small constant $\\lambda$." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Fit of transformed normally distributed data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 3.122 Nfcn = 168
EDM = 2.02e-05 (Goal: 0.0001)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 3.122 │ Nfcn = 168 │\n", "│ EDM = 2.02e-05 (Goal: 0.0001) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 cx 0.11 0.06 -0.08 0.05
1 cy 0.05 0.10 -0.11 0.08
" ], "text/plain": [ "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ cx │ 0.11 │ 0.06 │ -0.08 │ 0.05 │ │ │ │\n", "│ 1 │ cy │ 0.05 │ 0.10 │ -0.11 │ 0.08 │ │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
cx cy
Error -0.08 0.05 -0.11 0.08
Valid True True True True
At Limit False False False False
Max FCN False False False False
New Min False False False False
" ], "text/plain": [ "┌──────────┬───────────────────────┬───────────────────────â”\n", "│ │ cx │ cy │\n", "├──────────┼───────────┬───────────┼───────────┬───────────┤\n", "│ Error │ -0.08 │ 0.05 │ -0.11 │ 0.08 │\n", "│ Valid │ True │ True │ True │ True │\n", "│ At Limit │ False │ False │ False │ False │\n", "│ Max FCN │ False │ False │ False │ False │\n", "│ New Min │ False │ False │ False │ False │\n", "└──────────┴───────────┴───────────┴───────────┴───────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:25:35.736815\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "rng = np.random.default_rng(1)\n", "\n", "truth = Namespace(cr=0.1, cphi=0, sr=0.1, sphi=2)\n", "truth.cx = truth.cr * np.cos(truth.cphi)\n", "truth.cy = truth.cr * np.sin(truth.cphi)\n", "\n", "d_r = rng.normal(truth.cr, truth.sr, size=5)\n", "d_phi = rng.normal(truth.cphi, truth.sphi, size=d_r.shape)\n", "\n", "cov = np.eye(2)\n", "cov[0, 0] = truth.sr**2\n", "cov[1, 1] = truth.sphi**2\n", "\n", "\n", "def nll(cx, cy):\n", " cr = np.linalg.norm((cx, cy))\n", " cphi = np.arctan2(cy, cx)\n", " return -np.sum(\n", " multivariate_normal((cr, cphi), cov).logpdf(np.transpose((d_r, d_phi)))\n", " )\n", "\n", "\n", "m = Minuit(nll, cx=0.1, cy=0)\n", "m.errordef = Minuit.LIKELIHOOD\n", "m.migrad()\n", "m.hesse()\n", "m.minos()\n", "display(m.fmin, m.params)\n", "display(m.merrors)\n", "\n", "plt.figure(figsize=(9, 4))\n", "\n", "plt.subplot(121, polar=True)\n", "plt.plot(d_phi, d_r, \".\")\n", "\n", "plt.subplot(122, aspect=\"equal\")\n", "m.draw_mncontour(\"cx\", \"cy\", size=100)\n", "plt.plot(m.values[\"cx\"], m.values[\"cy\"], \"+k\")\n", "plt.xlim(-0.1, 0.2)\n", "plt.ylim(-0.1, 0.2);" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "truth = Namespace(cr=0.1, cphi=0, sr=0.1, sphi=2)\n", "truth.cx = truth.cr * np.cos(truth.cphi)\n", "truth.cy = truth.cr * np.sin(truth.cphi)\n", "truth.cov = np.eye(2)\n", "truth.cov[0, 0] = truth.sr**2\n", "truth.cov[1, 1] = truth.sphi**2\n", "\n", "n_tries = 500 # increase this to 500 get smoother curves (running will take a while)\n", "n_data = np.unique(np.geomspace(5, 100, 20, dtype=int))\n", "\n", "\n", "@joblib.delayed\n", "def run(n):\n", " rng = np.random.default_rng(seed=n)\n", "\n", " n_h = 0\n", " n_m = 0\n", " h_lus = []\n", " m_lus = []\n", " xs = []\n", " for i_try in range(n_tries):\n", " while True:\n", " d_r = rng.normal(truth.cr, truth.sr, size=n)\n", " d_phi = rng.normal(truth.cphi, truth.sphi, size=n)\n", "\n", " def nll(cx, cy):\n", " cr = np.linalg.norm((cx, cy))\n", " cphi = np.arctan2(cy, cx)\n", " return -np.sum(\n", " multivariate_normal((cr, cphi), truth.cov).logpdf(\n", " np.transpose((d_r, d_phi))\n", " )\n", " )\n", "\n", " m = Minuit(nll, cx=0.1, cy=0)\n", " m.errordef = Minuit.LIKELIHOOD\n", " try:\n", " m.migrad()\n", " if not m.valid:\n", " continue\n", "\n", " m.hesse()\n", "\n", " if not m.accurate:\n", " continue\n", "\n", " m.minos(\"cx\")\n", " if m.merrors[\"cx\"].is_valid:\n", " break\n", "\n", " except Exception as e:\n", " print(f\"exception in n={n} i_try={i_try}\")\n", " print(e)\n", "\n", " x = m.values[\"cx\"]\n", " dx = m.errors[\"cx\"]\n", " me = m.merrors[\"cx\"]\n", " h_lu = x - dx, x + dx\n", " m_lu = x + me.lower, x + me.upper\n", " if h_lu[0] < truth.cx < h_lu[1]:\n", " n_h += 1\n", " if m_lu[0] < truth.cx < m_lu[1]:\n", " n_m += 1\n", " xs.append(x)\n", " h_lus.append(h_lu)\n", " m_lus.append(m_lu)\n", "\n", " x = np.mean(xs)\n", " h_l, h_u = np.mean(h_lus, axis=0)\n", " m_l, m_u = np.mean(m_lus, axis=0)\n", " return n_h, n_m, x, h_l, h_u, m_l, m_u\n", "\n", "\n", "n_h, n_m, x, hl, hu, ml, mu = np.transpose(joblib.Parallel(-1)(run(x) for x in n_data))\n", "\n", "h_pcov = n_h.astype(float) / n_tries\n", "m_pcov = n_m.astype(float) / n_tries" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:26:45.991662\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(9, 4))\n", "plt.sca(ax[0])\n", "plt.fill_between(n_data, hl, hu, alpha=0.5, label=\"HESSE\")\n", "plt.fill_between(n_data, ml, mu, alpha=0.5, label=\"MINOS\")\n", "plt.plot(n_data, x, \"-k\")\n", "plt.legend()\n", "plt.xlabel(\"n\")\n", "plt.ylabel(\"cx\")\n", "plt.semilogx()\n", "plt.sca(ax[1])\n", "plt.plot(n_data, h_pcov, label=\"HESSE\")\n", "plt.plot(n_data, m_pcov, label=\"MINOS\")\n", "plt.axhline(0.68, ls=\":\", color=\"0.5\", zorder=0)\n", "plt.xlabel(r\"cx\")\n", "plt.ylabel(\"coverage probability\")\n", "plt.legend()\n", "plt.ylim(0, 1)\n", "plt.semilogx();" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/interactive.ipynb0000644000000000000000000002421014332717401016332 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Interactive fits\n", "\n", "This notebook showcases the interactive fitting capability of iminuit. Interactive fitting is useful to find good starting values and to debug the fit.\n", "\n", "**Note:** If you see this notebook on ReadTheDocs or otherwise statically rendered, changing the sliders won't change the plot. This requires a running Jupyter kernel." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import cost\n", "from iminuit import Minuit\n", "from numba_stats import norm, t, bernstein, truncexpon\n", "import numpy as np\n", "from matplotlib import pyplot as plt" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## UnbinnedNLL" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1)\n", "\n", "s = rng.normal(0.5, 0.1, size=1000)\n", "b = rng.exponential(1, size=1000)\n", "b = b[b < 1]\n", "x = np.append(s, b)\n", "\n", "truth = len(s) / len(x), 0.5, 0.1, 1.0\n", "\n", "n, xe = np.histogram(x, bins=50)\n", "\n", "\n", "def model(x, f, mu, sigma, slope):\n", " return f * norm.pdf(x, mu, sigma) + (1 - f) * truncexpon.pdf(x, 0, 1, 0, slope)\n", "\n", "\n", "c = cost.UnbinnedNLL(x, model)\n", "m = Minuit(c, *truth)\n", "m.limits[\"f\", \"mu\"] = (0, 1)\n", "m.limits[\"sigma\", \"slope\"] = (0, None)\n", "\n", "m.interactive(model_points=1000)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## ExtendedUnbinnedNLL" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1)\n", "\n", "s = rng.normal(0.5, 0.1, size=1000)\n", "b = rng.exponential(1, size=1000)\n", "b = b[b < 1]\n", "x = np.append(s, b)\n", "\n", "truth = len(s), 0.5, 0.1, len(b), 1.0\n", "\n", "n, xe = np.histogram(x, bins=50)\n", "\n", "\n", "def model(x, s, mu, sigma, b, slope):\n", " x = s * norm.pdf(x, mu, sigma) + b * truncexpon.pdf(x, 0, 1, 0, slope)\n", " return s + b, x\n", "\n", "\n", "c = cost.ExtendedUnbinnedNLL(x, model)\n", "m = Minuit(c, *truth)\n", "m.limits[\"mu\"] = (0, 1)\n", "m.limits[\"sigma\", \"slope\", \"s\", \"b\"] = (0, None)\n", "\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## BinnedNLL" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def model(xe, f, mu, sigma, nuinv, slope):\n", " nu = 1 / nuinv\n", " a, b = t.cdf((0, 1), nu, mu, sigma)\n", " sn = f * (t.cdf(xe, nu, mu, sigma) - a) / (b - a)\n", " bn = (1 - f) * truncexpon.cdf(xe, 0, 1, 0, slope)\n", " return sn + bn\n", "\n", "\n", "rng = np.random.default_rng(1)\n", "\n", "truth = 0.5, 0.5, 0.1, 0.1, 1\n", "\n", "xe = np.linspace(0, 1, 100)\n", "sm = truth[0] * np.diff(model(xe, 1, *truth[1:]))\n", "bm = (1 - truth[0]) * np.diff(model(xe, 0, *truth[1:]))\n", "n = rng.poisson(1000 * np.diff(model(xe, *truth)))\n", "\n", "c = cost.BinnedNLL(n, xe, model)\n", "\n", "m = Minuit(c, *truth)\n", "m.limits[\"sigma\", \"slope\"] = (0, None)\n", "m.limits[\"mu\", \"f\", \"nuinv\"] = (0, 1)\n", "\n", "m.interactive()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = cost.BinnedNLL(n, xe, model)\n", "\n", "cx = 0.5 * (xe[1:] + xe[:-1])\n", "c.mask = np.abs(cx - 0.5) > 0.3\n", "\n", "m = Minuit(c, *truth)\n", "m.limits[\"sigma\", \"slope\"] = (0, None)\n", "m.limits[\"mu\", \"f\", \"nuinv\"] = (0, 1)\n", "\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## ExtendedBinnedNLL" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def model(xe, s, mu, sigma, nuinv, b1, b2, b3):\n", " nu = 1 / nuinv\n", " sn = s * t.cdf(xe, nu, mu, sigma)\n", " bn = bernstein.integral(xe, (b1, b2, b3), 0, 1)\n", " return sn + bn\n", "\n", "\n", "truth = 1000.0, 0.5, 0.1, 0.1, 1000.0, 3000.0, 2000.0\n", "\n", "xe = np.linspace(0, 1, 100)\n", "\n", "rng = np.random.default_rng(1)\n", "n = rng.poisson(np.diff(model(xe, *truth)))\n", "\n", "c = cost.ExtendedBinnedNLL(n, xe, model)\n", "\n", "m = Minuit(c, *truth)\n", "m.limits[\"s\", \"sigma\", \"b1\", \"b2\", \"b3\"] = (0, None)\n", "m.limits[\"mu\", \"nuinv\"] = (0, 1)\n", "\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "You can pass a custom plotting routine with `Minuit.interactive` to draw more detail. A simple function works that accesses data from the outer scope, but we create a class in the following example to store the cost function, which has all data we need, because we override the variables in the outer scope in this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Visualize signal and background components with different colors\n", "class Plotter:\n", " def __init__(self, cost):\n", " self.cost = cost\n", "\n", " def __call__(self, args):\n", " xe = self.cost.xe\n", " n = self.cost.data\n", " cx = 0.5 * (xe[1:] + xe[:-1])\n", " plt.errorbar(cx, n, n**0.5, fmt=\"ok\")\n", " sm = np.diff(self.cost.scaled_cdf(xe, *args[:4], 0, 0, 0))\n", " bm = np.diff(self.cost.scaled_cdf(xe, 0, *args[1:]))\n", " plt.stairs(bm, xe, fill=True, color=\"C1\")\n", " plt.stairs(bm + sm, xe, baseline=bm, fill=True, color=\"C0\")\n", "\n", "\n", "m.interactive(Plotter(c))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = cost.ExtendedBinnedNLL(n, xe, model)\n", "\n", "cx = 0.5 * (xe[1:] + xe[:-1])\n", "c.mask = np.abs(cx - 0.5) > 0.3\n", "\n", "m = Minuit(c, *truth)\n", "m.limits[\"s\", \"sigma\", \"nuinv\", \"b1\", \"b2\", \"b3\"] = (0, None)\n", "m.limits[\"mu\", \"nuinv\"] = (0, 1)\n", "m.fixed[\"s\", \"mu\", \"sigma\", \"nuinv\"] = True\n", "m.values[\"s\"] = 0\n", "\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Template" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xe = np.linspace(0, 1, 20)\n", "bm = np.diff(truncexpon.cdf(xe, 0, 1, 0, 1))\n", "sm = np.diff(norm.cdf(xe, 0.5, 0.1))\n", "\n", "rng = np.random.default_rng(1)\n", "n = rng.poisson(1000 * bm + 100 * sm)\n", "b = rng.poisson(1e4 * bm)\n", "s = rng.poisson(1e2 * sm)\n", "\n", "c = cost.Template(n, xe, (b, s))\n", "\n", "m = Minuit(c, 1000, 100, name=(\"b\", \"s\"))\n", "m.limits = (0, None)\n", "\n", "m.interactive()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = cost.Template(n, xe, (b, s))\n", "cx = 0.5 * (xe[1:] + xe[:-1])\n", "c.mask = np.abs(cx - 0.5) > 0.2\n", "\n", "m = Minuit(c, 1000, 100, name=(\"b\", \"s\"))\n", "m.limits = (0, None)\n", "\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## LeastSquares" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def model(x, a, b):\n", " return a + b * x\n", "\n", "\n", "truth = (1.0, 2.0)\n", "x = np.linspace(0, 1)\n", "ym = model(x, *truth)\n", "ye = 0.1\n", "y = rng.normal(ym, ye)\n", "\n", "c = cost.LeastSquares(x, y, ye, model)\n", "\n", "m = Minuit(c, *truth)\n", "m.interactive()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = cost.LeastSquares(x, y, ye, model)\n", "c.mask = (x > 0.6) | (x < 0.2)\n", "\n", "m = Minuit(c, *truth)\n", "m.interactive()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Cost functions with shared parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def model(xe, s, mu, sigma, nuinv):\n", " nu = 1 / nuinv\n", " return s * t.cdf(xe, nu, mu, sigma)\n", "\n", "\n", "truth = 100.0, 0.5, 0.1, 0.5\n", "\n", "rng = np.random.default_rng(1)\n", "xe = np.linspace(0, 1, 20)\n", "m = np.diff(model(xe, *truth))\n", "n = rng.poisson(m)\n", "\n", "c = cost.ExtendedBinnedNLL(n, xe, model) + cost.NormalConstraint(\n", " [\"mu\", \"sigma\"], [0.5, 0.1], [0.1, 0.1]\n", ")\n", "\n", "m = Minuit(c, *truth)\n", "\n", "m.interactive()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.6" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/memory_layout.ipynb0000644000000000000000000000631314332717401016726 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Performance impact of memory layout\n", "\n", "Modern CPUs are so fast that they are often wait for memory to be transferred. In case of memory access with a regular pattern, the CPU will prefetch memory that is likely to be used next. We can optimise this a little bit by arranging the numbers in memory that they are easy to fetch. For 1D data, there is not much that we can do, but for ND data, we have the choice between two layouts\n", "\n", "- x0, y0, ... x1, y1, ...\n", "- x0, x1, ..., y0, y1, ...\n", "\n", "Which one is more efficient is not obvious, so we try both options here. It turns out that the second option is better and that is the one used internally in the builtin cost functions as well." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iminuit import Minuit\n", "from iminuit.cost import UnbinnedNLL\n", "import numpy as np\n", "from scipy.stats import multivariate_normal\n", "\n", "rng = np.random.default_rng(1)\n", "\n", "xy1 = rng.normal(size=(1_000_000, 2))\n", "xy2 = rng.normal(size=(2, 1_000_000))\n", "\n", "\n", "def cost1(x, y):\n", " return -np.sum(multivariate_normal.logpdf(xy1, (x, y)))\n", "\n", "\n", "cost1.errordef = Minuit.LIKELIHOOD\n", "\n", "\n", "def cost2(x, y):\n", " return -np.sum(multivariate_normal.logpdf(xy2.T, (x, y)))\n", "\n", "\n", "cost2.errordef = Minuit.LIKELIHOOD\n", "\n", "\n", "def logpdf(xy, x, y):\n", " return multivariate_normal.logpdf(xy.T, (x, y))\n", "\n", "\n", "cost3 = UnbinnedNLL(xy2, logpdf, log=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%timeit -n 1 -r 1\n", "m = Minuit(cost1, x=0, y=0)\n", "m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%timeit -n 1 -r 1\n", "m = Minuit(cost2, x=0, y=0)\n", "m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%timeit -n 1 -r 1\n", "m = Minuit(cost3, x=0, y=0)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "`cost2` and `cost3` are using the \"first all `x` then all `y`\" memory layout. `cost3` measures the small overhead incurred by using the built-in cost function `UnbinnedNLL` compared to a hand-tailored one." ] } ], "metadata": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" }, "kernelspec": { "display_name": "Python 3.8.12 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/numba.ipynb0000644000000000000000000024432314332717401015130 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Acceleration with Numba\n", "\n", "We explore how the computation of cost functions can be dramatically accelerated with numba's JIT compiler.\n", "\n", "The run-time of iminuit is usually dominated by the execution time of the cost function. To get good performance, it recommended to use array arthimetic and scipy and numpy functions in the body of the cost function. Python loops should be avoided, but if they are unavoidable, [Numba](https://numba.pydata.org/) can help. Numba can also parallelize numerical calculations to make full use of multi-core CPUs and even do computations on the GPU.\n", "\n", "Note: This tutorial shows how one can generate faster pdfs with Numba. Before you start to write your own pdf, please check whether one is already implemented in the [numba_stats library](https://github.com/HDembinski/numba-stats). If you have a pdf that is not included there, please consider contributing it to numba_stats." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# !pip install matplotlib numpy numba scipy iminuit\n", "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "import numpy as np\n", "import numba as nb\n", "import math\n", "from scipy.stats import expon, norm\n", "from matplotlib import pyplot as plt\n", "from argparse import Namespace" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The standard fit in particle physics is the fit of a peak over some smooth background. We generate a Gaussian peak over exponential background, using scipy." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:31:13.398908\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "np.random.seed(1) # fix seed\n", "\n", "# true parameters for signal and background\n", "truth = Namespace(n_sig=2000, f_bkg=10, sig=(5.0, 0.5), bkg=(0.0, 4.0))\n", "n_bkg = truth.n_sig * truth.f_bkg\n", "\n", "# make a data set\n", "x = np.empty(truth.n_sig + n_bkg)\n", "\n", "# fill m variables\n", "x[: truth.n_sig] = norm(*truth.sig).rvs(truth.n_sig)\n", "x[truth.n_sig :] = expon(*truth.bkg).rvs(n_bkg)\n", "\n", "# cut a range in x\n", "xrange = np.array((1.0, 9.0))\n", "ma = (xrange[0] < x) & (x < xrange[1])\n", "x = x[ma]\n", "\n", "plt.hist(\n", " (x[truth.n_sig :], x[: truth.n_sig]),\n", " bins=50,\n", " stacked=True,\n", " label=(\"background\", \"signal\"),\n", ")\n", "plt.xlabel(\"x\")\n", "plt.legend();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ideal starting values for iminuit\n", "start = np.array((truth.n_sig, n_bkg, truth.sig[0], truth.sig[1], truth.bkg[1]))\n", "\n", "\n", "# iminuit instance factory, will be called a lot in the benchmarks blow\n", "def m_init(fcn):\n", " m = Minuit(fcn, start, name=(\"ns\", \"nb\", \"mu\", \"sigma\", \"lambd\"))\n", " m.limits = ((0, None), (0, None), None, (0, None), (0, None))\n", " m.errordef = Minuit.LIKELIHOOD\n", " return m" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-103168.78482586428)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# extended likelihood (https://doi.org/10.1016/0168-9002(90)91334-8)\n", "# this version uses numpy and scipy and array arithmetic\n", "def nll(par):\n", " n_sig, n_bkg, mu, sigma, lambd = par\n", " s = norm(mu, sigma)\n", " b = expon(0, lambd)\n", " # normalisation factors are needed for pdfs, since x range is restricted\n", " sn = s.cdf(xrange)\n", " bn = b.cdf(xrange)\n", " sn = sn[1] - sn[0]\n", " bn = bn[1] - bn[0]\n", " return (n_sig + n_bkg) - np.sum(\n", " np.log(s.pdf(x) / sn * n_sig + b.pdf(x) / bn * n_bkg)\n", " )\n", "\n", "\n", "nll(start)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "327 ms ± 66.2 ms per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -r 3 -n 1\n", "m = m_init(nll) # setup time is negligible\n", "m.migrad();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see whether we can beat that. The code above is already pretty fast, because numpy and scipy routines are fast, and we spend most of the time in those. But these implementations do not parallelize the execution and are not optimised for this particular CPU, unlike numba-jitted functions.\n", "\n", "To use numba, in theory we just need to put the `njit` decorator on top of the function, but often that doesn't work out of the box. numba understands many numpy functions, but no scipy. We must evaluate the code that uses scipy in 'object mode', which is numba-speak for calling into the Python interpreter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n" ] }, { "data": { "text/plain": [ "-103168.78482586429" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# first attempt to use numba\n", "@nb.njit(parallel=True)\n", "def nll(par):\n", " n_sig, n_bkg, mu, sigma, lambd = par\n", " with nb.objmode(spdf=\"float64[:]\", bpdf=\"float64[:]\", sn=\"float64\", bn=\"float64\"):\n", " s = norm(mu, sigma)\n", " b = expon(0, lambd)\n", " # normalisation factors are needed for pdfs, since x range is restricted\n", " sn = np.diff(s.cdf(xrange))[0]\n", " bn = np.diff(b.cdf(xrange))[0]\n", " spdf = s.pdf(x)\n", " bpdf = b.pdf(x)\n", " no = n_sig + n_bkg\n", " return no - np.sum(np.log(spdf / sn * n_sig + bpdf / bn * n_bkg))\n", "\n", "\n", "nll(start) # test and warm-up JIT" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "432 ms ± 31.5 ms per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -r 3 -n 1 m = m_init(nll)\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is even a bit slower. :( Let's break the original function down by parts to see why." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.75 ms ± 24 μs per loop (mean ± std. dev. of 3 runs, 100 loops each)\n", "1.32 ms ± 92.1 μs per loop (mean ± std. dev. of 3 runs, 500 loops each)\n", "154 μs ± 9.82 μs per loop (mean ± std. dev. of 3 runs, 1,000 loops each)\n" ] } ], "source": [ "# let's time the body of the function\n", "n_sig, n_bkg, mu, sigma, lambd = start\n", "s = norm(mu, sigma)\n", "b = expon(0, lambd)\n", "# normalisation factors are needed for pdfs, since x range is restricted\n", "sn = np.diff(s.cdf(xrange))[0]\n", "bn = np.diff(b.cdf(xrange))[0]\n", "spdf = s.pdf(x)\n", "bpdf = b.pdf(x)\n", "\n", "%timeit -r 3 -n 100 norm(*start[2:4]).pdf(x)\n", "%timeit -r 3 -n 500 expon(0, start[4]).pdf(x)\n", "%timeit -r 3 -n 1000 n_sig + n_bkg - np.sum(np.log(spdf / sn * n_sig + bpdf / bn * n_bkg))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most of the time is spend in `norm` and `expon` which numba could not accelerate and the total time is dominated by the slowest part.\n", "\n", "This, unfortunately, means we have to do much more manual work to make the function faster, since we have to replace the scipy routines with Python code that numba can accelerate and run in parallel." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-103168.78482586428)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# when parallel is enabled, also enable associative math\n", "kwd = {\"parallel\": True, \"fastmath\": {\"reassoc\", \"contract\", \"arcp\"}}\n", "\n", "\n", "@nb.njit(**kwd)\n", "def sum_log(fs, spdf, fb, bpdf):\n", " return np.sum(np.log(fs * spdf + fb * bpdf))\n", "\n", "\n", "@nb.njit(**kwd)\n", "def norm_pdf(x, mu, sigma):\n", " invs = 1.0 / sigma\n", " z = (x - mu) * invs\n", " invnorm = 1 / np.sqrt(2 * np.pi) * invs\n", " return np.exp(-0.5 * z**2) * invnorm\n", "\n", "\n", "@nb.njit(**kwd)\n", "def nb_erf(x):\n", " y = np.empty_like(x)\n", " for i in nb.prange(len(x)):\n", " y[i] = math.erf(x[i])\n", " return y\n", "\n", "\n", "@nb.njit(**kwd)\n", "def norm_cdf(x, mu, sigma):\n", " invs = 1.0 / (sigma * np.sqrt(2))\n", " z = (x - mu) * invs\n", " return 0.5 * (1 + nb_erf(z))\n", "\n", "\n", "@nb.njit(**kwd)\n", "def expon_pdf(x, lambd):\n", " inv_lambd = 1.0 / lambd\n", " return inv_lambd * np.exp(-inv_lambd * x)\n", "\n", "\n", "@nb.njit(**kwd)\n", "def expon_cdf(x, lambd):\n", " inv_lambd = 1.0 / lambd\n", " return 1.0 - np.exp(-inv_lambd * x)\n", "\n", "\n", "def nll(par):\n", " n_sig, n_bkg, mu, sigma, lambd = par\n", " # normalisation factors are needed for pdfs, since x range is restricted\n", " sn = norm_cdf(xrange, mu, sigma)\n", " bn = expon_cdf(xrange, lambd)\n", " sn = sn[1] - sn[0]\n", " bn = bn[1] - bn[0]\n", " spdf = norm_pdf(x, mu, sigma)\n", " bpdf = expon_pdf(x, lambd)\n", " no = n_sig + n_bkg\n", " return no - sum_log(n_sig / sn, spdf, n_bkg / bn, bpdf)\n", "\n", "\n", "nll(start) # test and warm-up JIT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see how well these versions do:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 10.86 times longer than the fastest. This could mean that an intermediate result is being cached.\n", "191 μs ± 152 μs per loop (mean ± std. dev. of 5 runs, 100 loops each)\n", "45.6 μs ± 11.4 μs per loop (mean ± std. dev. of 5 runs, 500 loops each)\n", "64.2 μs ± 23.9 μs per loop (mean ± std. dev. of 5 runs, 1,000 loops each)\n" ] } ], "source": [ "%timeit -r 5 -n 100 norm_pdf(x, *start[2:4])\n", "%timeit -r 5 -n 500 expon_pdf(x, start[4])\n", "%timeit -r 5 -n 1000 sum_log(n_sig / sn, spdf, n_bkg / bn, bpdf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Only a minor improvement for `sum_log`, but the pdf calculation was drastically accelerated. Since this was the bottleneck before, we expect also Migrad to finish faster now." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "55.5 ms ± 24.6 ms per loop (mean ± std. dev. of 3 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit -r 3 -n 1\n", "m = m_init(nll) # setup time is negligible\n", "m.migrad();" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Success! We managed to get a big speed improvement over the initial code. This is impressive, but it cost us a lot of developer time. This is not always a good trade-off, especially if you consider that library routines are heavily tested, while you always need to test your own code in addition to writing it.\n", "\n", "By putting these faster functions into a library, however, we would only have to pay the developer cost once. You can find those in the [numba-stats](https://github.com/HDembinski/numba-stats) library." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "151 μs ± 19.2 μs per loop (mean ± std. dev. of 5 runs, 100 loops each)\n", "185 μs ± 31.9 μs per loop (mean ± std. dev. of 5 runs, 500 loops each)\n" ] } ], "source": [ "from numba_stats import norm, expon\n", "\n", "%timeit -r 5 -n 100 norm.pdf(x, *start[2:4])\n", "%timeit -r 5 -n 500 expon.pdf(x, 0, start[4])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The implementation of the normal pdf in numba-stats is even faster than our simple implementation here.\n", "\n", "Try to compile the functions again with `parallel=False` to see how much of the speed increase came from the parallelization and how much from the generally optimized code that `numba` generated for our specific CPU. On my machine, the gain was entirely due to numba.\n", "\n", "In general, it is good advice to not automatically add `parallel=True`, because this comes with an overhead of breaking data into chunks, copy chunks to the individual CPUs and finally merging everything back together. For large arrays, this overhead is negligible, but for small arrays, it can be a net loss.\n", "\n", "So why is `numba` so fast even without parallelization? We can look at the assembly code generated." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "signature: (Array(float64, 1, 'C', False, aligned=True), float64, float64)\n", "--------------------------------------------------------------------------\n", "\t.section\t__TEXT,__text,regular,pure_instructions\n", "\t.build_version macos, 14, 0\n", "\t.section\t__TEXT,__literal8,8byte_literals\n", "\t.p2align\t3\n", "LCPI0_0:\n", "\t.quad\t0x3ff0000000000000\n", "LCPI0_1:\n", "\t.quad\t0x3fd9884533d43651\n", "\t.section\t__TEXT,__const\n", "\t.p2align\t5\n", "LCPI0_2:\n", "\t.quad\t0\n", "\t.quad\t8\n", "\t.quad\t8\n", "\t.quad\t8\n", "\t.section\t__TEXT,__text,regular,pure_instructions\n", "\t.globl\t__ZN8__main__8norm_pdfB3v22B150c8tJTC_2fWQAliW1xhDEoY6EEMEUOEMISPGsAQMVj4QniQ4IXKQEMXwoMGLoQDDVsQR1NHAS2hQ9XgStYw86ABbYse0tXqiUXJBeo6CurJ_2bXklRYnJJSB2ETCRF_2bcnq9cC7QNGJsRqAA_3d_3dE5ArrayIdLi1E1C7mutable7alignedEdd\n", "\t.p2align\t4, 0x90\n", "__ZN8__main__8norm_pdfB3v22B150c8tJTC_2fWQAliW1xhDEoY6EEMEUOEMISPGsAQMVj4QniQ4IXKQEMXwoMGLoQDDVsQR1NHAS2hQ9XgStYw86ABbYse0tXqiUXJBeo6CurJ_2bXklRYnJJSB2ETCRF_2bcnq9cC7QNGJsRqAA_3d_3dE5ArrayIdLi1E1C7mutable7alignedEdd:\n", "\t.cfi_startproc\n", "\tpushq\t%rbp\n", "\t.cfi_def_cfa_offset 16\n", "\tpushq\t%r15\n", "\t.cfi_def_cfa_offset 24\n", "\tpushq\t%r14\n", "\t.cfi_def_cfa_offset 32\n", "\tpushq\t%r13\n", "\t.cfi_def_cfa_offset 40\n", "\tpushq\t%r12\n", "\t.cfi_def_cfa_offset 48\n", "\tpushq\t%r\n", "[...]\n" ] } ], "source": [ "for signature, code in norm_pdf.inspect_asm().items():\n", " print(\n", " f\"signature: {signature}\\n{'-'*(len(str(signature)) + 11)}\\n{code[:1000]}\\n[...]\"\n", " )" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This code section is very long, but the assembly grammar is very simple. Constants start with `.` and `SOMETHING:` is a jump label for the assembly equivalent of `goto`. Everything else is an instruction with its name on the left and the arguments are on the right.\n", "\n", "The SIMD instructions are the interesting commands that operate on multiple values at once. This is where the speed comes from. \n", "- If you are on the **x86** platform, those instructions end with `pd` and `ps`.\n", "- On **arch64**, they contain a dot `.` and some letters/numbers afterwards." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "signature: (Array(float64, 1, 'C', False, aligned=True), float64, float64)\n", "--------------------------------------------------------------------------\n", "Instructions\n", "addq : 26\n", "imulq : 10\n", "movabsq : 105\n", "movl : 23\n", "movq : 305\n", "movslq : 2\n", "subq : 8\n", "vmovapd : 17\n", "vmovaps : 7\n", "vmovsd : 28\n", "vmovupd : 34\n", "vmovups : 8\n", "vmulpd : 19\n", "vmulsd : 5\n", "vsubpd : 10\n", "vsubsd : 1\n" ] } ], "source": [ "from collections import Counter\n", "\n", "for signature, code in norm_pdf.inspect_asm().items():\n", " print(f\"signature: {signature}\\n{'-'*(len(str(signature)) + 11)}\")\n", " instructions = []\n", " for line in code.split(\"\\n\"):\n", " instr = line.strip().split(\"\\t\")[0]\n", " if instr.startswith(\".\"):\n", " continue\n", " for match in (\"add\", \"sub\", \"mul\", \"mov\"):\n", " if match in instr:\n", " instructions.append(instr)\n", " c = Counter(instructions)\n", " print(\"Instructions\")\n", " for k in sorted(c):\n", " print(f\"{k:10}: {c[k]:5}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "- `add`: subtract numbers\n", "- `sub`: subtract numbers\n", "- `mul`: multiply numbers\n", "- `mov`: copy values from memory to CPU registers and back\n", "\n", "You can google all the other commands.\n", "\n", "There is a lot of repetition in the assembly code, because the optimizer unrolls loops over subsequences to make them faster. Using an unrolled loop only works if the remaining chunk of data is large enough. Since the compiler does not know the length of the incoming array, it generates sections which handle shorter chunks and all the code to select which section to use. Finally, there is some code which does the translation from and to Python objects with corresponding error handling.\n", "\n", "We don't need to write SIMD instructions by hand, the optimizer does it for us and in a very sophisticated way." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.13 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/roofit/rf101_basics.ipynb0000644000000000000000000000367114332717401017504 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 101: Basics\n", "\n", "This example corresponds to [RF101](https://root.cern.ch/doc/master/rf101__basics_8py.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iminuit import Minuit\n", "from iminuit.cost import UnbinnedNLL\n", "from numba_stats import truncnorm\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "\n", "xrange = (-10, 10)\n", "\n", "\n", "def model(x, mu, sigma):\n", " return truncnorm.pdf(x, *xrange, mu, sigma)\n", "\n", "\n", "rng = np.random.default_rng(1)\n", "x = rng.normal(1, 3, size=10000)\n", "x = x[(x > xrange[0]) & (x < xrange[1])]\n", "\n", "c = UnbinnedNLL(x, model)\n", "m = Minuit(c, 1, 3)\n", "m.limits[\"mu\"] = (-10, 10)\n", "m.limits[\"sigma\"] = (0.1, 10)\n", "m.migrad()\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(8, 3.5), sharex=True, constrained_layout=True)\n", "\n", "plt.sca(ax[0])\n", "plt.title(\"Gaussian pdf\")\n", "xm = np.linspace(*xrange, 1000)\n", "plt.plot(xm, model(xm, 1, 1), label=\"sigma=1\")\n", "plt.plot(xm, model(xm, 1, 3), label=\"sigma=3\")\n", "plt.legend()\n", "plt.xlim(*xrange)\n", "\n", "plt.sca(ax[1])\n", "plt.title(\"Gaussian pdf with data\")\n", "m.visualize(bins=100)\n", "plt.xlim(*xrange);" ] } ], "metadata": { "kernelspec": { "display_name": "py39", "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.10.9" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/roofit/rf109_chi2residpull.ipynb0000644000000000000000000000573214332717401021021 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 109: chi-square residuals and pulls\n", "\n", "This example corresponds to [RF109](https://root.cern.ch/doc/master/rf109__chi2residpull_8py.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from numba_stats import norm\n", "from iminuit.cost import BinnedNLL\n", "import boost_histogram as bh\n", "from matplotlib import pyplot as plt\n", "\n", "# generate a sample of 1000 events with sigma=3\n", "rng = np.random.default_rng(1)\n", "x = rng.normal(scale=3, size=10000)\n", "\n", "# make histogram\n", "h = bh.Histogram(bh.axis.Regular(50, -10, 10))\n", "h.fill(x)\n", "cx = h.axes[0].centers\n", "xe = h.axes[0].edges\n", "\n", "# compute residuals and pulls for wrong Gaussian with sigma = 3.15\n", "pars = [\n", " 0, # mu\n", " 3.15, # sigma\n", "]\n", "\n", "\n", "# data model, this is a cdf for a binned analysis\n", "def model(x, mu, sigma):\n", " return norm.cdf(x, mu, sigma)\n", "\n", "\n", "# pulls can be computed from the cost functions in iminuit.cost\n", "cost = BinnedNLL(h.values(), xe, model)\n", "pulls = cost.pulls(pars)\n", "# expected count per bin from the model\n", "m = cost.prediction(pars)\n", "# residuals are not generally useful, so there is no library routine and\n", "# we compute them \"by hand\"\n", "residuals = cost.n - m\n", "\n", "# value returned by BinnedNLL functor is chi-square distributed\n", "chi_square = cost(*pars)\n", "# normally, we would subtract fitted degrees of freedom from cost.ndata, but\n", "# in this example nothing no parameters are fitted\n", "print(f\"𜒲/ndof = {chi_square / cost.ndata:.2f}\")\n", "\n", "fig, ax = plt.subplots(1, 3, figsize=(10, 3), sharex=True, constrained_layout=True)\n", "\n", "# plot data and gaussian model with sigma = 3.15\n", "plt.sca(ax[0])\n", "plt.title(\"data with distorted gaussian pdf\")\n", "plt.errorbar(cx, h.values(), h.variances() ** 0.5, fmt=\"ok\")\n", "plt.stairs(m, xe, fill=True)\n", "\n", "plt.sca(ax[1])\n", "plt.title(\"residual distribution\")\n", "plt.errorbar(cx, residuals, h.variances() ** 0.5, fmt=\"ok\")\n", "\n", "plt.sca(ax[2])\n", "plt.title(\"pull distribution\")\n", "plt.errorbar(cx, pulls, 1, fmt=\"ok\");" ] } ], "metadata": { "kernelspec": { "display_name": "py310", "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.10.9" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/roofit.ipynb0000644000000000000000000025626014332717401015333 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Fitting RooFit-generated likelihoods\n", "\n", "In this tutorial, we show how to create a negative log-likelihood function with the [RooFit framework](https://root.cern/manual/roofit/) and minimize it with iminuit. \n", "\n", "RooFit is a powerful fitting framework developed by CERN's ROOT team.\n", "RooFit is very powerful and sophisticated, but there are a few reasons to use iminuit instead:\n", "\n", "- RooFit documention is extensive, but lacking in important places\n", "- RooFit interfaces are not Pythonic, they mimic the C++ interfaces (which are also dated)\n", "- Errors are difficult to understand and debug since RooFit is internally executing C++ code\n", "- You may experience segmentation faults when using RooFit from Python due to bugs in the ROOT Python layer (problems with handling life-times of dynamic C++ objects in Python correctly)\n", "\n", "For these reasons, you may consider to transition to iminuit and its cost functions for your project. As a first step, you want to convince yourself that iminuit gives you the same fitting result as you get from RooFit. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Welcome to JupyROOT 6.26/10\n" ] } ], "source": [ "# ROOT is best installed via a conda virtual environment from conda-forge\n", "import ROOT" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# fix PRNG seed for RooFit random number generation\n", "ROOT.RooRandom.randomGenerator().SetSeed(1)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We generate a Gaussian with mean 1 and width 3 and draw 10000 data points from it. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = ROOT.RooRealVar(\"x\", \"x\", -10, 10)\n", "mean = ROOT.RooRealVar(\"mean\", \"mean of gaussian\", 1, -10, 10)\n", "sigma = ROOT.RooRealVar(\"sigma\", \"width of gaussian\", 3, 0.1, 10)\n", "\n", "gauss = ROOT.RooGaussian(\"gauss\", \"gaussian PDF\", x, mean, sigma)\n", "\n", "data = gauss.generate({x}, 10000)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We now fit this Gaussian. We use the `createNLL` method and a simple wrapper function `evaluate`. Note that this simple wrapping function does not propagate the parameter names of the Gaussian to iminuit. A future version of iminuit will come with a builtin wrapper that will also propagate the names and limits." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 2.514e+04 Nfcn = 31
EDM = 2.72e-08 (Goal: 0.0001)
Valid Minimum No Parameters at limit
Below EDM threshold (goal x 10) Below call limit
Covariance Hesse ok Accurate Pos. def. Not forced
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 1.003 0.030
1 x1 3.017 0.022
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 0.000926 0 (0.030)
x1 0 (0.030) 0.000497
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 2.514e+04 │ Nfcn = 31 │\n", "│ EDM = 2.72e-08 (Goal: 0.0001) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ No Parameters at limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Below EDM threshold (goal x 10) │ Below call limit │\n", "├───────────────┬──────────────────┼───────────┬─────────────┬────────────┤\n", "│ Covariance │ Hesse ok │ Accurate │ Pos. def. │ Not forced │\n", "└───────────────┴──────────────────┴───────────┴─────────────┴────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 1.003 │ 0.030 │ │ │ │ │ │\n", "│ 1 │ x1 │ 3.017 │ 0.022 │ │ │ │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 0.000926 0 │\n", "│ x1 │ 0 0.000497 │\n", "└────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from iminuit import Minuit\n", "\n", "nll = gauss.createNLL(data)\n", "\n", "\n", "def evaluate(*args):\n", " for par, arg in zip(nll.getVariables(), args):\n", " par.setVal(arg)\n", " # following RooMinimizerFcn.cxx\n", " nll.setHideOffset(False)\n", " r = nll.getVal()\n", " nll.setHideOffset(True)\n", " return r\n", "\n", "\n", "evaluate.errordef = Minuit.LIKELIHOOD\n", "\n", "m = Minuit(evaluate, *[p.getVal() for p in nll.getVariables()])\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Let's compare this to fitting directly with the `fitTo` method." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization\n", " **********\n", " ** 1 **SET PRINT 1\n", " **********\n", " **********\n", " ** 2 **SET NOGRAD\n", " **********\n", " PARAMETER DEFINITIONS:\n", " NO. NAME VALUE STEP SIZE LIMITS\n", " 1 mean 1.00653e+00 2.00000e+00 -1.00000e+01 1.00000e+01\n", " 2 sigma 3.01930e+00 9.90000e-01 1.00000e-01 1.00000e+01\n", " **********\n", " ** 3 **SET ERR 0.5\n", " **********\n", " **********\n", " ** 4 **SET PRINT 1\n", " **********\n", " **********\n", " ** 5 **SET STR 1\n", " **********\n", " NOW USING STRATEGY 1: TRY TO BALANCE SPEED AGAINST RELIABILITY\n", " **********\n", " ** 6 **MIGRAD 1000 1\n", " **********\n", " FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.\n", " START MIGRAD MINIMIZATION. STRATEGY 1. CONVERGENCE WHEN EDM .LT. 1.00e-03\n", " FCN=25136.7 FROM MIGRAD STATUS=INITIATE 10 CALLS 11 TOTAL\n", " EDM= unknown STRATEGY= 1 NO ERROR MATRIX \n", " EXT PARAMETER CURRENT GUESS STEP FIRST \n", " NO. NAME VALUE ERROR SIZE DERIVATIVE \n", " 1 mean 1.00653e+00 2.00000e+00 2.02444e-01 3.46428e+01\n", " 2 sigma 3.01930e+00 9.90000e-01 2.22272e-01 2.14205e+01\n", " ERR DEF= 0.5\n", " MIGRAD MINIMIZATION HAS CONVERGED.\n", " MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.\n", " COVARIANCE MATRIX CALCULATED SUCCESSFULLY\n", " FCN=25136.7 FROM MIGRAD STATUS=CONVERGED 25 CALLS 26 TOTAL\n", " EDM=1.96964e-05 STRATEGY= 1 ERROR MATRIX ACCURATE \n", " EXT PARAMETER STEP FIRST \n", " NO. NAME VALUE ERROR SIZE DERIVATIVE \n", " 1 mean 1.00330e+00 3.04253e-02 3.34944e-04 1.02604e+00\n", " 2 sigma 3.01694e+00 2.22842e-02 5.41347e-04 6.16930e-01\n", " ERR DEF= 0.5\n", " EXTERNAL ERROR MATRIX. NDIM= 25 NPAR= 2 ERR DEF=0.5\n", " 9.257e-04 2.032e-05 \n", " 2.032e-05 4.966e-04 \n", " PARAMETER CORRELATION COEFFICIENTS \n", " NO. GLOBAL 1 2\n", " 1 0.02997 1.000 0.030\n", " 2 0.02997 0.030 1.000\n", " **********\n", " ** 7 **SET ERR 0.5\n", " **********\n", " **********\n", " ** 8 **SET PRINT 1\n", " **********\n", " **********\n", " ** 9 **HESSE 1000\n", " **********\n", " COVARIANCE MATRIX CALCULATED SUCCESSFULLY\n", " FCN=25136.7 FROM HESSE STATUS=OK 10 CALLS 36 TOTAL\n", " EDM=1.96993e-05 STRATEGY= 1 ERROR MATRIX ACCURATE \n", " EXT PARAMETER INTERNAL INTERNAL \n", " NO. NAME VALUE ERROR STEP SIZE VALUE \n", " 1 mean 1.00330e+00 3.04246e-02 6.69888e-05 1.00499e-01\n", " 2 sigma 3.01694e+00 2.22838e-02 1.08269e-04 -4.23243e-01\n", " ERR DEF= 0.5\n", " EXTERNAL ERROR MATRIX. NDIM= 25 NPAR= 2 ERR DEF=0.5\n", " 9.257e-04 1.984e-05 \n", " 1.984e-05 4.966e-04 \n", " PARAMETER CORRELATION COEFFICIENTS \n", " NO. GLOBAL 1 2\n", " 1 0.02926 1.000 0.029\n", " 2 0.02926 0.029 1.000\n", "[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization\n" ] } ], "source": [ "gauss.fitTo(data);" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The results are in agreement, because the results of a fit cannot depend on the minimizer. Technically, RooFit uses a different minimizer than iminuit by default. Unless you change some options, RooFit uses the original MINUIT Fortran implementation translated to C, while iminuit uses the rewritten Minuit2 C++ library." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Just doing the fitting with iminuit does not offer you a lot of advantages. Eventually, you want to switch completely. The equivalent of this exercise in pure Python is the following." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 4.998e+04 Nfcn = 29
EDM = 3e-06 (Goal: 0.0002)
Valid Minimum No Parameters at limit
Below EDM threshold (goal x 10) Below call limit
Covariance Hesse ok Accurate Pos. def. Not forced
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 mu 0.96 0.03
1 sigma 2.985 0.022
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
mu sigma
mu 0.000906 0 (0.027)
sigma 0 (0.027) 0.000483
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 4.998e+04 │ Nfcn = 29 │\n", "│ EDM = 3e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ No Parameters at limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Below EDM threshold (goal x 10) │ Below call limit │\n", "├───────────────┬──────────────────┼───────────┬─────────────┬────────────┤\n", "│ Covariance │ Hesse ok │ Accurate │ Pos. def. │ Not forced │\n", "└───────────────┴──────────────────┴───────────┴─────────────┴────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ mu │ 0.96 │ 0.03 │ │ │ │ │ │\n", "│ 1 │ sigma │ 2.985 │ 0.022 │ │ │ │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬───────────────────â”\n", "│ │ mu sigma │\n", "├───────┼───────────────────┤\n", "│ mu │ 0.000906 0 │\n", "│ sigma │ 0 0.000483 │\n", "└───────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABP0UlEQVR4nO3de3xT9f0/8NdpoIXSC5SWXkih6LRYBHRs1narE+ELAm6yUqfIlG1MhqtKwflF/DpB/A6c+hWqosjGwN+8UyMIQxERaLUFAbkWqICFNumd0vRGm/bk/P7AhIYm6Umb5Jykr+fjkceDnPNJ8j7G0hfncxMkSZJAREREpCIBShdAREREdDUGFCIiIlIdBhQiIiJSHQYUIiIiUh0GFCIiIlIdBhQiIiJSHQYUIiIiUh0GFCIiIlKdPkoX0B1msxllZWUIDQ2FIAhKl0NEREQySJKEhoYGxMXFISDA+T0SnwwoZWVliI+PV7oMIiIi6obS0lJotVqnbXwyoISGhgK4fIFhYWEKV0NERERy1NfXIz4+3vp73BmfDCiWbp2wsDAGFCIiIh8jZ3gGB8kSERGR6jCgEBERkeowoBAREZHqMKAQERGR6jCgEBERkeowoBAREZHqMKAQERGR6jCgEBERkeowoBAREZHqMKAQERGR6jCgEBERkeowoBAREZHqMKAQERGR6jCgEFGv0NTUBEEQIAgCmpqalC6HiLrAgEJERESqw4BCREREqsOAQkRERKrDgEJERESqw4BCREREqsOAQkRERKrDgEJERESqw4BCREREqsOAQkS9giiK1j/n5ubaPCci9WFAISK/p9PpkJSUZH0+depUJCQkQKfTKVgVETnDgEJEfk2n0yEjIwMGg8HmuMFgQEZGBkMKkUoxoBCR3xJFEfPnz4ckSZ3OWY5lZWWxu4dIhRhQiMhv5eXlQa/XOzwvSRJKS0uRl5fnxaqISA4GFCLyW+Xl5S61447HROrBgEJEfis2Ntat7YjIexhQiMhvpaWlQavVQhAEu+cFQUB8fDzS0tK8XBkRdYUBhYhUrSfdLhqNBtnZ2QDQKaRYnq9atQoajcY9xRKR2zCgEJFfS09PR05ODuLi4myOa7Va5OTkID09XaHKiMiZPkoXQETkbpIkYe/3tThUehFnq5pwtjoaw+a+AcOSXwEAfvP0avx2xq/wX6NcH3vS1NSEkJAQAEBjYyMGDBjg1tqJ6DIGFCLyGxcaW5FzUI/395eiuMa2O8hsMln/XNAUjX3vH8GAwOO444Zo3H/LMKRcO9jb5RKREwwoROTz2kQz3th9Fq/tOgNTu1n265pMIrYcKcOWI2WYlBSNhbcP92CVROQKBhQi8mmHSi7iyY+OoaiyoUfv8/mJSuw8es76PDc3F5MmTeIAWiKFcJAsEfkkSZLw8udFmPFGfo/DCQA0F+Xj/JvzrM+5oSCRshhQiMjntIlmLPzwCF758gzMnbfZcVlzUT6qNy2H2HjB5jg3FCRSDgMKEalax438cnNzcbGpBbP/9Q0+PmRw8ir5JLOI2p1r7Z+TJEjghoJESmBAISLV0ul0SEpKsj6fOnUqYocOwxfbtrjtM1r1hRAbahw34IaCRIpgQCEiVdLpdMjIyIDBYHunpNVYjepNy9FclG89Zja14Pzf78L5v98Fs6nFpc8RGy/Kapd3+DuX3peIeoYBhYhURxRFzJ8/H5LkeIBJ7c61kMzyu10CAvth+KKtGL5oKwIC+1mPa0IGyXr9vw7V4XBpXacuJ3b9EHkGAwoRqU5eXh70er3TNmJDDVr1hT3+rCDtKGhCI5220YRGwhw9EtOfeBmJI2+wHudMHyLPYUAhItUpLy+X1U5u94wzQoAGERPmOm0TMWEuLp3eh/MfPIeK8jKbc5zpQ+QZDChEpDqxsfL2yJHbPdOV4MRURE1/CpoQ2+XuNaGRiJr+FPpfl+x0pg/AmT5E7saAQkSqk5aWhti4oU7baEIjEaQd5bbPDE5MReyc163PozKWYui8dQhOTO1ypo/EmT5EbseAQkTqIwTgml9mOm0SMWEuhAD3LkPf8f36xd9ofS63K0lu1xQRdY0BhYgU09TUBEEQIAgCmpqu7D6c/cV30A8c47TbJTgx1Wt1yu1Kkts1RURdcymgLF261PqXieUxcuRI6/mWlhZkZmZi8ODBCAkJwYwZM1BZWWnzHiUlJZg2bRqCg4MxZMgQPPHEE2hvb3fP1RCRzzuqr8Nru84AcN7t0lHH6cYtpcddmn4sR1czfQRBQHx8PNLS0tz6uUS9mct3UEaNGoXy8nLr46uvvrKeW7BgAbZs2YKNGzdiz549KCsrQ3p6uvW8KIqYNm0aTCYT8vPz8dZbb2HDhg145pln3HM1ROTTzGYJT286brO/jqNuF4vmonyUr/uz9Xl1zlIY1syxWcitp+TM9Fm1ahV3PiZyI5cDSp8+fRATE2N9REZe/leF0WjEunXr8PLLL+OOO+7AuHHjsH79euTn52Pv3r0AgM8//xwnTpzA22+/jZtuuglTpkzBc889h9WrV8NkMrn3yojI57yz7zyO6o2y2zva5E9sqOm02mxPOZvpc+tDf8Ovf/1rt30WEXUjoJw+fRpxcXG45pprMGvWLJSUlAAADh48iLa2NkycONHaduTIkRg2bBgKCgoAAAUFBRg9ejSio6OtbSZPnoz6+noUFjpecKm1tRX19fU2DyLyL9UNrXhxe5Hs9s42+bNwdbXZrjjqciobNAbv7y912+cQkYsBJTk5GRs2bMBnn32GN954A8XFxUhLS0NDQwMqKioQGBiIgQMH2rwmOjoaFRUVAICKigqbcGI5bznnyIoVKxAeHm59xMfHu1I2EfmAl7YXob5F/ni0Ljf5g/tWm+3IUZfTim0nUdXg2j5AROSYSwFlypQpuOeeezBmzBhMnjwZ27ZtQ11dHT788ENP1QcAWLx4MYxGo/VRWsp/qRD5m0+OlHXdqAO5U3/dsdqsHPUt7Vi25YRXPouoN+jRNOOBAwfi+uuvx5kzZxATEwOTyYS6ujqbNpWVlYiJiQEAxMTEdJrVY3luaWNPUFAQwsLCbB5E1LvJnfrrymqzjjYUlGvr0XLsOlXl8uuIqLMeBZTGxkacPXsWsbGxGDduHPr27YudO3dazxcVFaGkpAQpKSkAgJSUFBw7dgxVVVd+gHfs2IGwsDAkJSX1pBQi6mXkbvLnztVm5Xh603E0m7h0AlFPuRRQ/vKXv2DPnj04d+4c8vPz8etf/xoajQYzZ85EeHg45syZg4ULF2LXrl04ePAgfv/73yMlJQW33norAGDSpElISkrCAw88gCNHjmD79u14+umnkZmZiaCgII9cIBGpV+mFRuufXV2/RO4mf+5ebbYrhrpLWLnjO69+JpE/6uNKY71ej5kzZ+LChQuIiorCz3/+c+zduxdRUVEAgJUrVyIgIAAzZsxAa2srJk+ejNdfvzLiXaPRYOvWrXj44YeRkpKCAQMGYPbs2Vi2bJl7r4qIVE+n0+GBP86zPq/OWQpNaCQiJsy1WYjN0u1ij2Xqb+0Xb9pMNbb3Pt70r6/P4e6bhuLGoeGKfD6RPxAky1acPqS+vh7h4eEwGo0cj0Lkg3Q6HWZkZAAO/vpxdSl7saUJ+ux7L782Yyn6j7jZY3dOzKYWlK7MAADEL8hxOFblZz8ajHf+eKtHaiDyVa78/nbpDgoRUU+JoojH5s93GE6Ay+uX9L8uWXbI6Gq1WXdydkeno6/PXMC+7y8g+ZrBXbYlos64WSAReYSjjQDz8vJg0OudvtYT65d4k9nUgvN/vwu3Xhtpc+1EJB8DChF5VaneIKudt9Yv8bT8M84XkyMi+xhQiMirTtbL635xZf0SNXv1y9NKl0DkkxhQiMhrTO1m7LoYocr1SzzlcKkRu4o6L97mqAuMiC5jQCEir/nwQCnKG9pUuX6JJ63iuihELmNAISKvMLWb8cbuswCurF+iCbGd4aIJjXR5irEvOKI3YseJyq4bEpEVpxkTkVdsPFgKQ90l6/PgxFQEDR/rlvVL5E79VdLKHd9h4g1DIAiC0qUQ+QTeQSEijxDFK8vW79q9B6t3du7m8Ob6Jd7Uccl+yxL+J8rr8dnxCgWrIvItDChE5LKuBnjqdDqbDUB/edc0fPP8/WguyvdmmYpoLspH+bo/W59X5yyFYc0cNBflY+UX38Fs9rnFu4kUwYBCRG6l0+mQkZEBg8F2vROxoQbVm5b7dUhpLspH9ablNvsCAVeu/XDu59h6rFyh6oh8CwMKEbmNKIqYP38+nG3xVbtzrUu7FvsKySyidudap21qd67Fys9PQpR5F4VTkak3Y0AhIrfJy8uD3s+XsXekVV8IscH5qrFiQw1OHvoGnxwx2IzRyc3NtXlORAwoRORG5eXyui/8ZRn7juRek9h4Ecte3WAzRmfq1KlISEiATqfzVHlEPocBhYjcJjY2VlY7f1nGviO519R20YDD6//aaYyOwWBARkYGQwrRDxhQiMht0tLSoNVqna710XEZe8v6JcMXbUVAYD9vlekRQdpRXS7hHxAyGI2Ht9s9Zxm3k5WVxe4eIjCgEFE3OBo/odFokJ2d7fS1/raMvYUQoOlyCf/QsXd2muHTkSRJKC0tRV5enrvLI/I5DChE5JKr1zi5evxEeno6/u/Nt3rNMvYddbWEf9+IOFnvI3csD5E/Y0AhItkcrXFy9fiJ0rDRiJ3zuvV8VMZSDJ23zq/DiUVwYqrDa5c7TkXuWB4if8aAQkSyOFvjpOP4iYq6Zmw9Wu63y9jL4ejauxqnIggC4uPjkZaWBsBxVxpRb8CAQkSydLXGiWX8xP+u+wgm0ezFynyHs3EqloHFq1atgkaj6bIrjcjfMaAQkSxyx0Vs23fSw5X4NkfjVLRaLXJycpCeni67K43InzGgEJEscsdFNPcJ9XAlvu/qcSqpmS+huLgY6enpsrvS2N1D/o4BhYhk6WqNE0EQ0G/gEOsaJ+Rcx3EqpYEJOFbWAEB+VxqnIpO/Y0AhIlk6rnFydUgRBAESgNDb/9irBsO607++KgYgvyuNU5HJ3zGgEJFs6enpyMnJQVyc7XoeWq0Wd85/oVdMI/aUT4+Xo8LYIrsrjVORyd8JkrN90VWqvr4e4eHhMBqNCAsLU7ocol7H8jMIANu2bcPo5DTc/lIu2s0+99eJYsymFpSuzAAAxC/IQUBgPzx8+7X4y39dh4SEBBgMBrvjUARBgFarRXFxMTQa3q0i3+LK72/eQSEil3X8xXjbbbfh3W/0DCdu8N43JTCJcNqVBlyZikzkzxhQiKhHWtpEvL+/VOky/EJdcxt0h/ROu9IsU5GJ/B0DChH1yNajZahtMildht94Z28JgMvjfU6cOGE9vm3bNutUZKLeoI/SBRCRb/t3wXmlS/BJAYH9MHzR1k7HT5TX40hpHcbGD+zUlcZuHepNeAeFiHrku8pGpUvwO+/vL1G6BCLFMaAQEanMJ4fL0NTarnQZRIpiQCEiUpkmk4hPjpQpXQaRohhQiMhlAwYMwL8LzmH4oq0ICOyndDl+6f1v2M1DvRsDChF1ywecWuxRR/RGnCyvV7oMIsVwFg8RuaywzIhjBqPSZfi9Twov2F1Nlqg34B0UInLZ+9/w7ok3fHzIgJY2UekyiBTBgEJELmlpE7H5sEHpMnqFhpZ2bD3KXYupd2JAISKXbDtWjvoWToH1Fg6Wpd6KAYWIXMJ9d7zrwPmLOF3ZoHQZRF7HgEJENpqamiAIAgRBQFNTk82576sb8U1xrUKV9V7vccwP9UIMKEQkG6cWK+PjQ3q0tnOwLPUuDChEJEubaMZH33JwrBIuNrfhs+MVSpdB5FUMKEQky86TlahpbFW6jF7rPQ6WpV6GAYWIZOHgWGXt/b4WxTVNXTck8hMMKETUpbK6S8j9rlrpMnq99/d37y6Ks4HPRGrFgEJEXfrwQCnMXHFdcZsOGSDyi6BeggGFiGyI4pXZIrm5uWhra8fGA3oFKyKLyvpWfHWmRukyiLyiRwHl+eefhyAIyMrKsh5raWlBZmYmBg8ejJCQEMyYMQOVlZU2ryspKcG0adMQHByMIUOG4IknnkB7O1emJFKaTqdDUlKS9fnUqVMxdNhwnN63U8GqqCPdtwyL1Dt0O6Ds378fb775JsaMGWNzfMGCBdiyZQs2btyIPXv2oKysDOnp6dbzoihi2rRpMJlMyM/Px1tvvYUNGzbgmWee6f5VEFGP6XQ6ZGRkwGCwnUpcXVGO6k3L0VyUr1Bl1NH2wgo0tLQpXQaRx3UroDQ2NmLWrFn4xz/+gUGDBlmPG41GrFu3Di+//DLuuOMOjBs3DuvXr0d+fj727t0LAPj8889x4sQJvP3227jpppswZcoUPPfcc1i9ejVMJpN7roqIXCKKIubPnw9Jsje+4fKx2p1rIZm5WJjSWtrM2HaMGwiS/+tWQMnMzMS0adMwceJEm+MHDx5EW1ubzfGRI0di2LBhKCgoAAAUFBRg9OjRiI6OtraZPHky6uvrUVhYaPfzWltbUV9fb/MgIvfJy8uDXu+860BsqEGr3v7PKHmXqwvmXT2uqONzIrVyOaC8//77+Pbbb7FixYpO5yoqKhAYGIiBAwfaHI+OjkZFRYW1TcdwYjlvOWfPihUrEB4ebn3Ex8e7WjYROVFeLu9f5GLjRQ9XQnLsP1eL0tpmWW3tjStKSEiATqfzVHlEbuFSQCktLcX8+fPxzjvvoF+/fp6qqZPFixfDaDRaH6WlXDCKyJ1iY2NltdOEDOq6EXmcJAEfyRgs62hckcFgQEZGBkMKqZpLAeXgwYOoqqrCj3/8Y/Tp0wd9+vTBnj178Morr6BPnz6Ijo6GyWRCXV2dzesqKysRExMDAIiJiek0q8fy3NLmakFBQQgLC7N5EJH7pKWlQavVQhAEh200oZEI0o7yYlXkzMeHnHfzOBtXZDmWlZXF7h5SLZcCyoQJE3Ds2DEcPnzY+vjJT36CWbNmWf/ct29f7Nx5ZUpiUVERSkpKkJKSAgBISUnBsWPHUFVVZW2zY8cOhIWF2dyGJCLv0Wg0yM7OBgCHISViwlwIARpvlkVOnL/QjP3nah2e72pckSRJKC0tRV5enifKI+qxPq40Dg0NxY033mhzbMCAARg8eLD1+Jw5c7Bw4UJEREQgLCwMjz76KFJSUnDrrbcCACZNmoSkpCQ88MADeOGFF1BRUYGnn34amZmZCAoKctNlEZGr0tPTkZOTg8cee8ymS0ATGomICXMRnJiqYHVkj+5bPX6aEGH3nNxxRXLbEXmb21eSXblyJe666y7MmDEDt912G2JiYmz6OTUaDbZu3QqNRoOUlBT89re/xYMPPohly5a5uxQiclF6ejpOnDhhfR6VsRRD561jOFGprUfL0dJmv4tG7rgiue2IvE2Q7C98oGr19fUIDw+H0WjkeBQiN2tqakJISAgAIH5BDgICvTcgnlz3ysyb8auxcZ2Oi6KIhIQEGAwGu+NQBEGAVqtFcXExNBp23ZF3uPL7m3vxEJGNQyWOxzWQ+jha+t7ZuCLL81WrVjGckGoxoBCRjU+OlCldArkg73QNqhpa7J6zjCuKi7O9w6LVapGTk2OzDQmR2jCgEJFVm2jGp8cru25IqiGaJWw+5DhUXj2uaNu2bSguLmY4IdVjQCEiq12nqmBs5kZ0vqarRds6duPcdttt7NYhn8CAQkRWmw67tscLqcOpigYcNxiVLoPIrVxaB4WI/Fd9Sxu+OFmFgMB+GL5oq9LlkIt03xpw49BwpcsgchveQSEiAMC2o+UwtZuVLoO6acvRMohmn1s1gsgh3kEhIgBd7+1C6mQ2taB0ZQbOA9h5VzEmjU1QuiQit+AdFCKCoe4SvnGyrwv5hq1HKpQugchteAeFiLDpkAG+t6Y0Xe2Lk5VoaRPRr6/tLJ0BAwbYXU2WSM14B4WIsIndO36hsbUdX5zkOjbkHxhQiHq54wYjTlc1Kl0GuckmJ4u2EfkSBhSiXo53T/zLnu+qUNdsUroMoh5jQCHqxUSzxL13fJxkFq1/bik9DlNbO/5zrFzBiojcg4NkiXqRpqYmhISEAAAaGxtx0NCMqoZWhaui7mouykftF29an1fnLIUmNBKrjQsxK3mxgpUR9RzvoBD1Yuze8V3NRfmo3rQcYuMFm+NiQw0K1j6Ff/z7PYUqI3IPBhSiXuqSScT2Qq6b4Ysks4janWudtln0+OMQRdFpGyI1Y0Ah6qW+OFmJJhN/gfmiVn0hxIYap20uVpcjLy/PSxURuR8DClEvxcGxvktsvCir3YET33u4EiLPYUAh6qUKzl7ouhGpkiZkkKx2RQ2arhsRqRQDClEv0nFMQtP5YzZTVMl3BGlHQRMa6bSNJjQSx9tjucQ9+SwGFKJeQqfTISkpyfq8OmcpDGvmoLkoX8GqqDuEAA0iJsx12iZiwlyUN7RhXzE3gSTfxIBC1AvodDpkZGTAYLCdViw21KB603KGFB8UnJiKqOlPQRMy2Oa4JjQSUdOfQnBiKgBg82FOJSffxIBC5OdEUcT8+fOd3uqv3bmW3T0+KDgxFbFzXrc+j8pYiqHz1lnDCQBsO1YBU7tZifKIeoQBhcjP5eXlQa/XO20jNtSgVV/opYrInYSAKwNh+8XfaPMcAIyX2rCrqMrbZRH1GAMKkZ8rL5e3L4vcqavke9jNQ76IAYXIz8XGxspqJ3fqKvmenSer0NjarnQZRC5hQCHyc2lpadBqtRAEwWEbTWgkgrSjvFgVeVNruxmfHee2BuRbGFCI/JxGo0F2djacrYYRMWFup7EL5F/YzUO+hgGFqBdIT0/H5Mf+3uWUVPJf+WcvoKaxVekyiGTro3QBROR5ja3tKA65EbFzXoc++14Al6ek9h9xM++c+LiAwH4Yvmhrl+1Es4StR8rwu5+N8EJVRD3HOyhEvcBnxyvQ2m7uckoq+bfN3CCSfAgDClEvwPEHBACHSupQWtusdBlEsjCgEPm5msZW5HPnYvoBwyr5CgYUIj+39UgZRDN3tKXLNh9mNw/5BgYUIj/HcQfU0emqRpwoq1e6DKIucRYPkR8rudCMQyV11udyZ3yQf9t8xICkuDClyyByindQiPwYxxuQPVuPlDvd3ZpIDRhQiPwYu3fIHkPdJew/x80hSd0YUIj8VGGZEWeqGpUug1SKd9dI7RhQiPxAU1MTBEGAIAhoamoCAHzC2RrkxLZj5WgTzUqXQeQQAwqRH5IkCVvYvUNOXGxuQ97paqXLIHKIAYXID31TXIsyY4vSZZDKcU0UUjMGFCI/xMGxJMeOE5W4ZBKVLoPILgYUIj/TJprx6bFypcsgH9BsEvH5iQqlyyCyiwGFyA+I4pV/Bb/x3hbUNrJ7h+SxDKa2N9CaSEkMKEQ+TqfTISkpyfr8qXmzYFgzB81F+QpWRb4i93Q16ppNSpdB1AkDCpEP0+l0yMjIgMFgu6aF2FCD6k3LGVKoS22ihP+wS5BUyKWA8sYbb2DMmDEICwtDWFgYUlJS8Omnn1rPt7S0IDMzE4MHD0ZISAhmzJiByspKm/coKSnBtGnTEBwcjCFDhuCJJ55Ae3u7e66GqBcRRRHz5893umR57c61kMwcBEnOcTYPqZFLAUWr1eL555/HwYMHceDAAdxxxx24++67UVhYCABYsGABtmzZgo0bN2LPnj0oKytDenq69fWiKGLatGkwmUzIz8/HW2+9hQ0bNuCZZ55x71UR9QJ5eXnQ6/VO24gNNWjVF3qpIvJV+8/VosJ4SekyiGy4FFB++ctfYurUqbjuuutw/fXX429/+xtCQkKwd+9eGI1GrFu3Di+//DLuuOMOjBs3DuvXr0d+fj727t0LAPj8889x4sQJvP3227jpppswZcoUPPfcc1i9ejVMJvaBErmivFzebXmxkXuukHOSBGw5dCXs5ubm2gy8JlJCt8egiKKI999/H01NTUhJScHBgwfR1taGiRMnWtuMHDkSw4YNQ0FBAQCgoKAAo0ePRnR0tLXN5MmTUV9fb70LY09rayvq6+ttHkS9XWxsrKx2mpBBHq6EfF1zUT6enPVf1udTp05FQkICdDqdglVRb+dyQDl27BhCQkIQFBSEefPm4eOPP0ZSUhIqKioQGBiIgQMH2rSPjo5GRcXlefYVFRU24cRy3nLOkRUrViA8PNz6iI+Pd7VsIr+TlpYGrVYLQRActtGERiJIO8qLVZGvaS7KR/Wm5Wg11tgcNxgMyMjIYEghxbgcUBITE3H48GHs27cPDz/8MGbPno0TJ054ojarxYsXw2g0Wh+lpaUe/TwiX6DRaJCdnQ0ADkNKxIS5EAI03iyLfIhkFlG7c639cz8Mvs7KymJ3DynC5YASGBiIH/3oRxg3bhxWrFiBsWPHIjs7GzExMTCZTKirq7NpX1lZiZiYGABATExMp1k9lueWNvYEBQVZZw5ZHkQEpKenIycnB2GDh9gc14RGImr6UwhOTFWoMvIFrfpCiA01Ds9LkoTS0lLk5eV5sSqiy3q8DorZbEZrayvGjRuHvn37YufOndZzRUVFKCkpQUpKCgAgJSUFx44dQ1VVlbXNjh07EBYWZrPQFBHJl56ejnEL/2V9HpWxFEPnrWM4oS7JHUAtd0A2kTv1caXx4sWLMWXKFAwbNgwNDQ149913sXv3bmzfvh3h4eGYM2cOFi5ciIiICISFheHRRx9FSkoKbr31VgDApEmTkJSUhAceeAAvvPACKioq8PTTTyMzMxNBQUEeuUAif1dU0YDT1VemiPaLv5HdOiSL3AHUcgdkE7mTSwGlqqoKDz74IMrLyxEeHo4xY8Zg+/bt+K//ujz6e+XKlQgICMCMGTPQ2tqKyZMn4/XXX7e+XqPRYOvWrXj44YeRkpKCAQMGYPbs2Vi2bJl7r4qoF9l82NB1IyI7grSjoAmNdNjNIwgCtFot0tLSvFwZESBIzpahVKn6+nqEh4fDaDRyPAr1ej//+5coqbyI0pUZAID4BTkICOyncFXkKyyzeK5mGXidk5Njs+AmUU+48vube/EQ+bCD52uhv8gVQKn7ghNTETX9KWhCBtsc12q1DCekKAYUIpVramqCIAgQBAFNTU0257iHCrlDcGIqYudc6Y4fPvM5nPzuDMMJKcqlMShEpB7tohnbftiFNiCwH4Yv2qpwReTLOg6sNsfcgNzTFzBlNAfHknJ4B4XIR311pgY1jdzDijyDd+dIaQwoRD7qE/4CIQ/aVVSF+pY2pcugXowBhcgHtbSJ+PxEZdcNibqptd2Mz4473iONyNMYUIhUruM+KLm5uRBFETtOVKKxtV3BqsjfWMYxDV+01TpN/eq7dM4GbBO5GwMKkYrpdDqbbSCmTp2KhIQEZP/zbQWrot4i/2wNyo2cxk7KYEAhUimdToeMjAwYDLYrxRoMBux8bRGai/IVqox6C7MEfHyIKxWTMhhQiFRIFEXMnz8f9hZ6thyr3bkWklnsdJ7InT46qFe6BOqlGFCIVCgvLw96vfNfDGJDDVr1hV6qiHqrs9VNOFRyeddje+OhiDyFAYVIheRuby82XvRwJUTAR9/qHY6H0ul0ClZG/owBhUiF5G5vrwkZ5OFKiIC339vocDxURkYGQwp5BAMKkQqlpaVBq9Vad5S1RxMaiSDtKC9WRb2RZBah//QNp+OhsrKy2N1DbseAQqRCGo0G2dnZAOAwpERMmGuzfwqRJ7TqCyE21Dg8L0kSSktLkZeX58WqqDdgQCFSqfT0dOTk5CAuLs7muCY0ElHTn0JwYqpClVFvIneck9xxU0RycTdjIhVLT0/HxIkTER4eDgCIyliK/iNu5p0T8hq545zkjpsikot3UIhUTqO5Ekb6xd/IcEJeFaQdBU1opMPzgiAgPj4eaWlpXqyKegMGFCIickgI0CBiwlz7534YH7Vq1SqbIE3kDgwoRCpX12xSugTq5YITUxE1/SloQgbbHNdqtcjJyUF6erpClZE/4xgUIpX79BgHH5LyghNTETR8LPTZ9wIAtm3bhkmTJvHOCXkMAwqRyv3n1EUMX7RV6TKIbMY/3XbbbQwn5FHs4iFSseKaJhwqqVO6DCIir2NAIVKxj7/lTrKkThwbRZ7GgEKkUpIk4ePDhq4bEimAY6PI0zgGhUil9p+7iNLaS0qXQWQVENjPOh5qy8mL+OMdChdEfo13UIhU6uND7N4h9TpSWoczVY1Kl0F+jAGFSIVa2kT85yhvoZO6fcQxUuRBDChEKrTzZBXqW9qVLoPIqY+/NcBslpQug/wUAwqRCn1woFTpEoi6VFHfgq/P1ihdBvkpBhQilSk3XsJXp6uVLoNIlo8OspuHPIMBhUhlcg7owbvm5Cu2F1aisZXdkeR+DChEKiJJEnI48JB8yKU2Ef85WqZ0GeSHGFCIFNTU1ARBECAIApqamrD3+1qcv9CsdFlELvnoIBcUJPdjQCFSkY0cHEs+aP/5WpQwWJObMaAQqURDSxs+PV6hdBlELpMkrolC7seAQqQgURStf37535+guZUbsJFv0h3SQ5I4upvchwGFSCE6nQ5JSUnW5y8umA3DmjloLspXsCqi7imtvYRvimuVLoP8CAMKkQJ0Oh0yMjJgMNgOLhQbalC9aTlDCvkkdvOQOzGgEHmZKIqYP3++09vhtTvXQjKLDs8TqdG2YxW4ZOL/t+QeDChEXpaXlwe93vm/NMWGGrTqC71UEZF7NLa2Y3shB3qTezCgEHlZebm8XYrFxoseroTI/T4oOG2ztg9RdzGgEHlZbGysrHaakEEeroTI/QrOXlC6BPITDChEXpaWlgatVgtBEBy20YRGIkg7yotVEbkH95Eid2FAIfIyjUaD7OzsH57ZDykRE+ZCCNB4rygiN+k4uDs3N9dmrR8iVzCgECkgPT0dOTk5CAwbbHNcExqJqOlPITgxVaHKiLqvuSgf5ev+bH0+depUJCQkQKfTKVgV+SoGFCKFDB93O4b8frX1eVTGUgydt47hhHxSc1E+qjcth9hoOwbFYDAgIyODIYVcxoBC5CFX71R8tXf2ldh04/SLv5HdOuSTJLOI2p1r7Z/7Yb2frKwsdveQS1wKKCtWrMBPf/pThIaGYsiQIZg+fTqKiops2rS0tCAzMxODBw9GSEgIZsyYgcrKSps2JSUlmDZtGoKDgzFkyBA88cQTaG9v7/nVEPmIumYT/nNU3nRjIrVr1RdCbKhxeF6SJJSWliIvL8+LVZGvcymg7NmzB5mZmdi7dy927NiBtrY2TJo0yeZfhwsWLMCWLVuwceNG7NmzB2VlZUhPT7eeF0UR06ZNg8lkQn5+Pt566y1s2LABzzzzjPuuikjlNh7Qo7XdrHQZRG4hd80euWsAEQGAIPVg+8nq6moMGTIEe/bswW233Qaj0YioqCi8++67yMjIAACcOnUKN9xwAwoKCnDrrbfi008/xV133YWysjJER0cDANasWYNFixahuroagYGBXX5ufX09wsPDYTQaERYW1t3yiTyqqakJISEhAIDGxkYMGDAAwOV/Td7xf3tQXMNFrMg/tJQcReV7T3XZbteuXbj99ts9XxCpliu/v3s0BsVoNAIAIiIiAAAHDx5EW1sbJk6caG0zcuRIDBs2DAUFBQCAgoICjB492hpOAGDy5Mmor69HYSGX9ib/0bG/veN0y6/PXGA4Ib8SpB0FTWikw/OCICA+Ph5paWlerIp8XbcDitlsRlZWFn72s5/hxhtvBABUVFQgMDAQAwcOtGkbHR2NiooKa5uO4cRy3nLOntbWVtTX19s8iNRMp9MhKSnJ+rzjdMu3955XsDIi9xMCNIiYMNdpm1WrVkGj4SBwkq/bASUzMxPHjx/H+++/78567FqxYgXCw8Otj/j4eI9/JlF36XQ6ZGRkwGAw2By3TLfctInTLcn/BCemImr6U9CEdF7b53d/fcVmLCKRHN0KKI888gi2bt2KXbt2QavVWo/HxMTAZDKhrq7Opn1lZSViYmKsba6e1WN5bmlztcWLF8NoNFofpaWl3SmbyONEUcT8+fNhb2iXJEmQJKBmx1qb1TaJ/EVwYipi57xufW5Z2+dkvxsgcg18cpFLAUWSJDzyyCP4+OOP8eWXX2LEiBE258eNG4e+ffti586d1mNFRUUoKSlBSkoKACAlJQXHjh1DVVWVtc2OHTsQFhZmc0u8o6CgIISFhdk8iNQoLy8Per3eSQsJYkMNWvUcb0X+yd7aPuXGFuw8WenkVUSd9XGlcWZmJt59911s3rwZoaGh1jEj4eHh6N+/P8LDwzFnzhwsXLgQERERCAsLw6OPPoqUlBTceuutAIBJkyYhKSkJDzzwAF544QVUVFTg6aefRmZmJoKCgtx/hUReJHcapdxpmUT+4t1vSjBplP275ET2uBRQ3njjDQDoNE1s/fr1+N3vfgcAWLlyJQICAjBjxgy0trZi8uTJeP31K7f8NBoNtm7diocffhgpKSkYMGAAZs+ejWXLlvXsSohUIDY2VlY7TcggD1dCpC6531WjtLYZ8RHBSpdCPqJH66AoheugkFqJooiEhAQYDAa741CAy4MGh85bx2Xtqdf58+3X4r/vHKl0GaQgr62DQkS2NBoNsrOzAVxe+8GeiAlzGU6oV/rwgB5tIldQJnkYUIjcLD09HTk5OYiLi7M5rgmNRNT0p7hbMfVaNY2t2F5of70roqsxoBB5QHp6Ok6cOGF9bpluyXBCvd07e0uULoF8BAMKkYd0XDXTMt2SqLcr+P4CDn1fAUEQIAiCzWazRB0xoBARkVf9v/xzSpdAPsClacZEJN+AAQOwKOcI3t/PlY+JOtp6VN56QdS78Q4KkYfUNLbi40OGrhsS9TItpjbrnzvu9E3UEQMKkYf8u+A8Wts5pZKoo+aifJSv+7P1ecedvok6YkAh8oCWNhHv7DuvdBlEqtJclI/qTcshNl6wOW7Z6ZshhTpiQCHygE2HDKhpNCldBpFqSGYRtTvX2j/3w6rLWVlZ7O4hKwYUIg9Y91Wx0iUQqUqrvhBiQ43D85IkobS0FHl5eV6sitSMAYXIzfZ8V43TVY1Kl0GkKnJ38Ja7Izj5PwYUIjf7Z973SpdApDpyd/CWuyM4+T8GFCI3+q6yAXmnHd/GJuqtgrSjoAmNdHheEATEx8cjLS3Ni1WRmjGgELkR754Q2ScEaBAxYa7TNqtWrbLZIoJ6NwYUom5oamrqtJdITWMrNh0uU7gyIvUKTkxF1PSnoAkZbHNcExqJectWIz09XaHKSI241D2Rm/y/gvMwcWE2IqeCE1MRNHws9Nn3Ari803f/ETfjaN8QiGYJmgBB4QpJLXgHhcgNWtpEvLOXC7MRydFxZ2/LTt/6i5ew40SF9bi9u5TUuzCgEHVDx8WkcnNz8dGBElxo4sJsRD3B9YOoIwYUIhfpdDokJSVZn0+dOhVzpiSjuShfwaqIfEdAYD8MX7QVwxdtRUBgP+vx/ecu4sC5WgUrIzVhQCFygU6nQ0ZGBgwG212KW43VqN60nCGFqIde/fIMgM53KbkEfu/DgEIkkyiKmD9/vnXfEHtqd66FZOZfpETdtee7aqz8x7873aXkjse9DwMKkUx5eXnQ6/VO24gNNWjVF3qpIiL/01yUj4VzH+x0l5I7Hvc+DChEMsndI0TuniNEZIs7HlNHDChEMsndI0TuniNEZIs7HlNHDChEMqWlpUGr1UIQHC8kpQmNRJB2lBerIvIf3PGYOmJAIZJJo9EgOzv78hMHISViwlybRaiISD7ueEwdMaAQuSA9PR05OTkIDrfdlVUTGomo6U8hODFVocqIfB93PKaOGFCIXHR98gREzH7N+jwqYymGzlvHcELUQ852PLZ0rXLH496DAYXIRa/sPG13LxEi6jlHOx5rtVrk5ORwx+NehLsZE7ngVEU9dpystC7VTUTud/WOx79dugYbnv4j75z0MryDQuSCV3eegZOFZInITTrelfymORrGFq590tvwDgqRTGeqGvDpcU5vJPKGjncpWwH8M+97/PedI5UtiryKd1CIZHr1yzMw8+4JkSL+XXAeF5tMSpdBXsSAQiTD99WN2HqUd0+IlNLQ2o7Xdp1RugzyIgYUIhle2XkaIm+fECnq33vPQ3+xWekyyEsYUIi6cExvxOYjZUqXQdTrmdrN+L/Pv1O6DPISBhSiLizfdpIzd4hUYvNhA06U1StdBnkBAwqRE7tOVaHg+wtKl0FEPzBLwPOfnVK6DPICBhQiB0SzhBWfnlS6DCK6Su531cg/U6N0GeRhDChEDmw8UIrvKhuVLoOI7Hj+s1NobGyEIAgQBAFNTU1Kl0RuxoBCZEezqR0v7+BgPCK1Oqo34j9HDNbnubm5EEWuNutPGFCI7PhHbjGqGlqVLoOIHGguyseDU39ufT516lQkJCRAp9MpWBW5EwMK0VXOVdQi67+ux/m/3wWzqUXpcojoKs1F+ajetBymettxKAaDARkZGQwpfoIBhegqr+68MkOgpfQ4JDNvGxOphWQWUbtzrf1zP6wHkJWVxe4eP8CAQtTB6vXvIHver6zPq3OWwrBmDpqL8hWsiogsWvWFEBscz+CRJAmlpaXIy8vzYlXkCQwoRD/Q6XR45A+/hdhou+6J2FCD6k3LGVKIVEBsvCirXXk5987ydQwo1Ks0NTXZnZYoiiIeznzU6Wtrd65ldw+RwjQhg2S1i42N9XAl5GkMKNSrdOyX7jgtcffuPaiqcL7fjthQg1Z9oUfrIyLngrSjoAmNdHheEATEx8cjLS3Ni1WRJ7gcUHJzc/HLX/4ScXFxEAQBmzZtsjkvSRKeeeYZxMbGon///pg4cSJOnz5t06a2thazZs1CWFgYBg4ciDlz5qCxkQtikWfpdDokJSVZn3eclvjenqOy3kPu7WUi8gwhQIOICXOdtlm1ahU0Go2XKiJPcTmgNDU1YezYsVi9erXd8y+88AJeeeUVrFmzBvv27cOAAQMwefJktLRcma45a9YsFBYWYseOHdi6dStyc3Mxd67z/+GIekKn0yEjIwMGg8HmuGVa4uY9B2W9j9zby0TkOcGJqYia/hQ0IYNtjmtCI/Hg09lIT09XqDJyJ0GSur9PqyAI+PjjjzF9+nQAl++exMXF4fHHH8df/vIXAIDRaER0dDQ2bNiA++67DydPnkRSUhL279+Pn/zkJwCAzz77DFOnToVer0dcXFyXn1tfX4/w8HAYjUaEhYV1t3zqJURRREJCAvR6vcM2ASGDIQCdBsh2pAmNxNB56yAE8F9mRGogtjRBn30vACAqYyn6j7gZQX374rOsNFwTFaJwdWSPK7+/3ToGpbi4GBUVFZg4caL1WHh4OJKTk1FQUAAAKCgowMCBA63hBAAmTpyIgIAA7Nu3z+77tra2or6+3uZBJFdeXp7TcAIA5sYLCLlpstM2ERPmMpwQqUjHn8d+8TdCCNDAJJrx183HFayK3MWtAaWiogIAEB0dbXM8Ojraeq6iogJDhgyxOd+nTx9ERERY21xtxYoVCA8Ptz7i4+PdWTb5ObnTDfsOGurwtnHU9KcQnJjqifKIqJsCAvth+KKtGL5oKwIC+1mPf33mAjYfvtyd62jmHqmfT8ziWbx4MYxGo/VRWlqqdEnkQ+RON9SEDEJwYipi57xuPRaVsRRD561jOCHyMf/7n5Oob2lzOHOP1M+tASUmJgYAUFlZaXO8srLSei4mJgZVVVU259vb21FbW2ttc7WgoCCEhYXZPIjkSktLg1arhSAIDttoQiMRpB0FwP5tYyLyLdUNrfjj0tUOZ+6R+rk1oIwYMQIxMTHYuXOn9Vh9fT327duHlJQUAEBKSgrq6upw8OCVWRNffvklzGYzkpOT3VkOEQBAo9EgOzsbAByGlI7jSxzdNiYi39FclI+Nf1/gcOYeQ4r6uRxQGhsbcfjwYRw+fBjA5YGxhw8fRklJCQRBQFZWFv73f/8Xn3zyCY4dO4YHH3wQcXFx1pk+N9xwA+6880489NBD+Oabb/D111/jkUcewX333SdrBg9Rd6SnpyMnJ6fT/2McX0Lkf7ihoH9weZrx7t27MX78+E7HZ8+ejQ0bNkCSJCxZsgRr165FXV0dfv7zn+P111/H9ddfb21bW1uLRx55BFu2bEFAQABmzJiBV155BSEh8qaFcZoxddfJ8xVISrg8JsUyLZFdOET+paXkKCrfe6rLdrt27cLtt9/u+YLIypXf3z1aB0UpDCjUHZIkYfb6/cj9rlrpUojIg5pO7EHNlhe7bPfuu+9i5syZXqiILBRbB4VIzdZ9VcxwQtQLcENB/8CAQr1CYZkRL3xWpHQZROQF3FDQPzCgkN+7ZBLx2HuHYBLNSpdCRF7gdEPBH2bycUNB9WNAIb+3bGshzlZzBUmi3sTRhoJ9QyOx7t/vcUNBH8CAQn7t02PleO8brjxM1BvZWxk69k//xB7TCAWrIrn6KF0AkaeUGy/hSd0xpcsgIgVp+g3A8EVbbY7tLqrG/ys4hwdTEpQpimThHRTyS2azhKz3D8N4qU3pUohIhZZvO4kzVQ0ALk99tWwo+Omnn3IBN5VgQCG/9PruM9hXXKt0GUSkUi1tZjz23mF8uDGH+/WoFAMK+Z1vSy5i1RenlS6DiFTuwO7PcO9vfsP9elSKAYX8SnVDKx599xDazT63QDIRedGV/Xo6/13B/XrUgQGF/EbVhYsYEtYP+YsnoPnsAUhm/sVCRPa16gshNtQ4PC9JEkpLS5GXl+fFqqgjBhTyCzqdDtdcl2h9Xp2zFIY1c9BclK9gVUSkVmLjRVntysvLPVwJOcKAQj5Pp9NhxowMNF203WdHbKhB9ablDClE1An361E/BhTyaaIoYu6fH4G9fmSL2p1r2d1DRDa4X4/6MaCQT/tXzjZcqHR+C1ZsqEGrvtBLFRGRL3C6Xw8679cjiiJ2796N9957D7t37+bgWS9gQCGfZai7hBUfFchqK7e/mYh6D0f79WhCB2PB82us+/XodDoMHz4c48ePx/3334/x48dzrRQv4FL35JOaWtsxZ8N+NPcJldVebn8zEfUuwYmp6H9d8uVZPY0XoQkZhCDtKGwx9sWMMzWoOJqLjIwM69RjC8taKTk5Odx40EMYUMjntIlmPPLutzhV0WDtR3Y2XVATGokg7SgvVkhEvkQI0KDfsDE2x0yiGXM27EPtukc7hRPg8jRkQRCQlZWFu+++29oVRO7DLh7yKW2iGQ+//S12FV2eseO8H/myiAlzIQTwLw8ics3F74+iqqLM4XmuleJZDCjkMyzh5IuTlTbHHfcjRyJq+lMITkz1ZplE5Ce4Voqy2MVDPqHF1IYZS/6FbwrPWvuIO94VcdSPzDsnRNRdXCtFWQwopHof5uTg93P/jOYOC7FpQiMRMWGuzd0Re/3IRETd1dUYN0EQoNVquVaKh7CLh1Ttw5wc3HvPPTbhBOAqsUTkec7GuAlC57VSyL0YUEi1Wkxt+MPcTKdtuEosEXmSozFuMbFxnGLsYeziIVVqaRMxY8m/0HSxymk7yyqx7NohIk+xN8Yt8rqbEDv2FqVL82u8g0KqU1nfgt+8WYBvCs/Kas9VYonI0yxj3AYk/QL9ho1BfasZD/5rH3IO6pUuzW8xoJCqHNMb8avXvsJRvVH2CHquEktESmgTJfxl4xG8tL3I7mJu1DPs4iGPEkUReXl5KC8vR2xsLNLS0joNKLO02bbvBN4/3gAh9gYIARquEktEPuG1XWdwvrYZL2aMQb++HDDrLgwo5DE6nQ6PPfYYDAaD9ZhWq0V2drbNJlzz58+HXn/lNmnHKcQRE+aietNyh5/BVWKJSA22HClDWd0lrH1gHAaHBCldjl8QJB+8L1VfX4/w8HAYjUaEhYUpXQ7ZodPp7G6wZZmal5OTAwB221hYVoFtLspH7c61NndS7K2DQkSktGERwfjn7J/g+mh5G5n2Nq78/mZAIbvkdM04e21CQoLNXZGOBEHA0KFD0S6aUVHueJ8LTWgkhs5bByFAA8kscpVYIlI1y99TwqU6PHjHTfjbw/egTx92VHTEgEI9Yq/b5equGWd2796N8ePHu6WW6JnLOYWYiFTP3p3e4EFD8Nqr2fj9rPtceq+e/ANR7Vz5/c1ZPGTD0jVz9d0Pg8GAjIwM6HS6Lt/DnRtncQoxEaldc1E+qjct7zSgv/liFf7w25n466p1st9Lp9MhISEB48ePx/3334/x48cjISFB1t+9/oYBhaxEUcT8+fPtjgmxHMvKyoIoOl+51Z0bZ3EKMRGpmWQWUbtzrdM2K555Ev/94SE0m9ohiiJ2796N9957D7t377b5+9Qd/0D0J+ziISu5XTO7du3C7bff7vA2pGUMisFgcDgANiBkMAQAYuMFh5/TcQwKEZEatZQcReV7T3XZLnrmcgzuY0LNjrWoqrgy9s7SfX733Xd3OXZPq9WiuLjYp7t72MVD3SK3a6a8vNzpbUiNRoPs7OwfWgt232PwxD8hYuKfnH4OpxATkdrJ7YZuPr0PJ/691CacAFfujvztb39zGE6Ay3exS0tLkZeX16N6fQkDClnJ7Zo5ffq009uQH2zMQUPMj/Gjmc9AE2q7wZYmNNI6fdi6CVdopMM2RERqJrcbuqlwl93jlrvMV/5R55w7x/ipHbt4yKqrrhnL9GAATpK+gMDwSMTM/afs6cGcQkxEvkoyizCsmeN0xeuA/mEwX6p3y+dZuth9Fbt4qFs6ds1YFlSzsDx/6KGHnN6GBCSYjNVo1Rdeft1VG2zZCx5y2hARqZEQoEHEhLlO2wwYJW/ZhbDwQZ3+7rV+jiAgPj4eaWlpLtfoqxhQyEZ6ejpycnKsd0ostFotcnJycN1118l6H04PJqLeosvu6uuSZb2PMHrKD3ev7f8DcdWqVT49QNZVXOKOOklPT8fdd99td4bO7t27Zb0HpwcTUW8SnJiK/tcl2+2ulsyirI1Pw1PuRWBkQqcF37RaLVatWmWzUKY/L+ZmwYBCdmk0mk79nKZ2M873HYbAsEiY6rnDMBFRR5buanvH5W58enXQiYgagj/fexfu+Pk11rY9Xe3bV3CQrJ+Rk6pdTd5H9XX4vLASHx8ywFB3ybpqoiOcgUNE1FlPNj7tqxGQem0kBlcfwqrFDzvdiFXNIYV78fRSclK1nDbtohn7imvxeWEFdpyoRJmxpdNncYdhIiLX9WTWYlczhq5ezE2N3UAMKL2QZYlkZ6kagNM2//PyP9AUOw5fFlWhrrmty8/k9GAiIu+Ru2rtrl27UFtbq8puIAYUH9STpGtZv8TZEsldr1/CpeWJiNSs6cQe1Gx5sct24zN+h90fvSWrG8jbd1lc+f3NQbJOeGI8hz1yBzw5+qy8vLwul0h2vnbJD+/fUINWfaHdQV5ERKQsubMj9/xH53DTV0EQkJWVhbvvvhubN29W5V0WCwYUB9w1ngNwHmIcdc1Ylo23JF1nn9Xa2uq26+b6JURE6hSkHdXldOWuVq217Onz4KNP4r01/9fl7x4lKdrFs3r1arz44ouoqKjA2LFj8eqrr+KWW27p8nWe7uJxx3gOOcFC7u6VL7/8Mn7zm990TsSCAEjAbfc9jNz3X+/RNVtEz1zOOyhERCrV1SzK0J/cjYYDm7t8n4B+ITC3NNo958mdk31iDMoHH3yABx98EGvWrEFycjJWrVqFjRs3oqioCEOGDHH6Wk8GFHeM5+gqWFhCzNKlS7FkyZIuawodGIGGulqH5wNCBkMAIDZe6FEbjkEhIlI/Z7MoA/qHyBpIK4cn9v3xiYCSnJyMn/70p3jttdcAAGazGfHx8Xj00Ufx5JNPOn2tJwPK7t27MX68vH0TuhIVFYXq6mq75wRBwMBBg3Cx1nHwcEX4z++H8at3Hdcy/fL/sFy/hIjI9zmaRSln80KhXyikloYuP+Pdd9/FzJkz3Vm2+jcLNJlMOHjwICZOnHilkIAATJw4EQUFBZ3at7a2or6+3ubhKe7cytpROAEu9wO6K5wAQN9BQ53vBZGY2vV+EQwnREQ+wdEmq3I2Lwwb9ytZnxEbG9vjOntCkUGyNTU1EEUR0dHRNsejo6Nx6tSpTu1XrFiBZ5991iu1CcEDvfI5FsGh4WhuqAdg70aWgAHhg9Bk7DrI3D9+LK6/KRnmzAdx5tgB1F+oQtjgIfjR6J8goGMf4uTErtsQEZHvmpyIwzfFIWf1/6KuusJ6eGBULDIy/wdjfjYRz9y/E3XVlXD0u2dIbJziOycr0sVTVlaGoUOHIj8/HykpKdbj//3f/409e/Zg3759Nu1bW1ttZqrU19cjPj7eo2NQDAaD3WlaHcegOGsTGRnp9A6KxbPPPoulS5cCgM17WcapfPDBB1i4cKHTz/LUYCYiIvJdcmaQAvZ/93hqFo/qu3giIyOh0WhQWVlpc7yyshIxMTGd2gcFBSEsLMzm4SkajQbZ2dkArnxRFpbn2dnZXbZZvXo1tFptp/Md28XHx+N//ud/kJOTYw09FlqtFjk5Objnnnu6/KzetgU3ERF1zbLp68yZM3H77bfb/J5IT093+rtH6SnGAABJIbfccov0yCOPWJ+LoigNHTpUWrFiRZevNRqNEgDJaDR6rL6PPvpI0mq1Ei7f/5IASPHx8dJHH30ku81HH30kCYIgCYJg08ZyrON7tbe3S7t27ZLeffddadeuXVJ7e7vL9RAREbmiq9897ubK729FpxnPnj0bb775Jm655RasWrUKH374IU6dOtVpbMrVvLXUvTtWkrW3Dkp8fDxWrVrlckJV48ZPREREcvnENGMAeO2116wLtd1000145ZVXkJyc3OXrfG0vHgYLIiIiHwoo3eVrAYWIiIh8YJAsERERkTMMKERERKQ6DChERESkOgwoREREpDoMKERERKQ6DChERESkOgwoREREpDoMKERERKQ6DChERESkOn2ULqA7LIvf1tfXK1wJERERyWX5vS1nEXufDCgNDQ0ALm+6R0RERL6loaEB4eHhTtv45F48ZrMZZWVlCA0NhSAIbnvf+vp6xMfHo7S01G/3+PH3a/T36wP8/xp5fb7P36/R368P8Nw1SpKEhoYGxMXFISDA+SgTn7yDEhAQAK1W67H3DwsL89v/6Sz8/Rr9/foA/79GXp/v8/dr9PfrAzxzjV3dObHgIFkiIiJSHQYUIiIiUh0GlA6CgoKwZMkSBAUFKV2Kx/j7Nfr79QH+f428Pt/n79fo79cHqOMafXKQLBEREfk33kEhIiIi1WFAISIiItVhQCEiIiLVYUAhIiIi1el1AeVvf/sbUlNTERwcjIEDB9ptU1JSgmnTpiE4OBhDhgzBE088gfb2dqfvW1tbi1mzZiEsLAwDBw7EnDlz0NjY6IErcM3u3bshCILdx/79+x2+7vbbb+/Uft68eV6sXL6EhIROtT7//PNOX9PS0oLMzEwMHjwYISEhmDFjBiorK71UsXznzp3DnDlzMGLECPTv3x/XXnstlixZApPJ5PR1av/+Vq9ejYSEBPTr1w/Jycn45ptvnLbfuHEjRo4ciX79+mH06NHYtm2blyp13YoVK/DTn/4UoaGhGDJkCKZPn46ioiKnr9mwYUOn76tfv35eqtg1S5cu7VTryJEjnb7Gl74/e3+fCIKAzMxMu+194bvLzc3FL3/5S8TFxUEQBGzatMnmvCRJeOaZZxAbG4v+/ftj4sSJOH36dJfv6+rPsat6XUAxmUy455578PDDD9s9L4oipk2bBpPJhPz8fLz11lvYsGEDnnnmGafvO2vWLBQWFmLHjh3YunUrcnNzMXfuXE9cgktSU1NRXl5u8/jjH/+IESNG4Cc/+YnT1z700EM2r3vhhRe8VLXrli1bZlPro48+6rT9ggULsGXLFmzcuBF79uxBWVkZ0tPTvVStfKdOnYLZbMabb76JwsJCrFy5EmvWrMFTTz3V5WvV+v198MEHWLhwIZYsWYJvv/0WY8eOxeTJk1FVVWW3fX5+PmbOnIk5c+bg0KFDmD59OqZPn47jx497uXJ59uzZg8zMTOzduxc7duxAW1sbJk2ahKamJqevCwsLs/m+zp8/76WKXTdq1CibWr/66iuHbX3t+9u/f7/Nte3YsQMAcM899zh8jdq/u6amJowdOxarV6+2e/6FF17AK6+8gjVr1mDfvn0YMGAAJk+ejJaWFofv6erPcbdIvdT69eul8PDwTse3bdsmBQQESBUVFdZjb7zxhhQWFia1trbafa8TJ05IAKT9+/dbj3366aeSIAiSwWBwe+09YTKZpKioKGnZsmVO2/3iF7+Q5s+f752iemj48OHSypUrZbevq6uT+vbtK23cuNF67OTJkxIAqaCgwAMVutcLL7wgjRgxwmkbNX9/t9xyi5SZmWl9LoqiFBcXJ61YscJu+9/85jfStGnTbI4lJydLf/rTnzxap7tUVVVJAKQ9e/Y4bOPo7yM1WrJkiTR27FjZ7X39+5s/f7507bXXSmaz2e55X/ruJEmSAEgff/yx9bnZbJZiYmKkF1980Xqsrq5OCgoKkt577z2H7+Pqz3F39Lo7KF0pKCjA6NGjER0dbT02efJk1NfXo7Cw0OFrBg4caHNHYuLEiQgICMC+ffs8XrMrPvnkE1y4cAG///3vu2z7zjvvIDIyEjfeeCMWL16M5uZmL1TYPc8//zwGDx6Mm2++GS+++KLTLrmDBw+ira0NEydOtB4bOXIkhg0bhoKCAm+U2yNGoxERERFdtlPj92cymXDw4EGb//YBAQGYOHGiw//2BQUFNu2Byz+TvvBdAZe/LwBdfmeNjY0YPnw44uPjcffddzv8+0YNTp8+jbi4OFxzzTWYNWsWSkpKHLb15e/PZDLh7bffxh/+8AenG9P60nd3teLiYlRUVNh8R+Hh4UhOTnb4HXXn57g7fHKzQE+qqKiwCScArM8rKiocvmbIkCE2x/r06YOIiAiHr1HKunXrMHny5C43W7z//vsxfPhwxMXF4ejRo1i0aBGKioqg0+m8VKl8jz32GH784x8jIiIC+fn5WLx4McrLy/Hyyy/bbV9RUYHAwMBOY5Cio6NV931d7cyZM3j11Vfx0ksvOW2n1u+vpqYGoija/Rk7deqU3dc4+plU+3cFXN55PSsrCz/72c9w4403OmyXmJiIf/3rXxgzZgyMRiNeeuklpKamorCw0KMbo3ZHcnIyNmzYgMTERJSXl+PZZ59FWloajh8/jtDQ0E7tffn727RpE+rq6vC73/3OYRtf+u7ssXwPrnxH3fk57g6/CChPPvkk/v73vzttc/LkyS4HcvmS7lyzXq/H9u3b8eGHH3b5/h3Hz4wePRqxsbGYMGECzp49i2uvvbb7hcvkyvUtXLjQemzMmDEIDAzEn/70J6xYsUK1S1F35/szGAy48847cc899+Chhx5y+lqlvz+6LDMzE8ePH3c6RgMAUlJSkJKSYn2empqKG264AW+++Saee+45T5fpkilTplj/PGbMGCQnJ2P48OH48MMPMWfOHAUrc79169ZhypQpiIuLc9jGl747X+MXAeXxxx93mnAB4JprrpH1XjExMZ1GIltmd8TExDh8zdUDg9rb21FbW+vwNT3VnWtev349Bg8ejF/96lcuf15ycjKAy/+C98YvuJ58p8nJyWhvb8e5c+eQmJjY6XxMTAxMJhPq6ups7qJUVlZ67Pu6mqvXV1ZWhvHjxyM1NRVr1651+fO8/f05EhkZCY1G02nGlLP/9jExMS61V4tHHnnEOmDe1X9J9+3bFzfffDPOnDnjoercZ+DAgbj++usd1uqr39/58+fxxRdfuHzX0Ze+O+DK77XKykrExsZaj1dWVuKmm26y+5ru/Bx3i9tGs/iYrgbJVlZWWo+9+eabUlhYmNTS0mL3vSyDZA8cOGA9tn37dlUNkjWbzdKIESOkxx9/vFuv/+qrryQA0pEjR9xcmfu9/fbbUkBAgFRbW2v3vGWQbE5OjvXYqVOnVDtIVq/XS9ddd5103333Se3t7d16DzV9f7fccov0yCOPWJ+LoigNHTrU6SDZu+66y+ZYSkqKagdZms1mKTMzU4qLi5O+++67br1He3u7lJiYKC1YsMDN1blfQ0ODNGjQICk7O9vueV/7/iyWLFkixcTESG1tbS69Tu3fHRwMkn3ppZesx4xGo6xBsq78HHerVre9k484f/68dOjQIenZZ5+VQkJCpEOHDkmHDh2SGhoaJEm6/D/XjTfeKE2aNEk6fPiw9Nlnn0lRUVHS4sWLre+xb98+KTExUdLr9dZjd955p3TzzTdL+/btk7766ivpuuuuk2bOnOn163Pkiy++kABIJ0+e7HROr9dLiYmJ0r59+yRJkqQzZ85Iy5Ytkw4cOCAVFxdLmzdvlq655hrptttu83bZXcrPz5dWrlwpHT58WDp79qz09ttvS1FRUdKDDz5obXP19UmSJM2bN08aNmyY9OWXX0oHDhyQUlJSpJSUFCUuwSm9Xi/96Ec/kiZMmCDp9XqpvLzc+ujYxpe+v/fff18KCgqSNmzYIJ04cUKaO3euNHDgQOvMuQceeEB68sknre2//vprqU+fPtJLL70knTx5UlqyZInUt29f6dixY0pdglMPP/ywFB4eLu3evdvm+2pubra2ufoan332WWn79u3S2bNnpYMHD0r33Xef1K9fP6mwsFCJS3Dq8ccfl3bv3i0VFxdLX3/9tTRx4kQpMjJSqqqqkiTJ978/Sbr8y3bYsGHSokWLOp3zxe+uoaHB+rsOgPTyyy9Lhw4dks6fPy9JkiQ9//zz0sCBA6XNmzdLR48ele6++25pxIgR0qVLl6zvcccdd0ivvvqq9XlXP8fu0OsCyuzZsyUAnR67du2ytjl37pw0ZcoUqX///lJkZKT0+OOP26ToXbt2SQCk4uJi67ELFy5IM2fOlEJCQqSwsDDp97//vTX0qMHMmTOl1NRUu+eKi4tt/huUlJRIt912mxQRESEFBQVJP/rRj6QnnnhCMhqNXqxYnoMHD0rJyclSeHi41K9fP+mGG26Qli9fbnO36+rrkyRJunTpkvTnP/9ZGjRokBQcHCz9+te/tvmlrxbr16+3+/9rx5ufvvj9vfrqq9KwYcOkwMBA6ZZbbpH27t1rPfeLX/xCmj17tk37Dz/8ULr++uulwMBAadSoUdJ//vMfL1csn6Pva/369dY2V19jVlaW9b9HdHS0NHXqVOnbb7/1fvEy3HvvvVJsbKwUGBgoDR06VLr33nulM2fOWM/7+vcnSZfvgAOQioqKOp3zxe/O8jvr6oflOsxms/TXv/5Vio6OloKCgqQJEyZ0uvbhw4dLS5YssTnm7OfYHQRJkiT3dRgRERER9RzXQSEiIiLVYUAhIiIi1WFAISIiItVhQCEiIiLVYUAhIiIi1WFAISIiItVhQCEiIiLVYUAhIiIi1WFAISIiItVhQCEiIiLVYUAhIiIi1WFAISIiItX5/7YMGJZdDrL9AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy.stats import truncnorm\n", "from iminuit.cost import UnbinnedNLL\n", "import numpy as np\n", "\n", "xrange = (-10.0, 10.0)\n", "\n", "rng = np.random.default_rng(1)\n", "x = rng.normal(1, 3, size=10000)\n", "x = x[(xrange[0] < x) & (x < xrange[1])]\n", "\n", "\n", "def model(x, mu, sigma):\n", " zrange = np.subtract(xrange, mu) / sigma\n", " return truncnorm.pdf(x, *zrange, mu, sigma)\n", "\n", "\n", "# better use numba_stats.truncnorm, which is simpler to use and faster\n", "#\n", "# from numba_stats import truncnorm\n", "#\n", "# def model(x, mu, sigma):\n", "# return truncnorm.pdf(x, *xrange, mu, sigma)\n", "\n", "nll = UnbinnedNLL(x, model)\n", "m = Minuit(nll, 1, 3)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We do not get the exact same fitted values as before, since the data sample is different from the one generated by RooFit.\n", "\n", "To get the exact same result, we need to convert the variable `data` which has the type `RooDataSet` into a numpy array. The ROOT Python layer offers the method `to_numpy` for this purpose." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 5.027e+04 Nfcn = 31
EDM = 5.43e-08 (Goal: 0.0002)
Valid Minimum No Parameters at limit
Below EDM threshold (goal x 10) Below call limit
Covariance Hesse ok Accurate Pos. def. Not forced
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 mu 1.003 0.030
1 sigma 3.017 0.022
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
mu sigma
mu 0.000926 0 (0.030)
sigma 0 (0.030) 0.000497
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 5.027e+04 │ Nfcn = 31 │\n", "│ EDM = 5.43e-08 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ No Parameters at limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Below EDM threshold (goal x 10) │ Below call limit │\n", "├───────────────┬──────────────────┼───────────┬─────────────┬────────────┤\n", "│ Covariance │ Hesse ok │ Accurate │ Pos. def. │ Not forced │\n", "└───────────────┴──────────────────┴───────────┴─────────────┴────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ mu │ 1.003 │ 0.030 │ │ │ │ │ │\n", "│ 1 │ sigma │ 3.017 │ 0.022 │ │ │ │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬───────────────────â”\n", "│ │ mu sigma │\n", "├───────┼───────────────────┤\n", "│ mu │ 0.000926 0 │\n", "│ sigma │ 0 0.000497 │\n", "└───────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABNiUlEQVR4nO3de1xUdf4/8NcwCojcRJCLoNhlMa+1tRHsF7voV1PbXy5O28Utvy2b1WJBtq2r26bZd7W1viWVpe66WdtdGrXIS2oqFGiKmopKaigwMFxEboMwcOb8/mAZGWFuMDPnzMzr+XjM49E55zPD+3QE3nwu749CFEURRERERDLiI3UARERERFdjgkJERESywwSFiIiIZIcJChEREckOExQiIiKSHSYoREREJDtMUIiIiEh2mKAQERGR7AyQOoC+MBgMqKioQFBQEBQKhdThEBERkQ1EUURTUxNiYmLg42O5j8QtE5SKigrExcVJHQYRERH1QVlZGWJjYy22ccsEJSgoCEDnDQYHB0scDREREdmisbERcXFxxt/jlrhlgtI1rBMcHMwEhYiIyM3YMj2Dk2SJiIhIdpigEBERkewwQSEiIiLZYYJCREREssMEhYiIiGSHCQoRERHJDhMUIiIikh0mKERERCQ7TFCIiIhIdpigEBERkewwQSEiIiLZYYJCREREssMEhYiIiGSHCQoRuT2dTgeFQgGFQgGdTid1OETkAExQiIiISHaYoBAREZHsMEEhIiIi2WGCQkRERLLDBIWIiIhkhwkKEXkFW1b6cDUQkXwwQSEiIiLZYYJCREREssMEhYiIiGSHCQoRuT1BEIz/nZuba3JMRO6JCQoRuTW1Wo0xY8YYj2fMmIH4+Hio1WoJoyKi/mKCQkSyZmlljVqthkqlgkajMTmv0WigUqmYpBC5MSYoROSWBEFARkYGRFHsca3rXGZmJod7iNwUExQickt5eXkoLy83e10URZSVlSEvLw+AbfNUOJeFSD6YoBCRW6qsrLS53eeff44bbrA8T4VzWYjkZYDUARAR9UV0dLRN7Z7953ZUfvN+j/Nd81Sys7MBACqVqsdwUfc2qamp/Q+aiGymEHsbwJW5xsZGhISEoKGhAcHBwVKHQ0ROpNPpEBgYCABobm7G4MGDAXQOx8THx0Oj0fQ6DwUAfAKHQgFAaL5o9vOHDIvCoIFKVFw10baLQqFAbGwsSkpKoFQq+3czRF7Ont/fHOIhIrekVCqRlZVlsU3QxLstJicAcKlaazY5AXrOZSEi12CCQkRuK/amOzDm4aVQBg41Oa8MCkfErMUYGBbjsK9l65wXgJsOEjkC56AQkdu5rBfw9+2n8V7BeYjRNyM67W2UZ90PAIhQLcWgUTdB4aNEa+kxh31NW+e8EJFjMEEhIlm7eulv0LU3Y/HmIpTWtRjPK3yuzA3xjxtnPPaLHQtlUDiEplqzn29tnkrXHJSUlJR+3gkR2YNDPEQkW70t/b3jlrE4XbDLpvcrfJQImzzPYpuhUx5H2JTHzX0CAGDVqlWcIEvkYkxQiEiWzJWxF5pqUbN5OVqK8236nICEZETMWmx2nkpAQrKFNkMx85lXuMSYSAJMUIjIKfozUdRSGfsudbvXQTTYVuk1ICEZ0WlvG48jVEsx/In1CEhIttrm+MDReHP3GbviJ6L+sytBWbp0qfEHTtdr9OjRxuutra1IT0/H0KFDERgYiNmzZ6OqqsrkM0pLSzFz5kwEBARg2LBheO6559DR0eGYuyEit2IuibFWxh7o7ElpKy+y+WuZm6diS5vXdv2InGMVNn8tIuo/uyfJjh07Frt2XRn/HTDgykc888wz+Oqrr7Bx40aEhIRg/vz5SE1NxXfffQeg86+imTNnIioqCvn5+aisrMQjjzyCgQMHYvny5Q64HSLyBLYu6RWaLzk5kk6iCDz72Q8YHjoIN40Y4pKvSeTt7B7iGTBgAKKiooyv8PBwAEBDQwPWr1+P1157DXfddRduvvlmvPvuu8jPz8f+/fsBAF9//TVOnjyJDz74ADfeeCOmT5+Ol156CatXr4Zer3fsnRGR27J1Sa8y0HXJQluHAY+9XwhN/WWrbbnpIFH/2Z2gnDlzBjExMbjmmmswZ84clJaWAgAKCwvR3t6OKVOmGNuOHj0aI0aMQEFBAQCgoKAA48ePR2RkpLHNtGnT0NjYiKIi8121bW1taGxsNHkRkee6LfmXCBgyzGIbZVA4/GLHuiiiTrXNbUjbcBDNbeaHpbnpIJFj2JWgJCYmYsOGDdi+fTveeecdlJSUICUlBU1NTdBqtfD19UVoaKjJeyIjI6HVagEAWq3WJDnput51zZwVK1YgJCTE+IqLi7MnbCJyM4s3FWHw7b+32CZs8jzjHBEfX3+MXJiDkQtz4OPr79TYTmub8NRHhyEYek7gNbfyqGvTQSYpRLazK0GZPn067rvvPkyYMAHTpk3D1q1bUV9fj88++8xZ8QEAFi1ahIaGBuOrrKzMqV+PiKSTXVgO9RGNTcuDpWDQt2LD7xIxQOljMrHX0sqjrnOZmZkc7iGyUb+WGYeGhuJnP/sZzp49i6ioKOj1etTX15u0qaqqQlRUFAAgKiqqx6qeruOuNr3x8/NDcHCwyYuIPE91YyteyjlpPLZlebCUPi+8stLI2sojbjpIZJ9+JSjNzc04d+4coqOjcfPNN2PgwIHYvXu38XpxcTFKS0uRlJQEAEhKSsLx48dRXV1tbLNz504EBwebjNkSkfvry0TRv2w+gYbL7SbnbFkeLJWV20+juqkVgO0rj+zZdJDIm9mVoPzxj3/Evn37cP78eeTn5+PXv/41lEolHnzwQYSEhCAtLQ0LFizAnj17UFhYiEcffRRJSUm47bbbAABTp07FmDFj8PDDD+OHH37Ajh078PzzzyM9PR1+fn5OuUEicr2+TBTNOVaBnSerzF7vL1vmqdg7l6WxtQMvftHZ42PryiNuOkhkG7sSlPLycjz44INISEjAb37zGwwdOhT79+9HREQEAOD111/HPffcg9mzZ2PSpEmIiooy+YGkVCqRk5MDpVKJpKQk/Pa3v8UjjzyCZcuWOfauiEgy9kwU7d6rsvjtz2yuDCsnXx2vxDenq5CSkoLY2FgoFIpe2ykUCsTFxXHTQSIbKURLtaRlqrGxESEhIWhoaOB8FCIZEQQB8fHxZudidO0MXFJSgi1btuDpp582SWSUQeEImzzPZI6JQd+KstdVAIC4Z7KdvkrHmt7iGR46CDsXTML2nC+gUnVe6/6jtStpyc7O5r4+5NXs+f3NvXiIyGFsnSj6t7/9zSEbAcqFpv4y/u/rH5Gamors7GzExMSYXI+Nje2RnPRnryIib8AEhYgcxtYJoFlZWQ7bCFAuNuSfx/HyBqSmpuLkySsrkbZu3YqSkhL2nBDZiQkKETmMrRNA6+rqLF63dyNAV+qeOLWWnTAeCwYRizYdg2AQoVReWWk0adIkk2Misg0TFCJyGFsmioaFhdn0WV0bAbqySqw1LcX5qFz/B+NxTfZSaNakGYekTmga8e53JVKFR+RRmKAQkcMolUpkZWUBQI8kpes4IyPDts9y4UaAtmgpzkfN5uUQmi+anL963sxrO3+E5lKLFCESeRQmKETkUNYmiv7lL39BaLj5ytGANBsBWiIaBNTtXmexTde8mRa9gJe+OuWiyIg8FxMUInI4SxNFG1sFBN1p+0aActBWXgShqdZim+7zZvYV17giLCKPxgSFiJzC3ETRt/eehc81t8lyI0BzuubDOKodEVnHBIWIXKay4TLeL7gAQP4bAXZn63wYe+bN9GWvIiJvwgSFiFwma9cZtHUYjMdy3giwO7/YsVAGhVtsY27eTLtg6HGuL3sVEXkbJihE5BLnapqxsdB8lVk5U/goETZ5nsU23efNdF8anXPStOaLPXsVEXkzJihE5BKvff0jBIPbbf1lFJCQ3Kd5M299cxat7f8p5iYIyMjI6LWKbte5zMxMDvcQgQkKEbnACU0Dtp6wrQy+nPVl3oy2sRUfHigFYPteRXl5eY4LmshNMUEhIqdbtetHuN++6b3ry7yZd/aew2W9YPNeRba2I/JkTFCIyOm+O3vReiMPVtvchg35523eq8jWdkSejAkKETnF4MGDIYoi7n3rW8n30JGDtbnncOMvbrO6V1FcXBxSUlJcHB2R/DBBISKn2X5Ci6Nl9Wavy2kjQGerb2nHhoJSq3sVrVq1irsfE4EJChE5icEg4v++LpY6DFlZ/20JJt/9K4t7FaWmpkoUHZG8MEEhIqf4+qQWZ6qbpQ5DVppaO7A295zFvYqIqBMTFCJyirW5P0kdgixtyD+Pi81tZvcqIqJOTFCIyOEOna/DkdJ6qcOQpRa9gHV5TN6IrBkgdQBE5Hk8ufeka2Jvf3x8oBRpiTHWGxJ5MfagEJFD/VTTjN2nqqQOQ9YaWzugPuye+xIRuQoTFCJyqH/klcCNt9xxmff3n5c6BCJZY4JCRA5T29zGngEblde1Sh0CkawxQSEih3k//zzaOgxSh0FEHoAJChE5xGW9gH/vvyB1GG6ja7Lt4Qt1GDx4sNThEMkOExQicoiNhWW41NIudRhu55/flkgdApEsMUEhon4zGESs5y/aPtl+QovySy1Sh0EkO0xQiKjfthdpceEif8n2hWAQseG781KHQSQ7TFCIqN/WeXBhNlf49GAZmts6pA6DSFaYoBBRv3xfUoejZfVSh+HWmto68Mn3pVKHQSQrTFCIqF/W5Z6TOgSPsCH/PARWuCMyYoJCRH12vlaH3aerpQ7DI5RfuoztJ7RSh0EkG0xQiMhuOp0OCoUCoyICIbSxIqqj/PNbzuUh6sIEhYhIJo6U1qPwwiWpwyCSBSYoREQy8l7+ealDIJIFJihERDKy/YQWdTo9gCtDaQqFAjqdTuLIiFyLCQoR2e20tlHqEDyWXjAgu7BM6jCIJMcEhYjsxpodzvXx92UQRS45Ju/GBIWI7KJr68BXx7gc1plKanUoOHdR6jCIJMUEhYjssumIBk2X24zHrWUnIBoECSPyTB+yl4q8HBMUIrLL/637NyrX/8F4XJO9FJo1aWgpzpcwKs/zdZEWtc1t1hsSeSgmKERepL+rQl5Z+z6OvvtXCM2mww9CUy1qNi9nkuJA7YKITYc1UodBJBkmKERkE0EQsGzxnyy2qdu9jsM9DrTx0Hnjf+fm5kIQ+P+WvAcTFCKyybad36C5rspiG6GpFm3lRS6KyLO1FOfjwMpHjcczZsxAfHw81Gq1hFERuQ4TFCKyyZZ82xIPoZml2vurpTgfNZuX9xhK02g0UKlUTFLIKzBBISKrRFHEwRrb2ioDhzg3GA8nGgTU7V7X+7X/1EbJzMzkcA95PCYoRGTVd2cv4lLQNVAGhVtspwwKh1/sWBdF5ZnayosgNNWavS6KIsrKypCXl+fCqIhcjwkKEZnobaXPhwcuQOGjRNjkeRbfGzZ5HhQ+SleE6bFsHSKrrKx0ciRE0mKCQuRFug8L2LoqpLqpFTtPdk6ODUhIRsSsxVAGDjVpowwKR8SsxQhISHZswF7I1iGy6OhoJ0dCJK1+JSgvv/wyFAoFMjMzjedaW1uRnp6OoUOHIjAwELNnz0ZVlenM/9LSUsycORMBAQEYNmwYnnvuOXR0dPQnFCKyQq1WY8yYMcZjW1eFbD6iQYfhyr4wAQnJiE5723gcoVqK4U+sZ3LiIH6xYy0OpSkUCsTFxSElJcWFURG5Xp8TlIMHD2Lt2rWYMGGCyflnnnkGX375JTZu3Ih9+/ahoqICqampxuuCIGDmzJnQ6/XIz8/He++9hw0bNuCFF17o+10QkUVqtRoqlQoajWnhL1tWhXxe2LNYWPdhHP+4cRzWcSBLQ2kKhQIAsGrVKiiV/H9Onq1PCUpzczPmzJmDf/zjHxgy5Ep3ZENDA9avX4/XXnsNd911F26++Wa8++67yM/Px/79+wEAX3/9NU6ePIkPPvgAN954I6ZPn46XXnoJq1evhl6vd8xdEZGRIAjIyMjodXdca6tCiioaUFzV5PQYyZS5obSQ8ChkZ2eb/NFH5Kn6lKCkp6dj5syZmDJlisn5wsJCtLe3m5wfPXo0RowYgYKCAgBAQUEBxo8fj8jISGObadOmobGxEUVFvddZaGtrQ2Njo8mLiGyTl5eH8vJys9ctrQrZfISl1qXS21DauAXv49e//rWEURG5jt0JyieffILDhw9jxYoVPa5ptVr4+voiNDTU5HxkZCS0Wq2xTffkpOt617XerFixAiEhIcZXXFycvWETeS1bV3v01u6r41wpIqWrh9LK6ttwoKROwoiIXMeuBKWsrAwZGRn48MMP4e/v76yYeli0aBEaGhqMr7KyMpd9bSJ3Z+tqj6523Yd6Kk8f4d46MpNdaL43jMiT2JWgFBYWorq6Gj//+c8xYMAADBgwAPv27cMbb7yBAQMGIDIyEnq9HvX19Sbvq6qqQlRUFAAgKiqqx6qeruOuNlfz8/NDcHCwyYuIbJOSkoLY2FjjBMurdV8VcvVKn5rspdCsSeMuxTKy7XglWvRc9Uiez64EZfLkyTh+/DiOHj1qfN1yyy2YM2eO8b8HDhyI3bt3G99TXFyM0tJSJCUlAQCSkpJw/PhxVFdXG9vs3LkTwcHBJj8YicgxlEolsrKyAKBHktJ9VciWLVt6XekjNNWiZvNyJikyodML2Hq89+FwIk8ywJ7GQUFBGDdunMm5wYMHY+jQocbzaWlpWLBgAcLCwhAcHIynnnoKSUlJuO222wAAU6dOxZgxY/Dwww9j5cqV0Gq1eP7555Geng4/Pz8H3RYRdZeamors7Gw8/fTTJglIbGwsVq1ahXvvvRfx8fG9rvTpUrd7HQZdnwiFjxI+vv4YuTDHFaFTLzYeKoPq5lipwyByKodXkn399ddxzz33YPbs2Zg0aRKioqJMaiwolUrk5ORAqVQiKSkJv/3tb/HII49g2bJljg6FiLpJTU3FyZMnjcdbt25FSUkJUlNTra70ATp7UtrKbdvRmJzr+/N1KKtrkToMIqeyqwelN3v37jU59vf3x+rVq7F69Wqz7xk5ciS2bt3a3y9NRHbqXtxr0qRJxmNbV/rYuk8MOZcodk6Wfea/fwadTofAwEAAnTWqBg8eLHF0RI7R7wSFiNyfrSt9bN0nhhzD0lDa54fLkTnlehdHROQ63CyQiKyu9AE6NwT0ix3rwqjIkvJLl1Hw00WpwyByGiYoRGRc6WN+iiwQNnke99yRGdZEIU/GBIWIAHROop2esbLH/i/KoHBEzFrM3YplaPsJLXRtrIlCnolzUIgIANDU2o6fAsciOu1tlGfdD6Bz/5dBo25iz4lMtegFbD/BmijkmdiDQkQAgK+OVaK13dBj/xcmJ/LGDR3JUzFBIfIigwcPhiiKEEWxx3LUzw9zPoM7OnS+1vjfubm5JnspEbkzJihEhAsXdTh4njVO3E1LcT4q/vkH4/GMGTMQHx9vUhyTyF0xQSEifH6YwwTupqU4HzWbl0NoNl1qrNFooFKpmKSQ22OCQuTlRFGEmsM7bkU0CKjbva73a//ZTykzM5PDPeTWmKAQebn9P9Wh/NJlqcMgO7SVF0FoqjV7XRRFlJWVIS8vz4VRETkWlxkTebmrJ8dyp2L5s3VPJFv3WCKSI/agEHmxFn0Hth3nLzF3Y+ueSLbusUQkR0xQiLzY9hNa6PScp+Bu/GLHQhkUbva6QqFAXFwcUlJSXBgVkWMxQSHyYqx94p4UPkqETZ7X+7X/bPi4atUqKJUsskfuiwkKkZeqqL+MgnPcDdddBSQkI2LW4h57J4VGRCE7OxupqakSRUbkGJwkS+SlNh3RwGBp+2KSvYCEZPiNnGiyd9Itv7wdqal3SBsYkQOwB4XIS31eyOEdT3D13kkntTqcqWqSMCIix2CCQuSFDpdewk+1OqnDICdRcwNB8gBMUIi8EHtPPNsXRyuMFWWJ3BUTFCIv09YhIOcYa594Mk39Zez/qU7qMIj6hQkKkZfZdbIaDZfbpQ6DnGzTEfaSkXtjgkLkZVj7xDtsO6FFazuL8JH74jJjIi9S09SG3B9rpA6DHMjc3klNrR3YdaoK90yIkSAqov5jDwqRF9lyVIMOFj/xGpu5mofcGBMUIg+g0+mgUCigUCig05lfPpzN1TteZd+PNajT6aUOg6hPmKAQeYmTFY04rWUBL2/SLojIOVYhdRhEfcIEhchLbD7K7n5vpD7M507uiQkKkRcwGER8cZR/SXujo2X1KGHVYHJDTFCIvMD+ny5C29gqdRgkkU2cLEtuiAkKkRfg8I5328LnT26ICQqRBxCEKwW5cnNzTY7bOgRsO6GVIiySiQsXW3C49JLUYRDZhQkKkZtTq9UYM2aM8XjGjBmIj4+HWq0GAOw+VY2m1g6pwiMZMOhbcfPIMKvL0InkhJVkidyYWq2GSqXqsXOtRqOBSqVCdnY2tjePkCg6IqK+Yw8KkZsSBAEZGRk9khMAxnNPZ2RgzykO7xCR+2GCQuSm8vLyUF5uvjKsKIrQlJej6cJxF0ZFROQYTFCI3FRlZaVN7YRmTo6kK1r0nI9E7oEJCpGbio6OtqmdMnCIkyMhd7LrVJXUIRDZhAkKkZtKSUlBbGwsFAqFmRYKKIPC4Rc71qVxkfyIhivLzv+5cavJMnQiuWKCQuSmlEolsrKyAKBHktJ5LCJs8jwofJQSREdy0VKcj8r1fzAef7PqGYwYOdK4DJ1IrpigELmx1NRUZGdnIyYmxuR8ZHQMImYtRkBCskSRkRy0FOejZvNyCM0XTc5XaCqgUqmYpJCsKcTe1ijKXGNjI0JCQtDQ0IDg4GCpwyGSXNf3BABs3boVh4U4/OPbCxJHRVISDQI0a9IgNNX2el2hUCA2NhYlJSVQKtnLRq5hz+9v9qAQeYDuv2BSUlLw1XFOhPR2beVFZpMToHMZellZGfLy8lwYFZHtmKAQeZjvS+pQ0cCdi72drcvLbV2uTuRqTFCIPEzOsQqpQyAZsHV5eddydZ1OB4VCwf16SDaYoBB5mK+LOLxDgF/sWCiDwi22iYwejpSUFBdFRGQfJihEHqaROxcTAIWPEmGT51lsc/vcP3KCLMkWExQiDzB48GCIoojH3z8EH19/qcMhmQhISEbErMVQBg41Oa8MCkfErMU4N3gsOgSDRNERWTZA6gCIyDEaLrfjm+JqqcMgmQlISIbfyIkoz7ofABChWopBo26CwkeJ2mY9vj1bizsShkkcJVFP7EEh8hDbT1RC38G/hqmn7tWE/ePGmRxvPqIBAJPy97m5uSyHT5KzK0F55513MGHCBAQHByM4OBhJSUnYtm2b8XprayvS09MxdOhQBAYGYvbs2aiqMp2wV1paipkzZyIgIADDhg3Dc889h44OjpkT9dfmI1y9Q/b7+mQVPv5sI8aMGWM8N2PGDMTHx7PSLEnKrgQlNjYWL7/8MgoLC3Ho0CHcdddduPfee1FUVAQAeOaZZ/Dll19i48aN2LdvHyoqKpCammp8vyAImDlzJvR6PfLz8/Hee+9hw4YNeOGFFxx7V0ReprLhMg6UXLTekOgqtcfz8NAD90Oj0Zic12g0LIdPkup3qfuwsDC88sorUKlUiIiIwEcffQSVSgUAOH36NG644QYUFBTgtttuw7Zt23DPPfegoqICkZGRAIA1a9Zg4cKFqKmpga+vr01fk6XuiUyt3XcOK7adljoMkimDvhVlr3f+XI57Jts4kZrl8MnVXFLqXhAEfPLJJ9DpdEhKSkJhYSHa29sxZcoUY5vRo0djxIgRKCgoAAAUFBRg/PjxxuQEAKZNm4bGxkZjL0xv2tra0NjYaPIiois2H+XwDtmP5fBJzuxexXP8+HEkJSWhtbUVgYGB2LRpE8aMGYOjR4/C19cXoaGhJu0jIyOh1WoBAFqt1iQ56bredc2cFStW4MUXX7Q3VCKvUKxtwqlKJu1kno+vP0YuzOlxnuXwSc7s7kFJSEjA0aNHceDAATz55JOYO3cuTp486YzYjBYtWoSGhgbjq6yszKlfj8idbD6qsd6IqBf2lsMnciW7e1B8fX1x3XXXAQBuvvlmHDx4EFlZWbj//vuh1+tRX19v0otSVVWFqKgoAEBUVBS+//57k8/rWuXT1aY3fn5+8PPzszdUIo8niiK+4PAO9VFXOXxrc1BYDp+k0O86KAaDAW1tbbj55psxcOBA7N6923ituLgYpaWlSEpKAgAkJSXh+PHjqK6+Ukxq586dCA4ONlniRkRXWNrE7eD5S9DUX5YoMnJ3lsrhKxQKAMCqVas4QZYkYVcPyqJFizB9+nSMGDECTU1N+Oijj7B3717s2LEDISEhSEtLw4IFCxAWFobg4GA89dRTSEpKwm233QYAmDp1KsaMGYOHH34YK1euhFarxfPPP4/09HT2kBD1waYjHN6h/ukqh1+3ay2E5itL1WNjY7Fq1SqTUhFErmRXglJdXY1HHnkElZWVCAkJwYQJE7Bjxw7893//NwDg9ddfh4+PD2bPno22tjZMmzYNb7/9tvH9SqUSOTk5ePLJJ5GUlITBgwdj7ty5WLZsmWPvisgL6DsM2Hqckxep/64uh79161ZMnTqVPSckqX7XQZEC66CQN9HpdAgMDAQANDc3Y/DgwQCAr4u0mPfvQilDIw/SvVZK939nRI7kkjooRCStLZwcS04iGNzu71byQExQiGSut03cmlrbsetUlYV3EfVd/jnzxduIXIUJCpGMqdXqXjdxW/rGu2jjzsXkJF/9wLlNJD0mKEQypVaroVKpet3E7bWFj6OlOF+iyMjT7TpVhct6wXpDIidigkIkQ4IgICMjA73NYe86V7d7HUQDf4mQY3SVwx+5MAeXMRBfnzS//QiRKzBBIZKhvLw8lJeXW2wjNNWirdz8JptE/cFJ2CQ1JihEMmTr5my2bvZGZK/cH2tQp9NLHQZ5MSYoRDJk6+Zstm72RmSvDoOInGPsRSHpMEEhkqGUlBTExsYa90PpjTIoHH6xY10YFXkbbqVAUmKCQiRDSqUSWVlZAGA2SQmbPA8KH5YiJ+c5UlqPczXNUodBXooJCpFMpaamIjs7GzExMSbnlUHhiJi1GAEJyRJFRt4ku/DKZG1LO2sTORoTFCIZS01NxcmTJ43HEaqlGP7EeiYn5DKbDmtgYOl7kgATFCKZ676jrH/cOA7rkEtpG1uRd5al78n1mKAQEZFF3Yd5iFyFCQoREVn0dZEWja3tUodBXoYJCpHMaRsuSx0Cebm2DgNyfqjsdWdtImdhgkIkc1//2GDcI8XH11/qcMhLZa3/oNedtdVqtYRRkSdjgkIkc5uOcPyfpNVSnI/v//GXXnfWVqlUTFLIKZigEMnYCU0DfqxioSySjmgQULd7Xe/X/rOzdmZmJod7yOGYoBDJmPowS42TtNrKiyA0mV9mLIoiysrKkJeX58KoyBswQSGSqQ7BgC9+4GZtJC1bd8y2dQduIlsxQSGSqbwztahtbpM6DPJytu6YbesO3ES2YoJCJFOfH+bkWJKeX+xYKIPCzV5XKBSIi4tDSkqKC6Mib8AEhUiGmlrbsfNkldRhEEHho0TY5Hm9X/vPTturVq0y2ZKByBGYoBDJ0NbjlWjrMEgdBhEAICAhGRGzFkMZONTkfGxsLLKzs5GamipRZOTJmKAQydDGQxzeIXkJSEhGdNrbxuN/ffw5SkpKmJyQ0zBBIZKZn2qaceiCbSsniFyp+07aFYPiOaxDTsUEhUhmuHMsuYMvjlbAYBClDoM8GBMUIhkRDCKLs5FbqGxow3fnzBdwI+ovJihEMpJ7pgbaxlapwyCyCXv7yJkGSB0AEV2RzcmxJGM+vv4YuTDHeLyjSIum1nYE+Q+UMCryVOxBIZKJ+hY9dp5i7RNyH63tBuQcY4l7cg4mKEQyseVoBfSsfUJuhsM85CxMUIhkYmNhmdQhENmt8MIllNTqpA6DPBATFCIZOFXZiBOaRqnDIOqTbCbX5ARMUIhkgJVjyZ1tOqxhTRRyOCYoRBJrFwzYfJS1T8h9VTS0Iv/cRanDIA/DBIVIYrtPVaFOp5c6DKJ+4TAPORoTFCKJcXiHPMGOoio0tbZLHQZ5ECYoRBKqbmrF3h9rpA6DqN8utwv4ijVRyIGYoBBJaNNhDQROLiQPkV1YDp1OB4VCAYVCAZ2Oy4+p75igEEloI4tckQc5dOESLrAmCjkIExQiiRwpvYSz1c1Sh0HkUFyRRo7CBIVIIp98z1UP5Hm2MEEhB2GCQiSBptZ2fHmsQuowiByu4lKL8b9zc3MhCIKE0ZA7Y4JCJIHNRzRo0fMHN3mWluJ8VK7/g/F4xowZiI+Ph1qtljAqcldMUIgk8OGBUqlDIHKoluJ81GxeDqHZtKKsRqOBSqVikkJ2Y4JC5GKHSy/htLZJ6jCIHEY0CKjbva73a2LnMvrMzEwO95BdmKAQudhH3XpPDPpWXPj7Pbjw93tg0LdKGBVR37WVF0FoqjV7XRRFlJWVIS8vz4VRkbtjgkLkQo2t7ay2SR5HaL5kU7vKSv7bJ9vZlaCsWLECv/jFLxAUFIRhw4Zh1qxZKC4uNmnT2tqK9PR0DB06FIGBgZg9ezaqqqpM2pSWlmLmzJkICAjAsGHD8Nxzz6Gjo6P/d0MkI71V1Nx0WIPL7ezmJs+iDBxiU7vo6GgnR0KexK4EZd++fUhPT8f+/fuxc+dOtLe3Y+rUqSbljJ955hl8+eWX2LhxI/bt24eKigqkpqYarwuCgJkzZ0Kv1yM/Px/vvfceNmzYgBdeeMFxd0UkUx9dNTlWNFxJVlrLTpgcE7kLv9ixUAaFm72uUCgQFxeHlJQUF0ZF7k4hds1g6oOamhoMGzYM+/btw6RJk9DQ0ICIiAh89NFHUKlUAIDTp0/jhhtuQEFBAW677TZs27YN99xzDyoqKhAZGQkAWLNmDRYuXIiamhr4+vpa/bqNjY0ICQlBQ0MDgoOD+xo+kVPpdDoEBgYCAJqbm3G6tg2z3ykwXm8pzkfdrrUmqx6UQeEImzwPAQnJLo+XqD+6VvH0pIBCAWRnZ5v8sUreyZ7f3/2ag9LQ0AAACAsLAwAUFhaivb0dU6ZMMbYZPXo0RowYgYKCzh/MBQUFGD9+vDE5AYBp06ahsbERRUVF/QmHSNa6Ly02tyRTaKpFzeblaCnOd3V4RP0SkJCMiFmLoQwcanLeNyQcGzduZHJCdhvQ1zcaDAZkZmbil7/8JcaNGwcA0Gq18PX1RWhoqEnbyMhIaLVaY5vuyUnX9a5rvWlra0NbW5vxuLGxsa9hE7lM9yWV23buQc5RAFBYXJLZpW73Ogy6PhEKH6VTYyRypICEZPiNnIjyrPsBABGqpRg06iYMHXebxJGRO+pzD0p6ejpOnDiBTz75xJHx9GrFihUICQkxvuLi4pz+NYn6Q61WY8yYMcbj+379K/z01qNoKc63uiQT6OxJaStnjyK5n+5JtX/cOCh8lCxMSH3SpwRl/vz5yMnJwZ49exAbG2s8HxUVBb1ej/r6epP2VVVViIqKMra5elVP13FXm6stWrQIDQ0NxldZGTdZI/lSq9VQqVTQaEw3TTMO35w5YNPn2Lp0k0juvjldDW0D6/yQfexKUERRxPz587Fp0yZ88803GDVqlMn1m2++GQMHDsTu3buN54qLi1FaWoqkpCQAQFJSEo4fP47q6mpjm507dyI4ONjkL87u/Pz8EBwcbPIikiNBEJCRkQFLc891RXts+ixbl24SyZ1gEPHx9+xFIfvYNQclPT0dH330EbZs2YKgoCDjnJGQkBAMGjQIISEhSEtLw4IFCxAWFobg4GA89dRTSEpKwm23dY5BTp06FWPGjMHDDz+MlStXQqvV4vnnn0d6ejr8/Pwcf4dELpSXl4fy8nKLbQyXG+EzKBiGy+bnUimDwuEXO9bR4RE5nY+vP0YuzOlx/tODZXjqruswQMn6oGQbu/6lvPPOO2hoaMAdd9yB6Oho4+vTTz81tnn99ddxzz33YPbs2Zg0aRKioqJMNolSKpXIycmBUqlEUlISfvvb3+KRRx7BsmXLHHdXRBKxtVLm4LF3WrweNnkeJ8iSR9E2tmLXqc6e896KGBJdrV91UKTCOigkV3v37sWdd1pOPgAg8sHlMFxuZh0U8iop14fj32mJPWoEDR48WOLIyFXs+f3d52XGRNRTSkoKYmNjodFozM5D6Rq+Ufgoe12SyZ4T8lTfnq1F6cUWDPWXOhJyBxwMJHIgpVKJrKys/xwpem3TffimtyWZRJ5KFIEPv78gdRjkJpigEDlYamoqsrOzMSjUdG8SZVA4ImYt5vANebXsQ+VoadMbj3Nzc02KGhJ1YYJC5ARjkqdg6Ny3jMcRqqUY/sR6Jifk9coO70XC6CslJWbMmIH4+HiTxRREAOegEDnFhu/O2zR8Y25JJpEnMrehoEajgUql4oaCZII9KEQOdkmnx+ajGusNibyIpT2ouiaUZ2ZmcriHjNiDQuRgHx8sRWu7gb0jRN1Y24NKFEWUlZUhLy8Pd9xxh+sCI9liDwqRA3UIBvy7gKsUiK5m695SthY7JM/HBIXIgbYXaVHJTdGIerB1b6no6GgnR0LuggkKkQNt+O681CEQyZJf7Fgog8LNXlcoFIiLi0NKSooLoyI5Y4JC5CDHyxtw6IJt3dhE3kbho0TY5Hm9X1N0FjVctWoVlEoWK6ROTFCIHOTd70qkDoFI1gISkhExazGUgUNNzg+PjeUSY+qBCQqRA9Q0tSHnGCf3EVkTkJCM6LS3jccRqqV4+4t8JifUAxMUIgf48MAF6AWD1GEQuYWrixi+V1AqYTQkV0xQiPpJ32HAhwf4A5aorw5duIRj5fVSh0EywwSFqJ++Ol6BmqY2qcMgchtdRQxHLsyBj68/AOBf33IOF5ligkLUD6IoYu2+n6QOg8jtfXW8ElWNrCFEVzBBIeqHb05X47S2SeowiNxeuyDi/YLzUodBMsIEhagPdDodFAoFpoyJgkHPv/qIHOGjA6W4rOdmgdSJCQoREcnCpZZ2fPQ9J5xTJyYoREQkG//I/Qn6Di7ZJyYoRH1yovxKSfvWshMQDeyWJnIEbWMrsgvLpQ6DZIAJCpGd1Go1Jif93Hhck70UmjVpaCnOlzAqIs+xZt85CAZR6jBIYkxQiOygVquhUqmgu1Rjcl5oqkXN5uVMUogcoLSuBV/8oJE6DJIYExQiGwmCgIyMDIii+b/s6nav43APkQO8uf0EFAoFFAoFdDqd1OGQBJigENkoLy8P5eWWx8aFplq0lRe5KCIiz3W2hkmJt2OCQmSjykrbdisWmi9Zb0RERBYxQSGyUdCQCJvaKQOHODkSIs/Xfag0NzcXgsChU2/DBIXIRud8YqEMCrfYRhkUDr/YsS6KiMgztRTno3L9H4zHM2bMQHx8PNRqtYRRkasxQSGyQWu7gPcPlCFs8jyL7cImz4PCR+miqIg8T0txPmo2L4fQfNHkvEajgUqlYpLiRZigENng4+9LcVGnR0BCMiJmLYYycKjJdWVQOCJmLUZAQrJEERK5P9EgoG73ut6v/Wf1XGZmJod7vAQTFCIrLusFvL33nPE4ICEZ0WlvG48jVEsx/In1TE6I+qmtvAhCU63Z66IooqysDHl5eS6MiqTCBIXIig3551HT1GZyrvswjn/cOA7rEDmArSvgbF1RR+5tgNQBEMlZY2s71uae63Hex9cfIxfmSBARkeeydQVcdHS0kyMhOWAPCpEF/8j9CfUt7VKHQeQV/GLHWl0pFxcXh5SUFBdFRFJigkJkxsXmNvzr2xKpwyDyGgofpdWVcn9Y9BKUSg6pegMmKERmrN5zDjo9VwsQuZK1lXIHxOskioxcjXNQiHpRUX8ZHxy4IHUYRF4pICEZfiMnojzrfgCdK+UGjboJCh8ljpTWY0eRFtPGRkkcJTkbe1CIrqLT6TB8SADO/G0GDPpWqcMh8kqWVsq9uqMYgsH8ruLkGdiDQnSVC7XcRZVIapZWyp2pbsbnh8vxm1viXBwVuRJ7UIiukrWr2PjfrWUnTDYtIyJ5yNp1Bm0d/N70ZExQiLp5Y/0HWJ/5a+NxTfZSaNakoaU4X8KoiOhqmvrL+HcB54l5MiYoRP+hVquR8fuHe2xSJjTVombzciYpRDKzes9ZNLWyTpGnYoJCBEAQBDw5/ymLbep2r+NwD5GMXKxvQvAgXygUCuh0nDvmaZigEAHIy8tDdWWFxTZCUy3ayotcFBERkXdjgkIE4MsC2xIPWzczIyLn696jmZubC0FgD6cnYYJCXk/X1oGt52yrd2LrZmZE5FwtxfmoXP8H4/GMGTMQHx8PtVotYVTkSExQyOu9tecsWsKut7pJmTIoHH6xY10UFRGZ01Kcj5rNy3tMaNdoNFCpVExSPAQTFPJq52t1WJ9XYtMmZWGT55lUsyQi1xMNAup2r+v9mthZXTYzM5PDPR6ACQp5tWU5J6EXDACsb1IWkJAsRYhE1E1beRGEplqz10VRRFlZGfLy8lwYFTkDS92T19pzuhrfnK42OWdpkzIikp6tE9UrKyudHAk5m909KLm5ufjVr36FmJgYKBQKbN682eS6KIp44YUXEB0djUGDBmHKlCk4c+aMSZu6ujrMmTMHwcHBCA0NRVpaGpqbm/t1I0T20HcYsCznZK/XlP6DMXJhDkYuzEHAtbcwOSGSEVsnqkdHRzs5EnI2uxMUnU6HiRMnYvXq1b1eX7lyJd544w2sWbMGBw4cwODBgzFt2jS0tl5ZJTFnzhwUFRVh586dyMnJQW5uLubNszz+T+RI678tQQk3BSRyO36xY61OaA8YEomUlBQXRUTOohC7ZhX15c0KBTZt2oRZs2YB6Ow9iYmJwbPPPos//vGPAICGhgZERkZiw4YNeOCBB3Dq1CmMGTMGBw8exC233AIA2L59O2bMmIHy8nLExMRY/bqNjY0ICQlBQ0MDgoOD+xo+eamqxlbc9epe6PScREfkjrpW8ZgTMWsx3ls2H9PHsxdFbuz5/e3QSbIlJSXQarWYMmWK8VxISAgSExNRUFAAACgoKEBoaKgxOQGAKVOmwMfHBwcOHOj1c9va2tDY2GjyIuqrFVtPMTkhcmO2TGh/KeckLusF6HQ6KBQKlsN3Qw5NULRaLQAgMjLS5HxkZKTxmlarxbBhw0yuDxgwAGFhYcY2V1uxYgVCQkKMr7i4OEeGTR7Clh9Eh87XYfNRyyXtiUj+AhKSEZ32tvE4QrUUw59Yb1xtV9HQije/OWOy3JjVZt2LWywzXrRoERoaGoyvsrIyqUMiGbL2g0jfYcBfNp1wdVhE5CTWJrSv+scH+FnCaOMxq826F4cmKFFRUQCAqqoqk/NVVVXGa1FRUaiuNl3a2dHRgbq6OmObq/n5+SE4ONjkRdSdWq3GmDFjjMe9/SB6Y/cZFFc1SREeEblYS3E+KtV/Q5XWdLkxq826D4cmKKNGjUJUVBR2795tPNfY2IgDBw4gKSkJAJCUlIT6+noUFhYa23zzzTcwGAxITEx0ZDjkJdRqNVQqFTQajcn57j+IjpXXY82+cxJFSESuxGqznsHuQm3Nzc04e/as8bikpARHjx5FWFgYRowYgczMTPzv//4vrr/+eowaNQp//etfERMTY1zpc8MNN+Duu+/GY489hjVr1qC9vR3z58/HAw88YNMKHqLuBEFARkYGeluMJooiFAoFMjIyMDrzPXQYRAitOhZhI/Jw9lSbveOOO1wXGNnF7gTl0KFDuPPOO43HCxYsAADMnTsXGzZswJ/+9CfodDrMmzcP9fX1+K//+i9s374d/v7+xvd8+OGHmD9/PiZPngwfHx/Mnj0bb7zxhgNuh7xNXl4eysvLzV4XRRHl5eVoLzwAw+Vm1O1aa7xWk70UyqBwhE2exzL2RB6E1WY9Q7/qoEiFdVCoy8cff4yHHnrIarugW+5F06EtZq9zrx0iz9FaegxVHy+22m7Pnj3sQXExyeqgELmareWsdUV7LF6v270OooHj0USewFq1WYVCgbi4OFablTkmKOTWUlJSEBsbC4VCYbaNz6BgGC5bLu4nNNWirbzI0eERkQQUPkqETba8fcqqVaugVHL+mZwxQSG3plQqkZWVBQBmk5TBY+/s9fzVbB23JiL5s1RtNm3Jm0hNTZUoMrIVExRye6mpqcjOzu6xCsxY9vp625av27pLKhG5B3PVZvfqR6GookHCyMgWnCRLHkMQBOTl5eGdrYewr7wdfrFjofBRQjQI0KxJs7jsUBkUjuFPrOeSYyIvMToqCF/M/y/4DuDf6a7ESbLklZRKJTqG3YDvlTfAf8QEY7Jhy3h02OR5TE6IvMhpbRP+b2ex1GGQBUxQyGOUXmzBgs+Oorc+QVt2PyUi7/KP3J+Qf7YWjY2Nxo1Gt23bxgqzMsEEhTxCa7uAJz4oRGNrh9k21nY/JSLvYhCB3/71TSSMvsF4jhsKygfnoJBHeG7jD9hYaL6iLBHR1VqK81GzeXmP810rArOzs7nax8E4B4U8jqUu2E++L2VyQkR24YaC8scEhWRPrVZjzJgxxuPuXbAnNA1Y8gULrBGRfezZUJCkYfdmgUSupFaroVKpeuxWrNFooFKpkPDbJWiLuUWi6IjIXXFDQfljDwrJliAIyMjI6JGcAJ1/3YiiiDOb3+IeOkRkN1sLM9q63xc5HhMUkq28vDyUl1ueW8I9dIioL7ihoPwxQSHZsrVrlXvoEJG9rBVwFEXTDQVZK8X1mKCQbNnatco9dIioLywXcFyEhsibAFieqE/OwzooJFuCICA+Ph4ajabXeSgA99Ahov4TWnUoz7ofQGcBx0GjboLCRwmFAvjN0Aq88qfHe/wMYq2UvrHn9zcTFJK1rlU8AHpNUlimnoicxdpGowqFArGxsSgpKTEOBZFlLNRGHiM1NRXr3/8IA4O4hw4RuRZrpUiLdVBI1ppa2/HZxeGIenx95w+L5ktQBg6BX+xYDusQkVOxVoq0mKCQbLV1CHjs/UM4VdkIhY8S/iMmSB0SEXkR1kqRFod4SJbaBQMyPj6K/T/VSR0KEXkp1kqRFhMUkpwgCNi7dy8+/vhj7N27F7pWPea9fwjbi7RSh0ZEXsxSrZSuVTzda6WQY3GIhySlVqvx9NNPQ6PRGM8NCh2GwDt+zwmwRCS5rlopdbvWQmi+aDzvGxyOrKwsLjF2Ii4zJsmY2wiwC1fpEJFciAahx0T9iOAAvPe7X2BsTIjU4bkN1kEh2esqwmZprx0WYSMiuQvyG4C1j9yM5GvNz1WhK1gHhWSPGwESkSdoauvA//zrIL46xqXGjsY5KCQJbgRIRJ5CLxjw1MeHUd0wGqOEMlRWViI6OhopKSmcQNsPTFBIEtwIkIg8SfPpfDz21lyTibSxsbGcSNsPHOIhp7p6CbEgCBAMIgp0ERbrCwCdc1D8Yse6KFIior5pKc5HzeblJskJAGg0GqhUKu563EfsQaE+EwQBeXl5Zrsze1tCHDN8OK751XyUhYxH2OR5qNm83Oznh02exwmyRCRrokFA3e51vV8TRSgUCmRmZuLee+/lcI+d2INCfaJWqzFy5EjceeedeOihh3DnnXciPj7e+JdC1xLi7skJAFRoNPh2zSK0FOcb6wtc3ZPCjQCJyF3Yu6Fgb73K1Dv2oJDdzNUv6erO/PTTT7FgwQKz9U0AoG73Ogy6PhEBCckYdH0iNwIkIrdk60T+82XlUKvVyMjIMFnByHkq5rEOCtnFWv0ShUKB8PBw1NTUWP2syAeXcwNAInJrraXHUPXxYqvtRk17FOe/3tDjD7eukvnZ2dlekaSwDgo5jbX6JaIo2pScAFxCTETuz9qGggDgEzgUpd990Wuvcte5zMxM43APh4E6MUEhu9hav8QWXEJMRO7O0oaCXYIm3t1jhU933eepqNVqxMfHm53f502YoJBdbK1f4jPIctcdlxATkaewNuF/YFiMTZ+zZcsWqFSqHr3U3rpcmXNQyC5dc1A0Go3ZSbDKoHAMuev3qN3ystnP4SodIvI0vW0oqPBR2jxPJSIiwuwQuUKhQGxsLEpKSqBUKq2WeZAre35/cxUP2UWpVCIrKwsqlQoKhaLXJCVs8jwEJCRDoViMut3rTJbgKYPCjdeJiDyJwkfZ68T/rnkqlpYj+wcNsTh/r/swUF1dnVesBmIPCvXKWna+6h//xuI/PYvL9Ve+oXpLPsz9RUFE5E26qs2aE3TLvWg6tMXq52RmZiIrK8ttVwPZ8/ubCQr1YGmt/qSpM/HK9mJsLCyDIDD5ICKyVUtxvtleZZ9BgV4xDMQEhfrMXBG2zuEcIO43f4HPqNskio6IyL2Z61UWDQI0a9LMDgPZU2Nqz549sh0GYh0UssjcGntBEJCRkWFhrb6Iim1rIBq8c00+EVF/dc1TGTzmdviPmGDsdba2XFkUgbvumW3T17BnNZCca66wB8WNOKK7ztLwTVhYGO68806rn8EKsEREzuHKYaAtW7a4vJeFq3g8kCP2cLC2h87MB9Ns+hxWgCUicg5L+5OJBsHiaiBbhoG6VgP97W9/w9KlS83+PpDDZFv2oLgBS/NCANtmbVvbQwfoLK5muNxoNR72oBARScPiaiCFAvOfegpvvfGG1c8JCwtDXV2dmY8xnWzrSJyDIjO2jPH1fV6I6R4O5ljbQwcADJcbWQGWiEjGLFatvXcRvrg03KbPMZecAKY1V6TEIR4ns2Voxtq8EGub83X9Q7rjjjt6nadS3axHzv6TNsU7eOydFtfih02ex6XEREQS6u8w0JAhQywmKF0cufdaXzBBsaC/k1KtzfnIzs4GAIttMjIybPpalZWVvSY6viERCLnzMfgMCrTpcwKuT4R/7FhWgCUikjFzVWu7VgOZGwYSRRG/nPUwvvxXltWvYevea87COShm2Dop1VwSY23Oh0KhwPDhnV1xltrYuu797rlPY/t75scdw+/9My5980+LpZaVQeEY/sR6YxbOImxERO7J0mqgQdcnWq25Ioc5KJImKKtXr8Yrr7wCrVaLiRMn4s0338Stt95q9X3OTlBsnZTqiCW7toiIiEBtba3Zzfl8AodCAVjczpsb+BEReRdLf2haK73/4hv/wgtPPerwmNxikuynn36KBQsWYMmSJTh8+DAmTpyIadOmobq6WqqQANg+KTU7O9tiIZwtW6zvqWCz6/7LbHICAEET77aYnACA0FQLZUCwxS3BmZwQEXkOc0XhACuTbWcths+oRFeH24NkPSiJiYn4xS9+gbfeegsAYDAYEBcXh6eeegp//vOfLb7XmT0oe/futannw1ohHFuHZmwR+eByGC43m+2uE4V21H75itXPCf/Vcxg85nYO3xAREQDzvSy//69ReP6eMQ7/erIv1KbX61FYWIhFixYZz/n4+GDKlCkoKCjo0b6trQ1tbW3G48ZG67U6+upCmcamdtYK4dTU1FitK2Lr0EzXPxhzs7ZbS4/ZFLMycAgA85OriIjIu8j594EkCUptbS0EQUBkZKTJ+cjISJw+fbpH+xUrVuDFF190SWw+g4c47LNun5GKPZ+/95+j7h1VnXNZfvfHznv659KnzLZ59NmluHFS9yy2Z0ZrEK7DC7veQH1N1VWfceWzQiOi8JffpcJH4p0siYhI/m6MC5U6BPdYZrxo0SIsWLDAeNzY2Ii4uDinfK2H7p2GxbGx0Gg0vc77sGf45oX5czH/oV/1mEgbFxeLVatWGVcDTR8fbbWNNcPXrIZKpQKgMIm7a2Lv+jVvIXVKgk2fRUREJDVJ5qDo9XoEBAQgOzsbs2bNMp6fO3cu6uvrrU4wddUqHgC9/rLvmuBrKYnpvkTLlnoqztoIMC4uzq5Eh4iIyFncYplxYmIibr31Vrz55psAOifJjhgxAvPnz5d0kmwXa7/srSUxUm205IhEh4iIyBncIkH59NNPMXfuXKxduxa33norVq1ahc8++wynT5/uMTflaq7aLNDaL3v2WBAREdnOLRIUAHjrrbeMhdpuvPFGvPHGG0hMtL72Wk67GbPHgoiIyDZuk6D0lZwSFCIiIrKNW1SSJSIiIjKHCQoRERHJDhMUIiIikh0mKERERCQ7TFCIiIhIdpigEBERkewwQSEiIiLZYYJCREREssMEhYiIiGRngNQB9EVX8dvGxkaJIyEiIiJbdf3etqWIvVsmKE1NTQA6N+YjIiIi99LU1ISQkBCLbdxyLx6DwYCKigoEBQVBoVD06TMaGxsRFxeHsrIyj93Ph/foGbzhHgHvuE/eo2fwhnsEnHOfoiiiqakJMTEx8PGxPMvELXtQfHx8EBsb65DPCg4O9uh/YADv0VN4wz0C3nGfvEfP4A33CDj+Pq31nHThJFkiIiKSHSYoREREJDtem6D4+flhyZIl8PPzkzoUp+E9egZvuEfAO+6T9+gZvOEeAenv0y0nyRIREZFn89oeFCIiIpIvJihEREQkO0xQiIiISHaYoBAREZHseGyC8re//Q3JyckICAhAaGhor21KS0sxc+ZMBAQEYNiwYXjuuefQ0dFh8XPr6uowZ84cBAcHIzQ0FGlpaWhubnbCHdhv7969UCgUvb4OHjxo9n133HFHj/ZPPPGECyO3T3x8fI94X375ZYvvaW1tRXp6OoYOHYrAwEDMnj0bVVVVLorYPufPn0daWhpGjRqFQYMG4dprr8WSJUug1+stvs8dnuPq1asRHx8Pf39/JCYm4vvvv7fYfuPGjRg9ejT8/f0xfvx4bN261UWR2m/FihX4xS9+gaCgIAwbNgyzZs1CcXGxxfds2LChxzPz9/d3UcT2W7p0aY94R48ebfE97vQMu/T2M0ahUCA9Pb3X9u7wHHNzc/GrX/0KMTExUCgU2Lx5s8l1URTxwgsvIDo6GoMGDcKUKVNw5swZq59r7/e0PTw2QdHr9bjvvvvw5JNP9npdEATMnDkTer0e+fn5eO+997Bhwwa88MILFj93zpw5KCoqws6dO5GTk4Pc3FzMmzfPGbdgt+TkZFRWVpq8fv/732PUqFG45ZZbLL73scceM3nfypUrXRR13yxbtswk3qeeespi+2eeeQZffvklNm7ciH379qGiogKpqakuitY+p0+fhsFgwNq1a1FUVITXX38da9asweLFi62+V87P8dNPP8WCBQuwZMkSHD58GBMnTsS0adNQXV3da/v8/Hw8+OCDSEtLw5EjRzBr1izMmjULJ06ccHHkttm3bx/S09Oxf/9+7Ny5E+3t7Zg6dSp0Op3F9wUHB5s8swsXLrgo4r4ZO3asSbzffvut2bbu9gy7HDx40OQed+7cCQC47777zL5H7s9Rp9Nh4sSJWL16da/XV65ciTfeeANr1qzBgQMHMHjwYEybNg2tra1mP9Pe72m7iR7u3XffFUNCQnqc37p1q+jj4yNqtVrjuXfeeUcMDg4W29raev2skydPigDEgwcPGs9t27ZNVCgUokajcXjs/aXX68WIiAhx2bJlFtvdfvvtYkZGhmuCcoCRI0eKr7/+us3t6+vrxYEDB4obN240njt16pQIQCwoKHBChI63cuVKcdSoURbbyP053nrrrWJ6errxWBAEMSYmRlyxYkWv7X/zm9+IM2fONDmXmJgoPv74406N01Gqq6tFAOK+ffvMtjH380mulixZIk6cONHm9u7+DLtkZGSI1157rWgwGHq97m7PEYC4adMm47HBYBCjoqLEV155xXiuvr5e9PPzEz/++GOzn2Pv97S9PLYHxZqCggKMHz8ekZGRxnPTpk1DY2MjioqKzL4nNDTUpDdiypQp8PHxwYEDB5wes72++OILXLx4EY8++qjVth9++CHCw8Mxbtw4LFq0CC0tLS6IsO9efvllDB06FDfddBNeeeUVi0NzhYWFaG9vx5QpU4znRo8ejREjRqCgoMAV4fZbQ0MDwsLCrLaT63PU6/UoLCw0eQY+Pj6YMmWK2WdQUFBg0h7o/B51p2cGwOpza25uxsiRIxEXF4d7773X7M8fuThz5gxiYmJwzTXXYM6cOSgtLTXb1t2fIdD5b/eDDz7A7373O4ub07rbc+yupKQEWq3W5FmFhIQgMTHR7LPqy/e0vdxys0BH0Gq1JskJAOOxVqs1+55hw4aZnBswYADCwsLMvkdK69evx7Rp06xurPjQQw9h5MiRiImJwbFjx7Bw4UIUFxdDrVa7KFL7PP300/j5z3+OsLAw5OfnY9GiRaisrMRrr73Wa3utVgtfX98ec5EiIyNl+dyudvbsWbz55pt49dVXLbaT83Osra2FIAi9fs+dPn261/eY+x51h2dmMBiQmZmJX/7ylxg3bpzZdgkJCfjXv/6FCRMmoKGhAa+++iqSk5NRVFTksA1RHSkxMREbNmxAQkICKisr8eKLLyIlJQUnTpxAUFBQj/bu/Ay7bN68GfX19fif//kfs23c7Tleret52POs+vI9bS+3SlD+/Oc/4+9//7vFNqdOnbI6acvd9OW+y8vLsWPHDnz22WdWP7/7HJrx48cjOjoakydPxrlz53Dttdf2PXA72HOPCxYsMJ6bMGECfH198fjjj2PFihWyLj3dl+eo0Whw991347777sNjjz1m8b1yeI7UKT09HSdOnLA4PwMAkpKSkJSUZDxOTk7GDTfcgLVr1+Kll15ydph2mz59uvG/J0yYgMTERIwcORKfffYZ0tLSJIzMedavX4/p06cjJibGbBt3e47uwq0SlGeffdZiFgsA11xzjU2fFRUV1WO2cdeqjqioKLPvuXryT0dHB+rq6sy+xxH6ct/vvvsuhg4div/3//6f3V8vMTERQOdf7q76xdafZ5uYmIiOjg6cP38eCQkJPa5HRUVBr9ejvr7epBelqqrKqc/tavbeY0VFBe68804kJydj3bp1dn89KZ6jOeHh4VAqlT1WTll6BlFRUXa1l4v58+cbJ9Db+9fzwIEDcdNNN+Hs2bNOis6xQkND8bOf/cxsvO76DLtcuHABu3btsrsX0t2eY9fzqKqqQnR0tPF8VVUVbrzxxl7f05fvabs5ZCaLjFmbJFtVVWU8t3btWjE4OFhsbW3t9bO6JskeOnTIeG7Hjh2ymyRrMBjEUaNGic8++2yf3v/tt9+KAMQffvjBwZE5xwcffCD6+PiIdXV1vV7vmiSbnZ1tPHf69GlZT5ItLy8Xr7/+evGBBx4QOzo6+vQZcnuOt956qzh//nzjsSAI4vDhwy1Okr3nnntMziUlJcl2gqXBYBDT09PFmJgY8ccff+zTZ3R0dIgJCQniM8884+DonKOpqUkcMmSImJWV1et1d3uGV1uyZIkYFRUltre32/U+uT9HmJkk++qrrxrPNTQ02DRJ1p7vabvjdMinyNCFCxfEI0eOiC+++KIYGBgoHjlyRDxy5IjY1NQkimLnP6Bx48aJU6dOFY8ePSpu375djIiIEBctWmT8jAMHDogJCQlieXm58dzdd98t3nTTTeKBAwfEb7/9Vrz++uvFBx980OX3Z8muXbtEAOKpU6d6XCsvLxcTEhLEAwcOiKIoimfPnhWXLVsmHjp0SCwpKRG3bNkiXnPNNeKkSZNcHbZN8vPzxddff108evSoeO7cOfGDDz4QIyIixEceecTY5up7FEVRfOKJJ8QRI0aI33zzjXjo0CExKSlJTEpKkuIWrCovLxevu+46cfLkyWJ5eblYWVlpfHVv427P8ZNPPhH9/PzEDRs2iCdPnhTnzZsnhoaGGlfSPfzww+Kf//xnY/vvvvtOHDBggPjqq6+Kp06dEpcsWSIOHDhQPH78uFS3YNGTTz4phoSEiHv37jV5Zi0tLcY2V9/jiy++KO7YsUM8d+6cWFhYKD7wwAOiv7+/WFRUJMUtWPXss8+Ke/fuFUtKSsTvvvtOnDJlihgeHi5WV1eLouj+z7A7QRDEESNGiAsXLuxxzR2fY1NTk/H3IADxtddeE48cOSJeuHBBFEVRfPnll8XQ0FBxy5Yt4rFjx8R7771XHDVqlHj58mXjZ9x1113im2++aTy29j3dXx6boMydO1cE0OO1Z88eY5vz58+L06dPFwcNGiSGh4eLzz77rEmmvGfPHhGAWFJSYjx38eJF8cEHHxQDAwPF4OBg8dFHHzUmPXLx4IMPisnJyb1eKykpMfn/UFpaKk6aNEkMCwsT/fz8xOuuu0587rnnxIaGBhdGbLvCwkIxMTFRDAkJEf39/cUbbrhBXL58uUmv19X3KIqiePnyZfEPf/iDOGTIEDEgIED89a9/bfILX07efffdXv/tdu/wdNfn+Oabb4ojRowQfX19xVtvvVXcv3+/8drtt98uzp0716T9Z599Jv7sZz8TfX19xbFjx4pfffWViyO2nbln9u677xrbXH2PmZmZxv8fkZGR4owZM8TDhw+7Pngb3X///WJ0dLTo6+srDh8+XLz//vvFs2fPGq+7+zPsbseOHSIAsbi4uMc1d3yOXb/Prn513YfBYBD/+te/ipGRkaKfn584efLkHvc+cuRIccmSJSbnLH1P95dCFEXRMYNFRERERI7htXVQiIiISL6YoBAREZHsMEEhIiIi2WGCQkRERLLDBIWIiIhkhwkKERERyQ4TFCIiIpIdJihEREQkO0xQiIiISHaYoBAREZHsMEEhIiIi2WGCQkRERLLz/wFAUp2dHJH56wAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x = data.to_numpy()[\"x\"]\n", "\n", "nll = UnbinnedNLL(x, model)\n", "m = Minuit(nll, 1, 3)\n", "m.migrad()" ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "root", "language": "python", "name": "root" }, "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.11.0" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/scipy_and_constraints.ipynb0000644000000000000000000003451014332717401020421 0ustar00{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# SciPy minimizers and constraints\n", "\n", "The `Minuit` class can call SciPy minimizers implemented in `scipy.optimize.minimize` as alternatives to the standard Migrad minimizer to minimize the cost function. The SciPy minimizers may perform better or worse on some problems. You can give them a try when you are not satisfied with Migrad.\n", "\n", "More importantly, the SciPy minimizers support additional features that Migrad lacks.\n", "\n", "* Migrad does not allow one to use an externally computed hessian matrix.\n", "* Migrad does not allow one to use additional constraints of the form $\\vec a \\leq f(\\vec x) \\leq \\vec b$ in the minimization, where $\\vec x$ is the parameter vector of length $m$, $f$ is an arbitrary function $\\mathcal{R}^m \\rightarrow \\mathcal{R}^k$ and $\\vec a, \\vec b$ are vector bounds with length $k$.\n", "\n", "SciPy comes with a variety of minimization algorithms and some of them support these features. The ability to use constraints is interesting for HEP applications. In particular, it allows us to ensure that a pdf as a function of the parameters is always positive. This can be ensured sometimes with suitable limits on the parameters, but not always.\n", "\n", "We demonstrate this on a common example of fit of an additive model with a signal and background pdf." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "from iminuit.cost import ExtendedUnbinnedNLL\n", "import numpy as np\n", "from numba_stats import norm, bernstein\n", "import matplotlib.pyplot as plt\n", "import joblib" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "The signal pdf is a Gaussian, the background is modelled with second degree Bernstein polynomials. We perform an extended maximum likelihood fit, where the full density model is given by the sum of the signal and background component." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": {}, "outputs": [], "source": [ "xrange = (0, 1)\n", "\n", "\n", "def model(x, b0, b1, b2, sig, mu, sigma):\n", " beta = [b0, b1, b2]\n", " bint = np.diff(bernstein.integral(xrange, beta, *xrange))\n", " sint = sig * np.diff(norm.cdf(xrange, mu, sigma))[0]\n", " return bint + sint, bernstein.density(x, beta, *xrange) + sig * norm.pdf(\n", " x, mu, sigma\n", " )" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "In searches for rare decays, it is common to fit models like this to small simulated samples that contain only background, to calculate the distribution of some test statistic (usually the likelihood ratio of S+B and B-only hypotheses). Here, for simplicity, we use the signal amplitude itself as the test statistic.\n", "\n", "We run one such fit. The mean and width of the Gaussian are fixed, only the signal amplitude and the background parameters are varied." ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(2)\n", "x = rng.uniform(0, 1, size=35)\n", "\n", "cost = ExtendedUnbinnedNLL(x, model)\n", "n = len(x)\n", "m = Minuit(cost, b0=n, b1=n, b2=n, sig=0, mu=0.5, sigma=0.05)\n", "m.print_level = 0\n", "m.limits[\"b0\", \"b1\", \"b2\"] = (0, None)\n", "m.fixed[\"mu\", \"sigma\"] = True\n", "m.migrad()" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "In this example, the signal amplitude came out negative. This happens if the background has an underfluctuation where the signal is expected. This is not an issue if the sum of signal and background density is still positive everywhere where we evaluate it. As long as the total density is positive, individual components are allowed to be negative.\n", "\n", "There are, however, no restrictions in this example that prevent the sum of signal and background from becoming negative for some toy data sets. When that happens, the fit will fail, since the total density cannot mathematically become negative. Specifically, the logarithm of a negative number is taken in the calculation which results in a NaN." ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "## Migrad fit on toys\n", "\n", "We apply the fit many times on randomly sampled background-only data to observe this." ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "@joblib.delayed\n", "def compute(itry):\n", " rng = np.random.default_rng(itry)\n", " x = rng.uniform(0, 1, size=35)\n", " cost = ExtendedUnbinnedNLL(x, model)\n", " m = Minuit(cost, b0=n, b1=n, b2=n, sig=0, mu=0.5, sigma=0.05)\n", " m.limits[\"b0\", \"b1\", \"b2\"] = (0, None)\n", " m.fixed[\"mu\", \"sigma\"] = True\n", " m.migrad()\n", " return m\n", "\n", "\n", "fits = joblib.Parallel(-1)(compute(i) for i in range(200))" ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": {}, "outputs": [], "source": [ "nfailed = sum(not m.valid for m in fits)\n", "plt.title(f\"{nfailed} fits failed ({nfailed / len(fits) * 100:.0f} %)\")\n", "plt.hist([m.values[\"sig\"] for m in fits], bins=10, range=(-10, 10))\n", "plt.xlabel(\"sig\");" ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "The distribution of the signal amplitude looks fairly gaussian which is good, but the fit failed to converge in a few cases due to the problem just described. Simply discarding these cases is not acceptable, it would distort conclusions drawn from the distribution of the test statistic, which is commonly needed to set limits or to compute the p-value for an observed amplitude.\n", "\n", "We can repair this by placing a limit on the signal amplitude. This is a suitable solution, although it will bias the signal amplitude and change the shape of the distribution of the test statistic. \n", "\n", "An alternative is to perform a constrained minimization, which allows us to directly add a condition to the fit that the model density must be positive at each data point. We merely need to replace the call `m.migrad` with the call `m.scipy` and pass the (non-linear) constraint. An appropriate algorithm is automatically selected which performs a constrained minimization. The SciPy minimizers are fully integrated into Minuit, which means that Minuit computes an EDM value for the minimum and parameter uncertainties." ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "## SciPy constrained fit on toys \n", "\n", "We run SciPy with the constraint on the same simulated samples on which we ran Migrad before." ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "from scipy.optimize import NonlinearConstraint\n", "\n", "\n", "@joblib.delayed\n", "def compute(itry):\n", " rng = np.random.default_rng(itry)\n", " x = rng.uniform(0, 1, size=35)\n", " cost = ExtendedUnbinnedNLL(x, model)\n", " m = Minuit(cost, b0=n, b1=n, b2=n, sig=0, mu=0.5, sigma=0.05)\n", " m.limits[\"b0\", \"b1\", \"b2\"] = (0, None)\n", " m.fixed[\"mu\", \"sigma\"] = True\n", " m.scipy(constraints=NonlinearConstraint(lambda *par: model(x, *par)[1], 0, np.inf))\n", " return m\n", "\n", "\n", "fits_constrained = joblib.Parallel(-1)(compute(i) for i in range(200))" ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": {}, "outputs": [], "source": [ "nfailed = sum(not m.valid for m in fits_constrained)\n", "plt.title(\n", " f\"{nfailed} constrained fits failed ({nfailed / len(fits_constrained) * 100:.0f} %)\"\n", ")\n", "plt.hist(\n", " [m.values[\"sig\"] for m in fits],\n", " alpha=0.5,\n", " bins=10,\n", " range=(-10, 10),\n", " label=fits[0].fmin.algorithm,\n", ")\n", "plt.hist(\n", " [m.values[\"sig\"] for m in fits_constrained],\n", " alpha=0.5,\n", " bins=10,\n", " range=(-10, 10),\n", " label=fits_constrained[0].fmin.algorithm,\n", ")\n", "plt.xlabel(\"sig\")\n", "plt.legend();" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "There are no failures this time. \n", "\n", "For sig $\\gg 0$, the distributions are identical, as theoretically expected. In practice, there can be small bin migration effects due to finite precision of numerical algorithms. These are not of concern.\n", "\n", "Important are the differences for sig < 0, where Migrad did not converge in a few cases and where therefore samples are missing. Those missing samples are recovered in the distribution produced by the constrained fit.\n", "\n", "This demonstrates that it is important to not discard failed fits, as this will in general distort the distribution of the test statistic." ] }, { "cell_type": "markdown", "id": "15", "metadata": {}, "source": [ "## Bonus: unconstrained SciPy fit\n", "\n", "The issues we describe here are of a principal mathematical nature. We should not expect that an unconstrained minimiser from SciPy does better than Migrad, but let's test this assumption. The minimiser that SciPy uses when only box constraints are used is the L-BFGS-B method which is roughly comparable to Migrad. Let us see how well this algorithm does on the same toy samples." ] }, { "cell_type": "code", "execution_count": null, "id": "16", "metadata": {}, "outputs": [], "source": [ "@joblib.delayed\n", "def compute(itry):\n", " rng = np.random.default_rng(itry)\n", " x = rng.uniform(0, 1, size=35)\n", " cost = ExtendedUnbinnedNLL(x, model)\n", " m = Minuit(cost, b0=n, b1=n, b2=n, sig=0, mu=0.5, sigma=0.05)\n", " m.limits[\"b0\", \"b1\", \"b2\"] = (0, None)\n", " m.fixed[\"mu\", \"sigma\"] = True\n", " m.scipy()\n", " return m\n", "\n", "\n", "fits_bfgs = joblib.Parallel(-1)(compute(i) for i in range(200))" ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "nfailed = sum(not m.valid for m in fits_bfgs)\n", "plt.title(f\"{nfailed} BFGS fits failed ({nfailed / len(fits_bfgs) * 100:.0f} %)\")\n", "for f in (fits, fits_constrained, fits_bfgs):\n", " plt.hist(\n", " [m.values[\"sig\"] for m in f],\n", " alpha=0.5,\n", " bins=10,\n", " range=(-10, 10),\n", " label=f[0].fmin.algorithm,\n", " )\n", "plt.xlabel(\"sig\")\n", "plt.legend();" ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "In this example, the BFGS method actually failed less than Migrad, but it still fails in some cases, while the constrained fit did not fail at all." ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "## Speed comparison\n", "\n", "Since constrained fits are so useful, should you use them all the time? No.\n", "\n", "Constrained fits are more computationally expensive. Satisfying extra constrains generally slows down convergence. Let's compare the speed of the three minimisers tested here. We set the strategy to 0, to avoid computing the Hessian matrix automatically, since we want to measure only the time used by the minimiser." ] }, { "cell_type": "code", "execution_count": null, "id": "20", "metadata": {}, "outputs": [], "source": [ "m.strategy = 0" ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": {}, "outputs": [], "source": [ "%timeit -n3 m.reset(); m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "id": "22", "metadata": {}, "outputs": [], "source": [ "%timeit -n3 m.reset(); m.scipy()" ] }, { "cell_type": "code", "execution_count": null, "id": "23", "metadata": {}, "outputs": [], "source": [ "%timeit -n3 m.reset(); m.scipy(constraints=NonlinearConstraint(lambda *par: model(x, *par)[1], 0, np.inf))" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "Migrad is the fastest, followed by the L-BFGS-B method. The constrained fit is much slower, since it has to do more work.\n", "\n", "Migrad is quite fast because of its smart stopping criterion. Migrad stops the fit as soon as the improvement of the fitted parameters become small compared to their uncertainties. Migrad was explicitly designed for statistical fits, where the cost function is a log-likelihood or least-squares function. Since it assumes that, it can stops the fit as soon as the parameter improvements become negligible compared to the parameter uncertainty, which is given by the inverse of its internal approximation of the Hessian matrix.\n", "\n", "The SciPy minimisers do not expect the cost function to be a log-likelihood or least-squares and thus cannot assume that the Hessian matrix has a special meaning. Instead they tend to optimise until they hit the limits of machine precision. You can also see this in the benchmark section of the documentation." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 5 } iminuit-2.30.1/doc/notebooks/simultaneous_fits.ipynb0000644000000000000000000000771714332717401017607 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Fits with shared parameters\n", "\n", "We demonstrate how to simultaneously fit two datasets with different models that shares a common parameter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "from iminuit.cost import UnbinnedNLL\n", "from iminuit.util import describe\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "from numba_stats import norm" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# generate two data sets which are fitted simultaneously\n", "rng = np.random.default_rng(1)\n", "\n", "width = 2.0\n", "data1 = rng.normal(0, width, size=1000)\n", "data2 = rng.normal(5, width, size=1000)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# use two pdfs with different names for non-shared parameters,\n", "# so that they are fitted independently\n", "\n", "\n", "def pdf1(x, μ_1, σ):\n", " return norm.pdf(x, μ_1, σ)\n", "\n", "\n", "def pdf2(x, μ_2, σ):\n", " return norm.pdf(x, μ_2, σ)\n", "\n", "\n", "# combine two log-likelihood functions by adding them\n", "lh = UnbinnedNLL(data1, pdf1) + UnbinnedNLL(data2, pdf2)\n", "\n", "print(f\"{describe(lh)=}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `σ` parameter is shared between the data sets, while the means of the two normal distributions are independently fitted." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def plot(cost, xe, minuit, ax, **style):\n", " signature = describe(cost)\n", "\n", " values = minuit.values[signature]\n", " errors = minuit.errors[signature]\n", "\n", " cx = (xe[1:] + xe[:-1]) / 2\n", "\n", " ym = np.diff(norm.cdf(xe, *values)) * np.sum(w)\n", " t = []\n", " for n, v, e in zip(signature, values, errors):\n", " t.append(f\"${n} = {v:.3f} ± {e:.3f}$\")\n", " ax.plot(cx, ym, label=\"\\n\".join(t), **style)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = Minuit(lh, μ_1=1, μ_2=2, σ=1)\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(9, 4))\n", "\n", "hists = [np.histogram(lhi.data, bins=50) for lhi in lh]\n", "\n", "# draw data and model with initial parameters\n", "for lhi, (w, xe), axi in zip(lh, hists, ax):\n", " cx = (xe[1:] + xe[:-1]) / 2\n", " axi.errorbar(cx, w, np.sqrt(w), fmt=\"ok\", capsize=0, zorder=0)\n", " plot(lhi, xe, m, axi, ls=\"--\")\n", "\n", "m.migrad()\n", "\n", "# draw model with fitted parameters\n", "for lhi, (w, xe), axi in zip(lh, hists, ax):\n", " plot(lhi, xe, m, axi)\n", " axi.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The dashed line shows the initial model before the fit, the solid line shows the model after the fit. Note that the σ parameter is shared." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.14 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 4 } iminuit-2.30.1/doc/notebooks/template_fits.ipynb0000644000000000000000000152425714332717401016676 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Template fits\n", "\n", "In applications we are interested in separating a signal component from background components, we often fit parameteric models to data. Sometimes constructing a parametric model for some component is difficult. In that case, one fits a template instead which may be obtained from simulation or from a calibration sample in which a pure component can be isolated.\n", "\n", "The challenge then is to propagate the uncertainty of the template into the result. The template is now also estimated from a sample (be it simulated or a calibration sample), and the uncertainty associated to that can be substantial. We investigate different approaches for template fits, including the Barlow-Beeston and Barlow-Beeston-lite methods.\n", "\n", "**Note:** This work has been published: [H. Dembinski, A. Abdelmotteleb, Eur.Phys.J.C 82 (2022) 11, 1043](https://doi.org/10.1140/epjc/s10052-022-11019-z)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "from iminuit.cost import poisson_chi2, Template\n", "import numpy as np\n", "from scipy.stats import norm, truncexpon\n", "from scipy.optimize import minimize\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a toy example, we generate a mixture of two components: a normally distributed signal and exponentially distributed background." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def generate(rng, nmc, truth, bins):\n", " xe = np.linspace(0, 2, bins + 1)\n", " b = np.diff(truncexpon(1, 0, 2).cdf(xe))\n", " s = np.diff(norm(1, 0.1).cdf(xe))\n", " n = rng.poisson(b * truth[0]) + rng.poisson(s * truth[1])\n", " t = np.array([rng.poisson(b * nmc), rng.poisson(s * nmc)])\n", " return xe, n, t\n", "\n", "\n", "rng = np.random.default_rng(1)\n", "truth = 750, 250\n", "xe, n, t = generate(rng, 500, truth, 15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Data is visualized on the left-hand side. The templates are shown on the right-hand side. To show the effect of uncertainties in the template, this example intentially uses templates with poor statistical resolution." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:55.149783\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(10, 4), sharex=True)\n", "ax[0].stairs(n, xe, fill=True, color=\"k\", alpha=0.5, label=\"data\")\n", "for i, ti in enumerate(t):\n", " ax[1].stairs(ti, xe, fill=True, alpha=0.5, label=f\"template {i}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Bootstrapping template uncertainties\n", "\n", "Bootstrapping is a general purpose technique to include uncertainties backed up by bootstrap theory, so it can be applied to this problem.\n", "We perform a standard fit and pretend that the templates have no uncertainties. Then, we repeat this fit many times with templates that are fluctuated around the actual values assuming a Poisson distribution.\n", "\n", "Here is the cost function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = -991.9 (χ²/ndof = -76.3) Nfcn = 119
EDM = 0.000125 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 782 31 0
1 x1 201 20 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 985 -0.2e3 (-0.322)
x1 -0.2e3 (-0.322) 404
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = -991.9 (χ²/ndof = -76.3) │ Nfcn = 119 │\n", "│ EDM = 0.000125 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 782 │ 31 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 201 │ 20 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────┤\n", "│ x0 │ 985 -0.2e3 │\n", "│ x1 │ -0.2e3 404 │\n", "└────┴───────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def cost(yields):\n", " mu = 0\n", " for y, c in zip(yields, t):\n", " mu += y * c / np.sum(c)\n", " r = poisson_chi2(n, mu)\n", " return r\n", "\n", "\n", "cost.errordef = Minuit.LEAST_SQUARES\n", "cost.ndata = np.prod(n.shape)\n", "\n", "starts = np.ones(2)\n", "m = Minuit(cost, starts)\n", "m.limits = (0, None)\n", "m.migrad()\n", "m.hesse()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The uncertainties reported by the fit correspond to the uncertainty in the data, but not the uncertainty in the templates. The chi2/ndof is also very large, since the uncertainties in the template are not considered in the fit.\n", "\n", "We bootstrap the templates 1000 times and compute the covariance of the fitted results." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b = 100\n", "rng = np.random.default_rng(1)\n", "pars = []\n", "for ib in range(b):\n", " ti = rng.poisson(t)\n", "\n", " def cost(yields):\n", " mu = 0\n", " for y, c in zip(yields, ti):\n", " mu += y * c / np.sum(c)\n", " r = poisson_chi2(n, mu)\n", " return r\n", "\n", " mi = Minuit(cost, m.values[:])\n", " mi.errordef = Minuit.LEAST_SQUARES\n", " mi.limits = (0, None)\n", " mi.strategy = 0\n", " mi.migrad()\n", " assert mi.valid\n", " pars.append(mi.values[:])\n", "\n", "cov2 = np.cov(np.transpose(pars), ddof=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We print the uncertainties from the different stages and the correlation between the two yields.\n", "\n", "To obtain the full error, we add the independent covariance matrices from the original fit and the bootstrap." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fit\n", " b 782 +- 31\n", " s 201 +- 20\n", " correlation -0.32\n", "bootstrap\n", " b 782 +- 18\n", " s 201 +- 18\n", " correlation -1.00\n", "fit+bootstrap\n", " b 782 +- 36\n", " s 201 +- 27\n", " correlation -0.53\n" ] } ], "source": [ "cov1 = m.covariance\n", "\n", "for title, cov in zip((\"fit\", \"bootstrap\", \"fit+bootstrap\"), (cov1, cov2, cov1 + cov2)):\n", " print(title)\n", " for label, p, e in zip((\"b\", \"s\"), m.values, np.diag(cov) ** 0.5):\n", " print(f\" {label} {p:.0f} +- {e:.0f}\")\n", " print(f\" correlation {cov[0, 1] / np.prod(np.diag(cov)) ** 0.5:.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The bootstrapped template errors are much larger than the fit errors in this case, since the sample used to generate the templates is much smaller than the data sample.\n", "\n", "The bootstrapped errors for both yields are nearly equal (they become exactly equal if the template sample is large) and the correlation is close to -1 (and becomes exactly -1 in large samples). This is expected, since the data sample is fixed in each iteration. Under these conditions, a change in the templates can only increase the yield of one component at an equal loss for the other component." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Template fit with nuisance parameters\n", "\n", "As described in [Barlow and Beeston, Comput.Phys.Commun. 77 (1993) 219-228](https://doi.org/10.1016/0010-4655(93)90005-W), the correct treatment from first principles is to write down the likelihood function for this case, in which the observed values and unknown parameters are clearly stated. The insight is that the true contents of the bins for the templates are unknown and we need to introduce a nuisance parameter for each bin entry in the template. The combined likelihood for the problem is then combines the estimation of the template yields with the estimation of unknown templates.\n", "\n", "This problem can be handled straight-forwardly with Minuit, but it leads to the introduction of a large number of nuisance parameters, one for each entry in each template. We again write a cost function for this case (here a class for convenience).\n", "\n", "As a technical detail, it is necessary to increase the call limit in Migrad for the fit to fully converge, since the limit set by Minuit's default heuristic is too tight for this application." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = -2138 (χ²/ndof = -164.5) Nfcn = 1859
EDM = 1.87e-05 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
SOME parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 780 40 0
1 x1 199 26 0
2 x2 47 5 0
3 x3 50 5 0
4 x4 48 5 0
5 x5 43 4 0
6 x6 43 4 0
7 x7 39 4 0
8 x8 42 5 0
9 x9 29 5 0
10 x10 33 5 0
11 x11 28 4 0
12 x12 24.6 3.3 0
13 x13 21.5 3.0 0
14 x14 22.7 3.1 0
15 x15 23.1 3.2 0
16 x16 21.9 3.1 0
17 x17 0.0 0.4 0
18 x18 0.0 0.4 0
19 x19 0.0 0.4 0
20 x20 0.0 0.4 0
21 x21 1.0 0.9 0
22 x22 7.8 2.7 0
23 x23 109 10 0
24 x24 255 16 0
25 x25 111 10 0
26 x26 13 4 0
27 x27 0.0 0.4 0
28 x28 0.0 0.4 0
29 x29 0.0 0.4 0
30 x30 0.0 0.4 0
31 x31 0.0 0.4 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31
x0 1.26e+03 -0.5e3 (-0.516) -17 (-0.104) -18 (-0.106) -18 (-0.105) -16 (-0.100) -15 (-0.096) -10 (-0.065) 40 (0.213) 60 (0.331) 37 (0.221) -2 (-0.012) -9 (-0.078) -8 (-0.073) -8 (-0.075) -8 (-0.075) -8 (-0.074) -0 -0 -0 -0 -0.5 (-0.013) -3 (-0.028) -0.03e3 (-0.070) 0.05e3 (0.085) -0.01e3 (-0.034) -6 (-0.050) -0 -0 -0 -0 -0
x1 -0.5e3 (-0.516) 675 17 (0.142) 18 (0.145) 18 (0.143) 16 (0.137) 15 (0.131) 10 (0.088) -40 (-0.292) -60 (-0.453) -37 (-0.302) 2 (0.016) 9 (0.106) 8 (0.100) 8 (0.102) 8 (0.103) 8 (0.100) 0 0 0 0 0.5 (0.018) 3 (0.039) 0.03e3 (0.095) -0.05e3 (-0.116) 0.01e3 (0.047) 6 (0.068) 0 0 0 0 0
x2 -17 (-0.104) 17 (0.142) 22 3 (0.150) 3 (0.148) 3 (0.141) 3 (0.140) 3 (0.126) 1 (0.036) -1 (-0.024) 0 (0.022) 2 (0.093) 2 (0.110) 1 (0.103) 2 (0.106) 2 (0.107) 1 (0.104) -0 0 0 0 0 (0.004) 0 (0.008) 1 (0.019) -2 (-0.023) 0 (0.009) 0 (0.014) 0 0 0 0 0
x3 -18 (-0.106) 18 (0.145) 3 (0.150) 23.3 3 (0.152) 3 (0.144) 3 (0.143) 3 (0.128) 1 (0.037) -1 (-0.025) 1 (0.022) 2 (0.095) 2 (0.112) 2 (0.105) 2 (0.108) 2 (0.109) 2 (0.106) 0 -0 0 0 0.0 (0.004) 0 (0.008) 1 (0.020) -2 (-0.024) 0 (0.010) 0 (0.014) 0 0 0 0 0
x4 -18 (-0.105) 18 (0.143) 3 (0.148) 3 (0.152) 22.7 3 (0.143) 3 (0.141) 3 (0.127) 1 (0.037) -1 (-0.024) 0 (0.022) 2 (0.094) 2 (0.111) 2 (0.104) 2 (0.107) 2 (0.108) 2 (0.105) 0 0 -0 0 0.0 (0.004) 0 (0.008) 1 (0.019) -2 (-0.024) 0 (0.010) 0 (0.014) 0 0 0 0 0
x5 -16 (-0.100) 16 (0.137) 3 (0.141) 3 (0.144) 3 (0.143) 19.9 3 (0.135) 2 (0.121) 1 (0.035) -1 (-0.023) 0 (0.021) 1 (0.090) 2 (0.106) 1 (0.099) 1 (0.102) 1 (0.103) 1 (0.100) 0 0 0 -0 0.0 (0.004) 0 (0.008) 1 (0.018) -2 (-0.022) 0 (0.009) 0 (0.013) 0 0 0 0 0
x6 -15 (-0.096) 15 (0.131) 3 (0.140) 3 (0.143) 3 (0.141) 3 (0.135) 19.9 2 (0.120) 1 (0.036) -0 (-0.021) 0 (0.022) 1 (0.089) 2 (0.105) 1 (0.098) 1 (0.101) 1 (0.102) 1 (0.099) 0 0 0 0 -0.1 (-0.031) 0 (0.007) 1 (0.019) -1 (-0.021) 0 (0.010) 0 (0.013) 0 0 0 0 0
x7 -10 (-0.065) 10 (0.088) 3 (0.126) 3 (0.128) 3 (0.127) 2 (0.121) 2 (0.120) 18.1 1 (0.042) -0 (-0.006) 1 (0.029) 1 (0.082) 1 (0.094) 1 (0.088) 1 (0.090) 1 (0.091) 1 (0.089) 0 0 0 0 0.0 (0.003) -1 (-0.086) 1 (0.019) -1 (-0.008) 1 (0.012) 0 (0.012) 0 0 0 0 0
x8 40 (0.213) -40 (-0.292) 1 (0.036) 1 (0.037) 1 (0.037) 1 (0.035) 1 (0.036) 1 (0.042) 27.6 4 (0.137) 3 (0.113) 1 (0.048) 0 (0.027) 0 (0.025) 0 (0.026) 0 (0.026) 0 (0.026) -0 0 0 0 0.0 (0.001) 0 (0.006) -12 (-0.217) 9 (0.109) 2 (0.046) 0 (0.004) -0 -0 0 0 0
x9 60 (0.331) -60 (-0.453) -1 (-0.024) -1 (-0.025) -1 (-0.024) -1 (-0.023) -0 (-0.021) -0 (-0.006) 4 (0.137) 26.2 3 (0.138) 0 (0.017) -0 (-0.018) -0 (-0.017) -0 (-0.017) -0 (-0.017) -0 (-0.017) -0 0 -0 -0 -0.0 (-0.000) 0 (0.004) 2 (0.036) -5 (-0.060) 3 (0.056) -0 (-0.002) -0 -0 -0 0 0
x10 37 (0.221) -37 (-0.302) 0 (0.022) 1 (0.022) 0 (0.022) 0 (0.021) 0 (0.022) 1 (0.029) 3 (0.113) 3 (0.138) 22.2 1 (0.038) 0 (0.016) 0 (0.015) 0 (0.016) 0 (0.016) 0 (0.015) -0 0 0 0 0.0 (0.001) 0 (0.005) 2 (0.032) 8 (0.110) -10 (-0.204) 0 (0.003) -0 -0 -0 0 0
x11 -2 (-0.012) 2 (0.016) 2 (0.093) 2 (0.095) 2 (0.094) 1 (0.090) 1 (0.089) 1 (0.082) 1 (0.048) 0 (0.017) 1 (0.038) 13 1 (0.070) 1 (0.066) 1 (0.067) 1 (0.068) 1 (0.066) 0 0 0 0 0 (0.002) 0 (0.006) 1 (0.019) 1 (0.011) 1 (0.016) -2 (-0.150) 0 0 0 0 0
x12 -9 (-0.078) 9 (0.106) 2 (0.110) 2 (0.112) 2 (0.111) 2 (0.106) 2 (0.105) 1 (0.094) 0 (0.027) -0 (-0.018) 0 (0.016) 1 (0.070) 10.7 1 (0.077) 1 (0.079) 1 (0.080) 1 (0.078) 0 0 0 0 0.0 (0.003) 0 (0.006) 0 (0.014) -1 (-0.017) 0 (0.007) 0 (0.010) -0 0 0 0 0
x13 -8 (-0.073) 8 (0.100) 1 (0.103) 2 (0.105) 2 (0.104) 1 (0.099) 1 (0.098) 1 (0.088) 0 (0.025) -0 (-0.017) 0 (0.015) 1 (0.066) 1 (0.077) 9.19 1 (0.074) 1 (0.075) 1 (0.073) 0 0 0 0 0.0 (0.003) 0 (0.005) 0 (0.013) -1 (-0.016) 0 (0.007) 0 (0.010) 0 -0 0 0 0
x14 -8 (-0.075) 8 (0.102) 2 (0.106) 2 (0.108) 2 (0.107) 1 (0.102) 1 (0.101) 1 (0.090) 0 (0.026) -0 (-0.017) 0 (0.016) 1 (0.067) 1 (0.079) 1 (0.074) 9.75 1 (0.077) 1 (0.075) 0 0 0 0 0.0 (0.003) 0 (0.006) 0 (0.014) -1 (-0.017) 0 (0.007) 0 (0.010) 0 0 -0 0 0
x15 -8 (-0.075) 8 (0.103) 2 (0.107) 2 (0.109) 2 (0.108) 1 (0.103) 1 (0.102) 1 (0.091) 0 (0.026) -0 (-0.017) 0 (0.016) 1 (0.068) 1 (0.080) 1 (0.075) 1 (0.077) 9.93 1 (0.076) 0 0 0 0 0.0 (0.003) 0 (0.006) 0 (0.014) -1 (-0.017) 0 (0.007) 0 (0.010) 0 0 0 -0 0
x16 -8 (-0.074) 8 (0.100) 1 (0.104) 2 (0.106) 2 (0.105) 1 (0.100) 1 (0.099) 1 (0.089) 0 (0.026) -0 (-0.017) 0 (0.015) 1 (0.066) 1 (0.078) 1 (0.073) 1 (0.075) 1 (0.076) 9.37 0 0 0 0 0.0 (0.003) 0 (0.006) 0 (0.014) -1 (-0.017) 0 (0.007) 0 (0.010) 0 0 0 0 -0
x17 -0 0 -0 0 0 0 0 0 -0 -0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0
x18 -0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
x19 -0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0
x20 -0 0 0 0 0 -0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0
x21 -0.5 (-0.013) 0.5 (0.018) 0 (0.004) 0.0 (0.004) 0.0 (0.004) 0.0 (0.004) -0.1 (-0.031) 0.0 (0.003) 0.0 (0.001) -0.0 (-0.000) 0.0 (0.001) 0 (0.002) 0.0 (0.003) 0.0 (0.003) 0.0 (0.003) 0.0 (0.003) 0.0 (0.003) 0 0 0 0 0.99 0.0 0.0 (0.001) -0.0 (-0.000) 0.0 (0.000) 0.0 0 0 0 0 0
x22 -3 (-0.028) 3 (0.039) 0 (0.008) 0 (0.008) 0 (0.008) 0 (0.008) 0 (0.007) -1 (-0.086) 0 (0.006) 0 (0.004) 0 (0.005) 0 (0.006) 0 (0.006) 0 (0.005) 0 (0.006) 0 (0.006) 0 (0.006) 0 0 0 0 0.0 7.53 0 (0.002) 0 (0.003) 0 (0.002) 0 (0.001) 0 0 0 0 0
x23 -0.03e3 (-0.070) 0.03e3 (0.095) 1 (0.019) 1 (0.020) 1 (0.019) 1 (0.018) 1 (0.019) 1 (0.019) -12 (-0.217) 2 (0.036) 2 (0.032) 1 (0.019) 0 (0.014) 0 (0.013) 0 (0.014) 0 (0.014) 0 (0.014) 0 0 0 0 0.0 (0.001) 0 (0.002) 103 0 (0.028) 0 (0.013) 0 (0.002) 0 0 0 0 0
x24 0.05e3 (0.085) -0.05e3 (-0.116) -2 (-0.023) -2 (-0.024) -2 (-0.024) -2 (-0.022) -1 (-0.021) -1 (-0.008) 9 (0.109) -5 (-0.060) 8 (0.110) 1 (0.011) -1 (-0.017) -1 (-0.016) -1 (-0.017) -1 (-0.017) -1 (-0.017) -0 0 -0 -0 -0.0 (-0.000) 0 (0.003) 0 (0.028) 244 0.01e3 (0.045) -0 (-0.002) -0 -0 -0 -0 0
x25 -0.01e3 (-0.034) 0.01e3 (0.047) 0 (0.009) 0 (0.010) 0 (0.010) 0 (0.009) 0 (0.010) 1 (0.012) 2 (0.046) 3 (0.056) -10 (-0.204) 1 (0.016) 0 (0.007) 0 (0.007) 0 (0.007) 0 (0.007) 0 (0.007) -0 0 0 0 0.0 (0.000) 0 (0.002) 0 (0.013) 0.01e3 (0.045) 103 0 (0.001) -0 -0 -0 0 0
x26 -6 (-0.050) 6 (0.068) 0 (0.014) 0 (0.014) 0 (0.014) 0 (0.013) 0 (0.013) 0 (0.012) 0 (0.004) -0 (-0.002) 0 (0.003) -2 (-0.150) 0 (0.010) 0 (0.010) 0 (0.010) 0 (0.010) 0 (0.010) 0 0 0 0 0.0 0 (0.001) 0 (0.002) -0 (-0.002) 0 (0.001) 13.2 0 0 0 0 0
x27 -0 0 0 0 0 0 0 0 -0 -0 -0 0 -0 0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0
x28 -0 0 0 0 0 0 0 0 -0 -0 -0 0 0 -0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0
x29 -0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 -0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0
x30 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0
x31 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:55.875327\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = -2138 (χ²/ndof = -164.5) │ Nfcn = 1859 │\n", "│ EDM = 1.87e-05 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ SOME parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 780 │ 40 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 199 │ 26 │ │ │ 0 │ │ │\n", "│ 2 │ x2 │ 47 │ 5 │ │ │ 0 │ │ │\n", "│ 3 │ x3 │ 50 │ 5 │ │ │ 0 │ │ │\n", "│ 4 │ x4 │ 48 │ 5 │ │ │ 0 │ │ │\n", "│ 5 │ x5 │ 43 │ 4 │ │ │ 0 │ │ │\n", "│ 6 │ x6 │ 43 │ 4 │ │ │ 0 │ │ │\n", "│ 7 │ x7 │ 39 │ 4 │ │ │ 0 │ │ │\n", "│ 8 │ x8 │ 42 │ 5 │ │ │ 0 │ │ │\n", "│ 9 │ x9 │ 29 │ 5 │ │ │ 0 │ │ │\n", "│ 10│ x10 │ 33 │ 5 │ │ │ 0 │ │ │\n", "│ 11│ x11 │ 28 │ 4 │ │ │ 0 │ │ │\n", "│ 12│ x12 │ 24.6 │ 3.3 │ │ │ 0 │ │ │\n", "│ 13│ x13 │ 21.5 │ 3.0 │ │ │ 0 │ │ │\n", "│ 14│ x14 │ 22.7 │ 3.1 │ │ │ 0 │ │ │\n", "│ 15│ x15 │ 23.1 │ 3.2 │ │ │ 0 │ │ │\n", "│ 16│ x16 │ 21.9 │ 3.1 │ │ │ 0 │ │ │\n", "│ 17│ x17 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 18│ x18 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 19│ x19 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 20│ x20 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 21│ x21 │ 1.0 │ 0.9 │ │ │ 0 │ │ │\n", "│ 22│ x22 │ 7.8 │ 2.7 │ │ │ 0 │ │ │\n", "│ 23│ x23 │ 109 │ 10 │ │ │ 0 │ │ │\n", "│ 24│ x24 │ 255 │ 16 │ │ │ 0 │ │ │\n", "│ 25│ x25 │ 111 │ 10 │ │ │ 0 │ │ │\n", "│ 26│ x26 │ 13 │ 4 │ │ │ 0 │ │ │\n", "│ 27│ x27 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 28│ x28 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 29│ x29 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 30│ x30 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "│ 31│ x31 │ 0.0 │ 0.4 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌─────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────â”\n", "│ │ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 │\n", "├─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n", "│ x0 │ 1.26e+03 -0.5e3 -17 -18 -18 -16 -15 -10 40 60 37 -2 -9 -8 -8 -8 -8 -0 -0 -0 -0 -0.5 -3 -0.03e3 0.05e3 -0.01e3 -6 -0 -0 -0 -0 -0 │\n", "│ x1 │ -0.5e3 675 17 18 18 16 15 10 -40 -60 -37 2 9 8 8 8 8 0 0 0 0 0.5 3 0.03e3 -0.05e3 0.01e3 6 0 0 0 0 0 │\n", "│ x2 │ -17 17 22 3 3 3 3 3 1 -1 0 2 2 1 2 2 1 -0 0 0 0 0 0 1 -2 0 0 0 0 0 0 0 │\n", "│ x3 │ -18 18 3 23.3 3 3 3 3 1 -1 1 2 2 2 2 2 2 0 -0 0 0 0.0 0 1 -2 0 0 0 0 0 0 0 │\n", "│ x4 │ -18 18 3 3 22.7 3 3 3 1 -1 0 2 2 2 2 2 2 0 0 -0 0 0.0 0 1 -2 0 0 0 0 0 0 0 │\n", "│ x5 │ -16 16 3 3 3 19.9 3 2 1 -1 0 1 2 1 1 1 1 0 0 0 -0 0.0 0 1 -2 0 0 0 0 0 0 0 │\n", "│ x6 │ -15 15 3 3 3 3 19.9 2 1 -0 0 1 2 1 1 1 1 0 0 0 0 -0.1 0 1 -1 0 0 0 0 0 0 0 │\n", "│ x7 │ -10 10 3 3 3 2 2 18.1 1 -0 1 1 1 1 1 1 1 0 0 0 0 0.0 -1 1 -1 1 0 0 0 0 0 0 │\n", "│ x8 │ 40 -40 1 1 1 1 1 1 27.6 4 3 1 0 0 0 0 0 -0 0 0 0 0.0 0 -12 9 2 0 -0 -0 0 0 0 │\n", "│ x9 │ 60 -60 -1 -1 -1 -1 -0 -0 4 26.2 3 0 -0 -0 -0 -0 -0 -0 0 -0 -0 -0.0 0 2 -5 3 -0 -0 -0 -0 0 0 │\n", "│ x10 │ 37 -37 0 1 0 0 0 1 3 3 22.2 1 0 0 0 0 0 -0 0 0 0 0.0 0 2 8 -10 0 -0 -0 -0 0 0 │\n", "│ x11 │ -2 2 2 2 2 1 1 1 1 0 1 13 1 1 1 1 1 0 0 0 0 0 0 1 1 1 -2 0 0 0 0 0 │\n", "│ x12 │ -9 9 2 2 2 2 2 1 0 -0 0 1 10.7 1 1 1 1 0 0 0 0 0.0 0 0 -1 0 0 -0 0 0 0 0 │\n", "│ x13 │ -8 8 1 2 2 1 1 1 0 -0 0 1 1 9.19 1 1 1 0 0 0 0 0.0 0 0 -1 0 0 0 -0 0 0 0 │\n", "│ x14 │ -8 8 2 2 2 1 1 1 0 -0 0 1 1 1 9.75 1 1 0 0 0 0 0.0 0 0 -1 0 0 0 0 -0 0 0 │\n", "│ x15 │ -8 8 2 2 2 1 1 1 0 -0 0 1 1 1 1 9.93 1 0 0 0 0 0.0 0 0 -1 0 0 0 0 0 -0 0 │\n", "│ x16 │ -8 8 1 2 2 1 1 1 0 -0 0 1 1 1 1 1 9.37 0 0 0 0 0.0 0 0 -1 0 0 0 0 0 0 -0 │\n", "│ x17 │ -0 0 -0 0 0 0 0 0 -0 -0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0 │\n", "│ x18 │ -0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │\n", "│ x19 │ -0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 │\n", "│ x20 │ -0 0 0 0 0 -0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 │\n", "│ x21 │ -0.5 0.5 0 0.0 0.0 0.0 -0.1 0.0 0.0 -0.0 0.0 0 0.0 0.0 0.0 0.0 0.0 0 0 0 0 0.99 0.0 0.0 -0.0 0.0 0.0 0 0 0 0 0 │\n", "│ x22 │ -3 3 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 7.53 0 0 0 0 0 0 0 0 0 │\n", "│ x23 │ -0.03e3 0.03e3 1 1 1 1 1 1 -12 2 2 1 0 0 0 0 0 0 0 0 0 0.0 0 103 0 0 0 0 0 0 0 0 │\n", "│ x24 │ 0.05e3 -0.05e3 -2 -2 -2 -2 -1 -1 9 -5 8 1 -1 -1 -1 -1 -1 -0 0 -0 -0 -0.0 0 0 244 0.01e3 -0 -0 -0 -0 -0 0 │\n", "│ x25 │ -0.01e3 0.01e3 0 0 0 0 0 1 2 3 -10 1 0 0 0 0 0 -0 0 0 0 0.0 0 0 0.01e3 103 0 -0 -0 -0 0 0 │\n", "│ x26 │ -6 6 0 0 0 0 0 0 0 -0 0 -2 0 0 0 0 0 0 0 0 0 0.0 0 0 -0 0 13.2 0 0 0 0 0 │\n", "│ x27 │ -0 0 0 0 0 0 0 0 -0 -0 -0 0 -0 0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0 │\n", "│ x28 │ -0 0 0 0 0 0 0 0 -0 -0 -0 0 0 -0 0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0 │\n", "│ x29 │ -0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 -0 0 0 0 0 0 0 0 0 0 -0 -0 0 0 0 0 0 0 │\n", "│ x30 │ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 │\n", "│ x31 │ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │\n", "└─────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class BB:\n", " def __init__(self, xe, n, t):\n", " self.xe = xe\n", " self.data = n, t\n", "\n", " def _pred(self, par):\n", " bins = len(self.xe) - 1\n", " yields = par[:2]\n", " nuisances = np.array(par[2:])\n", " b = nuisances[:bins]\n", " s = nuisances[bins:]\n", " mu = 0\n", " for y, c in zip(yields, (b, s)):\n", " mu += y * np.array(c) / np.sum(c)\n", " return mu, b, s\n", "\n", " def __call__(self, par):\n", " n, t = self.data\n", " mu, b, s = self._pred(par)\n", " r = poisson_chi2(n, mu) + poisson_chi2(t[0], b) + poisson_chi2(t[1], s)\n", " return r\n", "\n", " @property\n", " def ndata(self):\n", " n, t = self.data\n", " return np.prod(n.shape) + np.prod(t.shape)\n", "\n", " def visualize(self, args):\n", " n, t = self.data\n", " ne = n**0.5\n", " xe = self.xe\n", " cx = 0.5 * (xe[1:] + xe[:-1])\n", " plt.errorbar(cx, n, ne, fmt=\"ok\")\n", " mu = 0\n", " mu_var = 0\n", " for y, c in zip(args[:2], t):\n", " f = 1 / np.sum(c)\n", " mu += c * y * f\n", " mu_var += c * (f * y) ** 2\n", " mu_err = mu_var**0.5\n", " plt.stairs(mu + mu_err, xe, baseline=mu - mu_err, fill=True, color=\"C0\")\n", " # plt.stairs(mu, xe, color=\"C0\")\n", "\n", "\n", "m1 = Minuit(BB(xe, n, t), np.concatenate([truth, t[0], t[1]]))\n", "m1.limits = (0, None)\n", "m1.migrad(ncall=100000)\n", "m1.hesse()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result of this fit is comparable to the bootstrap method for this example, but the chi2/ndof is now reasonable and the uncertainties are correct without further work. This method should perform better than the bootstrap method, if the count per bin in the templates is small.\n", "\n", "Another advantage is of this technique is that one can profile over the likelihood to obtain a 2D confidence regions, which is not possible with the bootstrap technique." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:57.151545\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "m1.draw_mncontour(\"x0\", \"x1\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before moving on, we briefly explore a possible refinement of the previous method, which is to hide the nuisance parameters from Minuit with a nested fit. It turns out that this technique is not an improvement, but it is useful to show that explicitly.\n", "\n", "The idea is to construct an outer cost function, which only has the yields as parameters. Inside the outer cost function, the best nuisance parameters are found for the current yields with an inner cost function. Technically, this is achieved by calling a minimizer on the inner cost function at every call to the outer cost function.\n", "\n", "Technical detail: It is important here to adjust Minuit's expectation of how accurate the cost function is computed. Usually, Minuit performs its internal calculations under the assumption that the cost function is accurate to machine precision. This is usually not the case when a minimizer is used internally to optimize the inner function. We perform the internal minimization with SciPy, which allows us to set the tolerance. We set it here to 1e-8, which is sufficient for this problem and saves a bit of time on the internal minimisation. We then instruct Minuit to expect only this precision." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = -2140 (χ²/ndof = -164.6) Nfcn = 55
EDM = 3.28e-05 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 784 35 0
1 x1 199 26 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 1.22e+03 -0.5e3 (-0.506)
x1 -0.5e3 (-0.506) 665
" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = -2140 (χ²/ndof = -164.6) │ Nfcn = 55 │\n", "│ EDM = 3.28e-05 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 784 │ 35 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 199 │ 26 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 1.22e+03 -0.5e3 │\n", "│ x1 │ -0.5e3 665 │\n", "└────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "precision = 1e-8\n", "\n", "\n", "def cost(yields):\n", " bins = len(n)\n", "\n", " def inner(nuisance):\n", " b = nuisance[:bins]\n", " s = nuisance[bins:]\n", " mu = 0\n", " for y, c in zip(yields, (b, s)):\n", " mu += y * c / np.sum(c)\n", " r = poisson_chi2(n, mu) + poisson_chi2(t[0], b) + poisson_chi2(t[1], s)\n", " return r\n", "\n", " bounds = np.zeros((2 * bins, 2))\n", " bounds[:, 1] = np.inf\n", " r = minimize(inner, np.ravel(t), bounds=bounds, tol=precision)\n", " assert r.success\n", " return r.fun\n", "\n", "\n", "cost.errordef = Minuit.LEAST_SQUARES\n", "cost.ndata = np.prod(n.shape)\n", "\n", "m2 = Minuit(cost, truth)\n", "m2.precision = precision\n", "m2.limits = (0, None)\n", "m2.migrad()\n", "m2.hesse()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We obtain the exact same result as expected, but the runtime is much longer (more than a factor 10), which disfavors this technique compared to the straight-forward fit. The minimization is not as efficient, because Minuit cannot exploit correlations between the internal and the external parameters that allow it to converge it faster when it sees all parameters at once." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Template fits\n", "\n", "The implementation described by [Barlow and Beeston, Comput.Phys.Commun. 77 (1993) 219-228](https://doi.org/10.1016/0010-4655(93)90005-W) solves the problem similarly to the nested fit described above, but the solution to the inner problem is found with an efficient algorithm.\n", "\n", "The Barlow-Beeston approach still requires numerically solving a non-linear equation per bin. Several authors tried to replace the stop with approximations.\n", "- [Conway, PHYSTAT 2011, https://arxiv.org/abs/1103.0354](https://doi.org/10.48550/arXiv.1103.0354) uses an approximation in which the optimal nuisance parameters can be found by bin-by-bin by solving a quadratic equation which has only one allowed solution.\n", "- [C.A. Argüelles, A. Schneider, T. Yuan, JHEP 06 (2019) 030](https://doi.org/10.48550/arXiv.1103.0354) use a Bayesian treatment in which the uncertainty from the finite size of the simulation sample is modeled with a prior (which is itself a posterior conditioned on the simulation result). A closed formula for the likelihood can be derived.\n", "- [H. Dembinski, A. Abdelmotteleb, Eur.Phys.J.C 82 (2022) 11, 1043](https://doi.org/10.1140/epjc/s10052-022-11019-z) derived an approximation similar to Conway, but which treats data and simulation symmetrically.\n", "\n", "All three methods are implemented in the built-in `Template` cost function (see documentation for details)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 8.447 (χ²/ndof = 0.6) Nfcn = 46
EDM = 7.7e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 790 50 0
1 x1 197 28 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 2.56e+03 -0.5e3 (-0.358)
x1 -0.5e3 (-0.358) 764
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:59.131447\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 8.447 (χ²/ndof = 0.6) │ Nfcn = 46 │\n", "│ EDM = 7.7e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 790 │ 50 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 197 │ 28 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 2.56e+03 -0.5e3 │\n", "│ x1 │ -0.5e3 764 │\n", "└────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = Template(n, xe, t, method=\"jsc\") # Conway\n", "m3 = Minuit(c, *truth)\n", "m3.limits = (0, None)\n", "m3.migrad()\n", "m3.hesse()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 54.95 Nfcn = 46
EDM = 5.98e-07 (Goal: 0.0001)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 760 50 0
1 x1 203 27 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 2.25e+03 -0.4e3 (-0.341)
x1 -0.4e3 (-0.341) 739
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:59.412000\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 54.95 │ Nfcn = 46 │\n", "│ EDM = 5.98e-07 (Goal: 0.0001) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 760 │ 50 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 203 │ 27 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 2.25e+03 -0.4e3 │\n", "│ x1 │ -0.4e3 739 │\n", "└────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = Template(n, xe, t, method=\"asy\") # Argüelles, Schneider, Yuan\n", "m4 = Minuit(c, *truth)\n", "m4.limits = (0, None)\n", "m4.migrad()\n", "m4.hesse()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 8.503 (χ²/ndof = 0.7) Nfcn = 45
EDM = 9.17e-06 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 780 50 0
1 x1 199 28 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 2.45e+03 -0.5e3 (-0.351)
x1 -0.5e3 (-0.351) 756
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:42:59.643360\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 8.503 (χ²/ndof = 0.7) │ Nfcn = 45 │\n", "│ EDM = 9.17e-06 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 780 │ 50 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 199 │ 28 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 2.45e+03 -0.5e3 │\n", "│ x1 │ -0.5e3 756 │\n", "└────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = Template(n, xe, t, method=\"da\") # Dembinski, Abdelmotteleb\n", "m5 = Minuit(c, *truth)\n", "m5.limits = (0, None)\n", "m5.migrad()\n", "m5.hesse()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "full fit\n", " x0 784 +- 35\n", " x1 199 +- 26\n", " correlation -0.52\n", "T(JSC)\n", " x0 793 +- 51\n", " x1 197 +- 28\n", " correlation -0.36\n", "T(ASY)\n", " x0 760 +- 47\n", " x1 203 +- 27\n", " correlation -0.34\n", "T(DA)\n", " x0 784 +- 49\n", " x1 199 +- 27\n", " correlation -0.35\n" ] } ], "source": [ "for title, m in zip((\"full fit\", \"T(JSC)\", \"T(ASY)\", \"T(DA)\"), (m1, m3, m4, m5)):\n", " print(title)\n", " cov = m.covariance\n", " for label, p, e in zip((\"x0\", \"x1\"), m.values, np.diag(cov) ** 0.5):\n", " print(f\" {label} {p:.0f} +- {e:.0f}\")\n", " print(f\" correlation {cov[0, 1] / (cov[0, 0] * cov[1, 1]) ** 0.5:.2f}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The yields found by the approximate Template methods (T) differ from those found with the exact Barlow-Beeston likelihood (BB) method, because the likelihoods are different. In this particular case, the uncertainty for the signal estimated by the Template methods is larger, but this not the case in general.\n", "\n", "The difference shows up in particular in the 68 % confidence regions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:43:01.217634\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c1 = m1.mncontour(\"x0\", \"x1\")\n", "c3 = m3.mncontour(\"x0\", \"x1\")\n", "c4 = m4.mncontour(\"x0\", \"x1\")\n", "c5 = m5.mncontour(\"x0\", \"x1\")\n", "plt.plot(c1[:, 0], c1[:, 1], label=\"BB\")\n", "plt.plot(c3[:, 0], c3[:, 1], label=\"T(JSC)\")\n", "plt.plot(c4[:, 0], c4[:, 1], label=\"T(ASY)\")\n", "plt.plot(c5[:, 0], c4[:, 1], label=\"T(DA)\")\n", "plt.xlabel(\"background yield\")\n", "plt.ylabel(\"signal yield\")\n", "plt.legend();" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In this particular example, the BB method produces the smallest uncertainty for the background yield. The uncertainty for the signal yield is similar for all methods.\n", "\n", "In general, the approximate methods perform well, the `T(DA)` method in particular is very close to the performance of the exact BB likelihood. The `T(DA)` method also has the advantage that it can be used with weighted data and/or weighted simulated samples.\n", "\n", "For an in-depth comparison of the four methods, see [H. Dembinski, A. Abdelmotteleb, Eur.Phys.J.C 82 (2022) 11, 1043](https://doi.org/10.1140/epjc/s10052-022-11019-z)." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "Python 3.8.12 ('venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/template_gof.ipynb0000644000000000000000000101664314332717401016477 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Template fits: comparing two chi-square distributed test statistics\n", "\n", "The builtin binned cost functions in `iminuit.cost` provide a method `pulls` which returns the pull distribution for a given data set. The sum of pulls squared is asymptotically chi-square distributed, but as is explained in the documentation, it is better to use the minimum value of the cost function instead of the pulls to compute this test statistic. The reason is that the cost function has been designed so that the minimum is chi-square distributed and it approaches the asymptotic limit faster than a simple sum of pulls squared.\n", "\n", "We demonstrate this in this example for a Template fit. We generate random samples from a mixed model (gaussian peak over exponential background), which is fitted many times. The distribution of the cost function minimum and alternatively the sum of pulls squared is compared with a chi-square distribution by computing p-values based on the expected distribution. If the test statistic follows the chi-square distribution, the distribution of p-values must be uniform." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import cost, Minuit\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from scipy.stats import chi2\n", "from IPython.display import display" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 13.87 (χ²/ndof = 0.8) Nfcn = 101
EDM = 2.91e-08 (Goal: 0.0002) time = 0.2 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 1.01e3 0.05e3 0
1 x1 870 50 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 2.49e+03 -0.5e3 (-0.196)
x1 -0.5e3 (-0.196) 2.21e+03
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:44:15.234319\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 13.87 (χ²/ndof = 0.8) │ Nfcn = 101 │\n", "│ EDM = 2.91e-08 (Goal: 0.0002) │ time = 0.2 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 1.01e3 │ 0.05e3 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 870 │ 50 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 2.49e+03 -0.5e3 │\n", "│ x1 │ -0.5e3 2.21e+03 │\n", "└────┴───────────────────┘" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 201.8 (χ²/ndof = 1.0) Nfcn = 100
EDM = 2.37e-05 (Goal: 0.0002)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x0 1.02e3 0.05e3 0
1 x1 810 40 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x0 x1
x0 2.41e+03 -0.3e3 (-0.161)
x1 -0.3e3 (-0.161) 1.92e+03
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:44:15.435767\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 201.8 (χ²/ndof = 1.0) │ Nfcn = 100 │\n", "│ EDM = 2.37e-05 (Goal: 0.0002) │ │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ x0 │ 1.02e3 │ 0.05e3 │ │ │ 0 │ │ │\n", "│ 1 │ x1 │ 810 │ 40 │ │ │ 0 │ │ │\n", "└───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌────┬───────────────────â”\n", "│ │ x0 x1 │\n", "├────┼───────────────────┤\n", "│ x0 │ 2.41e+03 -0.3e3 │\n", "│ x1 │ -0.3e3 1.92e+03 │\n", "└────┴───────────────────┘" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "xr = (0, 2) # xrange\n", "rng = np.random.default_rng(1)\n", "\n", "nmc = 1000\n", "trials = 1000\n", "\n", "data = {}\n", "data2 = {}\n", "\n", "first = True\n", "for trial in range(trials):\n", " for bins in (\n", " 20,\n", " 200,\n", " ):\n", " xdata = rng.normal(1, 0.1, size=1000)\n", " ydata = rng.exponential(size=len(xdata))\n", " xmix = np.append(xdata, ydata)\n", " xmix = xmix[(xr[0] < xmix) & (xmix < xr[1])]\n", "\n", " n, xe = np.histogram(xmix, bins=bins, range=xr)\n", "\n", " x = rng.normal(1, 0.1, size=nmc)\n", " y = rng.exponential(size=nmc)\n", " t = [\n", " np.histogram(x, bins=bins, range=xr)[0],\n", " np.histogram(y, bins=bins, range=xr)[0],\n", " ]\n", " c = cost.Template(n, xe, t)\n", " m = Minuit(c, 1, 1)\n", " m.migrad()\n", " assert m.valid\n", " assert m.accurate\n", " data.setdefault(bins, []).append(m.fmin.fval)\n", " data2.setdefault(bins, []).append(np.nansum(c.pulls(m.values) ** 2))\n", " # display one example fit\n", " if first:\n", " display(m)\n", " first = False\n", "\n", "for key in tuple(data):\n", " val = data[key]\n", " data[key] = np.array(val)\n", " val = data2[key]\n", " data2[key] = np.array(val)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:44:26.393355\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:44:26.481424\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for bins in data:\n", " plt.figure()\n", " plt.title(f\"bins = {bins}\")\n", " plt.hist(\n", " chi2(bins - 2).cdf(data[bins]), bins=10, range=(0, 1), label=\"cost function\"\n", " )\n", " plt.hist(\n", " chi2(bins - 2).cdf(data2[bins]),\n", " bins=10,\n", " range=(0, 1),\n", " alpha=0.5,\n", " label=\"sum of pulls squared\",\n", " )\n", " plt.legend()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "When 20 bins are used, the number of counts per bin is large enough so that both test statistics are chi-square distributed. When 200 bins are used with samples of the same size, the density in some bins drops low enough so that we are not in the asymptotic limit and see deviations from the theoretical chi-square distribution. These deviations are larger for the sum of pulls squared." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "py310", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/template_model_mix.ipynb0000644000000000000000000001405714332717401017675 0ustar00{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Fitting a mixture of templates and parametric models\n", "\n", "The class `iminuit.cost.Template` supports fitting a mixture of templates and parametric models. This is useful if some components have a simple shape like a Gaussian peak, while other components are complicated and need to be estimated from simulation or a control measurement.\n", "\n", "In this notebook, we demonstrate this usage. Our data consists of a Gaussian peak and exponential background. We fit the Gaussian peak with a parametric model and use a template to describe the exponential background." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from iminuit import Minuit\n", "from iminuit.cost import Template, ExtendedBinnedNLL\n", "from numba_stats import norm, truncexpon\n", "import numpy as np\n", "from matplotlib import pyplot as plt" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We generate the toy data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1)\n", "\n", "s = rng.normal(0.5, 0.05, size=1000)\n", "b = rng.exponential(1, size=1000)\n", "b = b[b < 1]\n", "\n", "ns, xe = np.histogram(s, bins=100, range=(0, 1))\n", "nb, _ = np.histogram(b, bins=xe)\n", "n = ns + nb\n", "\n", "plt.stairs(nb, xe, color=\"C1\", fill=True, label=\"background\")\n", "plt.stairs(n, xe, baseline=nb, color=\"C0\", fill=True, label=\"signal\")\n", "plt.legend();" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Fitting a parametric component and a template\n", "\n", "We now model the peaking component parametrically with a Gaussian. A template fit is an extended binned fit, so we need to provide a scaled cumulative density function like for `iminuit.cost.ExtendedBinnedNLL`. To obtain a background template, we generate more samples from the exponential distribution and make a histogram." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# signal model: scaled cdf of a normal distribution\n", "def signal(xe, n, mu, sigma):\n", " return n * norm.cdf(xe, mu, sigma)\n", "\n", "\n", "# background template: histogram of MC simulation\n", "rng = np.random.default_rng(2)\n", "b2 = rng.exponential(1, size=1000)\n", "b2 = b2[b2 < 1]\n", "template = np.histogram(b2, bins=xe)[0]\n", "\n", "# fit\n", "c = Template(n, xe, (signal, template))\n", "m = Minuit(c, x0_n=500, x0_mu=0.5, x0_sigma=0.05, x1=100)\n", "m.limits[\"x0_n\", \"x1\", \"x0_sigma\"] = (0, None)\n", "m.limits[\"x0_mu\"] = (0, 1)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The fit succeeded and the statistical uncertainty in the template is propagated into the result. You can play with this demo and see what happens if you increase the statistic of the template.\n", "\n", "Note: the parameters of a parametric components are prefixed with `xn_` where `n` is the index of the component. This is to avoid name clashes between the parameter names of individual components and for clarity which parameter belongs to which component." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Extreme case: Fitting two parametric components\n", "\n", "Although this is not recommended, you can also use the `Template` class with two parametric components and no template. If you are in that situation, however, it is simpler and more efficient to use `iminuit.cost.ExtendedBinnedNLL`. The following snipped is therefore just a proof that `iminuit.cost.Template` handles this limiting case as well." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# signal model: scaled cdf of a normal distribution\n", "def signal(xe, n, mu, sigma):\n", " return n * norm.cdf(xe, mu, sigma)\n", "\n", "\n", "# background model: scaled cdf a an exponential distribution\n", "def background(xe, n, mu):\n", " return n * truncexpon.cdf(xe, xe[0], xe[-1], 0, mu)\n", "\n", "\n", "# fit\n", "c = Template(n, xe, (signal, background))\n", "m = Minuit(c, x0_n=500, x0_mu=0.5, x0_sigma=0.05, x1_n=100, x1_mu=1)\n", "m.limits[\"x0_n\", \"x1_n\", \"x0_sigma\", \"x1_mu\"] = (0, None)\n", "m.limits[\"x0_mu\"] = (0, 1)\n", "m.migrad()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The result is identical when we fit with `iminuit.cost.ExtendedBinnedNLL`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def total(xe, x0_n, x0_mu, x0_sigma, x1_n, x1_mu):\n", " return signal(xe, x0_n, x0_mu, x0_sigma) + background(xe, x1_n, x1_mu)\n", "\n", "\n", "c = ExtendedBinnedNLL(n, xe, total)\n", "m = Minuit(c, x0_n=500, x0_mu=0.5, x0_sigma=0.05, x1_n=100, x1_mu=1)\n", "m.limits[\"x0_n\", \"x1_n\", \"x0_sigma\", \"x1_mu\"] = (0, None)\n", "m.limits[\"x0_mu\"] = (0, 1)\n", "m.migrad()" ] } ], "metadata": { "kernelspec": { "display_name": "venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" }, "vscode": { "interpreter": { "hash": "bdbf20ff2e92a3ae3002db8b02bd1dd1b287e934c884beb29a73dced9dbd0fa3" } } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/unstable_fit.ipynb0000644000000000000000000450016714332717401016512 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Unstable fits: why fits fail and how to fix it\n", "\n", "In practice, it is quite common that a fit does not work as intended in the beginning. The fit may fail to converge outright, or it works on some datasets but not on others. Debugging these issues requires experience and insight.\n", "\n", "The most common reasons for unstable or failing fits are:\n", "\n", "- Parameters which need bounds, for example, because they cannot be negative, do not have limits set and the fit enters the forbidden parameter region during minimization. This often causes the cost function to return infinity or NaN, which causes the fit to fail.\n", "- The model has parameters which are not constrained by data. The gradient with respect to this parameter is approximately zero.\n", "- The model is ambiguous: it has too many parameters and some parameters are perfectly (anti)correlated to others. This is a variation of the above problem. Perfect (anti)correlation means one can find a new basis in parameter space in which some parameters have approximately zero gradient.\n", "- The model is not smooth: the gradient is discontinuous or noisy.\n", "\n", "These issues cannot be solved by Minuit or any other fitting program, they need to be solved by the user. Ideally, Minuit would diagnose and report the exact issue to the user, but neither Minuit nor other fitting programs are very good at this.\n", "\n", "Minuit still tries to handle pathological cases as good as possible, and Minuit is actually better at this than other minimizers. You can influence how hard Minuit tries to recover a pathological fit with the `Minuit.strategy` setting. The default is 1, but increasing this to 2 may make the fit converge at the cost of an increase in function evaluations. In fact, in `iminuit` we are doing this automatically, if the initial fit fails to converge, and try again a few times. If you don't know good starting values, it can help to run `Minuit.simplex` first, before running `Minuit.migrad`. When the fit iteration is triggered, we alternate between `Minuit.simplex` and `Minuit.migrad` by default, which seems to help. You can turn off iteration and the use of `Minuit.simplex` with keyword options.\n", "\n", "Below we demonstrate the impact of these settings on a scenario with multiple pathologies. We do a least-squares fit of a line to data. Here are the pathologies:\n", "\n", "1) The line has an additive parameter which is multiplied by a small factor. If this factor is not small, the data constrain the parameter and the fit will converge fine. If the factor is zero, the data won't be able to constrain the parameter at all, which causes an ambiguity in the model: whatever the value of the parameter, there is no change in the least-squares function. This causes the fit to fail because the gradient along this parameter is zero. In reality, we are often inbetween these extremes. The smaller the factor is, the close the gradient becomes to zero. We do the fit many times, scanning over the factor from 1e-10 to 1.\n", "2) The line has a small random offset of 1e-6 added to it, so the gradient is slightly random. Minuit assumes that the gradient is exact to machine precision, so this will destabilize the fit.\n", "\n", "We see how `Minuit.migrad` does on this, and for comparison, also run a few Scipy minimizers on the same problem." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "from iminuit.cost import LeastSquares\n", "from iminuit import Minuit\n", "from matplotlib import pyplot as plt\n", "from dataclasses import dataclass" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:51.371087\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:51.589120\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:51.774643\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:52.010267\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:52.284974\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:52.499549\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:52.766257\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:52.982990\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:53.286198\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:53.560283\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:53.791847\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:54.046846\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:54.289172\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:54.518749\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:54.759605\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:47:55.000916\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@dataclass\n", "class Migrad:\n", " strategy: int\n", " iterate: int\n", " use_simplex: bool\n", "\n", " def __repr__(self):\n", " return f\"Migrad: strategy={self.strategy} iterate={self.iterate} use_simplex={self.use_simplex}\"\n", "\n", "\n", "for minimizer in (\n", " Migrad(0, 1, False),\n", " Migrad(0, 5, False),\n", " Migrad(0, 5, True),\n", " Migrad(1, 1, False),\n", " Migrad(1, 5, False),\n", " Migrad(1, 5, True),\n", " Migrad(2, 1, False),\n", " Migrad(2, 5, False),\n", " Migrad(2, 5, True),\n", " \"Nelder-Mead\",\n", " \"powell\",\n", " \"BFGS\",\n", " \"L-BFGS-B\",\n", " \"TNC\",\n", " \"SLSQP\",\n", " \"COBYLA\",\n", "):\n", " valid = []\n", " val = []\n", " err = []\n", " nfcn = []\n", " power = np.geomspace(1e-20, 1, 25)\n", "\n", " rng = np.random.default_rng(1)\n", " for p in power:\n", "\n", " def fn(x, par):\n", " return x * par[0] + 1 + p * par[1] + rng.normal(0.0, 1e-7)\n", "\n", " x = np.linspace(1, 3, 5)\n", " c = LeastSquares(x, fn(x, [1, 0]), 1, fn)\n", " m = Minuit(c, [10, 10])\n", " if isinstance(minimizer, Migrad):\n", " m.strategy = minimizer.strategy\n", " m.migrad(iterate=minimizer.iterate, use_simplex=minimizer.use_simplex)\n", " else:\n", " m.scipy(method=minimizer)\n", " m.hesse()\n", " valid.append(m.valid)\n", " val.append(m.values[:])\n", " err.append(m.errors[:])\n", " nfcn.append(m.nfcn)\n", "\n", " valid = np.array(valid)\n", " val = np.array(val)\n", " err = np.array(err)\n", " nfcn = np.array(nfcn)\n", "\n", " fig, ax = plt.subplots(1, 2, figsize=(9, 3), sharex=True)\n", " plt.suptitle(f\"{minimizer} median(nFCN)={np.mean(nfcn):.0f}\")\n", " for v in (True, False):\n", " m = valid == v\n", " plt.sca(ax[0])\n", " plt.errorbar(power[m], val[m, 0], err[m, 0], fmt=\"o\")\n", " plt.sca(ax[1])\n", " plt.errorbar(power[m], val[m, 1] * power[m], err[m, 1] * power[m], fmt=\"o\")\n", " plt.sca(ax[0])\n", " plt.semilogx()\n", " plt.ylabel(r\"$p_0$\")\n", " plt.ylim(-0.5, 2.5)\n", " plt.sca(ax[1])\n", " plt.semilogx()\n", " plt.ylabel(r\"$p_1 \\times factor$\")\n", " plt.ylim(-3, 3)\n", " fig.supxlabel(\"factor\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Minuit.migrad` handles pathological cases quite well compared to many Scipy minimizers. Scipy minimizers which don't compute a gradient (Nelder-Mead, Powell, COBYLA) also do well on our noisy model, as can be expected. Nevertheless, the performance of `Minuit.migrad` with strategy 1 is better, it reaches the minimum faster than the other minimizers while being similarly robust.\n", "\n", "The interleaving of `Minuit.migrad` and `Minuit.simplex` calls is a mixed bag in this toy scenario. The default is to use `Minuit.simplex` however, because `Minuit.simplex` can often reach the minimum from poorly chosen starting values, a pathological case which we are not testing here." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "py311", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/notebooks/weighted_histograms.ipynb0000644000000000000000000214636314332717401020075 0ustar00{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Fitting weighted histograms\n", "\n", "If histograms are filled with weighted data, we need to construct cost functions that handle this case correctly. Particularly troublesome is when bins contain a negative sum of weights, which can occur randomly if weights are partially negative, like sweights.\n", "\n", "Bohm and Zech showed a way to fit weighted histograms, but their approach formally only works if the sum of weights is non-negative. Here, we discuss the ideas behind the cost functions that iminuit uses for weighted histograms, and how to generalize the Bohm-Zech approach to bin entries that are negative. This work is based and references the following papers:\n", "\n", "- [1] Baker & Cousins, NIM 221 (1984) 437-442\n", "- [2] Bohm and Zech, NIMA 748 (2014) 1-6\n", "- [3] H. Dembinski, M. Schmelling, R. Waldi, NIMA 940 (2019) 135-141.\n", "\n", "## Baker-Cousins transform\n", "\n", "The maximum-likelihood method is widely very successful, and its qualities shine in particular in the application to Poisson-distributed data, because maximizing the likelihood yields an unbiased estimate of models fitted to this data [3], while naive least-squares does not unless one uses a special iterative scheme.\n", "\n", "In constrast to least-squares methods, maximizing the likelihood does not yield a chi-square distributed minimum value, that can be used as a goodness-of-fit test statistic. Baker and Cousins [1] showed that the log-likelihood for Poisson distributed data can be replaced by a delta-log-likelihood, which has this property and is otherwise equivalent. One essentially adds a constant to the log-likelihood, which does not change the location of the minimum. For a single bin in a histogram, one can derive the following statistic, which is also known as the Cash statistic:\n", "\n", "$$\n", "\\ell_\\text{poisson}(n; \\mu) = 2 [n (\\ln(n) - \\ln(\\mu)) - \\mu + n]\n", "$$\n", "\n", "It can be minimized to obtain an unbiased estimate for $\\mu$, and the minimum value is asymptotically chi-square distributed and serves as a goodness-of-fit test statistic. The case $n = 0$ is handled by formally extending the integer realm to the real realm, and realizing that $x \\ln x \\to 0$ for $x\\to 0$. In other words, in case of $n = 0$, $n \\ln n$ has to be replaced by 0.\n", "\n", "Furthermore, this form is beneficial for numerical computation on a computer, because near the minimum we have $\\mu \\approx n$ and $\\ell_\\text{poisson}(n;\\mu) \\approx 0$. This means that the sum $\\sum_k \\ell_\\text{poisson}(n_k;\\mu_k)$ over $k$ bins grows slowly and adds terms of similar size, which is ideal from the point of view of accuracy in floating point arithmetic.\n", "\n", "As shown by Baker & Cousins, a similar statistic with the same nice properties can be derived from the log-likelihood for multinomially-distributed data:\n", "\n", "$$\n", "\\ell_\\text{multinomial}(n; \\mu) = 2 [n (\\ln(n) - \\ln(\\mu))]\n", "$$\n", "\n", "We further note that $\\ell_\\text{multinomial}$ and $\\ell_\\text{poisson}$ are equivalent for multinomially-distributed data. Because $\\sum_k \\mu_k = \\sum_k n_k$ is always guaranteed, if the sum goes over all $k$ bins, the terms $n_k - \\mu_k$ always sum up to zero, so they can be removed altogether.\n", "\n", "## Bohm-Zech transform\n", "\n", "Bohm and Zech proposed the scaled Poisson distribution (SPD) as an approximate way to handle sums of weights instead of Poisson counts. This approach also works for multinomially distributed data, as we will see later. The idea of the Bohm and Zech is to use the likelihood for Poisson distributed data also for weighted data. They match the first and second moment of the compound Poisson distribution for weighted data with a single Poisson distribution through a scaling factor $s$, that is multiplied with the prediction and the observation.\n", "\n", "The scaling factor is computed as $s = \\sum_i w_i / \\sum_i w_i^2$, where $w_i$ are the weights in the current bin. Instead of the Baker & Cousins transformed log-likelihood $\\ell(n; \\mu)$ for Poisson-distributed data, where $n$ is the observed count and $\\mu$ is the expectation, we now compute $\\ell(s w; s \\mu)$ with $w = \\sum_i w_i$. This can be further simplified:\n", "\n", "$$\n", "\\begin{aligned}\n", "\\ell_\\text{poisson}(s w; s \\mu) &= 2 [(s w) (\\ln(s w) - \\ln(s \\mu)) - s \\mu + s w] \\\\\n", "&= 2 s [w (ln(w) - ln(\\mu)) - \\mu + w] \\\\\n", "&= s \\, \\ell_\\text{poisson}(w; \\mu)\n", "\\end{aligned}\n", "$$\n", "\n", "Eventually, we find that the normal delta-log-likelihood gets scaled by the factor $s$. Note that we did transformations here that are only allowed for $s > 0$ and $w > 0$, otherwise the logarithms are not defined. The case $w = 0$ can be included in the same way as $n = 0$ by replacing $w \\ln w$ with 0.\n", "\n", "### Handling $s=0$\n", "\n", "Often, $w = 0$ also implies $\\sum w_i^2 = 0$. In that case $s$ becomes undefined. There is no elegant solution for this, because we need to know the true value of $s$ to perform a correct scaling, but we cannot get it empirically, as there is no data.\n", "\n", "One might consider setting $s$ to 0 or 1, but these choices lead to problems. Using $s=0$ implies that empty bins cannot pull the prediction $\\mu$ down, which would result in $\\mu$ values that are overestimated. Similarly, $s=1$ may introduce a too strong pull if the average value of $s$ for the other bins is much smaller than 1, or too little if that average is way larger than 1. We cannot simply use the average value of $s$ either, because $s$ may vary systematically from bin-to-bin. This variation may not even be predictable.\n", "\n", "In iminuit, we use the median of $s$ values from bins with entries, which will reduce the bias in at least some scenarios, but in general, practitioners should avoid empty bins in weighted histograms altogether.\n", "\n", "### Multinomially-distributed weighted data\n", "\n", "While it is irrelvant whether we use $\\ell_\\text{multinomial}$ or $\\ell_\\text{poisson}$ for ordinary multinomially-distributed data, the situation becomes different when weights are involved. If we consider weighted data and apply the Bohm-Zech transform, we find that $\\ell_\\text{multinomial}(s w; s \\mu) \\neq \\ell_\\text{poisson}(s w; s \\mu)$. This is because $\\sum_k s_k (w_k - \\mu_k) \\neq 0$ in general, even if $\\sum_k (w_k - \\mu_k) = 0$ holds. Numerical experiments confirm that $\\ell_\\text{multinomial}(s w; s \\mu)$ yields biased results, the correct cost function for weighted multinomial data is therefore $\\ell_\\text{poisson}(s w; s \\mu)$.\n", "\n", "### Extension to datasets with negative sums of weights\n", "\n", "The Bohm-Zech formula is only applicable if $w = \\sum_i w_i \\ge 0$ (with the extra condition that we\n", "discussed), but formally fails if $w < 0$. Since $\\sum_i w_i^2$ is always non-negative, $w < 0$ implies $s < 0$.\n", "\n", "Our extension of $\\ell_\\text{poisson}(s w; s \\mu)$ to this case is to use $s = |\\sum_i w_i| / \\sum_i w_i^2$ and replace $w \\ln (w)$ with 0 for $w \\le 0$.\n", "\n", "This solution works, because it has the same gradient as a sum of squared studentized residuals $\\sum_k s_k (w_k - \\mu_k)^2/\\mu'_k$, where $\\mu'_k$ approaches $\\mu_k$ in successive iterations, but is fixed during the gradient computation [3]. We know from the Gauss-Markov-Aitken theorem that the minimum of this quadratic function yields an unbiased estimate of $\\mu_k$, if there are no additional constraints on $\\mu_k$. Here, we have the constraint $\\mu_k > 0$, so this won't be perfectly unbiased for very small $\\mu_k$, but otherwise. Since the quadratic function and the original function have the same gradient, the minima of both functions are the same, and the original function also yields an unbiased or a low-bias estimate for very small $\\mu_k$.\n", "\n", "We mention the sum of squared studentized residuals, because it provides better intuitive insight. For example, it is clear that $s$ should be positive, since it acts as a modifier of the variance, effectively replacing $\\mu'$ with $\\mu'/s$. A negative $s$ cannot fulfill this purpose. Also, a negative $s_k$ would allow us to reduce the sum by making the disagreement between $w_k$ and $\\mu_k$ larger, which is contradictory.\n", "\n", "The gradient is not affected by the particular choice of replacing $w \\ln(w)$ with 0 for $w < 0$, any other constant would also do, since this term drops out in the computation of the gradient. Our choice is motivated by the goal to keep the function minimum approximately chi-square distributed, although that property generally dissolves when negative weights are involved. The delta-log-likelihood compares the expectation from the model with the expectation from the so-called saturated model, but the definition of the latter breaks down for $w < 0$. Our ad hoc choices cannot fix that. The function minimum value can even become negative.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's visualize variations of $\\ell_\\text{poisson}$ for a signle bin and a couple of $w$ values, with $w^2 = 1$.\n", "\n", "* `l1`: This is the chosen extension of $\\ell_\\text{poisson}$ as discussed above, with $s = |\\sum_i w_i| / \\sum_i w_i^2$, and $w \\ln w$ replaced by 0 for $w < 0$.\n", "* `l2`: Like `l1`, but we replace $w \\ln w$ with $w \\ln|w|$.\n", "* `l3`: Like `l2`, but we use $s = \\sum_i w_i / \\sum_i w_i^2$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:48:56.446730\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "def log_or_zero(x):\n", " x = np.atleast_1d(x).copy()\n", " ma = x > 0\n", " x[ma] = np.log(x[ma])\n", " x[~ma] = 0\n", " return x\n", "\n", "\n", "def l1(w, w2, mu):\n", " s = np.abs(w) / w2\n", " return 2 * s * (w * (log_or_zero(w) - log_or_zero(mu)) + mu - w)\n", "\n", "\n", "def l2(w, w2, mu):\n", " s = np.abs(w) / w2\n", " return 2 * s * (w * log_or_zero(np.abs(w)) - w * log_or_zero(mu) + mu - w)\n", "\n", "\n", "def l3(w, w2, mu):\n", " s = w / w2\n", " return 2 * s * (w * (log_or_zero(np.abs(w)) - log_or_zero(mu)) + mu - w)\n", "\n", "\n", "w2 = 1\n", "fig, ax = plt.subplots(1, 3, figsize=(9, 3))\n", "for i, (axi, w) in enumerate(zip(ax, (-10, -5, 5))):\n", " mu = np.geomspace(1e-3, 10, 100)\n", " color = f\"C{i}\"\n", " plt.sca(axi)\n", " plt.plot(mu, l1(w, w2, mu), color=color, label=f\"l1 w={w}\")\n", " plt.plot(mu, l2(w, w2, mu), color=color, ls=\":\", label=f\"l2 w={w}\")\n", " plt.plot(mu, l3(w, w2, mu), color=color, ls=\"--\", label=f\"l3 w={w}\")\n", " plt.ylim(-1000, 1000)\n", " plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All cost functions only differ for $w < 0$. `l3` is contradictory, since it prefers an infinite value of $\\mu$ for $w < 0$. Both `l1` and `l2` prefer $\\mu = 0$, which is correct. The vertical offset between `l1` and `l2` grows as $w$ becomes more negative. For both `l1` and `l2`, the function value at the minimum can become arbitrarily negative, something that never happens for $w > 0$ and should not happen for a chi-square-distributed variable. For $w < 0$, we cannot ensure this property, and hence function minimum value is no longer chi-square distributed. It can still qualitatively used as a GoF test statistic, as we will see below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Toy experiments\n", "\n", "We illustrate these ideas with toy experiments. We generate data from an exponential distribution whose samples are weighted with a normal distribution. To make the toy more interesting, the width of the normal distribution is a function of the value realised by the exponential distribution. We then form weighted histograms from these data. The average weight per bin is constant, but the variance of the weights increases." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:48:57.444014\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from iminuit.cost import BinnedNLL, ExtendedBinnedNLL\n", "from iminuit import Minuit\n", "from scipy.stats import expon, norm, chi2\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import boost_histogram as bh\n", "from joblib import Parallel, delayed\n", "\n", "rng = np.random.default_rng(1)\n", "\n", "npoints = 100000\n", "bins = 20\n", "\n", "x = expon.rvs(size=npoints, random_state=rng)\n", "w = norm.rvs(0.1, x, size=len(x), random_state=rng)\n", "\n", "h = bh.Histogram(\n", " bh.axis.Regular(bins, np.min(x), np.max(x)), storage=bh.storage.Weight()\n", ")\n", "h.fill(x, weight=w)\n", "\n", "plt.stairs(h.values(), h.axes[0].edges)\n", "ma = h.values() > 0\n", "plt.errorbar(\n", " h.axes[0].centers[ma], h.values()[ma], h.variances()[ma] ** 0.5, fmt=\"o\", color=\"C0\"\n", ")\n", "plt.errorbar(\n", " h.axes[0].centers[~ma],\n", " h.values()[~ma],\n", " h.variances()[~ma] ** 0.5,\n", " fmt=\"s\",\n", " color=\"C3\",\n", ")\n", "plt.axhline(0, ls=\":\", color=\"0.5\", zorder=0)\n", "xm = np.linspace(0, h.axes[0].edges[-1])\n", "plt.plot(xm, expon.pdf(xm) * npoints * np.mean(w) * h.axes[0].widths[0]);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The line shows the true density, and the data points show the outcome of the sample. Error bars indicate the statistical uncertainty. Bins with negative sums of weights use square markers." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We fit this histogram with iminuit's builtin cost functions, which use the ideas discussed above, to obtain an estimate of the slope $\\lambda$ of the exponential." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xe = h.axes[0].edges\n", "n = h.values()\n", "vn = h.variances()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 22.93 (χ²/ndof = 1.3) Nfcn = 40
EDM = 4.77e-05 (Goal: 0.0002) time = 0.3 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 n 10.9e3 0.4e3 0
1 lambd 1.16 0.06 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
n lambd
n 2.01e+05 26.722 (0.927)
lambd 26.722 (0.927) 0.00413
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:48:57.888433\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 22.93 (χ²/ndof = 1.3) │ Nfcn = 40 │\n", "│ EDM = 4.77e-05 (Goal: 0.0002) │ time = 0.3 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ n │ 10.9e3 │ 0.4e3 │ │ │ 0 │ │ │\n", "│ 1 │ lambd │ 1.16 │ 0.06 │ │ │ 0 │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬───────────────────â”\n", "│ │ n lambd │\n", "├───────┼───────────────────┤\n", "│ n │ 2.01e+05 26.722 │\n", "│ lambd │ 26.722 0.00413 │\n", "└───────┴───────────────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def model1(x, n, lambd):\n", " return n * expon(0, lambd).cdf(x)\n", "\n", "\n", "c1 = ExtendedBinnedNLL(np.transpose((n, vn)), xe, model1)\n", "m = Minuit(c1, sum(n), 1)\n", "m.limits = (0, None)\n", "m.migrad()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Migrad
FCN = 32.6 (χ²/ndof = 1.7) Nfcn = 13
EDM = 1.18e-06 (Goal: 0.0002) time = 0.1 sec
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 lambd 0.996 0.021 0
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lambd
lambd 0.000457
\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:48:58.258224\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "┌─────────────────────────────────────────────────────────────────────────â”\n", "│ Migrad │\n", "├──────────────────────────────────┬──────────────────────────────────────┤\n", "│ FCN = 32.6 (χ²/ndof = 1.7) │ Nfcn = 13 │\n", "│ EDM = 1.18e-06 (Goal: 0.0002) │ time = 0.1 sec │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Valid Minimum │ Below EDM threshold (goal x 10) │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ No parameters at limit │ Below call limit │\n", "├──────────────────────────────────┼──────────────────────────────────────┤\n", "│ Hesse ok │ Covariance accurate │\n", "└──────────────────────────────────┴──────────────────────────────────────┘\n", "┌───┬───────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────â”\n", "│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │\n", "├───┼───────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤\n", "│ 0 │ lambd │ 0.996 │ 0.021 │ │ │ 0 │ │ │\n", "└───┴───────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘\n", "┌───────┬──────────â”\n", "│ │ lambd │\n", "├───────┼──────────┤\n", "│ lambd │ 0.000457 │\n", "└───────┴──────────┘" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def model2(x, lambd):\n", " return expon(0, lambd).cdf(x)\n", "\n", "\n", "c2 = BinnedNLL(np.transpose((n, vn)), xe, model2)\n", "m = Minuit(c2, 1)\n", "m.limits = (0, None)\n", "m.migrad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The true value is $\\lambda=1$. The estimates obtained with `ExtendedBinnedNLL` and `BinnedNLL` differ, and we note that the uncertainty of $\\lambda$ is smaller for `BinnedNLL`. That is a consequence of fitting weighted data. For ordinary data the estimates are equal.\n", "\n", "To see whether these estimates are biased, we repeat the toy experiment many times with independent data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def run(seed):\n", " rng = np.random.default_rng(seed)\n", " # we also randomize the sample size\n", " x = expon.rvs(size=rng.poisson(npoints), random_state=rng)\n", " w = norm.rvs(0.1, x, size=len(x), random_state=rng)\n", "\n", " h = bh.Histogram(\n", " bh.axis.Regular(bins, np.min(x), np.max(x)), storage=bh.storage.Weight()\n", " )\n", " h.fill(x, weight=w)\n", " xe = h.axes[0].edges\n", " n = h.values()\n", " vn = h.variances()\n", " data = np.transpose((n, vn))\n", " ntot = np.sum(n)\n", "\n", " m1 = Minuit(ExtendedBinnedNLL(data, xe, model1), ntot, 0.6)\n", " m1.limits[0] = (0, None)\n", " m1.limits[1] = (0, None)\n", " m1.migrad()\n", "\n", " m2 = Minuit(BinnedNLL(data, xe, model2), 0.6)\n", " m2.limits = (0, None)\n", " m2.migrad()\n", "\n", " return (\n", " ntot,\n", " m1.valid,\n", " m1.values[0],\n", " m1.values[1],\n", " m1.fval,\n", " m2.valid,\n", " m2.values[0],\n", " m2.fval,\n", " )\n", "\n", "\n", "result = Parallel(n_jobs=8)(delayed(run)(seed) for seed in range(1000))\n", "ntot, valid1, ntot1, lambd1, minval1, valid2, lambd2, minval2 = np.transpose(result)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:23.618867\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:23.736537\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.title(\"$\\\\lambda$ estimate\")\n", "plt.hist(\n", " lambd1,\n", " bins=20,\n", " alpha=0.5,\n", " label=f\"ExtendedBinnedNLL\\nvalid={np.mean(valid1)*100:.0f}%\\nmean = {np.mean(lambd1):.2f}\\nstd.dev. = {np.std(lambd1):.2f}\",\n", ")\n", "plt.hist(\n", " lambd2,\n", " bins=20,\n", " alpha=0.5,\n", " label=f\"BinnedNLL\\nvalid={np.mean(valid2)*100:.0f}%\\nmean = {np.mean(lambd2):.2f}\\nstd.dev. = {np.std(lambd2):.2f}\",\n", ")\n", "plt.legend()\n", "\n", "plt.figure()\n", "plt.hist(ntot1 / ntot - 1)\n", "plt.title(\n", " f\"ExtendedBinnedNLL: $n_\\\\mathrm{{tot}}$ estimate\\n(mean-truth)/truth = {np.mean(ntot1) / np.mean(ntot) - 1:.3f}\"\n", ")\n", "plt.xlabel(\"(estimate - truth) / truth\")\n", "plt.xlim(-0.2, 0.2);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As expected, we find that the estimates of $\\lambda$ have low bias, although they are not perfectly unbiased.\n", "\n", "The variance of $\\lambda$ is smaller for `BinnedNLL`. If you are not interested in the amplitude of the distribution, it is therefore better to use `BinnedNLL` for weighted histograms. Note that `BinnedNLL` and `ExtendedBinnedNLL` internally use the same cost function for weighted data, so the difference in precision originates from the additional information used in `BinnedNLL`, that the sample is complete, there are no further events in other bins.\n", "\n", "The second plot shows the estimate of the total sum of weights with `ExtendedBinnedNLL`, which is distributed around the true value. We observe a small upward bias of 2%.\n", "\n", "We claim above that estimates for our chosen cost function are unbiased, while these results show small bias. There are two reasons for that. i) The cost Bohm-Zech approach does not guarantee unbiasedness anymore, since we must estimate $s$ from the information in the bin, and the empirical estimate for $s$ that we use is not an unbiased estimate of the true value, because it is a non-linear function of the weights. ii) The unbiasedness was claimed for the bin expectations and linear functions thereof. The model parameter $\\lambda$ is not a linear function of the bin expectations, therefore it is also not guaranteed to be unbiased. We will come back to this point below.\n", "\n", "We further said that the minimum value is no longer chi-square distributed when bins with negative sums of weights are fitted, so let's look at the actual distribution of the minimum value of the cost function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:24.062732\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(10, 4))\n", "\n", "plt.sca(ax[0])\n", "plt.hist(minval1, bins=50, density=True)\n", "x = np.linspace(0, 100)\n", "plt.plot(x, chi2(bins - 2).pdf(x))\n", "plt.title(\n", " f\"ExtendedBinnedNLL minimum value\\nndf = {bins-2} mean = {np.mean(minval1):.2f} median = {np.median(minval1):.2f}\"\n", ")\n", "\n", "plt.sca(ax[1])\n", "plt.hist(minval2, bins=50, density=True)\n", "x = np.linspace(0, 100)\n", "plt.plot(x, chi2(bins - 2).pdf(x))\n", "plt.title(\n", " f\"BinnedNLL minimum value\\nndf = {bins-2} mean = {np.mean(minval2):.2f} median = {np.median(minval2):.2f}\"\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We find that these distributions are broader than the asymptotical chi-square distribution and contain negative values, as expected. One can qualitatively still use very large values compared ot the expected mean as evidence for a bad fit, however, since bins with $w < 0$ only reduce the function minimum value." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For reference, it is interesting to run the toy experiment again with a very narrow weight distribution. We expect that the bias largely disappears, as our original toy experiment with its broad weight distribution was designed to be challenging. For this run, we draw the weights from a narrow normal distribution with constant width of 0.01." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def run(seed):\n", " rng = np.random.default_rng(seed)\n", " # we also randomize the sample size\n", " x = expon.rvs(size=rng.poisson(npoints), random_state=rng)\n", " w = rng.normal(0.1, 0.01, size=len(x))\n", "\n", " h = bh.Histogram(\n", " bh.axis.Regular(bins, np.min(x), np.max(x)), storage=bh.storage.Weight()\n", " )\n", " h.fill(x, weight=w)\n", " xe = h.axes[0].edges\n", " n = h.values()\n", " vn = h.variances()\n", " data = np.transpose((n, vn))\n", " ntot = np.sum(n)\n", "\n", " m1 = Minuit(ExtendedBinnedNLL(data, xe, model1), ntot, 0.6)\n", " m1.limits[0] = (0, None)\n", " m1.limits[1] = (0, None)\n", " m1.migrad()\n", "\n", " m2 = Minuit(BinnedNLL(data, xe, model2), 0.6)\n", " m2.limits = (0, None)\n", " m2.migrad()\n", "\n", " return (\n", " ntot,\n", " m1.valid,\n", " m1.values[0],\n", " m1.values[1],\n", " m1.fval,\n", " m2.valid,\n", " m2.values[0],\n", " m2.fval,\n", " )\n", "\n", "\n", "result = Parallel(n_jobs=8)(delayed(run)(seed) for seed in range(1000))\n", "ntot, valid1, ntot1, lambd1, minval1, valid2, lambd2, minval2 = np.transpose(result)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:37.371002\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:37.484466\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.title(\"$\\\\lambda$ estimate\")\n", "plt.hist(\n", " lambd1,\n", " bins=20,\n", " alpha=0.5,\n", " label=f\"ExtendedBinnedNLL\\nvalid={np.mean(valid1)*100:.0f}%\\nmean = {np.mean(lambd1):.2f}\\nstd.dev. = {np.std(lambd1):.3f}\",\n", ")\n", "plt.hist(\n", " lambd2,\n", " bins=20,\n", " alpha=0.5,\n", " label=f\"BinnedNLL\\nvalid={np.mean(valid2)*100:.0f}%\\nmean = {np.mean(lambd2):.2f}\\nstd.dev. = {np.std(lambd2):.3f}\",\n", ")\n", "plt.legend()\n", "\n", "plt.figure()\n", "plt.hist(ntot1 / ntot - 1, bins=20)\n", "plt.title(\n", " f\"ExtendedBinnedNLL: $n_\\\\mathrm{{tot}}$ estimate\\n(mean-truth)/truth = {np.mean(ntot1) / np.mean(ntot) - 1:.3f}\"\n", ")\n", "plt.xlabel(\"(estimate - truth) / truth\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now find negligible bias for $\\lambda$ and $n_\\text{tot}$. The precision is also greatly improved, since the weight distribution is so narrow that it can effectively be neglected as a source of additional uncertainty to the underlying Poisson process.\n", "\n", "The estimates from `ExtendedBinnedNLL` and `BinnedNLL` for $\\lambda$ become equal in this case (and their precision), because the ordinary likelihood for unweighted samples factorizes into a part for $n_\\text{tot}$ and another for $\\lambda$. This means that the estimates for $n_\\text{tot}$ and $\\lambda$ are independent. This factorization is broken for weighted histograms in general, and only restored here, because the weight variance is negligible.\n", "\n", "Finally, we have another look at the function minimum values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2024-08-22T11:49:37.930557\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.9.2, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 2, figsize=(10, 4))\n", "\n", "plt.sca(ax[0])\n", "plt.hist(minval1, bins=50, density=True)\n", "x = np.linspace(0, 100)\n", "plt.plot(x, chi2(bins - 2).pdf(x))\n", "plt.title(\n", " f\"ExtendedBinnedNLL minimum value\\nndf = {bins-2} mean = {np.mean(minval1):.2f} median = {np.median(minval1):.2f}\"\n", ")\n", "\n", "plt.sca(ax[1])\n", "plt.hist(minval2, bins=50, density=True)\n", "x = np.linspace(0, 100)\n", "plt.plot(x, chi2(bins - 2).pdf(x))\n", "plt.title(\n", " f\"BinnedNLL minimum value\\nndf = {bins-2} mean = {np.mean(minval2):.2f} median = {np.median(minval2):.2f}\"\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The minimum values now follow the theoretical chi-square distribution very well, since bins with a negative sum of weights do not occur anymore." ] } ], "metadata": { "keep_output": true, "kernelspec": { "display_name": "venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 } iminuit-2.30.1/doc/plots/bench.py0000644000000000000000000001334414332717401013547 0ustar00import numpy as np from numpy.random import default_rng from matplotlib import pyplot as plt import matplotlib as mpl from matplotlib.ticker import LogLocator import os import pickle mpl.rcParams.update(mpl.rcParamsDefault) class TrackingFcn: errordef = 1 def __init__(self, rng, npar): self.ncall = 0 self.y = 5 * rng.standard_normal(npar) def __call__(self, par, *args): self.ncall += 1 # make problem non-linear z = self.y - par return np.sum(z**2 + 0.1 * z**4) class Runner: def __init__(self, npars): self.npars = npars def __call__(self, seed): from iminuit import Minuit import nlopt from scipy.optimize import minimize data = [] rng = default_rng(seed) for npar in self.npars: fcn = TrackingFcn(rng, npar) for stra in (0, 1, 2): key = f"Minuit2/strategy={stra}" print(key, npar) fcn.ncall = 0 m = Minuit(fcn, np.zeros(npar)) m.strategy = stra m.migrad() max_dev = np.max(np.abs(m.np_values() - fcn.y)) data.append((key, npar, fcn.ncall, max_dev)) for algo in ("BOBYQA", "NEWUOA", "PRAXIS", "SBPLX"): if npar == 1 and algo == "PRAXIS": continue # PRAXIS does not work for npar==1 print(algo, npar) fcn.ncall = 0 opt = nlopt.opt(getattr(nlopt, "LN_" + algo), npar) opt.set_min_objective(lambda par, grad: fcn(par)) opt.set_xtol_abs(1e-2) try: xopt = opt.optimize(np.zeros(npar)) max_dev = np.max(np.abs(xopt - fcn.y)) key = f"nlopt/{algo}" data.append((key, npar, fcn.ncall, max_dev)) except Exception: pass for algo in ("BFGS", "CG", "Powell", "Nelder-Mead"): print(algo, npar) fcn.ncall = 0 result = minimize(fcn, np.zeros(npar), method=algo, jac=False) max_dev = np.max(np.abs(result.x - fcn.y)) key = f"scipy/{algo}" data.append((key, npar, fcn.ncall, max_dev)) return data if os.path.exists("bench.pkl"): with open("bench.pkl", "rb") as f: results = pickle.load(f) else: npars = (1, 2, 3, 4, 6, 10, 20, 30, 40, 60, 100) from numpy.random import SeedSequence from concurrent.futures import ProcessPoolExecutor as Pool sg = SeedSequence(1) with Pool() as p: results = tuple(p.map(Runner(npars), sg.spawn(16))) with open("bench.pkl", "wb") as f: pickle.dump(results, f) # plt.figure() # f = TrackingFcn(default_rng(), 2) # x = np.linspace(-10, 10) # X, Y = np.meshgrid(x, x) # F = np.empty_like(X) # for i, xi in enumerate(x): # for j, yi in enumerate(x): # F[i, j] = f((xi, yi)) # plt.pcolormesh(X, Y, F.T) # plt.colorbar() methods = {} for data in results: for key, npar, ncal, maxdev in data: methods.setdefault(key, {}).setdefault(npar, []).append((ncal, maxdev)) fig, ax = plt.subplots(1, 2, figsize=(10, 5), sharex=True) plt.subplots_adjust( top=0.96, bottom=0.14, left=0.075, right=0.81, hspace=0.2, wspace=0.25 ) handles = [] labels = [] markers = ( ("o", 10), ("s", 7), ("D", 7), ("<", 7), (">", 7), ("^", 7), ("v", 7), ("*", 9), ("X", 7), ("P", 7), ("p", 8), ) for method, (m, ms) in zip(sorted(methods), markers): ls = "-" lw = 1 zorder = None color = None mfc = None mew = 1 if "Minuit" in method: ls = "-" lw = 2 zorder = 10 color = "k" mfc = "w" mew = 2 data = methods[method] npars = np.sort(list(data)) ncalls = np.empty_like(npars) max_devs = np.empty_like(npars, dtype=float) for i, npar in enumerate(npars): nc, md = np.transpose(data[npar]) ncalls[i] = np.median(nc) max_devs[i] = np.median(md) plt.sca(ax[0]) (p,) = plt.plot( npars, ncalls / npars, ls=ls, lw=lw, marker=m, ms=ms, zorder=zorder, color=color, mfc=mfc, mew=mew, ) handles.append(p) labels.append(method) plt.xlabel("$N_\\mathrm{par}$") plt.ylabel("$N_\\mathrm{call}$ / $N_\\mathrm{par}$") plt.loglog() plt.ylim(8, 5e2) plt.xlim(0.7, 150) plt.sca(ax[1]) plt.xlabel("$N_\\mathrm{par}$") plt.ylabel("maximum deviation") plt.plot( npars, max_devs, lw=lw, ls=ls, marker=m, ms=ms, zorder=zorder, color=color, mfc=mfc, mew=mew, ) plt.loglog() plt.gca().yaxis.set_major_locator(LogLocator(numticks=100)) plt.figlegend(handles, labels, loc="center right", fontsize="small") plt.savefig("bench.svg") plt.figure(constrained_layout=True) plt.loglog() for method, (m, ms) in zip(sorted(methods), markers): zorder = None color = None mfc = None mew = 1 if "Minuit" in method: zorder = 10 color = "k" mfc = "w" mew = 2 data = methods[method] x = [] y = [] s = [] for npar in (2, 10, 100): if npar not in data: continue nc, md = np.transpose(data[npar]) x.append(np.median(nc) / npar) y.append(np.median(md)) s.append(50 * npar**0.5) plt.scatter(x, y, s, marker=m, color=mfc, edgecolor=color, zorder=zorder) plt.xlabel("$N_\\mathrm{call}$ / $N_\\mathrm{par}$") plt.ylabel("maximum deviation") plt.title("small: npar = 2, medium: npar = 10, large: npar = 100") plt.savefig("bench2d.svg") plt.show() iminuit-2.30.1/doc/plots/interactive.py0000644000000000000000000000102514332717401014776 0ustar00from iminuit import Minuit, cost import numpy as np from matplotlib import pyplot as plt # custom visualization; x, y, model are taken from outer scope def viz(args): plt.plot(x, y, "ok") xm = np.linspace(x[0], x[-1], 100) plt.plot(xm, model(xm, *args)) def model(x, a, b): return a + b * x x = np.array([1, 2, 3, 4, 5]) y = np.array([1.03, 1.58, 2.03, 2.37, 3.09]) c = cost.LeastSquares(x, y, 0.1, model) m = Minuit(c, 0.5, 0.5) m.interactive(viz) # m.interactive() also works and calls LeastSquares.visualize iminuit-2.30.1/doc/plots/loss.py0000644000000000000000000000051714332717401013446 0ustar00from matplotlib import pyplot as plt import numpy as np def soft_l1(z): return 2 * ((1 + z) ** 0.5 - 1) x = np.linspace(-3, 3) z = x**2 plt.plot(x, z, label="linear $\\rho(z) = z$") plt.plot(x, soft_l1(z), label="soft L1-norm $\\rho(z) = 2(\\sqrt{1+z} - 1)$") plt.xlabel("studentized residual") plt.ylabel("cost") plt.legend() iminuit-2.30.1/doc/plots/mncontour.py0000644000000000000000000000032414332717401014506 0ustar00from iminuit import Minuit def cost(x, y, z): return (x - 1) ** 2 + (y - x) ** 2 + (z - 2) ** 2 cost.errordef = Minuit.LEAST_SQUARES m = Minuit(cost, x=0, y=0, z=0) m.migrad() m.draw_mncontour("x", "y") iminuit-2.30.1/doc/plots/mnmatrix.py0000644000000000000000000000042014332717401014316 0ustar00from iminuit import Minuit def cost(a, b, c): return ( a**2 + 0.25 * a**4 + a * b + ((b - 1) / 0.6) ** 2 - 2.5 * b * c + ((c - 2) / 0.5) ** 2 ) m = Minuit(cost, 1, 1, 1) m.migrad() m.draw_mnmatrix(cl=[1, 2, 3]) iminuit-2.30.1/doc/plots/mnprofile.py0000644000000000000000000000031714332717401014457 0ustar00from iminuit import Minuit def cost(x, y, z): return (x - 1) ** 2 + (y - x) ** 2 + (z - 2) ** 2 cost.errordef = Minuit.LEAST_SQUARES m = Minuit(cost, x=0, y=0, z=0) m.migrad() m.draw_mnprofile("y") iminuit-2.30.1/doc/reference.rst0000644000000000000000000000170614332717401013444 0ustar00.. include:: bibliography.txt .. _api: Reference ========= .. currentmodule:: iminuit Quick Summary ------------- These methods and properties you will probably use a lot: .. autosummary:: Minuit Minuit.migrad Minuit.hesse Minuit.minos Minuit.values Minuit.errors Minuit.merrors Minuit.fixed Minuit.limits Minuit.covariance Minuit.valid Minuit.accurate Minuit.fval Minuit.nfit Minuit.mnprofile Minuit.mncontour Minuit.visualize Minuit.draw_mnmatrix Main interface -------------- .. autoclass:: Minuit :members: :undoc-members: Scipy-like interface -------------------- .. autofunction:: minimize Cost functions -------------- .. automodule:: iminuit.cost :members: :inherited-members: Utilities --------- .. automodule:: iminuit.util :exclude-members: Matrix :inherited-members: .. autoclass:: iminuit.util.Matrix :members: :no-inherited-members: iminuit-2.30.1/doc/release.md0000644000000000000000000000160614332717401012715 0ustar00# How to make a release - Sync local `main` and `develop` with Github - `for x in main develop; git checkout $x; git pull` - On `develop` branch - Update version in `pyproject.toml` - For a beta release, add `.betaN`, where N is a number >= 0 - For a release candidate, add `.rcN` - Run `python3 doc/update_changelog.py` or update `doc/changelog.rst` manually - Check the output if you used the script - If necessary, update ROOT version in `doc/conf.py`, see instructions there - Merge `develop` into `main` - Every push to `main` triggers building wheels, uploading to PyPI, and tagging/publishing on GitHub - If there are problems with the wheels, commit fixes to `develop`, then merge again into `main` - Note: Upload to PyPI uses API tokens configured in PyPI and Github "Secrets" - conda-forge should pick up our release automatically and generate conda packages iminuit-2.30.1/doc/root_version.py0000644000000000000000000000131414332717401014051 0ustar00import subprocess as subp from pathlib import PurePath project_dir = PurePath(__file__).parent.parent # check that root version is up-to-date git_submodule = subp.check_output( ["git", "submodule", "status"], cwd=project_dir ).decode() for item in git_submodule.strip().split("\n"): parts = item.split() if PurePath(parts[1]) != PurePath("extern") / "root": continue assert len(parts) == 3, "module is not checked out" break # git submodule status does not yield the right state # we must use git describe --tags root_version = ( subp.check_output( ["git", "describe", "--tags"], cwd=project_dir / "extern" / "root" ) .decode() .strip() ) print(root_version) iminuit-2.30.1/doc/studies.rst0000644000000000000000000000077114332717401013167 0ustar00.. include:: bibliography.txt .. _studies: Studies ======= The following studies explore different aspects of the library, including its performance. This content is intended for an advanced audience. .. toctree:: :maxdepth: 1 notebooks/binned_vs_unbinned notebooks/weighted_histograms notebooks/hesse_and_minos notebooks/numba notebooks/automatic_differentiation notebooks/cost_function_benchmarks notebooks/gof notebooks/template_gof notebooks/memory_layout iminuit-2.30.1/doc/tutorials.rst0000644000000000000000000000252714332717401013536 0ustar00.. include:: bibliography.txt .. _tutorials: Tutorials ========= The following tutorials show how to use iminuit and explore different aspects of the library. The order is the recommended reading order, the later entries are about more and more specialized applications. Important for most users are only the first two entries. .. toctree:: :maxdepth: 1 notebooks/basic notebooks/cost_functions notebooks/unstable_fit notebooks/correlated_data notebooks/error_bands notebooks/interactive notebooks/simultaneous_fits notebooks/template_fits notebooks/template_model_mix notebooks/conditional_variable notebooks/scipy_and_constraints notebooks/roofit notebooks/external_minimizer notebooks/generic_least_squares notebooks/cython RooFit tutorials ---------------- The following tutorials correspond to a `RooFit`_ tutorial, which performs the same task but uses only iminuit and other libraries from the standard Python scientific stack and Scikit-HEP. It can be used as a learning resource or to decide which toolset to use. The list is incomplete. If you would like to see more tutorials, please leave an issue on Github with your request or feel free to make a PR to provide it yourself. .. toctree:: :maxdepth: 1 notebooks/roofit/rf101_basics notebooks/roofit/rf109_chi2residpull iminuit-2.30.1/doc/update_changelog.py0000644000000000000000000000365514332717401014624 0ustar00from pathlib import Path import re import subprocess as subp import datetime import warnings import sys from iminuit._parse_version import parse_version cwd = Path(__file__).parent new_version_string = ( subp.check_output([sys.executable, cwd.parent / "version.py"]).strip().decode() ) new_version = parse_version(new_version_string) with warnings.catch_warnings(): warnings.simplefilter("ignore") latest_tag = next( iter( sorted( ( parse_version(x.lstrip("v")) for x in subp.check_output(["git", "tag"]) .decode() .strip() .split("\n") ), reverse=True, ) ) ) with open(cwd / "changelog.rst") as f: content = f.read() # find latest entry m = re.search(r"([0-9]+\.[0-9]+\.[0-9]+) \([^\)]+\)\n-*", content, re.MULTILINE) assert m is not None previous_version_string = m.group(1) previous_version = parse_version(previous_version_string) position = m.span(0)[0] # sanity checks assert new_version > previous_version, f"{new_version} > {previous_version}" git_log = re.findall( r"[a-z0-9]+ ([^\n]+ \(#[0-9]+\))", subp.check_output( ["git", "log", "--oneline", f"v{previous_version_string}..HEAD"] ).decode(), ) today = datetime.date.today() header = f"{new_version_string} ({today.strftime('%B %d, %Y')})" new_content = f"{header}\n{'-' * len(header)}\n" if git_log: for x in git_log: if x.startswith("[pre-commit.ci]"): continue x = re.sub( "#([0-9]+)", r"`#\1 `_", x ) new_content += f"- {x.capitalize()}\n" else: new_content += "- Minor improvements\n" new_content += "\n" print(new_content, end="") with open(cwd / "changelog.rst", "w") as f: f.write(f"{content[:position]}{new_content}{content[position:]}") iminuit-2.30.1/extern/root/math/minuit2/inc/LinkDef.h0000644000000000000000000000437414332717401017261 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 10/2005 /********************************************************************** * * * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #ifdef __CLING__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; //#pragma link C++ namespace ROOT::Minuit2; #pragma link C++ class ROOT::Minuit2::GenericFunction; #pragma link C++ class ROOT::Minuit2::FCNBase; #pragma link C++ class ROOT::Minuit2::FCNGradientBase; #pragma link C++ class ROOT::Minuit2::FumiliFCNBase; #pragma link C++ class ROOT::Minuit2::Minuit2Minimizer; #pragma link C++ class ROOT::Minuit2::FunctionMinimum; #pragma link C++ class ROOT::Minuit2::MinuitParameter; #pragma link C++ class ROOT::Minuit2::MinosError; #pragma link C++ class ROOT::Minuit2::MnApplication; #pragma link C++ class ROOT::Minuit2::MnMigrad; #pragma link C++ class ROOT::Minuit2::MnMinos; #pragma link C++ class ROOT::Minuit2::MnHesse; #pragma link C++ class ROOT::Minuit2::MnMinimize; #pragma link C++ class ROOT::Minuit2::MnFumiliMinimize; #pragma link C++ class ROOT::Minuit2::MnScan; #pragma link C++ class ROOT::Minuit2::MnContours; #pragma link C++ class ROOT::Minuit2::MnSimplex; #pragma link C++ class ROOT::Minuit2::MnPlot; #pragma link C++ class ROOT::Minuit2::MnUserParameterState; #pragma link C++ class ROOT::Minuit2::MnUserParameters; #pragma link C++ class ROOT::Minuit2::MnStrategy; #pragma link C++ class ROOT::Minuit2::FunctionMinimizer; #pragma link C++ class ROOT::Minuit2::ModularFunctionMinimizer; #pragma link C++ class ROOT::Minuit2::VariableMetricMinimizer; #pragma link C++ class ROOT::Minuit2::SimplexMinimizer; #pragma link C++ class ROOT::Minuit2::CombinedMinimizer; #pragma link C++ class ROOT::Minuit2::ScanMinimizer; #pragma link C++ class ROOT::Minuit2::FumiliMinimizer; #pragma link C++ class ROOT::Minuit2::MnMachinePrecision; #pragma link C++ class ROOT::Minuit2::MnTraceObject; #pragma link C++ class std::vector; #pragma link C++ class TMinuit2TraceObject; #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ABObj.h0000644000000000000000000000763514332717401020214 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ABObj #define ROOT_Minuit2_ABObj #include "Minuit2/ABTypes.h" namespace ROOT { namespace Minuit2 { template class ABObj { public: typedef mtype Type; private: ABObj() : fObject(M()), fFactor(T(0.)) {} ABObj &operator=(const ABObj &) { return *this; } template ABObj(const ABObj &) : fObject(M()), fFactor(T(0.)) { } template ABObj &operator=(const ABObj &) { return *this; } public: ABObj(const M &obj) : fObject(obj), fFactor(T(1.)) {} ABObj(const M &obj, T factor) : fObject(obj), fFactor(factor) {} ~ABObj() {} ABObj(const ABObj &obj) : fObject(obj.fObject), fFactor(obj.fFactor) {} template ABObj(const ABObj &obj) : fObject(M(obj.Obj())), fFactor(T(obj.f())) { } const M &Obj() const { return fObject; } T f() const { return fFactor; } private: M fObject; T fFactor; }; class LAVector; template <> class ABObj { public: typedef vec Type; private: ABObj &operator=(const ABObj &) = delete; public: ABObj(const LAVector &obj) : fObject(obj), fFactor(double(1.)) {} ABObj(const LAVector &obj, double factor) : fObject(obj), fFactor(factor) {} ~ABObj() {} // remove copy constructor to Fix a problem in AIX // should be able to use the compiler generated one // ABObj(const ABObj& obj) : // fObject(obj.fObject), fFactor(obj.fFactor) {} template ABObj(const ABObj &obj) : fObject(obj.fObject), fFactor(double(obj.fFactor)) { } const LAVector &Obj() const { return fObject; } double f() const { return fFactor; } private: const LAVector &fObject; double fFactor; }; class LASymMatrix; template <> class ABObj { public: typedef sym Type; private: ABObj &operator=(const ABObj &) { return *this; } public: ABObj(const LASymMatrix &obj) : fObject(obj), fFactor(double(1.)) {} ABObj(const LASymMatrix &obj, double factor) : fObject(obj), fFactor(factor) {} ~ABObj() {} ABObj(const ABObj &obj) : fObject(obj.fObject), fFactor(obj.fFactor) {} template ABObj(const ABObj &obj) : fObject(obj.fObject), fFactor(double(obj.fFactor)) { } const LASymMatrix &Obj() const { return fObject; } double f() const { return fFactor; } private: const LASymMatrix &fObject; double fFactor; }; // templated scaling operator * template inline ABObj operator*(T f, const M &obj) { return ABObj(obj, f); } // templated operator / template inline ABObj operator/(const M &obj, T f) { return ABObj(obj, T(1.) / f); } // templated unary operator - template inline ABObj operator-(const M &obj) { return ABObj(obj, T(-1.)); } /* // specialization for LAVector inline ABObj operator*(double f, const LAVector& obj) { return ABObj(obj, f); } inline ABObj operator/(const LAVector& obj, double f) { return ABObj(obj, double(1.)/f); } inline ABObj operator-(const LAVector& obj) { return ABObj(obj, double(-1.)); } */ } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ABObj iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ABProd.h0000644000000000000000000000330414332717401020373 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ABProd #define ROOT_Minuit2_ABProd #include "Minuit2/ABObj.h" namespace ROOT { namespace Minuit2 { template class ABProd { private: ABProd() : fA(M1()), fB(M2()) {} ABProd &operator=(const ABProd &) { return *this; } template ABProd &operator=(const ABProd &) { return *this; } public: ABProd(const M1 &a, const M2 &b) : fA(a), fB(b) {} ~ABProd() {} ABProd(const ABProd &prod) : fA(prod.fA), fB(prod.fB) {} template ABProd(const ABProd &prod) : fA(M1(prod.A())), fB(M2(prod.B())) { } const M1 &A() const { return fA; } const M2 &B() const { return fB; } private: M1 fA; M2 fB; }; // ABObj * ABObj template inline ABObj::Type, ABProd, ABObj>, T> operator*(const ABObj &a, const ABObj &b) { return ABObj::Type, ABProd, ABObj>, T>( ABProd, ABObj>(a, b)); } } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ABProd iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ABSum.h0000644000000000000000000000421214332717401020232 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ABSum #define ROOT_Minuit2_ABSum #include "Minuit2/ABObj.h" namespace ROOT { namespace Minuit2 { template class ABSum { private: ABSum() : fA(M1()), fB(M2()) {} ABSum &operator=(const ABSum &) { return *this; } template ABSum &operator=(const ABSum &) { return *this; } public: ABSum(const M1 &a, const M2 &b) : fA(a), fB(b) {} ~ABSum() {} ABSum(const ABSum &sum) : fA(sum.fA), fB(sum.fB) {} template ABSum(const ABSum &sum) : fA(M1(sum.A())), fB(M2(sum.B())) { } const M1 &A() const { return fA; } const M2 &B() const { return fB; } private: M1 fA; M2 fB; }; // ABObj + ABObj template inline ABObj::Type, ABSum, ABObj>, T> operator+(const ABObj &a, const ABObj &b) { return ABObj::Type, ABSum, ABObj>, T>( ABSum, ABObj>(a, b)); } // ABObj - ABObj template inline ABObj::Type, ABSum, ABObj>, T> operator-(const ABObj &a, const ABObj &b) { return ABObj::Type, ABSum, ABObj>, T>( ABSum, ABObj>(a, ABObj(b.Obj(), T(-1.) * b.f()))); } } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ABSum iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ABTypes.h0000644000000000000000000000370714332717401020602 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ABTypes #define ROOT_Minuit2_ABTypes namespace ROOT { namespace Minuit2 { class gen { }; class sym { }; class vec { }; template class AlgebraicSumType { public: typedef gen Type; }; template class AlgebraicSumType { public: typedef T Type; }; template <> class AlgebraicSumType { private: typedef gen Type; }; template <> class AlgebraicSumType { private: typedef gen Type; }; template <> class AlgebraicSumType { private: typedef gen Type; }; template <> class AlgebraicSumType { private: typedef gen Type; }; // template class AlgebraicProdType { private: typedef gen Type; }; template class AlgebraicProdType { private: typedef T Type; }; template <> class AlgebraicProdType { public: typedef gen Type; }; template <> class AlgebraicProdType { public: typedef gen Type; }; template <> class AlgebraicProdType { public: typedef gen Type; }; template <> class AlgebraicProdType { public: typedef gen Type; }; template <> class AlgebraicProdType { private: typedef gen Type; }; template <> class AlgebraicProdType { public: typedef vec Type; }; template <> class AlgebraicProdType { private: typedef gen Type; }; template <> class AlgebraicProdType { public: typedef vec Type; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ABTypes iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/AnalyticalGradientCalculator.h0000644000000000000000000000331314332717401025035 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_AnalyticalGradientCalculator #define ROOT_Minuit2_AnalyticalGradientCalculator #include "Minuit2/GradientCalculator.h" #include "Minuit2/MnMatrixfwd.h" namespace ROOT { namespace Minuit2 { class FCNGradientBase; class MnUserTransformation; class AnalyticalGradientCalculator : public GradientCalculator { public: AnalyticalGradientCalculator(const FCNGradientBase &fcn, const MnUserTransformation &state) : fGradFunc(fcn), fTransformation(state) { } ~AnalyticalGradientCalculator() override {} FunctionGradient operator()(const MinimumParameters &) const override; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; /// compute Hessian matrix bool Hessian(const MinimumParameters &, MnAlgebraicSymMatrix &) const override; /// compute second derivatives (diagonal of Hessian) bool G2(const MinimumParameters &, MnAlgebraicVector &) const override; virtual bool CheckGradient() const; virtual bool CanComputeG2() const; virtual bool CanComputeHessian() const; protected: const FCNGradientBase &fGradFunc; const MnUserTransformation &fTransformation; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_AnalyticalGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/BFGSErrorUpdator.h0000644000000000000000000000201514332717401022354 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_BFGSErrorUpdator #define ROOT_Minuit2_BFGSErrorUpdator #include "Minuit2/MinimumErrorUpdator.h" namespace ROOT { namespace Minuit2 { /** Update of the covariance matrix for the Variable Metric minimizer (MIGRAD) */ class BFGSErrorUpdator : public MinimumErrorUpdator { public: BFGSErrorUpdator() {} ~BFGSErrorUpdator() override {} MinimumError Update(const MinimumState &, const MinimumParameters &, const FunctionGradient &) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_BFGSErrorUpdator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/CombinedMinimizer.h0000644000000000000000000000303514332717401022671 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_CombinedMinimizer #define ROOT_Minuit2_CombinedMinimizer #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/MnSeedGenerator.h" #include "Minuit2/CombinedMinimumBuilder.h" namespace ROOT { namespace Minuit2 { //__________________________________________________________________________ /** Combined minimizer: combination of Migrad and Simplex. I If the Migrad method fails at first attempt, a simplex minimization is performed and then migrad is tried again. */ class CombinedMinimizer : public ModularFunctionMinimizer { public: CombinedMinimizer() : fMinSeedGen(MnSeedGenerator()), fMinBuilder(CombinedMinimumBuilder()) {} ~CombinedMinimizer() override {} const MinimumSeedGenerator &SeedGenerator() const override { return fMinSeedGen; } const MinimumBuilder &Builder() const override { return fMinBuilder; } MinimumBuilder &Builder() override { return fMinBuilder; } private: MnSeedGenerator fMinSeedGen; CombinedMinimumBuilder fMinBuilder; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_CombinedMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/CombinedMinimumBuilder.h0000644000000000000000000000400414332717401023645 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_CombinedMinimumBuilder #define ROOT_Minuit2_CombinedMinimumBuilder #include "Minuit2/MinimumBuilder.h" #include "Minuit2/VariableMetricMinimizer.h" #include "Minuit2/SimplexMinimizer.h" namespace ROOT { namespace Minuit2 { class CombinedMinimumBuilder : public MinimumBuilder { public: CombinedMinimumBuilder() : fVMMinimizer(VariableMetricMinimizer()), fSimplexMinimizer(SimplexMinimizer()) {} ~CombinedMinimumBuilder() override {} FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const override; // re-implement setter of base class. Need also to store in the base class for consistency void SetPrintLevel(int level) override { MinimumBuilder::SetPrintLevel(level); fVMMinimizer.Builder().SetPrintLevel(level); fSimplexMinimizer.Builder().SetPrintLevel(level); } void SetStorageLevel(int level) override { MinimumBuilder::SetStorageLevel(level); fVMMinimizer.Builder().SetStorageLevel(level); fSimplexMinimizer.Builder().SetStorageLevel(level); } // set trace object (user manages it) void SetTraceObject(MnTraceObject &obj) override { MinimumBuilder::SetTraceObject(obj); fVMMinimizer.Builder().SetTraceObject(obj); fSimplexMinimizer.Builder().SetTraceObject(obj); } private: VariableMetricMinimizer fVMMinimizer; SimplexMinimizer fSimplexMinimizer; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_CombinedMinimumBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ContoursError.h0000644000000000000000000000442214332717401022114 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ContoursError #define ROOT_Minuit2_ContoursError #include "Minuit2/MnConfig.h" #include "Minuit2/MinosError.h" #include #include namespace ROOT { namespace Minuit2 { class ContoursError { public: ContoursError(unsigned int parX, unsigned int parY, const std::vector> &points, const MinosError &xmnos, const MinosError &ymnos, unsigned int nfcn) : fParX(parX), fParY(parY), fPoints(points), fXMinos(xmnos), fYMinos(ymnos), fNFcn(nfcn) { } ~ContoursError() {} ContoursError(const ContoursError &cont) : fParX(cont.fParX), fParY(cont.fParY), fPoints(cont.fPoints), fXMinos(cont.fXMinos), fYMinos(cont.fYMinos), fNFcn(cont.fNFcn) { } ContoursError &operator()(const ContoursError &cont) { fParX = cont.fParX; fParY = cont.fParY; fPoints = cont.fPoints; fXMinos = cont.fXMinos; fYMinos = cont.fYMinos; fNFcn = cont.fNFcn; return *this; } const std::vector> &operator()() const { return fPoints; } std::pair XMinos() const { return fXMinos(); } std::pair YMinos() const { return fYMinos(); } unsigned int Xpar() const { return fParX; } unsigned int Ypar() const { return fParY; } const MinosError &XMinosError() const { return fXMinos; } const MinosError &YMinosError() const { return fYMinos; } unsigned int NFcn() const { return fNFcn; } double XMin() const { return fXMinos.Min(); } double YMin() const { return fYMinos.Min(); } private: unsigned int fParX; unsigned int fParY; std::vector> fPoints; MinosError fXMinos; MinosError fYMinos; unsigned int fNFcn; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ContoursError iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/DavidonErrorUpdator.h0000644000000000000000000000203714332717401023223 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_DavidonErrorUpdator #define ROOT_Minuit2_DavidonErrorUpdator #include "Minuit2/MinimumErrorUpdator.h" namespace ROOT { namespace Minuit2 { /** Update of the covariance matrix for the Variable Metric minimizer (MIGRAD) */ class DavidonErrorUpdator : public MinimumErrorUpdator { public: DavidonErrorUpdator() {} ~DavidonErrorUpdator() override {} MinimumError Update(const MinimumState &, const MinimumParameters &, const FunctionGradient &) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_DavidonErrorUpdator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ExternalInternalGradientCalculator.h0000644000000000000000000000353414332717401026240 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ExternalInternalGradientCalculator #define ROOT_Minuit2_ExternalInternalGradientCalculator #include "Minuit2/AnalyticalGradientCalculator.h" namespace ROOT { namespace Minuit2 { class FCNGradientBase; class MnUserTransformation; /// Similar to the AnalyticalGradientCalculator, the ExternalInternalGradientCalculator /// supplies Minuit with an externally calculated gradient. The main difference is that /// ExternalInternalGradientCalculator expects that the external gradient calculator does /// things in Minuit2-internal parameter space, which means many int2ext and ext2int /// transformation steps are not necessary. This avoids loss of precision in some cases, /// where trigonometrically transforming parameters back and forth can lose a few bits of /// floating point precision on every pass. class ExternalInternalGradientCalculator : public AnalyticalGradientCalculator { public: ExternalInternalGradientCalculator(const FCNGradientBase &fcn, const MnUserTransformation &trafo) : AnalyticalGradientCalculator(fcn, trafo) { } ~ExternalInternalGradientCalculator() override {} FunctionGradient operator()(const MinimumParameters &) const override; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ExternalInternalGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FCNAdapter.h0000644000000000000000000000266414332717401021203 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 10/2006 /********************************************************************** * * * Copyright (c) 2006 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FCNAdapter #define ROOT_Minuit2_FCNAdapter #include "Minuit2/FCNBase.h" #include namespace ROOT { namespace Minuit2 { /** template wrapped class for adapting to FCNBase signature @author Lorenzo Moneta @ingroup Minuit */ template class FCNAdapter : public FCNBase { public: FCNAdapter(const Function &f, double up = 1.) : fFunc(f), fUp(up) {} ~FCNAdapter() override {} double operator()(const std::vector &v) const override { return fFunc.operator()(&v[0]); } double operator()(const double *v) const { return fFunc.operator()(v); } double Up() const override { return fUp; } void SetErrorDef(double up) override { fUp = up; } // virtual std::vector Gradient(const std::vector&) const; // forward interface // virtual double operator()(int npar, double* params,int iflag = 4) const; private: const Function &fFunc; double fUp; }; } // end namespace Minuit2 } // end namespace ROOT #endif // ROOT_Minuit2_FCNAdapter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FCNBase.h0000644000000000000000000000664114332717401020474 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FCNBase #define ROOT_Minuit2_FCNBase #include "Minuit2/MnConfig.h" #include #include "Minuit2/GenericFunction.h" namespace ROOT { namespace Minuit2 { /** \defgroup Minuit Minuit2 Minimization Library New Object-oriented implementation of the MINUIT minimization package. More information is available at the home page of the \ref Minuit2Page "Minuit2" minimization package". \ingroup Math */ //______________________________________________________________________________ /** Interface (abstract class) defining the function to be minimized, which has to be implemented by the user. @author Fred James and Matthias Winkler; modified by Andras Zsenei and Lorenzo Moneta \ingroup Minuit */ class FCNBase : public GenericFunction { public: ~FCNBase() override {} /** The meaning of the vector of parameters is of course defined by the user, who uses the values of those parameters to calculate their function Value. The order and the position of these parameters is strictly the one specified by the user when supplying the starting values for minimization. The starting values must be specified by the user, either via an std::vector or the MnUserParameters supplied as input to the MINUIT minimizers such as VariableMetricMinimizer or MnMigrad. Later values are determined by MINUIT as it searches for the Minimum or performs whatever analysis is requested by the user. @param v function parameters as defined by the user. @return the Value of the function. @see MnUserParameters @see VariableMetricMinimizer @see MnMigrad */ double operator()(const std::vector &v) const override = 0; /** Error definition of the function. MINUIT defines Parameter errors as the change in Parameter Value required to change the function Value by up. Normally, for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5. If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4, as Chi2(x+n*sigma) = Chi2(x) + n*n. Comment a little bit better with links!!!!!!!!!!!!!!!!! */ virtual double ErrorDef() const { return Up(); } /** Error definition of the function. MINUIT defines Parameter errors as the change in Parameter Value required to change the function Value by up. Normally, for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5. If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4, as Chi2(x+n*sigma) = Chi2(x) + n*n. \todo Comment a little bit better with links!!!!!!!!!!!!!!!!! Idem for ErrorDef() */ virtual double Up() const = 0; /** add interface to set dynamically a new error definition Re-implement this function if needed. */ virtual void SetErrorDef(double){}; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FCNBase iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FCNGradAdapter.h0000644000000000000000000000776414332717401022007 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 10/2006 /********************************************************************** * * * Copyright (c) 2006 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FCNGradAdapter #define ROOT_Minuit2_FCNGradAdapter #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnPrint.h" #include #include namespace ROOT { namespace Minuit2 { /** template wrapped class for adapting to FCNBase signature a IGradFunction @author Lorenzo Moneta @ingroup Minuit */ template class FCNGradAdapter : public FCNGradientBase { public: FCNGradAdapter(const Function &f, double up = 1.) : fFunc(f), fUp(up), fGrad(std::vector(fFunc.NDim())) {} ~FCNGradAdapter() override {} double operator()(const std::vector &v) const override { return fFunc.operator()(&v[0]); } double operator()(const double *v) const { return fFunc.operator()(v); } double Up() const override { return fUp; } std::vector Gradient(const std::vector &v) const override { fFunc.Gradient(&v[0], &fGrad[0]); return fGrad; } std::vector GradientWithPrevResult(const std::vector &v, double *previous_grad, double *previous_g2, double *previous_gstep) const override { fFunc.GradientWithPrevResult(&v[0], &fGrad[0], previous_grad, previous_g2, previous_gstep); return fGrad; } // forward interface // virtual double operator()(int npar, double* params,int iflag = 4) const; bool CheckGradient() const override { return false; } GradientParameterSpace gradParameterSpace() const override { if (fFunc.returnsInMinuit2ParameterSpace()) { return GradientParameterSpace::Internal; } else { return GradientParameterSpace::External; } } /// return second derivatives (diagonal of the Hessian matrix) std::vector G2(const std::vector & x) const override { if (fG2Func) return fG2Func(x); if (fHessianFunc) { unsigned int n = fFunc.NDim(); if (fG2Vec.empty() ) fG2Vec.resize(n); if (fHessian.empty() ) fHessian.resize(n*n); fHessianFunc(x,fHessian.data()); if (!fHessian.empty()) { // get diagonal element of h for (unsigned int i = 0; i < n; i++) fG2Vec[i] = fHessian[i*n+i]; } else fG2Vec.clear(); } else if (!fG2Vec.empty()) fG2Vec.clear(); return fG2Vec; } /// compute Hessian. Return Hessian as a std::vector of size(n*n) std::vector Hessian(const std::vector & x ) const override { unsigned int n = fFunc.NDim(); if (fHessianFunc) { if (fHessian.empty() ) fHessian.resize(n * n); bool ret = fHessianFunc(x,fHessian.data()); if (!ret) { fHessian.clear(); fHessianFunc = nullptr; } } else { fHessian.clear(); } return fHessian; } bool HasG2() const override { return bool(fG2Func); } bool HasHessian() const override { return bool(fHessianFunc); } template void SetG2Function(Func f) { fG2Func = f;} template void SetHessianFunction(Func f) { fHessianFunc = f;} void SetErrorDef(double up) override { fUp = up; } private: const Function &fFunc; double fUp; mutable std::vector fGrad; mutable std::vector fHessian; mutable std::vector fG2Vec; std::function(const std::vector &)> fG2Func; mutable std::function &, double *)> fHessianFunc; }; } // end namespace Minuit2 } // end namespace ROOT #endif // ROOT_Minuit2_FCNGradAdapter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FCNGradientBase.h0000644000000000000000000000471414332717401022151 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FCNGradientBase #define ROOT_Minuit2_FCNGradientBase #include "Minuit2/FCNBase.h" #include namespace ROOT { namespace Minuit2 { //________________________________________________________________________ /** Extension of the FCNBase for providing the analytical Gradient of the function. The user-Gradient is checked at the beginning of the minimization against the Minuit internal numerical Gradient in order to spot problems in the analytical Gradient calculation. This can be turned off by overriding CheckGradient() to make it return "false". The size of the output Gradient vector must be equal to the size of the input Parameter vector. Minuit does a check of the user Gradient at the beginning, if this is not wanted the method "CheckGradient()" has to be overridden to return "false". */ enum class GradientParameterSpace { External, Internal }; class FCNGradientBase : public FCNBase { public: ~FCNGradientBase() override {} virtual std::vector Gradient(const std::vector &) const = 0; virtual std::vector GradientWithPrevResult(const std::vector ¶meters, double * /*previous_grad*/, double * /*previous_g2*/, double * /*previous_gstep*/) const { return Gradient(parameters); }; virtual bool CheckGradient() const { return true; } virtual GradientParameterSpace gradParameterSpace() const { return GradientParameterSpace::External; }; /// return second derivatives (diagonal of the Hessian matrix) virtual std::vector G2(const std::vector &) const { return std::vector();} /// return Hessian virtual std::vector Hessian(const std::vector &) const { return std::vector();} virtual bool HasHessian() const { return false; } virtual bool HasG2() const { return false; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FCNGradientBase iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliBuilder.h0000644000000000000000000000751614332717401022031 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliBuilder #define ROOT_Minuit2_FumiliBuilder #include "Minuit2/MinimumBuilder.h" #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/FumiliErrorUpdator.h" #include "Minuit2/MnFcn.h" #include "Minuit2/FunctionMinimum.h" #include namespace ROOT { namespace Minuit2 { /** Builds the FunctionMinimum using the Fumili method. @author Andras Zsenei, Creation date: 29 Sep 2004 @see MINUIT Tutorial on function minimization, section 5 @ingroup Minuit \todo the role of the strategy in Fumili */ class FumiliBuilder : public MinimumBuilder { public: FumiliBuilder() : fEstimator(VariableMetricEDMEstimator()), fErrorUpdator(FumiliErrorUpdator()) {} ~FumiliBuilder() override {} /** Class the member function calculating the Minimum and verifies the result depending on the strategy. @param fMnFcn the function to be minimized. @param fGradienCalculator not used in Fumili. @param fMinimumSeed the seed generator. @param fMnStrategy the strategy describing the number of function calls allowed for Gradient calculations. @param maxfcn maximum number of function calls after which the calculation will be stopped even if it has not yet converged. @param edmval expected vertical distance to the Minimum. @return Returns the function Minimum found. \todo Complete the documentation by understanding what is the reason to have two Minimum methods. */ FunctionMinimum Minimum(const MnFcn &fMnFcn, const GradientCalculator &fGradienCalculator, const MinimumSeed &fMinimumSeed, const MnStrategy &fMnStrategy, unsigned int maxfcn, double edmval) const override; /** Calculates the Minimum based on the Fumili method @param fMnFcn the function to be minimized. @param fGradienCalculator not used in Fumili @param fMinimumSeed the seed generator. @param states vector containing the state result of each iteration @param maxfcn maximum number of function calls after which the calculation will be stopped even if it has not yet converged. @param edmval expected vertical distance to the Minimum @return Returns the function Minimum found. @see MINUIT Tutorial on function minimization, section 5 \todo some nice Latex based formula here... */ FunctionMinimum Minimum(const MnFcn &fMnFcn, const GradientCalculator &fGradienCalculator, const MinimumSeed &fMinimumSeed, std::vector &states, unsigned int maxfcn, double edmval) const; /** Accessor to the EDM (expected vertical distance to the Minimum) estimator. @return The EDM estimator used in the builder. \todo Maybe a little explanation concerning EDM in all relevant classes. */ const VariableMetricEDMEstimator &Estimator() const { return fEstimator; } /** Accessor to the Error updator of the builder. @return The FumiliErrorUpdator used by the FumiliBuilder. */ const FumiliErrorUpdator &ErrorUpdator() const { return fErrorUpdator; } private: VariableMetricEDMEstimator fEstimator; FumiliErrorUpdator fErrorUpdator; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliChi2FCN.h0000644000000000000000000001106214332717401021546 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliChi2FCN #define ROOT_Minuit2_FumiliChi2FCN #include "FumiliFCNBase.h" #include #include "Minuit2/ParametricFunction.h" namespace ROOT { namespace Minuit2 { /** Extension of the FCNBase for the Fumili method. Fumili applies only to minimization problems used for fitting. The method is based on a linearization of the model function negleting second derivatives. User needs to provide the model function. The figure-of-merit describing the difference between the model function and the actual measurements in the case of chi-square is the sum of the squares of the figures-of-merit calculated for each measurement point, which is implemented by the operator() member function. The user still has to implement the calculation of the individual figures-of-merit (which in the majority of the cases will be the (measured Value - the Value predicted by the model)/standard deviation implemented by the FumiliStandardChi2FCN; however this form can become more complicated (see for an example Numerical Recipes' section on "Straight-Line Data with Errors in Both Coordinates")). @author Andras Zsenei and Lorenzo Moneta, Creation date: 24 Aug 2004 @see MINUIT Tutorial on function minimization, section 5 @see FumiliStandardChi2FCN @ingroup Minuit */ class FumiliChi2FCN : public FumiliFCNBase { public: FumiliChi2FCN() {} ~FumiliChi2FCN() override {} /** Sets the model function for the data (for example gaussian+linear for a peak) @param modelFCN a reference to the model function. */ void SetModelFunction(const ParametricFunction &modelFCN) { fModelFunction = &modelFCN; } /** Returns the model function used for the data. @return Returns a pointer to the model function. */ const ParametricFunction *ModelFunction() const { return fModelFunction; } /** Evaluates the model function for the different measurement points and the Parameter values supplied, calculates a figure-of-merit for each measurement and returns a vector containing the result of this evaluation. @param par vector of Parameter values to feed to the model function. @return A vector containing the figures-of-merit for the model function evaluated for each set of measurements. */ virtual std::vector Elements(const std::vector &par) const = 0; /** Accessor to the parameters of a given measurement. For example in the case of a chi-square fit with a one-dimensional Gaussian, the Parameter characterizing the measurement will be the position. It is the Parameter that is passed to the model function. @param Index Index of the measueremnt the parameters of which to return @return A reference to a vector containing the values characterizing a measurement */ virtual const std::vector &GetMeasurement(int Index) const = 0; /** Accessor to the number of measurements used for calculating the present figure of merit. @return the number of measurements */ virtual int GetNumberOfMeasurements() const = 0; /** Calculates the sum of Elements squared, ie the chi-square. The user must implement in a class which inherits from FumiliChi2FCN the member function Elements() which will supply the Elements for the sum. @param par vector containing the Parameter values for the model function @return The sum of Elements squared @see FumiliFCNBase#elements */ double operator()(const std::vector &par) const override { double chiSquare = 0.0; std::vector vecElements = Elements(par); unsigned int vecElementsSize = vecElements.size(); for (unsigned int i = 0; i < vecElementsSize; ++i) chiSquare += vecElements[i] * vecElements[i]; return chiSquare; } /** !!!!!!!!!!!! to be commented */ double Up() const override { return 1.0; } private: // A pointer to the model function which describes the data const ParametricFunction *fModelFunction = nullptr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliChi2FCN iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliErrorUpdator.h0000644000000000000000000000603414332717401023065 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliErrorUpdator #define ROOT_Minuit2_FumiliErrorUpdator #include "Minuit2/MinimumErrorUpdator.h" namespace ROOT { namespace Minuit2 { class MinimumState; class MinimumParameters; class GradientCalculator; class FumiliFCNBase; class FunctionGradient; /** In the case of the Fumili algorithm the Error matrix (or the Hessian matrix containing the (approximate) second derivatives) is calculated using a linearization of the model function negleting second derivatives. (In some sense the Name Updator is a little bit misleading as the Error matrix is not calculated by iteratively updating, like in Davidon's or other similar variable metric methods, but by recalculating each time). @author Andras Zsenei and Lorenzo Moneta, Creation date: 28 Sep 2004 @see MINUIT Tutorial on function minimization, section 5 @see DavidonErrorUpdator @ingroup Minuit */ class FumiliErrorUpdator : public MinimumErrorUpdator { public: FumiliErrorUpdator() {} ~FumiliErrorUpdator() override {} /** Member function that calculates the Error matrix (or the Hessian matrix containing the (approximate) second derivatives) using a linearization of the model function negleting second derivatives. @param fMinimumState used to calculate the change in the covariance matrix between the two iterations @param fMinimumParameters the parameters at the present iteration @param fGradientCalculator the Gradient calculator used to retrieved the Parameter transformation @param lambda the Marquard lambda factor \todo Some nice latex mathematical formuli... */ virtual MinimumError Update(const MinimumState &fMinimumState, const MinimumParameters &fMinimumParameters, const GradientCalculator &fGradientCalculator, double lambda) const; /** Member function which is only present due to the design already in place of the software. As all classes calculating the Error matrix are supposed inherit from the MinimumErrorUpdator they must inherit this method. In some methods calculating the aforementioned matrix some of these parameters are not needed and other parameters are necessary... Hopefully, a more elegant solution will be found in the future. \todo How to get rid of this dummy method which is only due to the inheritance */ MinimumError Update(const MinimumState &, const MinimumParameters &, const FunctionGradient &) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliErrorUpdator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliFCNAdapter.h0000644000000000000000000001125014332717401022340 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 10/2006 /********************************************************************** * * * Copyright (c) 2006 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliFCNAdapter #define ROOT_Minuit2_FumiliFCNAdapter #include "Minuit2/FumiliFCNBase.h" #include "Math/FitMethodFunction.h" #include "Minuit2/MnPrint.h" // #ifndef ROOT_Math_Util // #include "Math/Util.h" // #endif #include #include #include namespace ROOT { namespace Minuit2 { /** template wrapped class for adapting to FumiliFCNBase signature @author Lorenzo Moneta @ingroup Minuit */ template class FumiliFCNAdapter : public FumiliFCNBase { public: // typedef ROOT::Math::FitMethodFunction Function; typedef typename Function::Type_t Type_t; FumiliFCNAdapter(const Function &f, unsigned int ndim, double up = 1.) : FumiliFCNBase(ndim), fFunc(f), fUp(up) {} ~FumiliFCNAdapter() override {} double operator()(const std::vector &v) const override { return fFunc.operator()(&v[0]); } double operator()(const double *v) const { return fFunc.operator()(v); } double Up() const override { return fUp; } void SetErrorDef(double up) override { fUp = up; } // virtual std::vector Gradient(const std::vector&) const; // forward interface // virtual double operator()(int npar, double* params,int iflag = 4) const; /** evaluate gradient hessian and function value needed by fumili */ void EvaluateAll(const std::vector &v) override; private: // data member const Function &fFunc; double fUp; }; template void FumiliFCNAdapter::EvaluateAll(const std::vector &v) { MnPrint print("FumiliFCNAdapter"); // typedef FumiliFCNAdapter::Function Function; // evaluate all elements unsigned int npar = Dimension(); if (npar != v.size()) print.Error("npar", npar, "v.size()", v.size()); assert(npar == v.size()); // must distinguish case of likelihood or LS std::vector &grad = Gradient(); std::vector &hess = Hessian(); // reset assert(grad.size() == npar); grad.assign(npar, 0.0); hess.assign(hess.size(), 0.0); unsigned int ndata = fFunc.NPoints(); std::vector gf(npar); std::vector h(hess.size()); // loop on the data points // if FCN is of type least-square if (fFunc.Type() == Function::kLeastSquare) { print.Debug("Chi2 FCN: Evaluate gradient and Hessian"); for (unsigned int i = 0; i < ndata; ++i) { // calculate data element and gradient (no need to compute Hessian) double fval = fFunc.DataElement(&v.front(), i, &gf[0]); for (unsigned int j = 0; j < npar; ++j) { grad[j] += 2. * fval * gf[j]; for (unsigned int k = j; k < npar; ++k) { int idx = j + k * (k + 1) / 2; hess[idx] += 2.0 * gf[j] * gf[k]; } } } } else if (fFunc.Type() == Function::kLogLikelihood) { print.Debug("LogLikelihood FCN: Evaluate gradient and Hessian"); for (unsigned int i = 0; i < ndata; ++i) { // calculate data element and gradient: returns derivative of log(pdf) fFunc.DataElement(&v.front(), i, &gf[0]); for (unsigned int j = 0; j < npar; ++j) { double gfj = gf[j]; grad[j] -= gfj; // need a minus sign since is a NLL for (unsigned int k = j; k < npar; ++k) { int idx = j + k * (k + 1) / 2; hess[idx] += gfj * gf[k]; } } } } else if (fFunc.Type() == Function::kPoissonLikelihood) { print.Debug("Poisson Likelihood FCN: Evaluate gradient and Hessian"); // for Poisson need Hessian computed in DataElement since one needs the bin expected value ad bin observed value for (unsigned int i = 0; i < ndata; ++i) { // calculate data element and gradient fFunc.DataElement(&v.front(), i, gf.data(), h.data()); for (size_t j = 0; j < npar; ++j) { grad[j] += gf[j]; for (unsigned int k = j; k < npar; ++k) { int idx = j + k * (k + 1) / 2; hess[idx] += h[idx]; } } } } else { print.Error("Type of fit method is not supported, it must be chi2 or log-likelihood or Poisson Likelihood"); } } } // end namespace Minuit2 } // end namespace ROOT #endif // ROOT_Minuit2_FCNAdapter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliFCNBase.h0000644000000000000000000001106614332717401021637 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliFCNBase #define ROOT_Minuit2_FumiliFCNBase #include "Minuit2/FCNGradientBase.h" #include #include namespace ROOT { namespace Minuit2 { //____________________________________________________________________________________________ /** Extension of the FCNBase for the Fumili method. Fumili applies only to minimization problems used for fitting. The method is based on a linearization of the model function negleting second derivatives. User needs to provide the model function. The figure-of-merit describing the difference between the model function and the actual measurements has to be implemented by the user in a subclass of FumiliFCNBase. For an example see the FumiliChi2FCN and FumiliStandardChi2FCN classes. @author Andras Zsenei and Lorenzo Moneta, Creation date: 23 Aug 2004 @see MINUIT Tutorial on function minimization, section 5 @see FumiliChi2FCN @see FumiliStandardChi2FCN @ingroup Minuit */ class FumiliFCNBase : public FCNGradientBase { public: /** Default Constructor. Need in this case to create when implementing EvaluateAll the Gradient and Hessian vectors with the right size */ FumiliFCNBase() : fNumberOfParameters(0), fValue(0) {} /** Constructor which initializes the class with the function provided by the user for modeling the data. @param npar the number of parameters */ FumiliFCNBase(unsigned int npar) : fNumberOfParameters(npar), fValue(0), fGradient(std::vector(npar)), fHessian(std::vector(static_cast(0.5 * npar * (npar + 1)))) { } // FumiliFCNBase(const ParametricFunction& modelFCN) { fModelFunction = &modelFCN; } ~FumiliFCNBase() override {} /** Evaluate function Value, Gradient and Hessian using Fumili approximation, for values of parameters p The result is cached inside and is return from the FumiliFCNBase::Value , FumiliFCNBase::Gradient and FumiliFCNBase::Hessian methods @param par vector of parameters **/ virtual void EvaluateAll(const std::vector &par) = 0; /** Return cached Value of objective function estimated previously using the FumiliFCNBase::EvaluateAll method **/ virtual double Value() const { return fValue; } /** Return cached Value of function Gradient estimated previously using the FumiliFCNBase::EvaluateAll method **/ virtual const std::vector &Gradient() const { return fGradient; } std::vector Gradient(const std::vector &) const override { return fGradient;} /** Return Value of the i-th j-th element of the Hessian matrix estimated previously using the FumiliFCNBase::EvaluateAll method @param row row Index of the matrix @param col col Index of the matrix **/ std::vector Hessian(const std::vector &) const override { return fHessian;} virtual double Hessian(unsigned int row, unsigned int col) const { assert(row < fGradient.size() && col < fGradient.size()); if (row > col) return fHessian[col + row * (row + 1) / 2]; else return fHessian[row + col * (col + 1) / 2]; } /** return number of function variable (parameters) , i.e. function dimension */ virtual unsigned int Dimension() { return fNumberOfParameters; } protected: /** initialize and reset values of gradien and Hessian */ virtual void InitAndReset(unsigned int npar) { fNumberOfParameters = npar; fGradient = std::vector(npar); fHessian = std::vector(static_cast(0.5 * npar * (npar + 1))); } // methods to be used by the derived classes to set the values void SetFCNValue(double value) { fValue = value; } std::vector &Gradient() { return fGradient; } std::vector &Hessian() { return fHessian; } private: unsigned int fNumberOfParameters; double fValue; std::vector fGradient; std::vector fHessian; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliFCNBase iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliGradientCalculator.h0000644000000000000000000000352414332717401024205 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliGradientCalculator #define ROOT_Minuit2_FumiliGradientCalculator #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { class FumiliFCNBase; class MnUserTransformation; /// Fumili gradient calculator using external gradient provided by FCN /// Note that the computed Hessian and G2 are an approximation valid for small residuals class FumiliGradientCalculator : public AnalyticalGradientCalculator { public: FumiliGradientCalculator(const FumiliFCNBase &fcn, const MnUserTransformation &trafo, int n); ~FumiliGradientCalculator() override {} FunctionGradient operator()(const MinimumParameters &) const override; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; const MnUserTransformation &Trafo() const { return fTransformation; } const MnAlgebraicSymMatrix &GetHessian() const { return fHessian; } bool Hessian(const MinimumParameters &, MnAlgebraicSymMatrix &) const override; bool G2(const MinimumParameters &, MnAlgebraicVector &) const override; bool CanComputeG2() const override { return true;} bool CanComputeHessian() const override { return true;} private: const FumiliFCNBase &fFcn; mutable MnAlgebraicSymMatrix fHessian; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliMaximumLikelihoodFCN.h0000644000000000000000000001066014332717401024405 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliMaximumLikelihoodFCN #define ROOT_Minuit2_FumiliMaximumLikelihoodFCN #include "FumiliFCNBase.h" #include "Minuit2/ParametricFunction.h" #include "Math/Util.h" #include #include namespace ROOT { namespace Minuit2 { /** Extension of the FCNBase for the Fumili method. Fumili applies only to minimization problems used for fitting. The method is based on a linearization of the model function negleting second derivatives. User needs to provide the model function. In this cased the function to be minimized is the sum of the logarithms of the model function for the different measurements times -1. @author Andras Zsenei and Lorenzo Moneta, Creation date: 3 Sep 2004 @see MINUIT Tutorial on function minimization, section 5 @see FumiliStandardMaximumLikelihoodFCN @ingroup Minuit \todo Insert a nice latex formula... */ class FumiliMaximumLikelihoodFCN : public FumiliFCNBase { public: FumiliMaximumLikelihoodFCN() {} ~FumiliMaximumLikelihoodFCN() override {} /** Sets the model function for the data (for example gaussian+linear for a peak) @param modelFCN a reference to the model function. */ void SetModelFunction(const ParametricFunction &modelFCN) { fModelFunction = &modelFCN; } /** Returns the model function used for the data. @return Returns a pointer to the model function. */ const ParametricFunction *ModelFunction() const { return fModelFunction; } /** Evaluates the model function for the different measurement points and the Parameter values supplied, calculates a figure-of-merit for each measurement and returns a vector containing the result of this evaluation. @param par vector of Parameter values to feed to the model function. @return A vector containing the figures-of-merit for the model function evaluated for each set of measurements. */ virtual std::vector Elements(const std::vector &par) const = 0; /** Accessor to the parameters of a given measurement. For example in the case of a chi-square fit with a one-dimensional Gaussian, the Parameter characterizing the measurement will be the position. It is the Parameter that is passed to the model function. @param Index Index of the measueremnt the parameters of which to return @return A vector containing the values characterizing a measurement */ virtual const std::vector &GetMeasurement(int Index) const = 0; /** Accessor to the number of measurements used for calculating the present figure of merit. @return the number of measurements */ virtual int GetNumberOfMeasurements() const = 0; /** Calculates the function for the maximum likelihood method. The user must implement in a class which inherits from FumiliChi2FCN the member function Elements() which will supply the Elements for the sum. @param par vector containing the Parameter values for the model function @return The sum of the natural logarithm of the Elements multiplied by -1 @see FumiliFCNBase#elements */ double operator()(const std::vector &par) const override { double sumoflogs = 0.0; std::vector vecElements = Elements(par); unsigned int vecElementsSize = vecElements.size(); for (unsigned int i = 0; i < vecElementsSize; ++i) { double tmp = vecElements[i]; // for max likelihood probability have to be positive assert(tmp >= 0); sumoflogs -= ROOT::Math::Util::EvalLog(tmp); // std::cout << " i " << tmp << " likelihood " << sumoflogs << std::endl; } return sumoflogs; } /** !!!!!!!!!!!! to be commented */ double Up() const override { return 0.5; } private: // A pointer to the model function which describes the data const ParametricFunction *fModelFunction; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliMaximumLikelihoodFCN iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliMinimizer.h0000644000000000000000000000532614332717401022403 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliMinimizer #define ROOT_Minuit2_FumiliMinimizer #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/MnSeedGenerator.h" #include "Minuit2/FumiliBuilder.h" #include namespace ROOT { namespace Minuit2 { class MinimumSeedGenerator; class MinimumBuilder; class MinimumSeed; class MnFcn; class FumiliFcnBase; class GradientCalculator; class MnUserParameterState; class MnUserParameters; class MnUserCovariance; class MnStrategy; //______________________________________________________________ /** Instantiates the seed generator and Minimum builder for the Fumili minimization method. Produces the Minimum via the Minimize methods inherited from ModularFunctionMinimizer. @author Andras Zsenei and Lorenzo Moneta, Creation date: 28 Sep 2004 @ingroup Minuit */ class FumiliMinimizer : public ModularFunctionMinimizer { public: /** Constructor initializing the FumiliMinimizer by instantiatiating the SeedGenerator and MinimumBuilder for the Fumili minimization method. @see MnSeedGenerator @see FumiliBuilder */ FumiliMinimizer() : fMinSeedGen(MnSeedGenerator()), fMinBuilder(FumiliBuilder()) {} ~FumiliMinimizer() override {} /** Accessor to the seed generator of the minimizer. @return A reference to the seed generator used by the minimizer */ const MinimumSeedGenerator &SeedGenerator() const override { return fMinSeedGen; } /** Accessor to the Minimum builder of the minimizer. @return a reference to the Minimum builder. */ const FumiliBuilder &Builder() const override { return fMinBuilder; } FumiliBuilder &Builder() override { return fMinBuilder; } // for Fumili FunctionMinimum Minimize(const FCNBase &, const MnUserParameterState &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const override; FunctionMinimum Minimize(const FCNGradientBase &, const MnUserParameterState &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const override; using ModularFunctionMinimizer::Minimize; private: MnSeedGenerator fMinSeedGen; FumiliBuilder fMinBuilder; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliStandardChi2FCN.h0000644000000000000000000001302614332717401023231 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliStandardChi2FCN #define ROOT_Minuit2_FumiliStandardChi2FCN #include "Minuit2/FumiliChi2FCN.h" #include "Minuit2/ParametricFunction.h" #include #include #include namespace ROOT { namespace Minuit2 { /** Class implementing the standard chi square function, which is the sum of the squares of the figures-of-merit calculated for each measurement point, the individual figures-of-merit being: (the Value predicted by the model-measured Value)/standard deviation. @author Andras Zsenei and Lorenzo Moneta, Creation date: 31 Aug 2004 @see FumiliChi2FCN @ingroup Minuit \todo nice formula for the documentation... */ class FumiliStandardChi2FCN : public FumiliChi2FCN { public: /** Constructor which initializes chi square function for one-dimensional model function @param modelFCN the model function used for describing the data. @param meas vector containing the measured values. @param pos vector containing the x values corresponding to the measurements @param mvar vector containing the variances corresponding to each measurement (where the variance equals the standard deviation squared). If the variances are zero, a Value of 1 is used (as it is done in ROOT/PAW) */ FumiliStandardChi2FCN(const ParametricFunction &modelFCN, const std::vector &meas, const std::vector &pos, const std::vector &mvar) { // this->fModelFCN = &modelFunction; this->SetModelFunction(modelFCN); assert(meas.size() == pos.size()); assert(meas.size() == mvar.size()); fMeasurements = meas; std::vector x(1); unsigned int n = mvar.size(); fPositions.reserve(n); // correct for variance == 0 fInvErrors.resize(n); for (unsigned int i = 0; i < n; ++i) { x[0] = pos[i]; fPositions.push_back(x); // PAW/ROOT hack : use 1 for 0 entries bins if (mvar[i] == 0) fInvErrors[i] = 1; else fInvErrors[i] = 1.0 / std::sqrt(mvar[i]); } } /** Constructor which initializes the multi-dimensional model function. @param modelFCN the model function used for describing the data. @param meas vector containing the measured values. @param pos vector containing the x values corresponding to the measurements @param mvar vector containing the variances corresponding to each measurement (where the variance equals the standard deviation squared). If the variances are zero, a Value of 1 is used (as it is done in ROOT/PAW) */ FumiliStandardChi2FCN(const ParametricFunction &modelFCN, const std::vector &meas, const std::vector> &pos, const std::vector &mvar) { // this->fModelFCN = &modelFunction; this->SetModelFunction(modelFCN); assert(meas.size() == pos.size()); assert(meas.size() == mvar.size()); fMeasurements = meas; fPositions = pos; // correct for variance == 0 unsigned int n = mvar.size(); fInvErrors.resize(n); for (unsigned int i = 0; i < n; ++i) { // PAW/ROOT hack : use 1 for 0 entries bins if (mvar[i] == 0) fInvErrors[i] = 1; else fInvErrors[i] = 1.0 / std::sqrt(mvar[i]); } } ~FumiliStandardChi2FCN() override {} /** Evaluates the model function for the different measurement points and the Parameter values supplied, calculates a figure-of-merit for each measurement and returns a vector containing the result of this evaluation. The figure-of-merit is (Value predicted by the model function-measured Value)/standard deviation. @param par vector of Parameter values to feed to the model function. @return A vector containing the figures-of-merit for the model function evaluated for each set of measurements. \todo What to do when the variances are 0???!! (right now just pushes back 0...) */ std::vector Elements(const std::vector &par) const override; /** Accessor to the position of the measurement (x coordinate). @param Index Index of the measuerement the position of which to return. @return the position of the measurement. */ const std::vector &GetMeasurement(int Index) const override; /** Accessor to the number of measurements used for calculating the chi-square. @return the number of measurements. */ int GetNumberOfMeasurements() const override; /** Evaluate function Value, Gradient and Hessian using Fumili approximation, for values of parameters p The result is cached inside and is return from the FumiliFCNBase::Value , FumiliFCNBase::Gradient and FumiliFCNBase::Hessian methods @param par vector of parameters **/ void EvaluateAll(const std::vector &par) override; private: std::vector fMeasurements; // support multi dim coordinates std::vector> fPositions; std::vector fInvErrors; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliStandardChi2FCN iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FumiliStandardMaximumLikelihoodFCN.h0000644000000000000000000000670714332717401026075 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN #define ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN #include "Minuit2/FumiliMaximumLikelihoodFCN.h" #include "Minuit2/ParametricFunction.h" #include namespace ROOT { namespace Minuit2 { /** Class implementing the Elements member function for the standard maximum likelihood method. @author Andras Zsenei and Lorenzo Moneta, Creation date: 4 Sep 2004 @see FumiliMaximumLikelihoodFCN @ingroup Minuit */ class FumiliStandardMaximumLikelihoodFCN : public FumiliMaximumLikelihoodFCN { public: /** Constructor which initializes the measurement points for the one dimensional model function. @param modelFCN the model function used for describing the data. @param pos vector containing the x values corresponding to the measurements */ FumiliStandardMaximumLikelihoodFCN(const ParametricFunction &modelFCN, const std::vector &pos) { this->SetModelFunction(modelFCN); unsigned int n = pos.size(); fPositions.reserve(n); std::vector x(1); for (unsigned int i = 0; i < n; ++i) { x[0] = pos[i]; fPositions.push_back(x); } } /** Constructor which initializes the measurement points for the multi dimensional model function. @param modelFCN the model function used for describing the data. @param pos vector containing the x values corresponding to the measurements */ FumiliStandardMaximumLikelihoodFCN(const ParametricFunction &modelFCN, const std::vector> &pos) { this->SetModelFunction(modelFCN); fPositions = pos; } ~FumiliStandardMaximumLikelihoodFCN() override {} /** Evaluates the model function for the different measurement points and the Parameter values supplied. @param par vector of Parameter values to feed to the model function. @return A vector containing the model function evaluated for each measurement point. */ std::vector Elements(const std::vector &par) const override; /** Accessor to the position of the measurement (x coordinate). @param Index Index of the measuerement the position of which to return. @return the position of the measurement. */ const std::vector &GetMeasurement(int Index) const override; /** Accessor to the number of measurements used for calculating the maximum likelihood. @return the number of measurements. */ int GetNumberOfMeasurements() const override; /** Evaluate function Value, Gradient and Hessian using Fumili approximation, for values of parameters p The result is cached inside and is return from the FumiliFCNBase::Value , FumiliFCNBase::Gradient and FumiliFCNBase::Hessian methods @param par vector of parameters **/ void EvaluateAll(const std::vector &par) override; private: std::vector> fPositions; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FunctionGradient.h0000644000000000000000000000405114332717401022527 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FunctionGradient #define ROOT_Minuit2_FunctionGradient #include "Minuit2/MnMatrix.h" #include namespace ROOT { namespace Minuit2 { class FunctionGradient { private: public: explicit FunctionGradient(unsigned int n) : fPtr{new Data{MnAlgebraicVector(n), MnAlgebraicVector(n), MnAlgebraicVector(n), false, false, false}} { } explicit FunctionGradient(const MnAlgebraicVector &grd) : fPtr{new Data{grd, MnAlgebraicVector(0), MnAlgebraicVector(0), true, true, false}} { } FunctionGradient(const MnAlgebraicVector &grd, const MnAlgebraicVector &g2) : fPtr{new Data{grd, g2, MnAlgebraicVector(0), true, true, true}} { } FunctionGradient(const MnAlgebraicVector &grd, const MnAlgebraicVector &g2, const MnAlgebraicVector &gstep) : fPtr{new Data{grd, g2, gstep, true, false, true}} { } const MnAlgebraicVector &Grad() const { return fPtr->fGradient; } const MnAlgebraicVector &Vec() const { return Grad(); } bool IsValid() const { return fPtr->fValid; } bool IsAnalytical() const { return fPtr->fAnalytical; } bool HasG2() const { return fPtr->fHasG2; } const MnAlgebraicVector &G2() const { return fPtr->fG2ndDerivative; } const MnAlgebraicVector &Gstep() const { return fPtr->fGStepSize; } private: struct Data { MnAlgebraicVector fGradient; MnAlgebraicVector fG2ndDerivative; MnAlgebraicVector fGStepSize; bool fValid; bool fAnalytical; bool fHasG2; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FunctionGradient iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FunctionMinimizer.h0000644000000000000000000000524314332717401022741 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FunctionMinimizer #define ROOT_Minuit2_FunctionMinimizer #include "Minuit2/MnConfig.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; class FCNGradientBase; class FunctionMinimum; //_____________________________________________________________________________________ /** base class for function minimizers; user may give FCN or FCN with Gradient, Parameter starting values and initial Error guess (sigma) (or "step size"), or Parameter starting values and initial covariance matrix; covariance matrix is stored in Upper triangular packed storage format, e.g. the Elements in the array are arranged like {a(0,0), a(0,1), a(1,1), a(0,2), a(1,2), a(2,2), ...}, the size is nrow*(nrow+1)/2 (see also MnUserCovariance.h); */ class FunctionMinimizer { public: virtual ~FunctionMinimizer() {} // starting values for parameters and errors virtual FunctionMinimum Minimize(const FCNBase &, const std::vector &par, const std::vector &err, unsigned int strategy, unsigned int maxfcn, double toler) const = 0; // starting values for parameters and errors and FCN with Gradient virtual FunctionMinimum Minimize(const FCNGradientBase &, const std::vector &par, const std::vector &err, unsigned int strategy, unsigned int maxfcn, double toler) const = 0; // starting values for parameters and covariance matrix virtual FunctionMinimum Minimize(const FCNBase &, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int strategy, unsigned int maxfcn, double toler) const = 0; // starting values for parameters and covariance matrix and FCN with Gradient virtual FunctionMinimum Minimize(const FCNGradientBase &, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int strategy, unsigned int maxfcn, double toler) const = 0; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FunctionMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/FunctionMinimum.h0000644000000000000000000001157214332717401022413 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_FunctionMinimum #define ROOT_Minuit2_FunctionMinimum #include "Minuit2/MinimumSeed.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnUserTransformation.h" #include #include #include #ifdef G__DICTIONARY typedef ROOT::Minuit2::MinimumState MinimumState; #endif namespace ROOT { namespace Minuit2 { //______________________________________________________________________________________________ /** class holding the full result of the minimization; both internal and external (MnUserParameterState) representation available for the parameters at the Minimum */ class FunctionMinimum { public: enum Status { MnValid, MnReachedCallLimit, MnAboveMaxEdm, }; public: /// Constructor from only MinimumSeed. Minimum is only from seed result not the full minimization FunctionMinimum(const MinimumSeed &seed, double up) : FunctionMinimum(seed, std::vector(1, MinimumState(seed.Parameters(), seed.Error(), seed.Gradient(), seed.Parameters().Fval(), seed.NFcn())), up) { } /// Constructor at the end of a minimization from seed and vector of states FunctionMinimum(const MinimumSeed &seed, const std::vector &states, double up, Status status = MnValid) : fPtr{new Data{seed, states, up, status == MnAboveMaxEdm, status == MnReachedCallLimit, {}}} { } /// add latest minimization state (for example add Hesse result after Migrad) void Add(const MinimumState &state, Status status = MnValid) { fPtr->fStates.push_back(state); // LM : update also the user state fPtr->fUserState = MnUserParameterState(State(), Up(), Seed().Trafo()); // reset maxedm flag. If new state has edm over max other method must be used fPtr->fAboveMaxEdm = status == MnAboveMaxEdm; fPtr->fReachedCallLimit = status == MnReachedCallLimit; } const MinimumSeed &Seed() const { return fPtr->fSeed; } const std::vector &States() const { return fPtr->fStates; } // user representation of state at Minimum const MnUserParameterState &UserState() const { if (!fPtr->fUserState.IsValid()) fPtr->fUserState = MnUserParameterState(State(), Up(), Seed().Trafo()); return fPtr->fUserState; } const MnUserParameters &UserParameters() const { return UserState().Parameters(); } const MnUserCovariance &UserCovariance() const { return UserState().Covariance(); } // forward interface of last state const MinimumState &State() const { return States().back(); } const MinimumParameters &Parameters() const { return States().back().Parameters(); } const MinimumError &Error() const { return States().back().Error(); } const FunctionGradient &Grad() const { return States().back().Gradient(); } double Fval() const { return States().back().Fval(); } double Edm() const { return States().back().Edm(); } int NFcn() const { return States().back().NFcn(); } double Up() const { return fPtr->fErrorDef; } bool IsValid() const { return State().IsValid() && !IsAboveMaxEdm() && !HasReachedCallLimit(); } bool HasValidParameters() const { return State().Parameters().IsValid(); } bool HasValidCovariance() const { return State().Error().IsValid(); } bool HasAccurateCovar() const { return State().Error().IsAccurate(); } bool HasPosDefCovar() const { return State().Error().IsPosDef(); } bool HasMadePosDefCovar() const { return State().Error().IsMadePosDef(); } bool HesseFailed() const { return State().Error().HesseFailed(); } bool HasCovariance() const { return State().Error().IsAvailable(); } bool IsAboveMaxEdm() const { return fPtr->fAboveMaxEdm || std::isnan(Edm()); } bool HasReachedCallLimit() const { return fPtr->fReachedCallLimit; } void SetErrorDef(double up) { fPtr->fErrorDef = up; // update user state for new value of up (scaling of errors) fPtr->fUserState = MnUserParameterState(State(), up, Seed().Trafo()); } private: struct Data { MinimumSeed fSeed; std::vector fStates; double fErrorDef; bool fAboveMaxEdm; bool fReachedCallLimit; mutable MnUserParameterState fUserState; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_FunctionMinimum iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/GenericFunction.h0000644000000000000000000000264014332717401022350 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_GenericFunction #define ROOT_Minuit2_GenericFunction #include "Minuit2/MnConfig.h" #include namespace ROOT { namespace Minuit2 { //_____________________________________________________________________ /** Class from which all the other classes, representing functions, inherit. That is why it defines only one method, the operator(), which allows to call the function. @author Andras Zsenei and Lorenzo Moneta, Creation date: 23 Sep 2004 @ingroup Minuit */ class GenericFunction { public: virtual ~GenericFunction() {} /** Evaluates the function using the vector containing the input values. @param x vector of the coordinates (for example the x coordinate for a one-dimensional Gaussian) @return the result of the evaluation of the function. */ virtual double operator()(const std::vector &x) const = 0; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_GenericFunction iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/GradientCalculator.h0000644000000000000000000000233714332717401023040 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_GradientCalculator #define ROOT_Minuit2_GradientCalculator #include "Minuit2/MnMatrixfwd.h" namespace ROOT { namespace Minuit2 { class MinimumParameters; class FunctionGradient; /** interface class for gradient calculators */ class GradientCalculator { public: virtual ~GradientCalculator() {} virtual FunctionGradient operator()(const MinimumParameters &) const = 0; virtual FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const = 0; virtual bool Hessian(const MinimumParameters &, MnAlgebraicSymMatrix &) const { return false;} virtual bool G2(const MinimumParameters &, MnAlgebraicVector &) const { return false;} }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_GradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/HessianGradientCalculator.h0000644000000000000000000000350414332717401024350 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_HessianGradientCalculator #define ROOT_Minuit2_HessianGradientCalculator #include "Minuit2/GradientCalculator.h" #include "Minuit2/MnMatrix.h" #include namespace ROOT { namespace Minuit2 { class MnFcn; class MnUserTransformation; class MnMachinePrecision; class MnStrategy; /** HessianGradientCalculator: class to calculate Gradient for Hessian */ class HessianGradientCalculator : public GradientCalculator { public: HessianGradientCalculator(const MnFcn &fcn, const MnUserTransformation &par, const MnStrategy &stra) : fFcn(fcn), fTransformation(par), fStrategy(stra) { } FunctionGradient operator()(const MinimumParameters &) const override; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; std::pair DeltaGradient(const MinimumParameters &, const FunctionGradient &) const; const MnFcn &Fcn() const { return fFcn; } const MnUserTransformation &Trafo() const { return fTransformation; } const MnMachinePrecision &Precision() const; const MnStrategy &Strategy() const { return fStrategy; } unsigned int Ncycle() const; private: const MnFcn &fFcn; const MnUserTransformation &fTransformation; const MnStrategy &fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_HessianGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/InitialGradientCalculator.h0000644000000000000000000000270114332717401024345 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_InitialGradientCalculator #define ROOT_Minuit2_InitialGradientCalculator #include "Minuit2/GradientCalculator.h" namespace ROOT { namespace Minuit2 { class MnFcn; class MnUserTransformation; class MnMachinePrecision; /** Class to calculate an initial estimate of the gradient */ class InitialGradientCalculator : public GradientCalculator { public: InitialGradientCalculator(const MnFcn &fcn, const MnUserTransformation &par) : fFcn(fcn), fTransformation(par) {} FunctionGradient operator()(const MinimumParameters &) const override; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; const MnFcn &Fcn() const { return fFcn; } const MnUserTransformation &Trafo() const { return fTransformation; } const MnMachinePrecision &Precision() const; private: const MnFcn &fFcn; const MnUserTransformation &fTransformation; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_InitialGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/LASymMatrix.h0000644000000000000000000003307114332717401021442 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_LASymMatrix #define ROOT_Minuit2_LASymMatrix #include "Minuit2/MnConfig.h" #include "Minuit2/ABSum.h" #include "Minuit2/VectorOuterProduct.h" #include "Minuit2/MatrixInverse.h" #include "Minuit2/StackAllocator.h" #include #include #include // for memcopy // extern StackAllocator StackAllocatorHolder::Get(); namespace ROOT { namespace Minuit2 { int Mndaxpy(unsigned int, double, const double *, int, double *, int); int Mndscal(unsigned int, double, double *, int); class LAVector; int Invert(LASymMatrix &); /** Class describing a symmetric matrix of size n. The size is specified as a run-time argument passed in the constructor. The class uses expression templates for the operations and functions. Only the independent data are kept in the fdata array of size n*(n+1)/2 containing the lower triangular data */ class LASymMatrix { private: LASymMatrix() : fSize(0), fNRow(0), fData(nullptr) {} public: typedef sym Type; LASymMatrix(unsigned int n) : fSize(n * (n + 1) / 2), fNRow(n), fData( (n> 0) ? (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * n * (n + 1) / 2) : nullptr ) { // assert(fSize>0); if (fData) std::memset(fData, 0, fSize * sizeof(double)); } ~LASymMatrix() { if (fData) StackAllocatorHolder::Get().Deallocate(fData); } LASymMatrix(const LASymMatrix &v) : fSize(v.size()), fNRow(v.Nrow()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.size())) { std::memcpy(fData, v.Data(), fSize * sizeof(double)); } LASymMatrix &operator=(const LASymMatrix &v) { if (fSize < v.size()) { if (fData) StackAllocatorHolder::Get().Deallocate(fData); fSize = v.size(); fNRow = v.Nrow(); fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize); } std::memcpy(fData, v.Data(), fSize * sizeof(double)); return *this; } template LASymMatrix(const ABObj &v) : fSize(v.Obj().size()), fNRow(v.Obj().Nrow()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size())) { // std::cout<<"LASymMatrix(const ABObj& v)"< LASymMatrix(const ABObj, ABObj>, T> &sum) : fSize(0), fNRow(0), fData(nullptr) { // std::cout<<"template LASymMatrix(const ABObj, // ABObj > >& sum)"< LASymMatrix(const ABObj..."< LASymMatrix(const ABObj, ABObj>, T> &sum) : fSize(0), fNRow(0), fData(nullptr) { // std::cout<<"template LASymMatrix(const ABObj, // ABObj >,T>& sum)"< LASymMatrix(const ABObj LASymMatrix(const ABObj, T> &something) : fSize(0), fNRow(0), fData(nullptr) { // std::cout<<"template LASymMatrix(const ABObj, T>& // something)"< LASymMatrix(const ABObj, T>& // something)"< LASymMatrix(const ABObj, T>, T> &inv) : fSize(inv.Obj().Obj().Obj().size()), fNRow(inv.Obj().Obj().Obj().Nrow()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * inv.Obj().Obj().Obj().size())) { std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double)); Mndscal(fSize, double(inv.Obj().Obj().f()), fData, 1); Invert(*this); Mndscal(fSize, double(inv.f()), fData, 1); } template LASymMatrix( const ABObj, T>, T>, ABObj>, T> &sum) : fSize(0), fNRow(0), fData(nullptr) { // std::cout<<"template LASymMatrix(const ABObj, T>, T>, ABObj >, T>& sum)"< LASymMatrix(const ABObj, double>, double> &); template LASymMatrix( const ABObj, T>, T>, ABObj>, T> &sum) : fSize(0), fNRow(0), fData(nullptr) { // std::cout<<"template LASymMatrix(const ABObj, T>, T> ABObj >,T>& sum)"< LASymMatrix(const ABObj LASymMatrix &operator+=(const ABObj &m) { // std::cout<<"template LASymMatrix& operator+=(const ABObj& m)"< LASymMatrix &operator+=(const ABObj &m) { // std::cout<<"template LASymMatrix& operator+=(const ABObj& m)"< LASymMatrix &operator+=(const ABObj, T>, T> &m) { // std::cout<<"template LASymMatrix& operator+=(const ABObj, T>, T>& m)"< 0); LASymMatrix tmp(m.Obj().Obj()); Invert(tmp); tmp *= double(m.f()); (*this) += tmp; return *this; } template LASymMatrix &operator+=(const ABObj, T>, T> &m) { // std::cout<<"template LASymMatrix& operator+=(const ABObj, T>, T>&"< 0); Outer_prod(*this, m.Obj().Obj().Obj(), m.f() * m.Obj().Obj().f() * m.Obj().Obj().f()); return *this; } LASymMatrix &operator*=(double scal) { Mndscal(fSize, scal, fData, 1); return *this; } double operator()(unsigned int row, unsigned int col) const { assert(row < fNRow && col < fNRow); if (row > col) return fData[col + row * (row + 1) / 2]; else return fData[row + col * (col + 1) / 2]; } double &operator()(unsigned int row, unsigned int col) { assert(row < fNRow && col < fNRow); if (row > col) return fData[col + row * (row + 1) / 2]; else return fData[row + col * (col + 1) / 2]; } const double *Data() const { return fData; } double *Data() { return fData; } unsigned int size() const { return fSize; } unsigned int Nrow() const { return fNRow; } unsigned int Ncol() const { return Nrow(); } private: unsigned int fSize; unsigned int fNRow; double *fData; public: template LASymMatrix &operator=(const ABObj &v) { // std::cout<<"template LASymMatrix& operator=(ABObj& v)"< LASymMatrix &operator=(const ABObj, T> &something) { // std::cout<<"template LASymMatrix& operator=(const ABObj, T>& // something)"< LASymMatrix& operator=(const ABObj, T>& // something)"< LASymMatrix &operator=(const ABObj, ABObj>, T> &sum) { // std::cout<<"template LASymMatrix& operator=(const ABObj, // ABObj >,T>& sum)"< LASymMatrix &operator=(const ABObj, ABObj>, T> &sum) { // std::cout<<"template LASymMatrix& operator=(const ABObj, ABObj >,T>& sum)"< LASymMatrix &operator=(const ABObj, T>, T> &inv) { if (fSize == 0 && fData == nullptr) { fSize = inv.Obj().Obj().Obj().size(); fNRow = inv.Obj().Obj().Obj().Nrow(); fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize); std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double)); (*this) *= inv.Obj().Obj().f(); Invert(*this); (*this) *= inv.f(); } else { LASymMatrix tmp(inv.Obj().Obj()); Invert(tmp); tmp *= double(inv.f()); assert(fSize == tmp.size()); std::memcpy(fData, tmp.Data(), fSize * sizeof(double)); } return *this; } LASymMatrix &operator=(const ABObj, double>, double> &); }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_LASymMatrix iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/LAVector.h0000644000000000000000000002554414332717401020755 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_LAVector #define ROOT_Minuit2_LAVector #include "Minuit2/ABSum.h" #include "Minuit2/ABProd.h" #include "Minuit2/LASymMatrix.h" #include #include #include "Minuit2/StackAllocator.h" namespace ROOT { namespace Minuit2 { // extern StackAllocator StackAllocatorHolder::Get(); int Mndaxpy(unsigned int, double, const double *, int, double *, int); int Mndscal(unsigned int, double, double *, int); int Mndspmv(const char *, unsigned int, double, const double *, const double *, int, double, double *, int); class LAVector { private: LAVector() : fSize(0), fData(nullptr) {} public: typedef vec Type; LAVector(unsigned int n) : fSize(n), fData( (n>0) ? (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * n) : nullptr) { // assert(fSize>0); if (fData) std::memset(fData, 0, size() * sizeof(double)); // std::cout<<"LAVector(unsigned int n), n= "< fSize) { if (fData) StackAllocatorHolder::Get().Deallocate(fData); fSize = v.size(); fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize); } std::memcpy(fData, v.Data(), fSize * sizeof(double)); return *this; } template LAVector(const ABObj &v) : fSize(v.Obj().size()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size())) { // std::cout<<"LAVector(const ABObj& v)"< LAVector(const ABObj, ABObj>, T> &sum) : fSize(0), fData(nullptr) { // std::cout<<"template LAVector(const ABObj, ABObj > >& // sum)"< LAVector(const ABObj, ABObj>, T> &sum) : fSize(0), fData(nullptr) { // std::cout<<"template LAVector(const ABObj, ABObj >,T>& // sum)"< LAVector(const ABObj LAVector(const ABObj, T> &something) : fSize(0), fData(nullptr) { // std::cout<<"template LAVector(const ABObj, T>& something)"< LAVector(const ABObj, ABObj>, T> &prod) : fSize(prod.Obj().B().Obj().size()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * prod.Obj().B().Obj().size())) { // std::cout<<"template LAVector(const ABObj, ABObj >, T>& prod)"< LAVector(const ABObj< vec, ABSum, ABObj>, T>, ABObj>, T> &prod) : fSize(0), fData(nullptr) { (*this) = prod.Obj().B(); (*this) += prod.Obj().A(); (*this) *= double(prod.f()); } // LAVector &operator+=(const LAVector &m) { // std::cout<<"LAVector& operator+=(const LAVector& m)"< LAVector &operator+=(const ABObj &m) { // std::cout<<"template LAVector& operator+=(const ABObj& m)"< LAVector &operator+=(const ABObj &m) { // std::cout<<"template LAVector& operator+=(const ABObj& m)"< LAVector &operator+=(const ABObj, ABObj>, T> &prod) { Mndspmv("U", fSize, prod.f() * prod.Obj().A().f() * prod.Obj().B().f(), prod.Obj().A().Obj().Data(), prod.Obj().B().Data(), 1, 1., fData, 1); return *this; } LAVector &operator*=(double scal) { Mndscal(fSize, scal, fData, 1); return *this; } double operator()(unsigned int i) const { assert(i < fSize); return fData[i]; } double &operator()(unsigned int i) { assert(i < fSize); return fData[i]; } double operator[](unsigned int i) const { assert(i < fSize); return fData[i]; } double &operator[](unsigned int i) { assert(i < fSize); return fData[i]; } const double *Data() const { return fData; } double *Data() { return fData; } unsigned int size() const { return fSize; } private: unsigned int fSize; double *fData; public: template LAVector &operator=(const ABObj &v) { // std::cout<<"template LAVector& operator=(ABObj& v)"< LAVector &operator=(const ABObj, T> &something) { // std::cout<<"template LAVector& operator=(const ABObj, T>& // something)"< LAVector &operator=(const ABObj, ABObj>, T> &sum) { if (fSize == 0 && !fData) { (*this) = sum.Obj().A(); (*this) += sum.Obj().B(); } else { LAVector tmp(sum.Obj().A()); tmp += sum.Obj().B(); assert(fSize == tmp.size()); std::memcpy(fData, tmp.Data(), fSize * sizeof(double)); } (*this) *= sum.f(); return *this; } template LAVector &operator=(const ABObj, ABObj>, T> &sum) { if (fSize == 0 && !fData) { (*this) = sum.Obj().B(); (*this) += sum.Obj().A(); } else { LAVector tmp(sum.Obj().A()); tmp += sum.Obj().B(); assert(fSize == tmp.size()); std::memcpy(fData, tmp.Data(), fSize * sizeof(double)); } (*this) *= sum.f(); return *this; } // template LAVector &operator=(const ABObj, ABObj>, T> &prod) { if (fSize == 0 && !fData) { fSize = prod.Obj().B().Obj().size(); fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize); Mndspmv("U", fSize, double(prod.f() * prod.Obj().A().f() * prod.Obj().B().f()), prod.Obj().A().Obj().Data(), prod.Obj().B().Obj().Data(), 1, 0., fData, 1); } else { LAVector tmp(prod.Obj().B()); assert(fSize == tmp.size()); Mndspmv("U", fSize, double(prod.f() * prod.Obj().A().f()), prod.Obj().A().Obj().Data(), tmp.Data(), 1, 0., fData, 1); } return *this; } // template LAVector & operator=(const ABObj< vec, ABSum, ABObj>, T>, ABObj>, T> &prod) { if (fSize == 0 && !fData) { (*this) = prod.Obj().B(); (*this) += prod.Obj().A(); } else { // std::cout<<"creating tmp variable"<, double>, double> Inverse(const ABObj &obj) { return ABObj, double>, double>( MatrixInverse, double>(obj)); } template inline ABObj, double>, double> operator*(T f, const ABObj, double>, double> &inv) { return ABObj, double>, double>(inv.Obj(), f * inv.f()); } template inline ABObj, double>, double> operator/(const ABObj, double>, double> &inv, T f) { return ABObj, double>, double>(inv.Obj(), inv.f() / f); } template inline ABObj, double>, double> operator-(const ABObj, double>, double> &inv) { return ABObj, double>, double>(inv.Obj(), T(-1.) * inv.f()); } int Invert(LASymMatrix &); int Invert_undef_sym(LASymMatrix &); /* template inline ABObj, double>, double> Inverse(const ABObj& obj) { return ABObj, double>, double>(MatrixInverse, double>(obj)); } inline ABObj, double>, double> Inverse(const ABObj& obj) { return ABObj, double>, double>(MatrixInverse, double>(obj)); } */ } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_LaInverse iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/LaOuterProduct.h0000644000000000000000000000541414332717401022204 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef MA_LaOuterProd_H_ #define MA_LaOuterProd_H_ #include "Minuit2/VectorOuterProduct.h" #include "Minuit2/ABSum.h" #include "Minuit2/LAVector.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { /// LAPACK Algebra function /// specialize the Outer_product function for LAVector; inline ABObj, double>, double> Outer_product(const ABObj &obj) { // std::cout<<"ABObj, double>, double> Outer_product(const // ABObj& obj)"<, double>, double>( VectorOuterProduct, double>(obj)); } // f*outer template inline ABObj, T>, T> operator*(T f, const ABObj, T>, T> &obj) { // std::cout<<"ABObj, T>, T> operator*(T f, const ABObj, T>, T>& obj)"<, T>, T>(obj.Obj(), obj.f() * f); } // outer/f template inline ABObj, T>, T> operator/(const ABObj, T>, T> &obj, T f) { // std::cout<<"ABObj, T>, T> operator/(const ABObj, T>, T>& obj, T f)"<, T>, T>(obj.Obj(), obj.f() / f); } // -outer template inline ABObj, T>, T> operator-(const ABObj, T>, T> &obj) { // std::cout<<"ABObj, T>, T> operator/(const ABObj, T>, T>& obj, T f)"<, T>, T>(obj.Obj(), T(-1.) * obj.f()); } void Outer_prod(LASymMatrix &, const LAVector &, double f = 1.); } // namespace Minuit2 } // namespace ROOT #endif // MA_LaOuterProd_H_ iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/LaProd.h0000644000000000000000000000473014332717401020451 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_LaProd #define ROOT_Minuit2_LaProd #include "Minuit2/ABProd.h" #include "Minuit2/LAVector.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { /* LM" remove this for fixing alpha poblem #define OP_MULT1(MT1,MT2,MAT1,MAT2,T) \ template \ inline ABObj::Type,ABProd, ABObj >,T> operator*(const ABObj& a, const ABObj& b) { return ABObj::Type,ABProd, ABObj >,T>(ABProd, ABObj >(a, b)); } \ template \ inline ABObj::Type,ABProd, ABObj >,T> operator*(const ABObj& a, const ABObj& b) { \ return ABObj::Type,ABProd, ABObj >,T>(ABProd, ABObj >(a, b)); \ } \ \ */ #define OP_MULT1(MT1, MT2, MAT1, MAT2, T) \ inline ABObj::Type, ABProd, ABObj>, T> operator*( \ const ABObj &a, const ABObj &b) \ { \ return ABObj::Type, ABProd, ABObj>, T>( \ ABProd, ABObj>(a, b)); \ } OP_MULT1(sym, vec, LASymMatrix, LAVector, double) // OP_MULT1(sym,gen,LASymMatrix,LAGenMatrix,double) // OP_MULT1(sym,sym,LASymMatrix,LASymMatrix,double) // OP_MULT1(gen,vec,LAGenMatrix,LAVector,double) // OP_MULT1(gen,sym,LAGenMatrix,LASymMatrix,double) // OP_MULT1(gen,gen,LAGenMatrix,LAGenMatrix,double) } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_LaProd iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/LaSum.h0000644000000000000000000000631614332717401020313 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_LaSum #define ROOT_Minuit2_LaSum #include "Minuit2/ABSum.h" #include "Minuit2/LAVector.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { #define OP_ADD1(MT, MAT1, T) \ inline ABObj operator-(const ABObj &m) \ { \ return ABObj(m.Obj(), T(-1.) * m.f()); \ } \ \ inline ABObj, ABObj>, T> operator+(const ABObj &a, \ const ABObj &b) \ { \ return ABObj, ABObj>, T>( \ ABSum, ABObj>(a, b)); \ } \ inline ABObj, ABObj>, T> operator-(const ABObj &a, \ const ABObj &b) \ { \ return ABObj, ABObj>, T>( \ ABSum, ABObj>(a, ABObj(b.Obj(), T(-1.) * b.f()))); \ } OP_ADD1(vec, LAVector, double) OP_ADD1(sym, LASymMatrix, double) #define OP_SCALE(MT, MAT1, T) \ inline ABObj operator*(T f, const MAT1 &obj) { return ABObj(obj, f); } OP_SCALE(sym, LASymMatrix, double) OP_SCALE(vec, LAVector, double) #define OP_SCALE1(MT, MAT1, T) \ inline ABObj operator/(const MAT1 &obj, T f) { return ABObj(obj, 1. / f); } OP_SCALE1(sym, LASymMatrix, double) OP_SCALE1(vec, LAVector, double) #define OP_MIN(MT, MAT1, T) \ inline ABObj operator-(const MAT1 &obj) { return ABObj(obj, T(-1.)); } OP_MIN(sym, LASymMatrix, double) OP_MIN(vec, LAVector, double) } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_LaSum iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MPIProcess.h0000644000000000000000000001016314332717401021251 0ustar00// @(#)root/minuit2:$Id$ // Author: A. Lazzaro 2009 /*************************************************************************** * Package: Minuit2 * * File: $Id$ * * Author: Alfio Lazzaro, alfio.lazzaro@mi.infn.it * * * * Copyright: (C) 2008 by Universita' and INFN, Milan * ***************************************************************************/ #ifndef ROOT_Minuit2_MPIProcess #define ROOT_Minuit2_MPIProcess // disable MPI calls //#define MPIPROC #include "Minuit2/MnMatrix.h" #ifdef MPIPROC #include "mpi.h" #include #endif namespace ROOT { namespace Minuit2 { class MPITerminate { public: ~MPITerminate() { #ifdef MPIPROC if (MPI::Is_initialized() && !(MPI::Is_finalized())) { std::cout << "Info --> MPITerminate:: End MPI on #" << MPI::COMM_WORLD.Get_rank() << " processor" << std::endl; MPI::Finalize(); } #endif } }; class MPIProcess { public: MPIProcess(unsigned int nelements, unsigned int indexComm); ~MPIProcess(); inline unsigned int NumElements4JobIn() const { return fNumElements4JobIn; } inline unsigned int NumElements4JobOut() const { return fNumElements4JobOut; } inline unsigned int NumElements4Job(unsigned int rank) const { return NumElements4JobIn() + ((rank < NumElements4JobOut()) ? 1 : 0); } inline unsigned int StartElementIndex() const { return ((fRank < NumElements4JobOut()) ? (fRank * NumElements4Job(fRank)) : (fNelements - (fSize - fRank) * NumElements4Job(fRank))); } inline unsigned int EndElementIndex() const { return StartElementIndex() + NumElements4Job(fRank); } inline unsigned int GetMPISize() const { return fSize; } inline unsigned int GetMPIRank() const { return fRank; } bool SyncVector(ROOT::Minuit2::MnAlgebraicVector &mnvector); bool SyncSymMatrixOffDiagonal(ROOT::Minuit2::MnAlgebraicSymMatrix &mnmatrix); static unsigned int GetMPIGlobalRank() { StartMPI(); return fgGlobalRank; } static unsigned int GetMPIGlobalSize() { StartMPI(); return fgGlobalSize; } static inline void StartMPI() { #ifdef MPIPROC if (!(MPI::Is_initialized())) { MPI::Init(); std::cout << "Info --> MPIProcess::StartMPI: Start MPI on #" << MPI::COMM_WORLD.Get_rank() << " processor" << std::endl; } fgGlobalSize = MPI::COMM_WORLD.Get_size(); fgGlobalRank = MPI::COMM_WORLD.Get_rank(); #endif } static void TerminateMPI() { #ifdef MPIPROC if (fgCommunicators[0] != 0 && fgCommunicators[1] != 0) { delete fgCommunicators[0]; fgCommunicators[0] = 0; fgIndicesComm[0] = 0; delete fgCommunicators[1]; fgCommunicators[1] = 0; fgIndicesComm[1] = 0; } MPITerminate(); #endif } static bool SetCartDimension(unsigned int dimX, unsigned int dimY); static bool SetDoFirstMPICall(bool doFirstMPICall = true); inline void SumReduce(const double &sub, double &total) { total = sub; #ifdef MPIPROC if (fSize > 1) { fgCommunicator->Allreduce(&sub, &total, 1, MPI::DOUBLE, MPI::SUM); } #endif } private: #ifdef MPIPROC void MPISyncVector(double *ivector, int svector, double *ovector); #endif private: unsigned int fNelements; unsigned int fSize; unsigned int fRank; static unsigned int fgGlobalSize; static unsigned int fgGlobalRank; static unsigned int fgCartSizeX; static unsigned int fgCartSizeY; static unsigned int fgCartDimension; static bool fgNewCart; unsigned int fNumElements4JobIn; unsigned int fNumElements4JobOut; #ifdef MPIPROC static MPI::Intracomm *fgCommunicator; static int fgIndexComm; // maximum 2 communicators, so index can be 0 and 1 static MPI::Intracomm *fgCommunicators[2]; // maximum 2 communicators static unsigned int fgIndicesComm[2]; #endif }; } // namespace Minuit2 } // namespace ROOT #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MatrixInverse.h0000644000000000000000000000263614332717401022073 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MatrixInverse #define ROOT_Minuit2_MatrixInverse #include "Minuit2/ABTypes.h" #include "Minuit2/ABObj.h" namespace ROOT { namespace Minuit2 { template class MatrixInverse { public: MatrixInverse(const M &obj) : fObject(obj) {} ~MatrixInverse() {} typedef mtype Type; const M &Obj() const { return fObject; } private: M fObject; }; template class MatrixInverse { private: MatrixInverse(const M &obj) : fObject(obj) {} public: ~MatrixInverse() {} typedef vec Type; const M &Obj() const { return fObject; } private: M fObject; }; template inline ABObj, T>, T> Inverse(const ABObj &obj) { return ABObj, T>, T>(MatrixInverse, T>(obj)); } } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MatrixInverse iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumBuilder.h0000644000000000000000000000344514332717401022214 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumBuilder #define ROOT_Minuit2_MinimumBuilder #include "Minuit2/MnTraceObject.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { class FunctionMinimum; class MnFcn; class GradientCalculator; class MinimumSeed; class MinimumState; class MnStrategy; class MinimumBuilder { public: MinimumBuilder(); virtual ~MinimumBuilder() {} virtual FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const = 0; int StorageLevel() const { return fStorageLevel; } int PrintLevel() const { return fPrintLevel; } bool TraceIter() const { return (fTracer); } MnTraceObject *TraceObject() const { return (fTracer); } virtual void SetPrintLevel(int level) { fPrintLevel = level; } virtual void SetStorageLevel(int level) { fStorageLevel = level; } // set trace object (user manages it) virtual void SetTraceObject(MnTraceObject &obj) { fTracer = &obj; } void TraceIteration(int iter, const MinimumState &state) const { if (fTracer) (*fTracer)(iter, state); } private: int fPrintLevel; int fStorageLevel; MnTraceObject *fTracer; //! tracer object (it is managed by user) }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumError.h0000644000000000000000000000655514332717401021724 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumError #define ROOT_Minuit2_MinimumError #include "Minuit2/MnConfig.h" #include "Minuit2/MnMatrix.h" #include "Minuit2/MnPrint.h" #include "Minuit2/LaSum.h" #include namespace ROOT { namespace Minuit2 { /** MinimumError keeps the inv. 2nd derivative (inv. Hessian) used for calculating the Parameter step size (-V*g) and for the covariance Update (ErrorUpdator). The covariance matrix is equal to twice the inv. Hessian. */ class MinimumError { public: enum Status { MnUnset, MnPosDef, MnMadePosDef, MnNotPosDef, MnHesseFailed, MnInvertFailed, MnReachedCallLimit, }; public: MinimumError(unsigned int n) : fPtr{new Data{{n}, 1.0, MnUnset}} {} MinimumError(const MnAlgebraicSymMatrix &mat, double dcov) : fPtr{new Data{mat, dcov, MnPosDef}} {} MinimumError(const MnAlgebraicSymMatrix &mat, Status status) : fPtr{new Data{mat, 1.0, status}} {} MnAlgebraicSymMatrix Matrix() const { return 2. * fPtr->fMatrix; } // why *2 ? const MnAlgebraicSymMatrix &InvHessian() const { return fPtr->fMatrix; } // calculate invert of matrix. Used to compute Hessian by inverting matrix MnAlgebraicSymMatrix Hessian() const { return InvertMatrix(fPtr->fMatrix); } static MnAlgebraicSymMatrix InvertMatrix(const MnAlgebraicSymMatrix & matrix, int & ifail) { // calculate inverse of given matrix MnAlgebraicSymMatrix tmp(matrix); ifail = ROOT::Minuit2::Invert(tmp); if (ifail != 0) { MnPrint print("MinimumError::Invert"); print.Warn("Inversion fails; return diagonal matrix"); for (unsigned int i = 0; i < matrix.Nrow(); ++i) for (unsigned int j = 0; j <= i; j++) tmp(i, j) = i == j ? 1. / matrix(i, i) : 0; } return tmp; } static MnAlgebraicSymMatrix InvertMatrix(const MnAlgebraicSymMatrix & matrix) { int ifail = 0; return InvertMatrix(matrix, ifail); } double Dcovar() const { return fPtr->fDCovar; } Status GetStatus() const { return fPtr->fStatus; } bool IsValid() const { return IsAvailable() && (IsPosDef() || IsMadePosDef() || IsNotPosDef()); } bool IsAccurate() const { return IsPosDef() && Dcovar() < 0.1; } bool IsPosDef() const { return GetStatus() == MnPosDef; } bool IsMadePosDef() const { return GetStatus() == MnMadePosDef; } bool IsNotPosDef() const { return GetStatus() == MnNotPosDef; } bool HesseFailed() const { return GetStatus() == MnHesseFailed; } bool InvertFailed() const { return GetStatus() == MnInvertFailed; } bool HasReachedCallLimit() const { return GetStatus() == MnReachedCallLimit; } bool IsAvailable() const { return GetStatus() != MnUnset; } private: struct Data { MnAlgebraicSymMatrix fMatrix; double fDCovar; Status fStatus; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumError iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumErrorUpdator.h0000644000000000000000000000166714332717401023262 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumErrorUpdator #define ROOT_Minuit2_MinimumErrorUpdator namespace ROOT { namespace Minuit2 { class MinimumState; class MinimumError; class MinimumParameters; class FunctionGradient; class MinimumErrorUpdator { public: virtual ~MinimumErrorUpdator() {} virtual MinimumError Update(const MinimumState &, const MinimumParameters &, const FunctionGradient &) const = 0; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumErrorUpdator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumParameters.h0000644000000000000000000000340014332717401022720 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumParameters #define ROOT_Minuit2_MinimumParameters #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { class MinimumParameters { public: MinimumParameters(unsigned int n, double fval = 0) : fPtr{new Data{MnAlgebraicVector(n), MnAlgebraicVector(n), fval, false, false}} { } /** takes the Parameter vector */ MinimumParameters(const MnAlgebraicVector &avec, double fval) : fPtr{new Data{avec, MnAlgebraicVector(avec.size()), fval, true, false}} { } /** takes the Parameter vector plus step size x1 - x0 = dirin */ MinimumParameters(const MnAlgebraicVector &avec, const MnAlgebraicVector &dirin, double fval) : fPtr{new Data{avec, dirin, fval, true, true}} { } const MnAlgebraicVector &Vec() const { return fPtr->fParameters; } const MnAlgebraicVector &Dirin() const { return fPtr->fStepSize; } double Fval() const { return fPtr->fFVal; } bool IsValid() const { return fPtr->fValid; } bool HasStepSize() const { return fPtr->fHasStep; } private: struct Data { MnAlgebraicVector fParameters; MnAlgebraicVector fStepSize; double fFVal; bool fValid; bool fHasStep; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumParameters iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumSeed.h0000644000000000000000000000334114332717401021501 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumSeed #define ROOT_Minuit2_MinimumSeed #include "Minuit2/MinimumState.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/MinimumError.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MnUserTransformation.h" namespace ROOT { namespace Minuit2 { class MinimumSeed { public: MinimumSeed(const MinimumState &state, const MnUserTransformation &trafo) : fPtr{new Data{state, trafo, true}} {} const MinimumState &State() const { return fPtr->fState; } const MinimumParameters &Parameters() const { return State().Parameters(); } const MinimumError &Error() const { return State().Error(); }; const FunctionGradient &Gradient() const { return State().Gradient(); } const MnUserTransformation &Trafo() const { return fPtr->fTrafo; } const MnMachinePrecision &Precision() const { return Trafo().Precision(); } double Fval() const { return State().Fval(); } double Edm() const { return State().Edm(); } unsigned int NFcn() const { return State().NFcn(); } bool IsValid() const { return fPtr->fValid; } private: struct Data { MinimumState fState; MnUserTransformation fTrafo; bool fValid; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumSeed iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumSeedGenerator.h0000644000000000000000000000256114332717401023353 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumSeedGenerator #define ROOT_Minuit2_MinimumSeedGenerator namespace ROOT { namespace Minuit2 { class MinimumSeed; class MnFcn; class GradientCalculator; class MnUserParameterState; class MnStrategy; class AnalyticalGradientCalculator; /** base class for seed generators (starting values); the seed generator prepares initial starting values from the input (MnUserParameterState) for the minimization; */ class MinimumSeedGenerator { public: virtual ~MinimumSeedGenerator() {} virtual MinimumSeed operator()(const MnFcn &, const GradientCalculator &, const MnUserParameterState &, const MnStrategy &) const = 0; virtual MinimumSeed operator()(const MnFcn &, const AnalyticalGradientCalculator &, const MnUserParameterState &, const MnStrategy &) const = 0; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumSeedGenerator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinimumState.h0000644000000000000000000000622714332717401021707 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinimumState #define ROOT_Minuit2_MinimumState #include "Minuit2/MinimumParameters.h" #include "Minuit2/MinimumError.h" #include "Minuit2/FunctionGradient.h" #include namespace ROOT { namespace Minuit2 { /** MinimumState keeps the information (position, Gradient, 2nd deriv, etc) after one minimization step (usually in MinimumBuilder). */ class MinimumState { public: /// Invalid state. MinimumState(unsigned int n) : MinimumState(MinimumParameters(n, 0.0), MinimumError(n), FunctionGradient(n), 0.0, 0) { } /// Constructor without parameter values, but with function value, edm and nfcn. /// This constructor will result in a state that is flagged as not valid MinimumState(double fval, double edm, int nfcn) : MinimumState(MinimumParameters(0, fval), MinimumError(0), FunctionGradient(0), edm, nfcn) { } /// Constructor with only parameter values, edm and nfcn, but without errors (covariance). /// The resulting state it will be considered valid, since it contains the parameter values, /// although it has not the error matrix (MinimumError) and HasCovariance() returns false. MinimumState(const MinimumParameters &states, double edm, int nfcn) : MinimumState(states, MinimumError(states.Vec().size()), FunctionGradient(states.Vec().size()), edm, nfcn) { } /// Constructor with parameters values, errors and gradient MinimumState(const MinimumParameters &states, const MinimumError &err, const FunctionGradient &grad, double edm, int nfcn) : fPtr{new Data{states, err, grad, edm, nfcn}} { } const MinimumParameters &Parameters() const { return fPtr->fParameters; } const MnAlgebraicVector &Vec() const { return Parameters().Vec(); } int size() const { return Vec().size(); } const MinimumError &Error() const { return fPtr->fError; } const FunctionGradient &Gradient() const { return fPtr->fGradient; } double Fval() const { return Parameters().Fval(); } double Edm() const { return fPtr->fEDM; } int NFcn() const { return fPtr->fNFcn; } bool IsValid() const { if (HasParameters() && HasCovariance()) return Parameters().IsValid() && Error().IsValid(); else if (HasParameters()) return Parameters().IsValid(); else return false; } bool HasParameters() const { return Parameters().IsValid(); } bool HasCovariance() const { return Error().IsAvailable(); } private: struct Data { MinimumParameters fParameters; MinimumError fError; FunctionGradient fGradient; double fEDM; int fNFcn; }; std::shared_ptr fPtr; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinimumState iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinosError.h0000644000000000000000000001012714332717401021364 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinosError #define ROOT_Minuit2_MinosError #include "Minuit2/MnCross.h" #include namespace ROOT { namespace Minuit2 { //____________________________________________________________________________________ /** Class holding the result of Minos (lower and upper values) for a specific parameter */ class MinosError { public: MinosError() : fParameter(0), fMinParValue(0.), fUpper(MnCross()), fLower(MnCross()) {} MinosError(unsigned int par, double value, const MnCross &low, const MnCross &up) : fParameter(par), fMinParValue(value), fUpper(up), fLower(low) { } ~MinosError() {} MinosError(const MinosError &err) : fParameter(err.fParameter), fMinParValue(err.fMinParValue), fUpper(err.fUpper), fLower(err.fLower) { } MinosError &operator=(const MinosError &) = default; MinosError &operator()(const MinosError &err) { fParameter = err.fParameter; fMinParValue = err.fMinParValue; fUpper = err.fUpper; fLower = err.fLower; return *this; } std::pair operator()() const { return std::pair(Lower(), Upper()); } double Lower() const { if (AtLowerLimit()) return LowerState().Parameter(Parameter()).LowerLimit() - fMinParValue; if (LowerValid()) { // Minos error is value - error - aopt * error where aopt is MnCross.Value() // If value - error is below the limit, error must be truncated at limit double err = LowerState().Error(Parameter()); // error is truncated if over the limit if (LowerState().Parameter(Parameter()).HasLowerLimit()) err = std::min(err, fMinParValue - LowerState().Parameter(Parameter()).LowerLimit()); return -1. * err * (1. + fLower.Value()); } // return Hessian Error in case is invalid return -LowerState().Error(Parameter()); } double Upper() const { if (AtUpperLimit()) return UpperState().Parameter(Parameter()).UpperLimit() - fMinParValue; if (UpperValid()) { // Minos error is value + error + aopt * error where aopt is MnCross.Value() // If value + error is over the limit, err must be truncated at limit double err = UpperState().Error(Parameter()); if (UpperState().Parameter(Parameter()).HasUpperLimit()) err = std::min(err, UpperState().Parameter(Parameter()).UpperLimit() - fMinParValue); return err * (1. + fUpper.Value()); } // return Hessian Error in case is invalid return UpperState().Error(Parameter()); } unsigned int Parameter() const { return fParameter; } const MnUserParameterState &LowerState() const { return fLower.State(); } const MnUserParameterState &UpperState() const { return fUpper.State(); } bool IsValid() const { return fLower.IsValid() && fUpper.IsValid(); } bool LowerValid() const { return fLower.IsValid(); } bool UpperValid() const { return fUpper.IsValid(); } bool AtLowerLimit() const { return fLower.AtLimit(); } bool AtUpperLimit() const { return fUpper.AtLimit(); } bool AtLowerMaxFcn() const { return fLower.AtMaxFcn(); } bool AtUpperMaxFcn() const { return fUpper.AtMaxFcn(); } bool LowerNewMin() const { return fLower.NewMinimum(); } bool UpperNewMin() const { return fUpper.NewMinimum(); } unsigned int NFcn() const { return fUpper.NFcn() + fLower.NFcn(); } // return parameter value at the minimum double Min() const { return fMinParValue; } private: unsigned int fParameter; double fMinParValue; MnCross fUpper; MnCross fLower; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinosError iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/Minuit2Minimizer.h0000644000000000000000000003150314332717401022501 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta Wed Oct 18 11:48:00 2006 /********************************************************************** * * * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT * * * * * **********************************************************************/ // Header file for class Minuit2Minimizer #ifndef ROOT_Minuit2_Minuit2Minimizer #define ROOT_Minuit2_Minuit2Minimizer #include "Math/Minimizer.h" #include "Minuit2/MnUserParameterState.h" #include "Math/IFunctionfwd.h" #include #include #include namespace ROOT { namespace Minuit2 { class ModularFunctionMinimizer; class FCNBase; class FunctionMinimum; class MnTraceObject; // enumeration specifying the type of Minuit2 minimizers enum EMinimizerType { kMigrad, kSimplex, kCombined, kScan, kFumili, kMigradBFGS }; } // namespace Minuit2 namespace Minuit2 { //_____________________________________________________________________________________________________ /** Minuit2Minimizer class implementing the ROOT::Math::Minimizer interface for Minuit2 minimization algorithm. In ROOT it can be instantiated using the plug-in manager (plug-in "Minuit2") Using a string (used by the plugin manager) or via an enumeration an one can set all the possible minimization algorithms (Migrad, Simplex, Combined, Scan and Fumili). Refer to the [guide](https://root.cern/root/htmldoc/guides/minuit2/Minuit2.html) for an introduction how Minuit works. @ingroup Minuit */ class Minuit2Minimizer : public ROOT::Math::Minimizer { public: /** Default constructor */ Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type = ROOT::Minuit2::kMigrad); /** Constructor with a char (used by PM) */ Minuit2Minimizer(const char *type); /** Destructor (no operations) */ ~Minuit2Minimizer() override; private: // usually copying is non trivial, so we make this unaccessible /** Copy constructor */ Minuit2Minimizer(const Minuit2Minimizer &); /** Assignment operator */ Minuit2Minimizer &operator=(const Minuit2Minimizer &rhs); public: // clear resources (parameters) for consecutives minimizations void Clear() override; /// set the function to minimize void SetFunction(const ROOT::Math::IMultiGenFunction &func) override; /// set the function implementing Hessian computation void SetHessianFunction(std::function &, double *)> hfunc) override; /// set free variable bool SetVariable(unsigned int ivar, const std::string &name, double val, double step) override; /// set lower limit variable (override if minimizer supports them ) bool SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower) override; /// set upper limit variable (override if minimizer supports them ) bool SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper) override; /// set upper/lower limited variable (override if minimizer supports them ) bool SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double /* lower */, double /* upper */) override; /// set fixed variable (override if minimizer supports them ) bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */) override; /// set variable bool SetVariableValue(unsigned int ivar, double val) override; // set variable values bool SetVariableValues(const double *val) override; /// set the step size of an already existing variable bool SetVariableStepSize(unsigned int ivar, double step) override; /// set the lower-limit of an already existing variable bool SetVariableLowerLimit(unsigned int ivar, double lower) override; /// set the upper-limit of an already existing variable bool SetVariableUpperLimit(unsigned int ivar, double upper) override; /// set the limits of an already existing variable bool SetVariableLimits(unsigned int ivar, double lower, double upper) override; /// fix an existing variable bool FixVariable(unsigned int ivar) override; /// release an existing variable bool ReleaseVariable(unsigned int ivar) override; /// query if an existing variable is fixed (i.e. considered constant in the minimization) /// note that by default all variables are not fixed bool IsFixedVariable(unsigned int ivar) const override; /// get variable settings in a variable object (like ROOT::Fit::ParamsSettings) bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const override; /// get name of variables (override if minimizer support storing of variable names) std::string VariableName(unsigned int ivar) const override; /// get index of variable given a variable given a name /// return -1 if variable is not found int VariableIndex(const std::string &name) const override; /** method to perform the minimization. Return false in case the minimization did not converge. In this case a status code different than zero is set (retrieved by the derived method Minimizer::Status() )" status = 1 : Covariance was made pos defined status = 2 : Hesse is invalid status = 3 : Edm is above max status = 4 : Reached call limit status = 5 : Any other failure */ bool Minimize() override; /// return minimum function value double MinValue() const override { return fState.Fval(); } /// return expected distance reached from the minimum double Edm() const override { return fState.Edm(); } /// return pointer to X values at the minimum const double *X() const override { return &fValues.front(); } /// return pointer to gradient values at the minimum const double *MinGradient() const override { return nullptr; } // not available in Minuit2 /// number of function calls to reach the minimum unsigned int NCalls() const override { return fState.NFcn(); } /// this is <= Function().NDim() which is the total /// number of variables (free+ constrained ones) unsigned int NDim() const override { return fDim; } /// number of free variables (real dimension of the problem) /// this is <= Function().NDim() which is the total unsigned int NFree() const override { return fState.VariableParameters(); } /// minimizer provides error and error matrix bool ProvidesError() const override { return true; } /// return errors at the minimum const double *Errors() const override; /** return covariance matrix elements if the variable is fixed or const the value is zero The ordering of the variables is the same as in errors and parameter value. This is different from the direct interface of Minuit2 or TMinuit where the values were obtained only to variable parameters */ double CovMatrix(unsigned int i, unsigned int j) const override; /** Fill the passed array with the covariance matrix elements if the variable is fixed or const the value is zero. The array will be filled as cov[i *ndim + j] The ordering of the variables is the same as in errors and parameter value. This is different from the direct interface of Minuit2 or TMinuit where the values were obtained only to variable parameters */ bool GetCovMatrix(double *cov) const override; /** Fill the passed array with the Hessian matrix elements The Hessian matrix is the matrix of the second derivatives and is the inverse of the covariance matrix If the variable is fixed or const the values for that variables are zero. The array will be filled as h[i *ndim + j] */ bool GetHessianMatrix(double *h) const override; /** return the status of the covariance matrix status = -1 : not available (inversion failed or Hesse failed) status = 0 : available but not positive defined status = 1 : covariance only approximate status = 2 : full matrix but forced pos def status = 3 : full accurate matrix */ int CovMatrixStatus() const override; /** return correlation coefficient between variable i and j. If the variable is fixed or const the return value is zero */ double Correlation(unsigned int i, unsigned int j) const override; /** get global correlation coefficient for the variable i. This is a number between zero and one which gives the correlation between the i-th variable and that linear combination of all other variables which is most strongly correlated with i. If the variable is fixed or const the return value is zero */ double GlobalCC(unsigned int i) const override; /** get the minos error for parameter i, return false if Minos failed A minimizaiton must be performed befre, return false if no minimization has been done In case of Minos failed the status error is updated as following status += 10 * minosStatus. The Minos status of last Minos run can also be retrieved by calling MinosStatus() */ bool GetMinosError(unsigned int i, double &errLow, double &errUp, int = 0) override; /** MINOS status code of last Minos run `status & 1 > 0` : invalid lower error `status & 2 > 0` : invalid upper error `status & 4 > 0` : invalid because maximum number of function calls exceeded `status & 8 > 0` : a new minimum has been found `status & 16 > 0` : error is truncated because parameter is at lower/upper limit */ int MinosStatus() const override { return fMinosStatus; } /** scan a parameter i around the minimum. A minimization must have been done before, return false if it is not the case */ bool Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin = 0, double xmax = 0) override; /** find the contour points (xi,xj) of the function for parameter i and j around the minimum The contour will be find for value of the function = Min + ErrorUp(); */ bool Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) override; /** perform a full calculation of the Hessian matrix for error calculation If a valid minimum exists the calculation is done on the minimum point otherwise is performed in the current set values of parameters Status code of minimizer is updated according to the following convention (in case Hesse failed) status += 100*hesseStatus where hesse status is: status = 1 : hesse failed status = 2 : matrix inversion failed status = 3 : matrix is not pos defined */ bool Hesse() override; /// return reference to the objective function /// virtual const ROOT::Math::IGenFunction & Function() const; /// print result of minimization void PrintResults() override; /// set an object to trace operation for each iteration /// The object must be a (or inherit from) ROOT::Minuit2::MnTraceObject and implement operator() (int, const /// MinimumState & state) void SetTraceObject(MnTraceObject &obj); /// set storage level = 1 : store all iteration states (default) /// = 0 : store only first and last state to save memory void SetStorageLevel(int level); /// return the minimizer state (containing values, step size , etc..) const ROOT::Minuit2::MnUserParameterState &State() { return fState; } protected: // protected function for accessing the internal Minuit2 object. Needed for derived classes virtual const ROOT::Minuit2::ModularFunctionMinimizer *GetMinimizer() const { return fMinimizer; } virtual void SetMinimizer(ROOT::Minuit2::ModularFunctionMinimizer *m) { fMinimizer = m; } void SetMinimizerType(ROOT::Minuit2::EMinimizerType type); virtual const ROOT::Minuit2::FCNBase *GetFCN() const { return fMinuitFCN; } /// examine the minimum result bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min); // internal function to compute Minos errors int RunMinosError(unsigned int i, double &errLow, double &errUp, int runopt); private: unsigned int fDim; // dimension of the function to be minimized bool fUseFumili; int fMinosStatus = -1; // Minos status code ROOT::Minuit2::MnUserParameterState fState; // std::vector fMinosErrors; ROOT::Minuit2::ModularFunctionMinimizer *fMinimizer; ROOT::Minuit2::FCNBase *fMinuitFCN; ROOT::Minuit2::FunctionMinimum *fMinimum; mutable std::vector fValues; mutable std::vector fErrors; }; } // namespace Minuit2 } // end namespace ROOT #endif /* ROOT_Minuit2_Minuit2Minimizer */ iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MinuitParameter.h0000644000000000000000000001234414332717401022376 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MinuitParameter #define ROOT_Minuit2_MinuitParameter #include #include #include #include namespace ROOT { namespace Minuit2 { //____________________________________________________________________________ /** class for the individual Minuit Parameter with Name and number; contains the input numbers for the minimization or the output result from minimization; possible interactions: Fix/release, set/remove limits, set Value/error; From version 5.20: use string to store the name to avoid limitation of name length of 20 characters */ class MinuitParameter { public: // default constructor standard with value/error = 0 MinuitParameter() : fNum(0), fValue(0), fError(0.), fConst(false), fFix(false), fLoLimit(0.), fUpLimit(0.), fLoLimValid(false), fUpLimValid(false), fName("") { } // constructor for constant Parameter MinuitParameter(unsigned int num, const std::string &name, double val) : fNum(num), fValue(val), fError(0.), fConst(true), fFix(false), fLoLimit(0.), fUpLimit(0.), fLoLimValid(false), fUpLimValid(false), fName(name) { } // constructor for standard Parameter MinuitParameter(unsigned int num, const std::string &name, double val, double err) : fNum(num), fValue(val), fError(err), fConst(false), fFix(false), fLoLimit(0.), fUpLimit(0.), fLoLimValid(false), fUpLimValid(false), fName(name) { } // constructor for limited Parameter MinuitParameter(unsigned int num, const std::string &name, double val, double err, double min, double max) : fNum(num), fValue(val), fError(err), fConst(false), fFix(false), fLoLimit(min), fUpLimit(max), fLoLimValid(true), fUpLimValid(true), fName(name) { assert(min != max); if (min > max) { fLoLimit = max; fUpLimit = min; } } ~MinuitParameter() {} MinuitParameter(const MinuitParameter &par) : fNum(par.fNum), fValue(par.fValue), fError(par.fError), fConst(par.fConst), fFix(par.fFix), fLoLimit(par.fLoLimit), fUpLimit(par.fUpLimit), fLoLimValid(par.fLoLimValid), fUpLimValid(par.fUpLimValid), fName(par.fName) { } MinuitParameter &operator=(const MinuitParameter &par) { if (this != &par) { fNum = par.fNum; fName = par.fName; fValue = par.fValue; fError = par.fError; fConst = par.fConst; fFix = par.fFix; fLoLimit = par.fLoLimit; fUpLimit = par.fUpLimit; fLoLimValid = par.fLoLimValid; fUpLimValid = par.fUpLimValid; } return *this; } // access methods unsigned int Number() const { return fNum; } // new API returning a string const std::string &GetName() const { return fName; } // return const char * for maintaining backward compatibility const char *Name() const { return fName.c_str(); } double Value() const { return fValue; } double Error() const { return fError; } // interaction void SetName(const std::string &name) { fName = name; } void SetValue(double val) { fValue = val; } void SetError(double err) { fError = err; } void SetLimits(double low, double up) { assert(low != up); fLoLimit = low; fUpLimit = up; fLoLimValid = true; fUpLimValid = true; if (low > up) { fLoLimit = up; fUpLimit = low; } } void SetUpperLimit(double up) { fLoLimit = 0.; fUpLimit = up; fLoLimValid = false; fUpLimValid = true; } void SetLowerLimit(double low) { fLoLimit = low; fUpLimit = 0.; fLoLimValid = true; fUpLimValid = false; } void RemoveLimits() { fLoLimit = 0.; fUpLimit = 0.; fLoLimValid = false; fUpLimValid = false; } void Fix() { fFix = true; } void Release() { fFix = false; } // state of Parameter (fixed/const/limited) bool IsConst() const { return fConst; } bool IsFixed() const { return fFix; } bool HasLimits() const { return fLoLimValid || fUpLimValid; } bool HasLowerLimit() const { return fLoLimValid; } bool HasUpperLimit() const { return fUpLimValid; } double LowerLimit() const { return fLoLimit; } double UpperLimit() const { return fUpLimit; } private: unsigned int fNum; double fValue; double fError; bool fConst; bool fFix; double fLoLimit; double fUpLimit; bool fLoLimValid; bool fUpLimValid; std::string fName; private: // void SetName(const std::string & name) { // int l = std::min(int(strlen(name)), 11); // memset(fName, 0, 11*sizeof(char)); // memcpy(fName, name, l*sizeof(char)); // fName[10] = '\0'; // } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MinuitParameter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnApplication.h0000644000000000000000000001123714332717401022026 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnApplication #define ROOT_Minuit2_MnApplication #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnStrategy.h" #include namespace ROOT { namespace Minuit2 { class FunctionMinimum; class MinuitParameter; class MnMachinePrecision; class ModularFunctionMinimizer; class FCNBase; class FCNGradientBase; //___________________________________________________________________________ /** application interface class for minimizers (migrad, simplex, Minimize, Scan) User normally instantiates the derived class like ROOT::Minuit2::MnMigrad for using Migrad for minimization */ class MnApplication { public: /// constructor from non-gradient functions MnApplication(const FCNBase &fcn, const MnUserParameterState &state, const MnStrategy &stra, unsigned int nfcn = 0); /// constructor from gradient function MnApplication(const FCNGradientBase &fcn, const MnUserParameterState &state, const MnStrategy &stra, unsigned int nfcn = 0); virtual ~MnApplication() {} /** Minimize the function @param maxfcn : max number of function calls (if = 0) default is used which is set to 200 + 100 * npar + 5 * npar**2 @param tolerance : value used for terminating iteration procedure. For example, MIGRAD will stop iterating when edm (expected distance from minimum) will be: edm < tolerance * 10**-3 Default value of tolerance used is 0.1 */ virtual FunctionMinimum operator()(unsigned int maxfcn = 0, double tolerance = 0.1); virtual ModularFunctionMinimizer &Minimizer() = 0; virtual const ModularFunctionMinimizer &Minimizer() const = 0; const MnMachinePrecision &Precision() const { return fState.Precision(); } const MnUserParameterState &State() const { return fState; } const MnUserParameters &Parameters() const { return fState.Parameters(); } const MnUserCovariance &Covariance() const { return fState.Covariance(); } virtual const FCNBase &Fcnbase() const { return fFCN; } const MnStrategy &Strategy() const { return fStrategy; } unsigned int NumOfCalls() const { return fNumCall; } protected: const FCNBase &fFCN; MnUserParameterState fState; MnStrategy fStrategy; unsigned int fNumCall; bool fUseGrad; public: // facade: forward interface of MnUserParameters and MnUserTransformation // via MnUserParameterState // access to parameters (row-wise) const std::vector &MinuitParameters() const; // access to parameters and errors in column-wise representation std::vector Params() const; std::vector Errors() const; // access to single Parameter const MinuitParameter &Parameter(unsigned int i) const; // add free Parameter void Add(const char *Name, double val, double err); // add limited Parameter void Add(const char *Name, double val, double err, double, double); // add const Parameter void Add(const char *, double); // interaction via external number of Parameter void Fix(unsigned int); void Release(unsigned int); void SetValue(unsigned int, double); void SetError(unsigned int, double); void SetLimits(unsigned int, double, double); void RemoveLimits(unsigned int); double Value(unsigned int) const; double Error(unsigned int) const; // interaction via Name of Parameter void Fix(const char *); void Release(const char *); void SetValue(const char *, double); void SetError(const char *, double); void SetLimits(const char *, double, double); void RemoveLimits(const char *); void SetPrecision(double); double Value(const char *) const; double Error(const char *) const; // convert Name into external number of Parameter unsigned int Index(const char *) const; // convert external number into Name of Parameter const char *Name(unsigned int) const; // transformation internal <-> external double Int2ext(unsigned int, double) const; double Ext2int(unsigned int, double) const; unsigned int IntOfExt(unsigned int) const; unsigned int ExtOfInt(unsigned int) const; unsigned int VariableParameters() const; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnApplication iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnConfig.h0000644000000000000000000000124414332717401020765 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnConfig #define ROOT_Minuit2_MnConfig #ifdef _MSC_VER #pragma warning(disable : 4244) // conversion from __w64 to int #endif #if defined(__sun) && !defined(linux) #include #endif #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnContours.h0000644000000000000000000000436414332717401021402 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnContours #define ROOT_Minuit2_MnContours #include "Minuit2/MnConfig.h" #include "Minuit2/MnStrategy.h" #include #include namespace ROOT { namespace Minuit2 { class FCNBase; class FunctionMinimum; class ContoursError; //_____________________________________________________________ /** API class for Contours Error analysis (2-dim errors); minimization has to be done before and Minimum must be valid; possibility to ask only for the points or the points and associated Minos errors; */ class MnContours { public: /// construct from FCN + Minimum MnContours(const FCNBase &fcn, const FunctionMinimum &min) : fFCN(fcn), fMinimum(min), fStrategy(MnStrategy(1)) {} /// construct from FCN + Minimum + strategy MnContours(const FCNBase &fcn, const FunctionMinimum &min, unsigned int stra) : fFCN(fcn), fMinimum(min), fStrategy(MnStrategy(stra)) { } /// construct from FCN + Minimum + strategy MnContours(const FCNBase &fcn, const FunctionMinimum &min, const MnStrategy &stra) : fFCN(fcn), fMinimum(min), fStrategy(stra) { } ~MnContours() {} /// ask for one Contour (points only) from number of points (>=4) and parameter indices std::vector> operator()(unsigned int, unsigned int, unsigned int npoints = 20) const; /// ask for one Contour ContoursError (MinosErrors + points) /// from number of points (>=4) and parameter indices /// can be printed via std::cout ContoursError Contour(unsigned int, unsigned int, unsigned int npoints = 20) const; const MnStrategy &Strategy() const { return fStrategy; } private: const FCNBase &fFCN; const FunctionMinimum &fMinimum; MnStrategy fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnContours iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnCovarianceSqueeze.h0000644000000000000000000000227114332717401023175 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnCovarianceSqueeze #define ROOT_Minuit2_MnCovarianceSqueeze #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { class MnUserCovariance; class MinimumError; /** class to reduce the covariance matrix when a parameter is fixed by removing the corresponding row and index */ class MnCovarianceSqueeze { public: MnCovarianceSqueeze() {} ~MnCovarianceSqueeze() {} MnUserCovariance operator()(const MnUserCovariance &, unsigned int) const; MinimumError operator()(const MinimumError &, unsigned int) const; MnAlgebraicSymMatrix operator()(const MnAlgebraicSymMatrix &, unsigned int) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnCovarianceSqueeze iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnCross.h0000644000000000000000000000614214332717401020653 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnCross #define ROOT_Minuit2_MnCross #include "Minuit2/MnUserParameterState.h" namespace ROOT { namespace Minuit2 { class MnCross { public: class CrossParLimit { }; class CrossFcnLimit { }; class CrossNewMin { }; public: MnCross() : fValue(0.), fState(MnUserParameterState()), fNFcn(0), fValid(false), fLimset(false), fMaxFcn(false), fNewMin(false) { } MnCross(unsigned int nfcn) : fValue(0.), fState(MnUserParameterState()), fNFcn(nfcn), fValid(false), fLimset(false), fMaxFcn(false), fNewMin(false) { } MnCross(const MnUserParameterState &state, unsigned int nfcn) : fValue(0.), fState(state), fNFcn(nfcn), fValid(false), fLimset(false), fMaxFcn(false), fNewMin(false) { } MnCross(double value, const MnUserParameterState &state, unsigned int nfcn) : fValue(value), fState(state), fNFcn(nfcn), fValid(true), fLimset(false), fMaxFcn(false), fNewMin(false) { } MnCross(const MnUserParameterState &state, unsigned int nfcn, CrossParLimit) : fValue(0.), fState(state), fNFcn(nfcn), fValid(true), fLimset(true), fMaxFcn(false), fNewMin(false) { } MnCross(const MnUserParameterState &state, unsigned int nfcn, CrossFcnLimit) : fValue(0.), fState(state), fNFcn(nfcn), fValid(false), fLimset(false), fMaxFcn(true), fNewMin(false) { } MnCross(const MnUserParameterState &state, unsigned int nfcn, CrossNewMin) : fValue(0.), fState(state), fNFcn(nfcn), fValid(false), fLimset(false), fMaxFcn(false), fNewMin(true) { } ~MnCross() {} MnCross(const MnCross &cross) : fValue(cross.fValue), fState(cross.fState), fNFcn(cross.fNFcn), fValid(cross.fValid), fLimset(cross.fLimset), fMaxFcn(cross.fMaxFcn), fNewMin(cross.fNewMin) { } MnCross &operator=(const MnCross &) = default; MnCross &operator()(const MnCross &cross) { fValue = cross.fValue; fState = cross.fState; fNFcn = cross.fNFcn; fValid = cross.fValid; fLimset = cross.fLimset; fMaxFcn = cross.fMaxFcn; fNewMin = cross.fNewMin; return *this; } double Value() const { return fValue; } const MnUserParameterState &State() const { return fState; } bool IsValid() const { return fValid; } bool AtLimit() const { return fLimset; } bool AtMaxFcn() const { return fMaxFcn; } bool NewMinimum() const { return fNewMin; } unsigned int NFcn() const { return fNFcn; } private: double fValue; MnUserParameterState fState; unsigned int fNFcn; bool fValid; bool fLimset; bool fMaxFcn; bool fNewMin; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnCross iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnEigen.h0000644000000000000000000000166714332717401020620 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnEigen #define ROOT_Minuit2_MnEigen #include "Minuit2/MnConfig.h" #include namespace ROOT { namespace Minuit2 { class MnUserCovariance; /** API class for calculating the eigenvalues of symmetric matrix */ class MnEigen { public: MnEigen() {} ~MnEigen() {} /// calculate the eigenvalues std::vector operator()(const MnUserCovariance &) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnEigen iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnFcn.h0000644000000000000000000000333314332717401020267 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnFcn #define ROOT_Minuit2_MnFcn #include "Minuit2/MnConfig.h" #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { class FCNBase; /** Wrapper class to FCNBase interface used internally by Minuit. Apply conversion from calling the function from a Minuit Vector (MnAlgebraicVector) to a std::vector for the function coordinates. The class counts also the number of function calls. By default counter start from zero, but a different value might be given if the class is instantiated later on, for example for a set of different minimizaitons Normally the derived class MnUserFCN should be instantiated with performs in addition the transformatiopn internal-> external parameters */ class MnFcn { public: /// constructor of explicit MnFcn(const FCNBase &fcn, int ncall = 0) : fFCN(fcn), fNumCall(ncall) {} virtual ~MnFcn(); virtual double operator()(const MnAlgebraicVector &) const; unsigned int NumOfCalls() const { return fNumCall; } // // forward interface // double ErrorDef() const; double Up() const; const FCNBase &Fcn() const { return fFCN; } private: const FCNBase &fFCN; protected: mutable int fNumCall; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnFcn iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnFumiliMinimize.h0000644000000000000000000000764614332717401022523 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnFumiliMinimize #define ROOT_Minuit2_MnFumiliMinimize #include "Minuit2/MnApplication.h" #include "Minuit2/FumiliMinimizer.h" #include "Minuit2/FumiliFCNBase.h" #include namespace ROOT { namespace Minuit2 { // class FumiliFCNBase; // class FCNBase; //___________________________________________________________________________ /** API class for minimization using Fumili technology; allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc.; also used by MnMinos and MnContours; */ class MnFumiliMinimize : public MnApplication { public: /// construct from FumiliFCNBase + std::vector for parameters and errors MnFumiliMinimize(const FumiliFCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } /// construct from FumiliFCNBase + std::vector for parameters and covariance MnFumiliMinimize(const FumiliFCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } /// construct from FumiliFCNBase + std::vector for parameters and MnUserCovariance MnFumiliMinimize(const FumiliFCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } /// construct from FumiliFCNBase + MnUserParameters MnFumiliMinimize(const FumiliFCNBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } /// construct from FumiliFCNBase + MnUserParameters + MnUserCovariance MnFumiliMinimize(const FumiliFCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } /// construct from FumiliFCNBase + MnUserParameterState + MnStrategy MnFumiliMinimize(const FumiliFCNBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(FumiliMinimizer()), fFCN(fcn) { } MnFumiliMinimize(const MnFumiliMinimize &migr) : MnApplication(migr.Fcnbase(), migr.State(), migr.Strategy(), migr.NumOfCalls()), fMinimizer(migr.fMinimizer), fFCN(migr.Fcnbase()) { } ~MnFumiliMinimize() override {} FumiliMinimizer &Minimizer() override { return fMinimizer; } const FumiliMinimizer &Minimizer() const override { return fMinimizer; } const FumiliFCNBase &Fcnbase() const override { return fFCN; } /// overwrite Minimize to use FumiliFCNBase FunctionMinimum operator()(unsigned int = 0, double = 0.1) override; private: FumiliMinimizer fMinimizer; const FumiliFCNBase &fFCN; private: // forbidden assignment of migrad (const FumiliFCNBase& = ) MnFumiliMinimize &operator=(const MnFumiliMinimize &) { return *this; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnFumiliMinimize iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnFunctionCross.h0000644000000000000000000000247614332717401022367 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnFunctionCross #define ROOT_Minuit2_MnFunctionCross #include "Minuit2/MnConfig.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; class MnUserParameterState; class MnStrategy; class MnCross; /** MnFunctionCross */ class MnFunctionCross { public: MnFunctionCross(const FCNBase &fcn, const MnUserParameterState &state, double fval, const MnStrategy &stra) : fFCN(fcn), fState(state), fFval(fval), fStrategy(stra) { } ~MnFunctionCross() {} MnCross operator()(const std::vector &, const std::vector &, const std::vector &, double, unsigned int) const; private: const FCNBase &fFCN; const MnUserParameterState &fState; double fFval; const MnStrategy &fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnFunctionCross iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnGlobalCorrelationCoeff.h0000644000000000000000000000227214332717401024127 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnGlobalCorrelationCoeff #define ROOT_Minuit2_MnGlobalCorrelationCoeff #include "Minuit2/MnConfig.h" #include "Minuit2/MnMatrix.h" #include namespace ROOT { namespace Minuit2 { /** class for global correlation coefficient */ class MnGlobalCorrelationCoeff { public: MnGlobalCorrelationCoeff() : fGlobalCC(std::vector()), fValid(false) {} MnGlobalCorrelationCoeff(const MnAlgebraicSymMatrix &); ~MnGlobalCorrelationCoeff() {} const std::vector &GlobalCC() const { return fGlobalCC; } bool IsValid() const { return fValid; } private: std::vector fGlobalCC; bool fValid; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnGlobalCorrelationCoeff iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnHesse.h0000644000000000000000000000776614332717401020646 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnHesse #define ROOT_Minuit2_MnHesse #include "Minuit2/MnConfig.h" #include "Minuit2/MnStrategy.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; class MnUserParameterState; class MnUserParameters; class MnUserCovariance; class MnUserTransformation; class MinimumState; class MnMachinePrecision; class MnFcn; class FunctionMinimum; class FCNGradientBase; //_______________________________________________________________________ /** API class for calculating the numerical covariance matrix (== 2x Inverse Hessian == 2x Inverse 2nd derivative); can be used by the user or Minuit itself */ class MnHesse { public: /// default constructor with default strategy MnHesse() : fStrategy(MnStrategy(1)) {} /// constructor with user-defined strategy level MnHesse(unsigned int stra) : fStrategy(MnStrategy(stra)) {} /// conctructor with specific strategy MnHesse(const MnStrategy &stra) : fStrategy(stra) {} ~MnHesse() {} /// /// low-level API /// /// FCN + parameters + errors MnUserParameterState operator()(const FCNBase &, const std::vector &, const std::vector &, unsigned int maxcalls = 0) const; /// FCN + parameters + covariance MnUserParameterState operator()(const FCNBase &, const std::vector &, unsigned int nrow, const std::vector &, unsigned int maxcalls = 0) const; /// FCN + parameters + MnUserCovariance MnUserParameterState operator()(const FCNBase &, const std::vector &, const MnUserCovariance &, unsigned int maxcalls = 0) const; /// /// high-level API /// /// FCN + MnUserParameters MnUserParameterState operator()(const FCNBase &, const MnUserParameters &, unsigned int maxcalls = 0) const; /// FCN + MnUserParameters + MnUserCovariance MnUserParameterState operator()(const FCNBase &, const MnUserParameters &, const MnUserCovariance &, unsigned int maxcalls = 0) const; /// FCN + MnUserParameterState MnUserParameterState operator()(const FCNBase &, const MnUserParameterState &, unsigned int maxcalls = 0) const; /// /// API to use MnHesse after minimization when function minimum is avalilable, otherwise information on the last /// state will be lost. (It would be needed to re-call the gradient and spend extra useless function calls) The /// Function Minimum is updated (modified) by adding the Hesse results as last state of minimization /// void operator()(const FCNBase &, FunctionMinimum &, unsigned int maxcalls = 0) const; /// internal interface /// MinimumState operator()(const MnFcn &, const MinimumState &, const MnUserTransformation &, unsigned int maxcalls = 0) const; /// forward interface of MnStrategy unsigned int Ncycles() const { return fStrategy.HessianNCycles(); } double Tolerstp() const { return fStrategy.HessianStepTolerance(); } double TolerG2() const { return fStrategy.HessianG2Tolerance(); } private: /// internal function to compute the Hessian using numerical derivative computation MinimumState ComputeNumerical(const MnFcn &, const MinimumState &, const MnUserTransformation &, unsigned int maxcalls) const; /// internal function to compute the Hessian using an analytical computation or externally provided in the FCNGradientBase class MinimumState ComputeAnalytical(const FCNGradientBase &, const MinimumState &, const MnUserTransformation &) const; MnStrategy fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnHesse iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnLineSearch.h0000644000000000000000000000343014332717401021574 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnLineSearch #define ROOT_Minuit2_MnLineSearch #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { class MnFcn; class MinimumParameters; class MnMachinePrecision; class MnParabolaPoint; /** Implements a 1-dimensional minimization along a given direction (i.e. quadratic interpolation) It is independent of the algorithm that generates the direction vector. It brackets the 1-dimensional Minimum and iterates to approach the real Minimum of the n-dimensional function. @author Fred James and Matthias Winkler; comments added by Andras Zsenei and Lorenzo Moneta @ingroup Minuit */ class MnLineSearch { public: MnLineSearch() {} ~MnLineSearch() {} MnParabolaPoint operator()(const MnFcn &, const MinimumParameters &, const MnAlgebraicVector &, double, const MnMachinePrecision &) const; #ifdef USE_OTHER_LS MnParabolaPoint CubicSearch(const MnFcn &, const MinimumParameters &, const MnAlgebraicVector &, double, double, const MnMachinePrecision &) const; MnParabolaPoint BrentSearch(const MnFcn &, const MinimumParameters &, const MnAlgebraicVector &, double, double, const MnMachinePrecision &) const; #endif private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnLineSearch iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMachinePrecision.h0000644000000000000000000000355214332717401023004 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMachinePrecision #define ROOT_Minuit2_MnMachinePrecision #include namespace ROOT { namespace Minuit2 { /** Sets the relative floating point (double) arithmetic precision. By default the precision values are obtained from the standard functions std::numeric_limits::epsilon. The values can optionally be computed directly using the ComputePrecision() member function. For a IEEE standard floating point arithmetic the computed values and the one from std::numeric_limits::epsilon are the same. SetPrecision() method can instead be used to override Minuit's own determination, when the user knows that the {FCN} function Value is not calculated to the nominal machine accuracy. */ class MnMachinePrecision { public: MnMachinePrecision(); /// eps returns the smallest possible number so that 1.+eps > 1. double Eps() const { return fEpsMac; } /// eps2 returns 2*sqrt(eps) double Eps2() const { return fEpsMa2; } /// override Minuit's own determination void SetPrecision(double prec) { fEpsMac = prec; fEpsMa2 = 2. * std::sqrt(fEpsMac); } /// compute Machine precision directly instead /// of using default values from std::numeric_limits void ComputePrecision(); private: double fEpsMac; double fEpsMa2; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnMachinePrecision iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMatrix.h0000644000000000000000000000153214332717401021024 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMatrix #define ROOT_Minuit2_MnMatrix // add MnConfig file to define before everything compiler // dependent macros #include "Minuit2/MnConfig.h" // define typedf's in MnMatrixfwd #include "Minuit2/MnMatrixfwd.h" #include "Minuit2/LASymMatrix.h" #include "Minuit2/LAVector.h" #include "Minuit2/LaInverse.h" #include "Minuit2/LaOuterProduct.h" #endif // ROOT_Minuit2_MnMatrix iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMatrixfwd.h0000644000000000000000000000136514332717401021531 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMatrixfwd #define ROOT_Minuit2_MnMatrixfwd namespace ROOT { namespace Minuit2 { class LASymMatrix; class LAVector; typedef LASymMatrix MnAlgebraicSymMatrix; typedef LAVector MnAlgebraicVector; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnMatrixfwd iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMigrad.h0000644000000000000000000001251114332717401020762 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMigrad #define ROOT_Minuit2_MnMigrad #include "Minuit2/MnApplication.h" #include "Minuit2/VariableMetricMinimizer.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; //_____________________________________________________________________________ /** API class for minimization using Variable Metric technology ("MIGRAD"); allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc.; also used by MnMinos and MnContours; */ class MnMigrad : public MnApplication { public: /// construct from FCNBase + std::vector for parameters and errors MnMigrad(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNBase + std::vector for parameters and covariance MnMigrad(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNBase + std::vector for parameters and MnUserCovariance MnMigrad(const FCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNBase + MnUserParameters MnMigrad(const FCNBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNBase + MnUserParameters + MnUserCovariance MnMigrad(const FCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNBase + MnUserParameterState + MnStrategy MnMigrad(const FCNBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(VariableMetricMinimizer()) { } // constructs from gradient FCN /// construct from FCNGradientBase + std::vector for parameters and errors MnMigrad(const FCNGradientBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNGradientBase + std::vector for parameters and covariance MnMigrad(const FCNGradientBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNGradientBase + std::vector for parameters and MnUserCovariance MnMigrad(const FCNGradientBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNGradientBase + MnUserParameters MnMigrad(const FCNGradientBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNGradientBase + MnUserParameters + MnUserCovariance MnMigrad(const FCNGradientBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(VariableMetricMinimizer()) { } /// construct from FCNGradientBase + MnUserParameterState + MnStrategy MnMigrad(const FCNGradientBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(VariableMetricMinimizer()) { } ~MnMigrad() override {} /// Copy constructor, copy shares the reference to the same FCNBase in MnApplication MnMigrad(const MnMigrad &) = default; // Copy assignment deleted, since MnApplication has unassignable reference to FCNBase MnMigrad &operator=(const MnMigrad &) = delete; ModularFunctionMinimizer &Minimizer() override { return fMinimizer; } const ModularFunctionMinimizer &Minimizer() const override { return fMinimizer; } private: VariableMetricMinimizer fMinimizer; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnMigrad iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMinimize.h0000644000000000000000000001232214332717401021340 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMinimize #define ROOT_Minuit2_MnMinimize #include "Minuit2/MnApplication.h" #include "Minuit2/CombinedMinimizer.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; /** API class for minimization using Variable Metric technology ("MIGRAD"); allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc.; also used by MnMinos and MnContours; */ class MnMinimize : public MnApplication { public: /// construct from FCNBase + std::vector for parameters and errors MnMinimize(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNBase + std::vector for parameters and covariance MnMinimize(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNBase + std::vector for parameters and MnUserCovariance MnMinimize(const FCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNBase + MnUserParameters MnMinimize(const FCNBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNBase + MnUserParameters + MnUserCovariance MnMinimize(const FCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNBase + MnUserParameterState + MnStrategy MnMinimize(const FCNBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(CombinedMinimizer()) { } // interfaces using FCNGradientBase /// construct from FCNGradientBase + std::vector for parameters and errors MnMinimize(const FCNGradientBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNGradientBase + std::vector for parameters and covariance MnMinimize(const FCNGradientBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNGradientBase + std::vector for parameters and MnUserCovariance MnMinimize(const FCNGradientBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNGradientBase + MnUserParameters MnMinimize(const FCNGradientBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNGradientBase + MnUserParameters + MnUserCovariance MnMinimize(const FCNGradientBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(CombinedMinimizer()) { } /// construct from FCNGradientBase + MnUserParameterState + MnStrategy MnMinimize(const FCNGradientBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(CombinedMinimizer()) { } MnMinimize(const MnMinimize &migr) : MnApplication(migr.Fcnbase(), migr.State(), migr.Strategy(), migr.NumOfCalls()), fMinimizer(migr.fMinimizer) { } ~MnMinimize() override {} ModularFunctionMinimizer &Minimizer() override { return fMinimizer; } const ModularFunctionMinimizer &Minimizer() const override { return fMinimizer; } private: CombinedMinimizer fMinimizer; private: // forbidden assignment operator MnMinimize &operator=(const MnMinimize &) { return *this; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnMinimize iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnMinos.h0000644000000000000000000000461614332717401020653 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnMinos #define ROOT_Minuit2_MnMinos #include "Minuit2/MnStrategy.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; class FunctionMinimum; class MinosError; class MnCross; //__________________________________________________________________ /** API class for Minos Error analysis (asymmetric errors); minimization has to be done before and Minimum must be valid; possibility to ask only for one side of the Minos Error; */ class MnMinos { public: /// construct from FCN + Minimum + strategy MnMinos(const FCNBase &fcn, const FunctionMinimum &min, unsigned int stra = 1); /// construct from FCN + Minimum + strategy MnMinos(const FCNBase &fcn, const FunctionMinimum &min, const MnStrategy &stra); ~MnMinos() {} /// returns the negative (pair.first) and the positive (pair.second) /// Minos Error of the Parameter std::pair operator()(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; /// calculate one side (negative or positive Error) of the Parameter /// give as input (optionally) maxcalls and tolerance double Lower(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; double Upper(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; MnCross Loval(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; MnCross Upval(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; /// ask for MinosError (Lower + Upper) /// can be printed via std::cout MinosError Minos(unsigned int, unsigned int maxcalls = 0, double toler = 0.1) const; protected: /// internal method to get crossing value via MnFunctionCross MnCross FindCrossValue(int dir, unsigned int, unsigned int maxcalls, double toler) const; private: const FCNBase &fFCN; const FunctionMinimum &fMinimum; MnStrategy fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnMinos iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnParabola.h0000644000000000000000000000662414332717401021310 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnParabola #define ROOT_Minuit2_MnParabola #include namespace ROOT { namespace Minuit2 { /** This class defines a parabola of the form a*x*x + b*x + c @author Fred James and Matthias Winkler; comments added by Andras Zsenei and Lorenzo Moneta @ingroup Minuit */ class MnParabola { public: /** Constructor that initializes the parabola with its three parameters. @param a the coefficient of the quadratic term @param b the coefficient of the linear term @param c the constant */ MnParabola(double a, double b, double c) : fA(a), fB(b), fC(c) {} ~MnParabola() {} /** Evaluates the parabola a the point x. @param x the coordinate where the parabola needs to be evaluated. @return the y coordinate of the parabola corresponding to x. */ double Y(double x) const { return (fA * x * x + fB * x + fC); } /** Calculates the bigger of the two x values corresponding to the given y Value.

???????!!!!!!!!! And when there is none?? it looks like it will crash?? what is sqrt (-1.0) ? @param y the y Value for which the x Value is to be calculated. @return the bigger one of the two corresponding values. */ // ok, at first glance it does not look like the formula for the quadratic // equation, but it is! ;-) double X_pos(double y) const { return (std::sqrt(y / fA + Min() * Min() - fC / fA) + Min()); } // maybe it is worth to check the performance improvement with the below formula?? // double X_pos(double y) const {return (std::sqrt(y/fA + fB*fB/(4.*fA*fA) - fC/fA) - fB/(2.*fA));} /** Calculates the smaller of the two x values corresponding to the given y Value.

???????!!!!!!!!! And when there is none?? it looks like it will crash?? what is sqrt (-1.0) ? @param y the y Value for which the x Value is to be calculated. @return the smaller one of the two corresponding values. */ double X_neg(double y) const { return (-std::sqrt(y / fA + Min() * Min() - fC / fA) + Min()); } /** Calculates the x coordinate of the Minimum of the parabola. @return x coordinate of the Minimum. */ double Min() const { return -fB / (2. * fA); } /** Calculates the y coordinate of the Minimum of the parabola. @return y coordinate of the Minimum. */ double YMin() const { return (-fB * fB / (4. * fA) + fC); } /** Accessor to the coefficient of the quadratic term. @return the coefficient of the quadratic term. */ double A() const { return fA; } /** Accessor to the coefficient of the linear term. @return the coefficient of the linear term. */ double B() const { return fB; } /** Accessor to the coefficient of the constant term. @return the coefficient of the constant term. */ double C() const { return fC; } private: double fA; double fB; double fC; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnParabola iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnParabolaFactory.h0000644000000000000000000000175314332717401022636 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnParabolaFactory #define ROOT_Minuit2_MnParabolaFactory namespace ROOT { namespace Minuit2 { class MnParabola; class MnParabolaPoint; class MnParabolaFactory { public: MnParabolaFactory() {} ~MnParabolaFactory() {} MnParabola operator()(const MnParabolaPoint &, const MnParabolaPoint &, const MnParabolaPoint &) const; MnParabola operator()(const MnParabolaPoint &, double, const MnParabolaPoint &) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnParabolaFactory iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnParabolaPoint.h0000644000000000000000000000317614332717401022321 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnParabolaPoint #define ROOT_Minuit2_MnParabolaPoint namespace ROOT { namespace Minuit2 { /** A point of a parabola.

????!!!! in reality it is just a general point in two dimensional space, there is nothing that would indicate, that it belongs to a parabola. This class defines simply an (x,y) pair!!!! @author Fred James and Matthias Winkler; comments added by Andras Zsenei and Lorenzo Moneta @ingroup Minuit \todo Should it be called MnParabolaPoint or just Point? */ class MnParabolaPoint { public: /** Initializes the point with its coordinates. @param x the x (first) coordinate of the point. @param y the y (second) coordinate of the point. */ MnParabolaPoint(double x, double y) : fX(x), fY(y) {} ~MnParabolaPoint() {} /** Accessor to the x (first) coordinate. @return the x (first) coordinate of the point. */ double X() const { return fX; } /** Accessor to the y (second) coordinate. @return the y (second) coordinate of the point. */ double Y() const { return fY; } private: double fX; double fY; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnParabolaPoint iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnParameterScan.h0000644000000000000000000000275314332717401022313 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnParameterScan #define ROOT_Minuit2_MnParameterScan #include "Minuit2/MnConfig.h" #include "Minuit2/MnUserParameters.h" #include #include namespace ROOT { namespace Minuit2 { class FCNBase; /** Scans the values of FCN as a function of one Parameter and retains the best function and Parameter values found. */ class MnParameterScan { public: MnParameterScan(const FCNBase &, const MnUserParameters &); MnParameterScan(const FCNBase &, const MnUserParameters &, double); ~MnParameterScan() {} // returns pairs of (x,y) points, x=parameter Value, y=function Value of FCN std::vector> operator()(unsigned int par, unsigned int maxsteps = 41, double low = 0., double high = 0.); const MnUserParameters &Parameters() const { return fParameters; } double Fval() const { return fAmin; } private: const FCNBase &fFCN; MnUserParameters fParameters; double fAmin; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnParameterScan iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnPlot.h0000644000000000000000000000264614332717401020505 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnPlot #define ROOT_Minuit2_MnPlot #include "Minuit2/MnConfig.h" #include #include namespace ROOT { namespace Minuit2 { /** MnPlot produces a text-screen graphical output of (x,y) points, e.g. from Scan or Contours. */ class MnPlot { public: MnPlot() : fPageWidth(80), fPageLength(30) {} MnPlot(unsigned int width, unsigned int length) : fPageWidth(width), fPageLength(length) { if (fPageWidth > 120) fPageWidth = 120; if (fPageLength > 56) fPageLength = 56; } ~MnPlot() {} void operator()(const std::vector> &) const; void operator()(double, double, const std::vector> &) const; unsigned int Width() const { return fPageWidth; } unsigned int Length() const { return fPageLength; } private: unsigned int fPageWidth; unsigned int fPageLength; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnPlot iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnPosDef.h0000644000000000000000000000202714332717401020740 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnPosDef #define ROOT_Minuit2_MnPosDef namespace ROOT { namespace Minuit2 { class MinimumState; class MinimumError; class MnMachinePrecision; /** Force the covariance matrix to be positive defined by adding extra terms in the diagonal */ class MnPosDef { public: MnPosDef() {} ~MnPosDef() {} MinimumState operator()(const MinimumState &, const MnMachinePrecision &) const; MinimumError operator()(const MinimumError &, const MnMachinePrecision &) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnPosDef iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnPrint.h0000644000000000000000000001365414332717401020664 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnPrint #define ROOT_Minuit2_MnPrint #include "Minuit2/MnConfig.h" #include #include #include #include #include namespace ROOT { namespace Minuit2 { /** define std::ostream operators for output */ class FunctionMinimum; std::ostream &operator<<(std::ostream &, const FunctionMinimum &); class MinimumState; std::ostream &operator<<(std::ostream &, const MinimumState &); class LAVector; std::ostream &operator<<(std::ostream &, const LAVector &); class LASymMatrix; std::ostream &operator<<(std::ostream &, const LASymMatrix &); class MnUserParameters; std::ostream &operator<<(std::ostream &, const MnUserParameters &); class MnUserCovariance; std::ostream &operator<<(std::ostream &, const MnUserCovariance &); class MnGlobalCorrelationCoeff; std::ostream &operator<<(std::ostream &, const MnGlobalCorrelationCoeff &); class MnUserParameterState; std::ostream &operator<<(std::ostream &, const MnUserParameterState &); class MnMachinePrecision; std::ostream &operator<<(std::ostream &, const MnMachinePrecision &); class MinosError; std::ostream &operator<<(std::ostream &, const MinosError &); class ContoursError; std::ostream &operator<<(std::ostream &, const ContoursError &); // std::pair is used by MnContour std::ostream &operator<<(std::ostream &os, const std::pair &point); /* Design notes: 1) We want to delay the costly conversion from object references to strings to a point after we have decided whether or not to show that string to the user at all. 2) We want to offer a customization point for external libraries that want to replace the MnPrint logging. The actual implementation is in a separate file, MnPrintImpl.cxx file that external libraries can replace with their own implementation. */ // logging class for messages of varying severity class MnPrint { public: // want this to be an enum class for strong typing... enum class Verbosity { Error = 0, Warn = 1, Info = 2, Debug = 3, Trace = 4 }; // ...but also want the values accessible from MnPrint scope for convenience static constexpr auto eError = Verbosity::Error; static constexpr auto eWarn = Verbosity::Warn; static constexpr auto eInfo = Verbosity::Info; static constexpr auto eDebug = Verbosity::Debug; static constexpr auto eTrace = Verbosity::Trace; // used for one-line printing of fcn minimum state class Oneline { public: Oneline(double fcn, double edm, int ncalls, int iter = -1); Oneline(const MinimumState &state, int iter = -1); Oneline(const FunctionMinimum &fmin, int iter = -1); private: double fFcn, fEdm; int fNcalls, fIter; friend std::ostream &operator<<(std::ostream &os, const Oneline &x); }; MnPrint(const char *prefix, int level = MnPrint::GlobalLevel()); ~MnPrint(); // set global print level and return the previous one static int SetGlobalLevel(int level); // return current global print level static int GlobalLevel(); // Whether to show the full prefix stack or only the end static void ShowPrefixStack(bool yes); static void AddFilter(const char *prefix); static void ClearFilter(); // Whether to cut the maximum number of parameters shown for vector and matrices // set maximum number of printed parameters and return previous value // A negative value will mean all parameters are printed static int SetMaxNP(int value); // retrieve maximum number of printed parameters static int MaxNP(); // set print level and return the previous one int SetLevel(int level); // return current print level int Level() const; template void Error(const Ts &... args) { Log(eError, args...); } template void Warn(const Ts &... args) { Log(eWarn, args...); } template void Info(const Ts &... args) { Log(eInfo, args...); } template void Debug(const Ts &... args) { Log(eDebug, args...); } template void Trace(const Ts &... args) { Log(eTrace, args...); } private: // low level logging template void Log(Verbosity level, const Ts &... args) { if (Level() < static_cast(level)) return; if (Hidden()) return; std::ostringstream os; StreamPrefix(os); StreamArgs(os, args...); Impl(level, os.str()); } static void StreamPrefix(std::ostringstream &os); // returns true if filters are installed and message is not selected by any filter static bool Hidden(); // see MnPrintImpl.cxx static void Impl(Verbosity level, const std::string &s); // TMP to handle lambda argument correctly, exploiting overload resolution rules template static auto HandleLambda(std::ostream &os, const T &t, int) -> decltype(t(os), void()) { t(os); } template static void HandleLambda(std::ostream &os, const T &t, float) { os << t; } static void StreamArgs(std::ostringstream &) {} // end of recursion template static void StreamArgs(std::ostringstream &os, const T &t) { os << " "; HandleLambda(os, t, 0); } template static void StreamArgs(std::ostringstream &os, const T &t, const Ts &... ts) { os << " " << t; StreamArgs(os, ts...); } int fLevel; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnPrint iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnRefCountedPointer.h0000644000000000000000000000511014332717401023153 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnRefCountedPointer #define ROOT_Minuit2_MnRefCountedPointer #include "MnReferenceCounter.h" namespace ROOT { namespace Minuit2 { template class MnRefCountedPointer { public: // Default constructor needed for use inside array, vector, etc. MnRefCountedPointer() : fPtr(0), fCounter(nullptr) {} MnRefCountedPointer(T *pt) : fPtr(pt), fCounter(new MnReferenceCounter()) { AddReference(); } MnRefCountedPointer(const MnRefCountedPointer &other) : fPtr(other.fPtr), fCounter(other.fCounter) { AddReference(); } ~MnRefCountedPointer() { /* if(References() == 0) { if(fPtr) delete fPtr; if(fCounter) delete fCounter; } else RemoveReference(); */ if (References() != 0) RemoveReference(); } bool IsValid() const { return fPtr != 0; } MnRefCountedPointer &operator=(const MnRefCountedPointer &other) { if (this != &other && fPtr != other.fPtr) { RemoveReference(); fPtr = other.fPtr; fCounter = other.fCounter; AddReference(); } return *this; } MnRefCountedPointer &operator=(T *ptr) { if (fPtr != ptr) { fPtr = ptr; fCounter = new MnReferenceCounter(); } return *this; } T *Get() const { return fPtr; } T *operator->() const { DoCheck(); return fPtr; } T &operator*() const { DoCheck(); return *fPtr; } bool operator==(const T *otherP) const { return fPtr == otherP; } bool operator<(const T *otherP) const { return fPtr < otherP; } unsigned int References() const { return fCounter->References(); } void AddReference() const { fCounter->AddReference(); } void RemoveReference() { fCounter->RemoveReference(); if (References() == 0) { delete fPtr; fPtr = 0; delete fCounter; fCounter = nullptr; } } private: T *fPtr; MnReferenceCounter *fCounter; private: void DoCheck() const { assert(IsValid()); } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnRefCountedPointer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnReferenceCounter.h0000644000000000000000000000276614332717401023030 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnReferenceCounter #define ROOT_Minuit2_MnReferenceCounter #include #include "StackAllocator.h" namespace ROOT { namespace Minuit2 { // extern StackAllocator gStackAllocator; class MnReferenceCounter { public: MnReferenceCounter() : fReferences(0) {} MnReferenceCounter(const MnReferenceCounter &other) : fReferences(other.fReferences) {} MnReferenceCounter &operator=(const MnReferenceCounter &other) { fReferences = other.fReferences; return *this; } ~MnReferenceCounter() { assert(fReferences == 0); } void *operator new(size_t nbytes) { return StackAllocatorHolder::Get().Allocate(nbytes); } void operator delete(void *p, size_t /*nbytes */) { StackAllocatorHolder::Get().Deallocate(p); } unsigned int References() const { return fReferences; } void AddReference() const { fReferences++; } void RemoveReference() const { fReferences--; } private: mutable unsigned int fReferences; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnReferenceCounter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnScan.h0000644000000000000000000000657614332717401020461 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnScan #define ROOT_Minuit2_MnScan #include "Minuit2/MnApplication.h" #include "Minuit2/ScanMinimizer.h" #include #include namespace ROOT { namespace Minuit2 { class FCNBase; //_______________________________________________________________________ /** API class for minimization using a scan method to find the minimum; allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc.; */ class MnScan : public MnApplication { public: /// construct from FCNBase + std::vector for parameters and errors MnScan(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(ScanMinimizer()) { } /// construct from FCNBase + std::vector for parameters and covariance MnScan(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(ScanMinimizer()) { } /// construct from FCNBase + std::vector for parameters and MnUserCovariance MnScan(const FCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(ScanMinimizer()) { } /// construct from FCNBase + MnUserParameters MnScan(const FCNBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(ScanMinimizer()) { } /// construct from FCNBase + MnUserParameters + MnUserCovariance MnScan(const FCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(ScanMinimizer()) { } /// construct from FCNBase + MnUserParameterState + MnStrategy MnScan(const FCNBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(ScanMinimizer()) { } MnScan(const MnScan &migr) : MnApplication(migr.Fcnbase(), migr.State(), migr.Strategy(), migr.NumOfCalls()), fMinimizer(migr.fMinimizer) { } ~MnScan() override {} ModularFunctionMinimizer &Minimizer() override { return fMinimizer; } const ModularFunctionMinimizer &Minimizer() const override { return fMinimizer; } std::vector> Scan(unsigned int par, unsigned int maxsteps = 41, double low = 0., double high = 0.); private: ScanMinimizer fMinimizer; private: /// forbidden assignment (const FCNBase& = ) MnScan &operator=(const MnScan &) { return *this; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnScan iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnSeedGenerator.h0000644000000000000000000000236114332717401022310 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnSeedGenerator #define ROOT_Minuit2_MnSeedGenerator #include "Minuit2/MinimumSeedGenerator.h" namespace ROOT { namespace Minuit2 { /** concrete implementation of the MinimumSeedGenerator interface; used within ModularFunctionMinimizer; */ class MnSeedGenerator : public MinimumSeedGenerator { public: MnSeedGenerator() {} ~MnSeedGenerator() override {} MinimumSeed operator()(const MnFcn &, const GradientCalculator &, const MnUserParameterState &, const MnStrategy &) const override; MinimumSeed operator()(const MnFcn &, const AnalyticalGradientCalculator &, const MnUserParameterState &, const MnStrategy &) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnSeedGenerator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnSimplex.h0000644000000000000000000000703614332717401021206 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnSimplex #define ROOT_Minuit2_MnSimplex #include "Minuit2/MnApplication.h" #include "Minuit2/SimplexMinimizer.h" #include namespace ROOT { namespace Minuit2 { class FCNBase; //_________________________________________________________________________ /** API class for minimization using the Simplex method, which does not need and use the derivatives of the function, but only function values. More information on the minimization method is available here. It allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc.; */ class MnSimplex : public MnApplication { public: /// construct from FCNBase + std::vector for parameters and errors MnSimplex(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, err), MnStrategy(stra)), fMinimizer(SimplexMinimizer()) { } /// construct from FCNBase + std::vector for parameters and covariance MnSimplex(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov, nrow), MnStrategy(stra)), fMinimizer(SimplexMinimizer()) { } /// construct from FCNBase + std::vector for parameters and MnUserCovariance MnSimplex(const FCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(SimplexMinimizer()) { } /// construct from FCNBase + MnUserParameters MnSimplex(const FCNBase &fcn, const MnUserParameters &par, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par), MnStrategy(stra)), fMinimizer(SimplexMinimizer()) { } /// construct from FCNBase + MnUserParameters + MnUserCovariance MnSimplex(const FCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int stra = 1) : MnApplication(fcn, MnUserParameterState(par, cov), MnStrategy(stra)), fMinimizer(SimplexMinimizer()) { } /// construct from FCNBase + MnUserParameterState + MnStrategy MnSimplex(const FCNBase &fcn, const MnUserParameterState &par, const MnStrategy &str) : MnApplication(fcn, MnUserParameterState(par), str), fMinimizer(SimplexMinimizer()) { } MnSimplex(const MnSimplex &migr) : MnApplication(migr.Fcnbase(), migr.State(), migr.Strategy(), migr.NumOfCalls()), fMinimizer(migr.fMinimizer) { } ~MnSimplex() override {} ModularFunctionMinimizer &Minimizer() override { return fMinimizer; } const ModularFunctionMinimizer &Minimizer() const override { return fMinimizer; } private: SimplexMinimizer fMinimizer; private: // forbidden assignment of migrad (const FCNBase& = ) MnSimplex &operator=(const MnSimplex &) { return *this; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnSimplex iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnStrategy.h0000644000000000000000000000701014332717401021357 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnStrategy #define ROOT_Minuit2_MnStrategy namespace ROOT { namespace Minuit2 { //_________________________________________________________________________ /** API class for defining four levels of strategies: low (0), medium (1), high (2), very high (>=3); acts on: Migrad (behavioural), Minos (lowers strategy by 1 for Minos-own minimization), Hesse (iterations), Numerical2PDerivative (iterations) */ class MnStrategy { public: // default strategy MnStrategy(); // user defined strategy (0, 1, 2, >=3) explicit MnStrategy(unsigned int); ~MnStrategy() {} unsigned int Strategy() const { return fStrategy; } unsigned int GradientNCycles() const { return fGradNCyc; } double GradientStepTolerance() const { return fGradTlrStp; } double GradientTolerance() const { return fGradTlr; } unsigned int HessianNCycles() const { return fHessNCyc; } double HessianStepTolerance() const { return fHessTlrStp; } double HessianG2Tolerance() const { return fHessTlrG2; } unsigned int HessianGradientNCycles() const { return fHessGradNCyc; } unsigned int HessianCentralFDMixedDerivatives() const { return fHessCFDG2; } unsigned int HessianForcePosDef() const { return fHessForcePosDef; } int StorageLevel() const { return fStoreLevel; } bool IsLow() const { return fStrategy == 0; } bool IsMedium() const { return fStrategy == 1; } bool IsHigh() const { return fStrategy == 2; } bool IsVeryHigh() const { return fStrategy >= 3; } void SetLowStrategy(); void SetMediumStrategy(); void SetHighStrategy(); void SetVeryHighStrategy(); void SetGradientNCycles(unsigned int n) { fGradNCyc = n; } void SetGradientStepTolerance(double stp) { fGradTlrStp = stp; } void SetGradientTolerance(double toler) { fGradTlr = toler; } void SetHessianNCycles(unsigned int n) { fHessNCyc = n; } void SetHessianStepTolerance(double stp) { fHessTlrStp = stp; } void SetHessianG2Tolerance(double toler) { fHessTlrG2 = toler; } void SetHessianGradientNCycles(unsigned int n) { fHessGradNCyc = n; } // 1 = calculate central finite difference mixed derivatives (involves 3 extra evaluations per derivative) // 0 = use forward finite difference (default) void SetHessianCentralFDMixedDerivatives(unsigned int flag) { fHessCFDG2 = flag; } // 1 = returned matrix from Hesse should be forced positive definite (default) // 0 = do not force matrix positive definite void SetHessianForcePosDef(unsigned int flag) { fHessForcePosDef = flag; } // set storage level of iteration quantities // 0 = store only last iterations 1 = full storage (default) void SetStorageLevel(unsigned int level) { fStoreLevel = level; } private: unsigned int fStrategy; unsigned int fGradNCyc; double fGradTlrStp; double fGradTlr; unsigned int fHessNCyc; double fHessTlrStp; double fHessTlrG2; unsigned int fHessGradNCyc; int fHessCFDG2; int fHessForcePosDef; int fStoreLevel; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnStrategy iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnTiny.h0000644000000000000000000000142614332717401020505 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnTiny #define ROOT_Minuit2_MnTiny namespace ROOT { namespace Minuit2 { class MnTiny { public: MnTiny() : fOne(1.) {} ~MnTiny() {} double One() const; double operator()(double epsp1) const; private: double fOne; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnTiny iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnTraceObject.h0000644000000000000000000000226414332717401021750 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 2012 /********************************************************************** * * * Copyright (c) 2012 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnTraceObject #define ROOT_Minuit2_MnTraceObject namespace ROOT { namespace Minuit2 { class MinimumState; class MnUserParameterState; class MnTraceObject { public: MnTraceObject(int parNumber = -1) : fUserState(nullptr), fParNumber(parNumber) {} virtual ~MnTraceObject() {} virtual void Init(const MnUserParameterState &state) { fUserState = &state; } virtual void operator()(int i, const MinimumState &state); const MnUserParameterState &UserState() const { return *fUserState; } void SetParNumber(int number) { fParNumber = number; } int ParNumber() const { return fParNumber; } private: const MnUserParameterState *fUserState; int fParNumber; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnTraceIter iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnUserCovariance.h0000644000000000000000000000522014332717401022467 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnUserCovariance #define ROOT_Minuit2_MnUserCovariance #include "Minuit2/MnConfig.h" #include #include namespace ROOT { namespace Minuit2 { /** Class containing the covariance matrix data represented as a vector of size n*(n+1)/2 Used to hide internal matrix representation to user */ class MnUserCovariance { public: MnUserCovariance() : fData(std::vector()), fNRow(0) {} // safe constructor using std::vector MnUserCovariance(const std::vector &data, unsigned int nrow) : fData(data), fNRow(nrow) { assert(data.size() == nrow * (nrow + 1) / 2); } // unsafe constructor using just a pointer MnUserCovariance(const double *data, unsigned int nrow) : fData(std::vector(data, data + nrow * (nrow + 1) / 2)), fNRow(nrow) { } MnUserCovariance(unsigned int n) : fData(std::vector(n * (n + 1) / 2, 0.)), fNRow(n) {} ~MnUserCovariance() {} MnUserCovariance(const MnUserCovariance &cov) : fData(cov.fData), fNRow(cov.fNRow) {} MnUserCovariance &operator=(const MnUserCovariance &cov) { if (this != &cov) { fData = cov.fData; fNRow = cov.fNRow; } return *this; } double operator()(unsigned int row, unsigned int col) const { assert(row < fNRow && col < fNRow); if (row > col) return fData[col + row * (row + 1) / 2]; else return fData[row + col * (col + 1) / 2]; } double &operator()(unsigned int row, unsigned int col) { assert(row < fNRow && col < fNRow); if (row > col) return fData[col + row * (row + 1) / 2]; else return fData[row + col * (col + 1) / 2]; } void Scale(double f) { for (unsigned int i = 0; i < fData.size(); i++) fData[i] *= f; } const std::vector &Data() const { return fData; } unsigned int Nrow() const { return fNRow; } // VC 7.1 warning: conversion from size_t to unsigned int unsigned int size() const { return static_cast(fData.size()); } private: std::vector fData; unsigned int fNRow; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnUserCovariance iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnUserFcn.h0000644000000000000000000000215114332717401021123 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnUserFcn #define ROOT_Minuit2_MnUserFcn #include "Minuit2/MnFcn.h" namespace ROOT { namespace Minuit2 { class MnUserTransformation; /** Wrapper used by Minuit of FCN interface containing a reference to the transformation object */ class MnUserFcn : public MnFcn { public: MnUserFcn(const FCNBase &fcn, const MnUserTransformation &trafo, int ncall = 0) : MnFcn(fcn, ncall), fTransform(trafo) { } ~MnUserFcn() override {} double operator()(const MnAlgebraicVector &) const override; private: const MnUserTransformation &fTransform; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnUserFcn iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnUserParameterState.h0000644000000000000000000001363114332717401023343 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnUserParameterState #define ROOT_Minuit2_MnUserParameterState #include "Minuit2/MnUserParameters.h" #include "Minuit2/MnUserCovariance.h" #include "Minuit2/MnGlobalCorrelationCoeff.h" #include #include namespace ROOT { namespace Minuit2 { class MinimumState; //_____________________________________________________________________________ /** class which holds the external user and/or internal Minuit representation of the parameters and errors; transformation internal <-> external on demand; */ class MnUserParameterState { public: /// default constructor (invalid state) MnUserParameterState() : fValid(false), fCovarianceValid(false), fGCCValid(false), fCovStatus(-1), fFVal(0), fEDM(0), fNFcn(0), fParameters(MnUserParameters()), fCovariance(MnUserCovariance()), fIntParameters(std::vector()), fIntCovariance(MnUserCovariance()) { } /// construct from user parameters (before minimization) MnUserParameterState(const std::vector &, const std::vector &); MnUserParameterState(const MnUserParameters &); /// construct from user parameters + covariance (before minimization) MnUserParameterState(const std::vector &, const std::vector &, unsigned int); MnUserParameterState(const std::vector &, const MnUserCovariance &); MnUserParameterState(const MnUserParameters &, const MnUserCovariance &); /// construct from internal parameters (after minimization) MnUserParameterState(const MinimumState &, double, const MnUserTransformation &); // user external representation const MnUserParameters &Parameters() const { return fParameters; } const MnUserCovariance &Covariance() const { return fCovariance; } const MnGlobalCorrelationCoeff &GlobalCC() const { return fGlobalCC; } // hessian (inverse of covariance matrix) MnUserCovariance Hessian() const; // Minuit internal representation const std::vector &IntParameters() const { return fIntParameters; } const MnUserCovariance &IntCovariance() const { return fIntCovariance; } // covariance matrix status (0 = not valid, 1 approximate, 2, full but made pos def, 3 accurate and not pos def int CovarianceStatus() const { return fCovStatus; } // transformation internal <-> external const MnUserTransformation &Trafo() const { return fParameters.Trafo(); } bool IsValid() const { return fValid; } bool HasCovariance() const { return fCovarianceValid; } bool HasGlobalCC() const { return fGCCValid; } double Fval() const { return fFVal; } double Edm() const { return fEDM; } unsigned int NFcn() const { return fNFcn; } public: /** facade: forward interface of MnUserParameters and MnUserTransformation */ // access to parameters (row-wise) const std::vector &MinuitParameters() const; // access to parameters and errors in column-wise representation std::vector Params() const; std::vector Errors() const; // access to single Parameter const MinuitParameter &Parameter(unsigned int i) const; // add free Parameter void Add(const std::string &name, double val, double err); // add limited Parameter void Add(const std::string &name, double val, double err, double, double); // add const Parameter void Add(const std::string &, double); // interaction via external number of Parameter void Fix(unsigned int); void Release(unsigned int); void RemoveLimits(unsigned int); void SetValue(unsigned int, double); void SetError(unsigned int, double); void SetLimits(unsigned int, double, double); void SetUpperLimit(unsigned int, double); void SetLowerLimit(unsigned int, double); void SetName(unsigned int iext, const std::string &name) { fParameters.SetName(iext, name); } double Value(unsigned int) const; double Error(unsigned int) const; // interaction via Name of Parameter void Fix(const std::string &); void Release(const std::string &); void SetValue(const std::string &, double); void SetError(const std::string &, double); void SetLimits(const std::string &, double, double); void SetUpperLimit(const std::string &, double); void SetLowerLimit(const std::string &, double); void RemoveLimits(const std::string &); double Value(const std::string &) const; double Error(const std::string &) const; // convert Name into external number of Parameter unsigned int Index(const std::string &) const; // convert external number into Name of Parameter const std::string &GetName(unsigned int) const; // maintain interface with const char * for backward compatibility const char *Name(unsigned int) const; // transformation internal <-> external double Int2ext(unsigned int, double) const; double Ext2int(unsigned int, double) const; unsigned int IntOfExt(unsigned int) const; unsigned int ExtOfInt(unsigned int) const; unsigned int VariableParameters() const; const MnMachinePrecision &Precision() const; void SetPrecision(double eps); private: bool fValid; bool fCovarianceValid; bool fGCCValid; int fCovStatus; // covariance matrix status double fFVal; double fEDM; unsigned int fNFcn; MnUserParameters fParameters; MnUserCovariance fCovariance; MnGlobalCorrelationCoeff fGlobalCC; std::vector fIntParameters; MnUserCovariance fIntCovariance; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnUserParameterState iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnUserParameters.h0000644000000000000000000001020514332717401022517 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnUserParameters #define ROOT_Minuit2_MnUserParameters #include "Minuit2/MnUserTransformation.h" #include #include namespace ROOT { namespace Minuit2 { class MnMachinePrecision; /** API class for the user interaction with the parameters; serves as input to the minimizer as well as output from it; users can interact: Fix/release parameters, set values and errors, etc.; parameters can be accessed via their Parameter number (determined internally by Minuit and followed the order how the parameters are created) or via their user-specified Name (10 character string). Minuit has also an internal parameter number which is used during the minimization (the fix parameter are skipped). The parameter number used in this class is the external one. The class ROOT::Minuit2::MnUserTransformation is used to keep the internal <-> external transformation */ class MnUserParameters { public: MnUserParameters() : fTransformation(MnUserTransformation()) {} MnUserParameters(const std::vector &, const std::vector &); ~MnUserParameters() {} MnUserParameters(const MnUserParameters &par) : fTransformation(par.fTransformation) {} MnUserParameters &operator=(const MnUserParameters &par) { fTransformation = par.fTransformation; return *this; } const MnUserTransformation &Trafo() const { return fTransformation; } unsigned int VariableParameters() const { return fTransformation.VariableParameters(); } /// access to parameters (row-wise) const std::vector &Parameters() const; /// access to parameters and errors in column-wise representation std::vector Params() const; std::vector Errors() const; /// access to single Parameter const MinuitParameter &Parameter(unsigned int) const; /// Add free Parameter Name, Value, Error bool Add(const std::string &, double, double); /// Add limited Parameter Name, Value, Lower bound, Upper bound bool Add(const std::string &, double, double, double, double); /// Add const Parameter Name, vale bool Add(const std::string &, double); /// interaction via external number of Parameter void Fix(unsigned int); void Release(unsigned int); void RemoveLimits(unsigned int); void SetValue(unsigned int, double); void SetError(unsigned int, double); void SetLimits(unsigned int, double, double); void SetUpperLimit(unsigned int, double); void SetLowerLimit(unsigned int, double); void SetName(unsigned int, const std::string &); double Value(unsigned int) const; double Error(unsigned int) const; /// interaction via Name of Parameter void Fix(const std::string &); void Release(const std::string &); void SetValue(const std::string &, double); void SetError(const std::string &, double); void SetLimits(const std::string &, double, double); void SetUpperLimit(const std::string &, double); void SetLowerLimit(const std::string &, double); void RemoveLimits(const std::string &); double Value(const std::string &) const; double Error(const std::string &) const; // convert Name into external number of Parameter unsigned int Index(const std::string &) const; // convert external number into Name of Parameter const std::string &GetName(unsigned int) const; // maintain interface with const char * for backward compatibility const char *Name(unsigned int) const; const MnMachinePrecision &Precision() const; void SetPrecision(double eps) { fTransformation.SetPrecision(eps); } private: MnUserTransformation fTransformation; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnUserParameters iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnUserTransformation.h0000644000000000000000000001433414332717401023431 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnUserTransformation #define ROOT_Minuit2_MnUserTransformation #include "Minuit2/MnConfig.h" #include "Minuit2/MnMatrix.h" #include "Minuit2/MinuitParameter.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/SinParameterTransformation.h" #include "Minuit2/SqrtLowParameterTransformation.h" #include "Minuit2/SqrtUpParameterTransformation.h" #include #include #include namespace ROOT { namespace Minuit2 { class MnUserCovariance; // class MnMachinePrecision; /** class dealing with the transformation between user specified parameters (external) and internal parameters used for minimization */ class MnUserTransformation { public: MnUserTransformation() : fPrecision(MnMachinePrecision()), fParameters(std::vector()), fExtOfInt(std::vector()), fDoubleLimTrafo(SinParameterTransformation()), fUpperLimTrafo(SqrtUpParameterTransformation()), fLowerLimTrafo(SqrtLowParameterTransformation()), fCache(std::vector()) { } MnUserTransformation(const std::vector &, const std::vector &); ~MnUserTransformation() {} MnUserTransformation(const MnUserTransformation &trafo) : fPrecision(trafo.fPrecision), fParameters(trafo.fParameters), fExtOfInt(trafo.fExtOfInt), fDoubleLimTrafo(trafo.fDoubleLimTrafo), fUpperLimTrafo(trafo.fUpperLimTrafo), fLowerLimTrafo(trafo.fLowerLimTrafo), fCache(trafo.fCache) { } MnUserTransformation &operator=(const MnUserTransformation &trafo) { if (this != &trafo) { fPrecision = trafo.fPrecision; fParameters = trafo.fParameters; fExtOfInt = trafo.fExtOfInt; fDoubleLimTrafo = trafo.fDoubleLimTrafo; fUpperLimTrafo = trafo.fUpperLimTrafo; fLowerLimTrafo = trafo.fLowerLimTrafo; fCache = trafo.fCache; } return *this; } //#ifdef MINUIT2_THREAD_SAFE // thread-safe version (do not use cache) std::vector operator()(const MnAlgebraicVector &) const; //#else // not thread safe // const std::vector& operator()(const MnAlgebraicVector&) const; //#endif // Index = internal Parameter double Int2ext(unsigned int, double) const; // Index = internal Parameter double Int2extError(unsigned int, double, double) const; MnUserCovariance Int2extCovariance(const MnAlgebraicVector &, const MnAlgebraicSymMatrix &) const; // Index = external Parameter double Ext2int(unsigned int, double) const; // Index = internal Parameter double DInt2Ext(unsigned int, double) const; // // Index = external Parameter // double dExt2Int(unsigned int, double) const; // Index = external Parameter unsigned int IntOfExt(unsigned int) const; // Index = internal Parameter unsigned int ExtOfInt(unsigned int internal) const { assert(internal < fExtOfInt.size()); return fExtOfInt[internal]; } const std::vector &Parameters() const { return fParameters; } unsigned int VariableParameters() const { return static_cast(fExtOfInt.size()); } // return initial parameter values (useful especially to get fixed parameter values) const std::vector &InitialParValues() const { return fCache; } /** forwarded interface */ const MnMachinePrecision &Precision() const { return fPrecision; } void SetPrecision(double eps) { fPrecision.SetPrecision(eps); } /// access to parameters and errors in column-wise representation std::vector Params() const; std::vector Errors() const; // access to single Parameter const MinuitParameter &Parameter(unsigned int) const; // add free Parameter bool Add(const std::string &, double, double); // add limited Parameter bool Add(const std::string &, double, double, double, double); // add const Parameter bool Add(const std::string &, double); // interaction via external number of Parameter void Fix(unsigned int); void Release(unsigned int); void RemoveLimits(unsigned int); void SetValue(unsigned int, double); void SetError(unsigned int, double); void SetLimits(unsigned int, double, double); void SetUpperLimit(unsigned int, double); void SetLowerLimit(unsigned int, double); void SetName(unsigned int, const std::string &); double Value(unsigned int) const; double Error(unsigned int) const; // interaction via Name of Parameter void Fix(const std::string &); void Release(const std::string &); void SetValue(const std::string &, double); void SetError(const std::string &, double); void SetLimits(const std::string &, double, double); void SetUpperLimit(const std::string &, double); void SetLowerLimit(const std::string &, double); void RemoveLimits(const std::string &); double Value(const std::string &) const; double Error(const std::string &) const; // convert Name into external number of Parameter (will assert if parameter is not found) unsigned int Index(const std::string &) const; // find parameter index given a name. If it is not found return a -1 int FindIndex(const std::string &) const; // convert external number into Name of Parameter (will assert if index is out of range) const std::string &GetName(unsigned int) const; // maintain interface with const char * for backward compatibility const char *Name(unsigned int) const; private: MnMachinePrecision fPrecision; std::vector fParameters; std::vector fExtOfInt; SinParameterTransformation fDoubleLimTrafo; SqrtUpParameterTransformation fUpperLimTrafo; SqrtLowParameterTransformation fLowerLimTrafo; mutable std::vector fCache; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnUserTransformation iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/MnVectorTransform.h0000644000000000000000000000205214332717401022714 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_MnVectorTransform #define ROOT_Minuit2_MnVectorTransform #include "Minuit2/MnMatrix.h" #include namespace ROOT { namespace Minuit2 { class MnVectorTransform { public: MnVectorTransform() {} ~MnVectorTransform() {} std::vector operator()(const MnAlgebraicVector &avec) const { std::vector result; result.reserve(avec.size()); for (unsigned int i = 0; i < avec.size(); i++) result.push_back(avec(i)); return result; } }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_MnVectorTransform iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ModularFunctionMinimizer.h0000644000000000000000000001121514332717401024261 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ModularFunctionMinimizer #define ROOT_Minuit2_ModularFunctionMinimizer #include "Minuit2/MnConfig.h" #include "Minuit2/FunctionMinimizer.h" #include namespace ROOT { namespace Minuit2 { class MinimumSeedGenerator; class MinimumBuilder; class MinimumSeed; class MnFcn; class GradientCalculator; class MnUserParameterState; class MnUserParameters; class MnUserCovariance; class MnStrategy; class FumiliFCNBase; //_____________________________________________________________ /** Base common class providing the API for all the minimizer Various Minimize methods are provided varying on the type of FCN function passesd and on the objects used for the parameters */ class ModularFunctionMinimizer : public FunctionMinimizer { public: ~ModularFunctionMinimizer() override {} // inherited interface FunctionMinimum Minimize(const FCNBase &, const std::vector &, const std::vector &, unsigned int stra = 1, unsigned int maxfcn = 0, double toler = 0.1) const override; FunctionMinimum Minimize(const FCNGradientBase &, const std::vector &, const std::vector &, unsigned int stra = 1, unsigned int maxfcn = 0, double toler = 0.1) const override; FunctionMinimum Minimize(const FCNBase &, const std::vector &, unsigned int, const std::vector &, unsigned int stra = 1, unsigned int maxfcn = 0, double toler = 0.1) const override; FunctionMinimum Minimize(const FCNGradientBase &, const std::vector &, unsigned int, const std::vector &, unsigned int stra = 1, unsigned int maxfcn = 0, double toler = 0.1) const override; // extension virtual FunctionMinimum Minimize(const FCNBase &, const MnUserParameters &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; virtual FunctionMinimum Minimize(const FCNGradientBase &, const MnUserParameters &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; virtual FunctionMinimum Minimize(const FCNBase &, const MnUserParameters &, const MnUserCovariance &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; virtual FunctionMinimum Minimize(const FCNGradientBase &, const MnUserParameters &, const MnUserCovariance &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; virtual FunctionMinimum Minimize(const FCNBase &, const MnUserParameterState &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; virtual FunctionMinimum Minimize(const FCNGradientBase &, const MnUserParameterState &, const MnStrategy &, unsigned int maxfcn = 0, double toler = 0.1) const; // for Fumili // virtual FunctionMinimum Minimize(const FumiliFCNBase&, const std::vector&, const std::vector&, // unsigned int stra=1, unsigned int maxfcn = 0, double toler = 0.1) const; // virtual FunctionMinimum Minimize(const FumiliFCNBase&, const MnUserParameters&, const MnStrategy&, unsigned int // maxfcn = 0, double toler = 0.1) const; // virtual FunctionMinimum Minimize(const FumiliFCNBase&, const MnUserParameters&, const MnUserCovariance&, const // MnStrategy&, unsigned int maxfcn = 0, double toler = 0.1) const; // virtual FunctionMinimum Minimize(const FumiliFCNBase&, const MnUserParameterState&, const MnStrategy&, unsigned // int maxfcn = 0, double toler = 0.1) const; virtual const MinimumSeedGenerator &SeedGenerator() const = 0; virtual const MinimumBuilder &Builder() const = 0; virtual MinimumBuilder &Builder() = 0; public: virtual FunctionMinimum Minimize(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ModularFunctionMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/NegativeG2LineSearch.h0000644000000000000000000000253714332717401023164 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_NegativeG2LineSearch #define ROOT_Minuit2_NegativeG2LineSearch namespace ROOT { namespace Minuit2 { class MnFcn; class MinimumState; class GradientCalculator; class MnMachinePrecision; class FunctionGradient; /** In case that one of the components of the second derivative g2 calculated by the numerical Gradient calculator is negative, a 1dim line search in the direction of that component is done in order to find a better position where g2 is again positive. */ class NegativeG2LineSearch { public: NegativeG2LineSearch() {} ~NegativeG2LineSearch() {} MinimumState operator()(const MnFcn &, const MinimumState &, const GradientCalculator &, const MnMachinePrecision &) const; bool HasNegativeG2(const FunctionGradient &, const MnMachinePrecision &) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_NegativeG2LineSearch iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/Numerical2PGradientCalculator.h0000644000000000000000000000361714332717401025104 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_Numerical2PGradientCalculator #define ROOT_Minuit2_Numerical2PGradientCalculator #include "Minuit2/MnConfig.h" #include "Minuit2/GradientCalculator.h" #include namespace ROOT { namespace Minuit2 { class MnFcn; class MnUserTransformation; class MnMachinePrecision; class MnStrategy; /** class performing the numerical gradient calculation */ class Numerical2PGradientCalculator : public GradientCalculator { public: Numerical2PGradientCalculator(const MnFcn &fcn, const MnUserTransformation &par, const MnStrategy &stra) : fFcn(fcn), fTransformation(par), fStrategy(stra) { } ~Numerical2PGradientCalculator() override {} FunctionGradient operator()(const MinimumParameters &) const override; virtual FunctionGradient operator()(const std::vector ¶ms) const; FunctionGradient operator()(const MinimumParameters &, const FunctionGradient &) const override; const MnFcn &Fcn() const { return fFcn; } const MnUserTransformation &Trafo() const { return fTransformation; } const MnMachinePrecision &Precision() const; const MnStrategy &Strategy() const { return fStrategy; } unsigned int Ncycle() const; double StepTolerance() const; double GradTolerance() const; private: const MnFcn &fFcn; const MnUserTransformation &fTransformation; const MnStrategy &fStrategy; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_Numerical2PGradientCalculator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/NumericalDerivator.h0000644000000000000000000001142014332717401023061 0ustar00// @(#)root/mathcore:$Id$ // Authors: L. Moneta, J.T. Offermann, E.G.P. Bos 2013-2018 // /********************************************************************** * * * Copyright (c) 2013 , LCG ROOT MathLib Team * * * **********************************************************************/ /* * NumericalDerivator.h * * Original version created on: Aug 14, 2013 * Authors: L. Moneta, J. T. Offermann * Modified version created on: Sep 27, 2017 * Author: E. G. P. Bos */ #ifndef ROOT_Minuit2_NumericalDerivator #define ROOT_Minuit2_NumericalDerivator #include #include #include "Fit/ParameterSettings.h" #include "Minuit2/SinParameterTransformation.h" #include "Minuit2/SqrtUpParameterTransformation.h" #include "Minuit2/SqrtLowParameterTransformation.h" #include "Minuit2/MnMachinePrecision.h" namespace ROOT { namespace Minuit2 { // Holds all necessary derivatives and associated numbers (per parameter) used in the NumericalDerivator class. struct DerivatorElement { double derivative; double second_derivative; double step_size; }; class NumericalDerivator { public: explicit NumericalDerivator(bool always_exactly_mimic_minuit2 = true); NumericalDerivator(const NumericalDerivator &other); NumericalDerivator(double step_tolerance, double grad_tolerance, unsigned int ncycles, double error_level, bool always_exactly_mimic_minuit2 = true); void SetupDifferentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *cx, const std::vector ¶meters); std::vector Differentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, const std::vector &previous_gradient); DerivatorElement PartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, DerivatorElement previous); DerivatorElement FastPartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous); DerivatorElement operator()(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous); double GetValue() const { return fVal; } inline void SetStepTolerance(double value) { fStepTolerance = value; } inline void SetGradTolerance(double value) { fGradTolerance = value; } inline void SetNCycles(unsigned int value) { fNCycles = value; } inline void SetErrorLevel(double value) { fUp = value; } double Int2ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const; double Ext2int(const ROOT::Fit::ParameterSettings ¶meter, double val) const; double DInt2Ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const; void SetInitialGradient(const ROOT::Math::IBaseFunctionMultiDim *function, const std::vector ¶meters, std::vector &gradient); inline bool AlwaysExactlyMimicMinuit2() const { return fAlwaysExactlyMimicMinuit2; } inline void SetAlwaysExactlyMimicMinuit2(bool flag) { fAlwaysExactlyMimicMinuit2 = flag; } private: double fStepTolerance = 0.5; double fGradTolerance = 0.1; double fUp = 1; double fVal = 0; std::vector fVx; std::vector fVxExternal; std::vector fVxFValCache; double fDfmin; double fVrysml; // MODIFIED: Minuit2 determines machine precision in a slightly different way than // std::numeric_limits::epsilon()). We go with the Minuit2 one. ROOT::Minuit2::MnMachinePrecision fPrecision; ROOT::Minuit2::SinParameterTransformation fDoubleLimTrafo; ROOT::Minuit2::SqrtUpParameterTransformation fUpperLimTrafo; ROOT::Minuit2::SqrtLowParameterTransformation fLowerLimTrafo; unsigned int fNCycles = 2; bool fAlwaysExactlyMimicMinuit2; }; std::ostream &operator<<(std::ostream &out, const DerivatorElement &value); } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_NumericalDerivator ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ParametricFunction.h����������������������������0000644�0000000�0000000�00000010513�14332717401�023061� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ParametricFunction #define ROOT_Minuit2_ParametricFunction #include "Minuit2/MnConfig.h" #include #include #include "Minuit2/FCNBase.h" namespace ROOT { namespace Minuit2 { /** Function which has parameters. For example, one could define a one-dimensional Gaussian, by considering x as an input coordinate for the evaluation of the function, and the mean and the square root of the variance as parameters.

AS OF NOW PARAMETRICFUNCTION INHERITS FROM FCNBASE INSTEAD OF GENERICFUNCTION. THIS IS ONLY BECAUSE NUMERICAL2PGRADIENTCALCULATOR NEEDS AN FCNBASE OBJECT AND WILL BE CHANGED!!!!!!!!!!!!!!!! @ingroup Minuit \todo ParametricFunction and all the classes that inherit from it are inheriting also FCNBase so that the Gradient calculation has the Up() member function. That is not really good... */ class ParametricFunction : public FCNBase { public: /** Constructor which initializes the ParametricFunction with the parameters given as input. @param params vector containing the initial Parameter values */ ParametricFunction(const std::vector ¶ms) : par(params) {} /** Constructor which initializes the ParametricFunction by setting the number of parameters. @param nparams number of parameters of the parametric function */ ParametricFunction(int nparams) : par(nparams) {} ~ParametricFunction() override {} /** Sets the parameters of the ParametricFunction. @param params vector containing the Parameter values */ virtual void SetParameters(const std::vector ¶ms) const { assert(params.size() == par.size()); par = params; } /** Accessor for the state of the parameters. @return vector containing the present Parameter settings */ virtual const std::vector &GetParameters() const { return par; } /** Accessor for the number of parameters. @return the number of function parameters */ virtual unsigned int NumberOfParameters() const { return par.size(); } // Why do I need to declare it here, it should be inherited without // any problems, no? /** Evaluates the function with the given coordinates. @param x vector containing the input coordinates @return the result of the function evaluation with the given coordinates. */ double operator()(const std::vector &x) const override = 0; /** Evaluates the function with the given coordinates and Parameter values. This member function is useful to implement when speed is an issue as it is faster to call only one function instead of two (SetParameters and operator()). The default implementation, provided for convenience, does the latter. @param x vector containing the input coordinates @param params vector containing the Parameter values @return the result of the function evaluation with the given coordinates and parameters */ virtual double operator()(const std::vector &x, const std::vector ¶ms) const { SetParameters(params); return operator()(x); } /** Member function returning the Gradient of the function with respect to its variables (but without including gradients with respect to its internal parameters). @param x vector containing the coordinates of the point where the Gradient is to be calculated. @return the Gradient vector of the function at the given point. */ virtual std::vector GetGradient(const std::vector &x) const; protected: /** The vector containing the parameters of the function It is mutable for "historical reasons" as in the hierarchy methods and classes are const and all the implications of changing them back to non-const are not clear. */ mutable std::vector par; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ParametricFunction iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ScanBuilder.h0000644000000000000000000000217514332717401021464 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ScanBuilder #define ROOT_Minuit2_ScanBuilder #include "Minuit2/MinimumBuilder.h" namespace ROOT { namespace Minuit2 { class FunctionMinimum; class MnFcn; class MinimumSeed; /** Performs a minimization using the simplex method of Nelder and Mead (ref. Comp. J. 7, 308 (1965)). */ class ScanBuilder : public MinimumBuilder { public: ScanBuilder() {} ~ScanBuilder() override {} FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ScanBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/ScanMinimizer.h0000644000000000000000000000274414332717401022043 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_ScanMinimizer #define ROOT_Minuit2_ScanMinimizer #include "Minuit2/MnConfig.h" #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/ScanBuilder.h" #include "Minuit2/SimplexSeedGenerator.h" namespace ROOT { namespace Minuit2 { //_____________________________________________________________ /** Class implementing the required methods for a minimization using SCAN API is provided in the upper ROOT::Minuit2::ModularFunctionMinimizer class */ class ScanMinimizer : public ModularFunctionMinimizer { public: ScanMinimizer() : fSeedGenerator(SimplexSeedGenerator()), fBuilder(ScanBuilder()) {} ~ScanMinimizer() override {} const MinimumSeedGenerator &SeedGenerator() const override { return fSeedGenerator; } const MinimumBuilder &Builder() const override { return fBuilder; } MinimumBuilder &Builder() override { return fBuilder; } private: SimplexSeedGenerator fSeedGenerator; ScanBuilder fBuilder; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_ScanMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SimplexBuilder.h0000644000000000000000000000221714332717401022216 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_SimplexBuilder #define ROOT_Minuit2_SimplexBuilder #include "Minuit2/MinimumBuilder.h" namespace ROOT { namespace Minuit2 { class FunctionMinimum; class MnFcn; class MinimumSeed; /** Performs a minimization using the simplex method of Nelder and Mead (ref. Comp. J. 7, 308 (1965)). */ class SimplexBuilder : public MinimumBuilder { public: SimplexBuilder() {} ~SimplexBuilder() override {} FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_SimplexBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SimplexMinimizer.h0000644000000000000000000000300314332717401022565 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_SimplexMinimizer #define ROOT_Minuit2_SimplexMinimizer #include "Minuit2/MnConfig.h" #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/SimplexBuilder.h" #include "Minuit2/SimplexSeedGenerator.h" namespace ROOT { namespace Minuit2 { //_____________________________________________________________ /** Class implementing the required methods for a minimization using Simplex. API is provided in the upper ROOT::Minuit2::ModularFunctionMinimizer class */ class SimplexMinimizer : public ModularFunctionMinimizer { public: SimplexMinimizer() : fSeedGenerator(SimplexSeedGenerator()), fBuilder(SimplexBuilder()) {} ~SimplexMinimizer() override {} const MinimumSeedGenerator &SeedGenerator() const override { return fSeedGenerator; } const MinimumBuilder &Builder() const override { return fBuilder; } MinimumBuilder &Builder() override { return fBuilder; } private: SimplexSeedGenerator fSeedGenerator; SimplexBuilder fBuilder; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_SimplexMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SimplexParameters.h0000644000000000000000000000342714332717401022737 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_SimplexParameters #define ROOT_Minuit2_SimplexParameters #include #include "Minuit2/MnMatrix.h" #include #include namespace ROOT { namespace Minuit2 { /** class describing the simplex set of points (f(x), x ) which evolve during the minimization iteration process. */ class SimplexParameters { public: SimplexParameters(const std::vector> &simpl, unsigned int jh, unsigned int jl) : fSimplexParameters(simpl), fJHigh(jh), fJLow(jl) { } ~SimplexParameters() {} void Update(double, const MnAlgebraicVector &); const std::vector> &Simplex() const { return fSimplexParameters; } const std::pair &operator()(unsigned int i) const { assert(i < fSimplexParameters.size()); return fSimplexParameters[i]; } unsigned int Jh() const { return fJHigh; } unsigned int Jl() const { return fJLow; } double Edm() const { return fSimplexParameters[Jh()].first - fSimplexParameters[Jl()].first; } MnAlgebraicVector Dirin() const; private: std::vector> fSimplexParameters; unsigned int fJHigh; unsigned int fJLow; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_SimplexParameters iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SimplexSeedGenerator.h0000644000000000000000000000243714332717401023363 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_SimplexSeedGenerator #define ROOT_Minuit2_SimplexSeedGenerator #include "Minuit2/MinimumSeedGenerator.h" namespace ROOT { namespace Minuit2 { class MinimumSeed; class MnFcn; class MnUserParameterState; class MnStrategy; /** generate Simplex starting point (state) */ class SimplexSeedGenerator : public MinimumSeedGenerator { public: SimplexSeedGenerator() {} ~SimplexSeedGenerator() override {} MinimumSeed operator()(const MnFcn &, const GradientCalculator &, const MnUserParameterState &, const MnStrategy &) const override; MinimumSeed operator()(const MnFcn &, const AnalyticalGradientCalculator &, const MnUserParameterState &, const MnStrategy &) const override; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_SimplexSeedGenerator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SinParameterTransformation.h0000644000000000000000000000243514332717401024611 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_SinParameterTransformation #define ROOT_Minuit2_SinParameterTransformation namespace ROOT { namespace Minuit2 { class MnMachinePrecision; /** class for the transformation for double-limited parameter Using a sin function one goes from a double-limited parameter range to an unlimited one */ class SinParameterTransformation { public: SinParameterTransformation() {} ~SinParameterTransformation() {} long double Int2ext(long double Value, long double Upper, long double Lower) const; long double Ext2int(long double Value, long double Upper, long double Lower, const MnMachinePrecision &) const; long double DInt2Ext(long double Value, long double Upper, long double Lower) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_SinParameterTransformation iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SqrtLowParameterTransformation.h0000644000000000000000000000303614332717401025471 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ // Project : LCG // Package : Minuit // Author : Lorenzo.MONETA@cern.ch // Created by: moneta at Thu Apr 8 10:26:22 2004 #ifndef ROOT_Minuit2_SqrtLowParameterTransformation #define ROOT_Minuit2_SqrtLowParameterTransformation namespace ROOT { namespace Minuit2 { class MnMachinePrecision; /** * Transformation from external to internal Parameter based on sqrt(1 + x**2) * * This transformation applies for the case of single side Lower Parameter limits */ class SqrtLowParameterTransformation /* : public ParameterTransformation */ { public: SqrtLowParameterTransformation() {} ~SqrtLowParameterTransformation() {} // transformation from internal to external long double Int2ext(long double Value, long double Lower) const; // transformation from external to internal long double Ext2int(long double Value, long double Lower, const MnMachinePrecision &) const; // derivative of transformation from internal to external long double DInt2Ext(long double Value, long double Lower) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/SqrtUpParameterTransformation.h0000644000000000000000000000310214332717401025306 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ // Project : LCG // Package : Minuit // Author : Lorenzo.MONETA@cern.ch // Created by: moneta at Thu Apr 8 10:26:22 2004 #ifndef ROOT_Minuit2_SqrtUpParameterTransformation #define ROOT_Minuit2_SqrtUpParameterTransformation namespace ROOT { namespace Minuit2 { class MnMachinePrecision; /** * Transformation from external to internal Parameter based on sqrt(1 + x**2) * * This transformation applies for the case of single side Upper Parameter limits */ class SqrtUpParameterTransformation /* : public ParameterTransformation */ { public: // create with user defined precision SqrtUpParameterTransformation() {} ~SqrtUpParameterTransformation() {} // transformation from internal to external long double Int2ext(long double Value, long double Upper) const; // transformation from external to internal long double Ext2int(long double Value, long double Upper, const MnMachinePrecision &) const; // derivative of transformation from internal to external long double DInt2Ext(long double Value, long double Upper) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/StackAllocator.h0000644000000000000000000001433614332717401022201 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_StackAllocator #define ROOT_Minuit2_StackAllocator #include "Minuit2/MnConfig.h" // comment out this line and recompile if you want to gain additional // performance (the gain is mainly for "simple" functions which are easy // to calculate and vanishes quickly if going to cost-intensive functions) // the library is no longer thread save however #ifdef MN_USE_STACK_ALLOC #define _MN_NO_THREAD_SAVE_ #endif #include #include namespace ROOT { namespace Minuit2 { /// define stack allocator symbol class StackOverflow { }; class StackError { }; /** StackAllocator controls the memory allocation/deallocation of Minuit. If _MN_NO_THREAD_SAVE_ is defined, memory is taken from a pre-allocated piece of heap memory which is then used like a stack, otherwise via standard malloc/free. Note that defining _MN_NO_THREAD_SAVE_ makes the code thread- unsave. The gain in performance is mainly for cost-cheap FCN functions. */ class StackAllocator { public: // enum {default_size = 1048576}; enum { default_size = 524288 }; StackAllocator() : fStack(nullptr) { #ifdef _MN_NO_THREAD_SAVE_ // std::cout<<"StackAllocator Allocate "<(fStack + offset); *ip = Value; } int ToInt(void *p) { unsigned char *pc = static_cast(p); // std::cout << "toInt: p = " << p << " fStack = " << (void*) fStack << std::endl; // VC 7.1 warning:conversion from __w64 int to int int userBlock = pc - fStack; return userBlock - sizeof(int); // correct for starting int } int AlignedSize(int nBytes) { const int fAlignment = 4; int needed = nBytes % fAlignment == 0 ? nBytes : (nBytes / fAlignment + 1) * fAlignment; return needed + 2 * sizeof(int); } void CheckOverflow(int n) { if (fStackOffset + n >= default_size) { // std::cout << " no more space on stack allocator" << std::endl; throw StackOverflow(); } } bool CheckConsistency() { // std::cout << "checking consistency for " << fBlockCount << " blocks"<< std::endl; // loop over all blocks int beg = 0; int end = fStackOffset; int nblocks = 0; while (beg < fStackOffset) { end = ReadInt(beg); // std::cout << "beg = " << beg << " end = " << end // << " fStackOffset = " << fStackOffset << std::endl; int beg2 = ReadInt(end - sizeof(int)); if (beg != beg2) { // std::cout << " beg != beg2 " << std::endl; return false; } nblocks++; beg = end; } if (end != fStackOffset) { // std::cout << " end != fStackOffset" << std::endl; return false; } if (nblocks != fBlockCount) { // std::cout << "nblocks != fBlockCount" << std::endl; return false; } // std::cout << "Allocator is in consistent state, nblocks = " << nblocks << std::endl; return true; } private: unsigned char *fStack; // unsigned char fStack[default_size]; int fStackOffset; int fBlockCount; }; class StackAllocatorHolder { // t.b.d need to use same trick as Boost singleton.hpp to be sure that // StackAllocator is created before main() public: static StackAllocator &Get() { static StackAllocator gStackAllocator; return gStackAllocator; } }; } // namespace Minuit2 } // namespace ROOT #endif iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/VariableMetricBuilder.h0000644000000000000000000000467214332717401023475 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_VariableMetricBuilder #define ROOT_Minuit2_VariableMetricBuilder #include "Minuit2/MnConfig.h" #include "Minuit2/MinimumBuilder.h" #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/DavidonErrorUpdator.h" #include "Minuit2/BFGSErrorUpdator.h" #include #include namespace ROOT { namespace Minuit2 { /** Build (find) function minimum using the Variable Metric method (MIGRAD) Two possible error updators can be chosen - Davidon : this is the standard formula used in Migrad - BFGS this is the new formula based on BFGS algorithm (see Broyden–Fletcher–Goldfarb–Shanno algorithm https://en.wikipedia.org/wiki/Broyden–Fletcher–Goldfarb–Shanno_algorithm ) */ class VariableMetricBuilder : public MinimumBuilder { public: enum ErrorUpdatorType { kDavidon, kBFGS }; VariableMetricBuilder(ErrorUpdatorType type = kDavidon) : fEstimator(VariableMetricEDMEstimator()) { if (type == kBFGS) fErrorUpdator = std::unique_ptr(new BFGSErrorUpdator()); else fErrorUpdator = std::unique_ptr(new DavidonErrorUpdator()); } ~VariableMetricBuilder() override {} FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, const MnStrategy &, unsigned int, double) const override; FunctionMinimum Minimum(const MnFcn &, const GradientCalculator &, const MinimumSeed &, std::vector &, unsigned int, double) const; const VariableMetricEDMEstimator &Estimator() const { return fEstimator; } const MinimumErrorUpdator &ErrorUpdator() const { return *fErrorUpdator; } void AddResult(std::vector &result, const MinimumState &state) const; private: VariableMetricEDMEstimator fEstimator; std::shared_ptr fErrorUpdator; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_VariableMetricBuilder iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/VariableMetricEDMEstimator.h0000644000000000000000000000165014332717401024375 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_VariableMetricEDMEstimator #define ROOT_Minuit2_VariableMetricEDMEstimator namespace ROOT { namespace Minuit2 { class FunctionGradient; class MinimumError; class VariableMetricEDMEstimator { public: VariableMetricEDMEstimator() {} ~VariableMetricEDMEstimator() {} double Estimate(const FunctionGradient &, const MinimumError &) const; private: }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_VariableMetricEDMEstimator iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/VariableMetricMinimizer.h0000644000000000000000000000346114332717401024045 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_VariableMetricMinimizer #define ROOT_Minuit2_VariableMetricMinimizer #include "Minuit2/MnConfig.h" #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/MnSeedGenerator.h" #include "Minuit2/VariableMetricBuilder.h" namespace ROOT { namespace Minuit2 { class BFGSMinimizerType { }; //______________________________________________________________________________ /** Instantiates the SeedGenerator and MinimumBuilder for Variable Metric Minimization method. API is provided in the upper ROOT::Minuit2::ModularFunctionMinimizer class */ class VariableMetricMinimizer : public ModularFunctionMinimizer { public: class BFGSType { }; VariableMetricMinimizer() : fMinSeedGen(MnSeedGenerator()), fMinBuilder(VariableMetricBuilder()) {} VariableMetricMinimizer(BFGSType) : fMinSeedGen(MnSeedGenerator()), fMinBuilder(VariableMetricBuilder(VariableMetricBuilder::kBFGS)) { } ~VariableMetricMinimizer() override {} const MinimumSeedGenerator &SeedGenerator() const override { return fMinSeedGen; } const MinimumBuilder &Builder() const override { return fMinBuilder; } MinimumBuilder &Builder() override { return fMinBuilder; } private: MnSeedGenerator fMinSeedGen; VariableMetricBuilder fMinBuilder; }; } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_VariableMetricMinimizer iminuit-2.30.1/extern/root/math/minuit2/inc/Minuit2/VectorOuterProduct.h0000644000000000000000000000227314332717401023112 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_VectorOuterProduct #define ROOT_Minuit2_VectorOuterProduct #include "Minuit2/ABTypes.h" #include "Minuit2/ABObj.h" namespace ROOT { namespace Minuit2 { template class VectorOuterProduct { public: VectorOuterProduct(const M &obj) : fObject(obj) {} ~VectorOuterProduct() {} typedef sym Type; const M &Obj() const { return fObject; } private: M fObject; }; template inline ABObj, T>, T> Outer_product(const ABObj &obj) { return ABObj, T>, T>(VectorOuterProduct, T>(obj)); } } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_VectorOuterProduct iminuit-2.30.1/extern/root/math/minuit2/inc/TMinuit2TraceObject.h0000644000000000000000000000300714332717401021516 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 2012 /********************************************************************** * * * Copyright (c) 2012 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_TMinuit2TraceObject #define ROOT_TMinuit2TraceObject #include "TNamed.h" #include "Minuit2/MnTraceObject.h" class TH1; class TVirtualPad; class TList; namespace ROOT { namespace Minuit2 { class MinimumState; class MnUserParameterState; } // namespace Minuit2 } // namespace ROOT class TMinuit2TraceObject : public ROOT::Minuit2::MnTraceObject, public TNamed { public: TMinuit2TraceObject(int parNumber = -1); ~TMinuit2TraceObject() override; void Init(const ROOT::Minuit2::MnUserParameterState &state) override; void operator()(int i, const ROOT::Minuit2::MinimumState &state) override; ClassDefOverride(TMinuit2TraceObject, 0) // Example Trace Object for Minuit2 private : int fIterOffset; // offset in iteration in case of combined minimizers TH1 *fHistoFval; // Function value histogram TH1 *fHistoEdm; // Edm histogram TList *fHistoParList; // list of parameter values histograms TVirtualPad *fOldPad; // old existing current pad TVirtualPad *fMinuitPad; // new pad with trace histograms }; #endif // ROOT_TMinuit2TraceObject iminuit-2.30.1/extern/root/math/minuit2/src/AnalyticalGradientCalculator.cxx0000644000000000000000000001135614332717401024105 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/MnMatrix.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { FunctionGradient AnalyticalGradientCalculator::operator()(const MinimumParameters &par) const { // evaluate analytical gradient. take care of parameter transformations std::vector grad = fGradFunc.Gradient(fTransformation(par.Vec())); assert(grad.size() == fTransformation.Parameters().size()); MnAlgebraicVector v(par.Vec().size()); for (unsigned int i = 0; i < par.Vec().size(); i++) { unsigned int ext = fTransformation.ExtOfInt(i); if (fTransformation.Parameter(ext).HasLimits()) { double dd = fTransformation.DInt2Ext(i, par.Vec()(i)); v(i) = dd * grad[ext]; } else { v(i) = grad[ext]; } } MnPrint print("AnalyticalGradientCalculator"); print.Debug("User given gradient in Minuit2", v); // in case we can compute Hessian do not waste re-computing G2 here if (!CanComputeG2() || CanComputeHessian()) return FunctionGradient(v); // compute G2 if possible MnAlgebraicVector g2(par.Vec().size()); if (!this->G2(par, g2)) { print.Error("Error computing G2"); return FunctionGradient(v); } return FunctionGradient(v,g2); } FunctionGradient AnalyticalGradientCalculator::operator()(const MinimumParameters &par, const FunctionGradient &) const { // needed from base class return (*this)(par); } bool AnalyticalGradientCalculator::CheckGradient() const { // check to be sure FCN implements analytical gradient return fGradFunc.CheckGradient(); } // G2 can be computed directly without Hessian or via the Hessian bool AnalyticalGradientCalculator::CanComputeG2() const { return fGradFunc.HasG2() || fGradFunc.HasHessian(); } bool AnalyticalGradientCalculator::CanComputeHessian() const { return fGradFunc.HasHessian(); } bool AnalyticalGradientCalculator::Hessian(const MinimumParameters &par, MnAlgebraicSymMatrix & hmat) const { // compute Hessian using external gradient unsigned int n = par.Vec().size(); assert(hmat.size() == n *(n+1)/2); // compute external Hessian and then transform std::vector extHessian = fGradFunc.Hessian(fTransformation(par.Vec())); if (extHessian.empty()) { MnPrint print("AnalyticalGradientCalculator::Hessian"); print.Info("FCN cannot compute Hessian matrix"); return false; } unsigned int next = sqrt(extHessian.size()); // we need now to transform the matrix from external to internal coordinates for (unsigned int i = 0; i < n; i++) { unsigned int iext = fTransformation.ExtOfInt(i); double dxdi = 1.; if (fTransformation.Parameters()[iext].HasLimits()) { dxdi = fTransformation.DInt2Ext(i, par.Vec()(i)); } for (unsigned int j = i; j < n; j++) { double dxdj = 1.; unsigned int jext = fTransformation.ExtOfInt(j); if (fTransformation.Parameters()[jext].HasLimits()) { dxdj = fTransformation.DInt2Ext(j, par.Vec()(j)); } hmat(i, j) = dxdi * extHessian[i*next+ j] * dxdj; } } return true; } bool AnalyticalGradientCalculator::G2(const MinimumParameters &par, MnAlgebraicVector & g2) const { // compute G2 using external calculator unsigned int n = par.Vec().size(); // n is size of internal parameters assert(g2.size() == n ); std::vector extG2 = fGradFunc.G2(fTransformation(par.Vec())); if (extG2.empty()) { MnPrint print("AnalyticalGradientCalculator::G2"); print.Info("FCN cannot compute the 2nd derivatives vector (G2)"); return false; } assert(extG2.size() == fTransformation.Parameters().size()); // we need now to transform the matrix from external to internal coordinates for (unsigned int i = 0; i < n; i++) { unsigned int iext = fTransformation.ExtOfInt(i); if (fTransformation.Parameters()[iext].HasLimits()) { double dxdi = fTransformation.DInt2Ext(i, par.Vec()(i)); g2(i) = dxdi * dxdi * extG2[iext]; } else { g2(i) = extG2[iext]; } } return true; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/BFGSErrorUpdator.cxx0000644000000000000000000001055414332717401021425 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/BFGSErrorUpdator.h" #include "Minuit2/MinimumState.h" #include "Minuit2/LaSum.h" #include "Minuit2/LaProd.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { double inner_product(const LAVector &, const LAVector &); double similarity(const LAVector &, const LASymMatrix &); double sum_of_elements(const LASymMatrix &); // define here a square matrix that it is needed for computing the BFGS update // define just the class, no need for defining operations as done for the Symmetric matrices // since the square matrix will be converted in a symmetric one afterwards class LASquareMatrix { public: LASquareMatrix(unsigned int n) : fNRow(n), fData(std::vector(n * n)) {} double operator()(unsigned int row, unsigned int col) const { assert(row < fNRow && col < fNRow); return fData[col + row * fNRow]; } double &operator()(unsigned int row, unsigned int col) { assert(row < fNRow && col < fNRow); return fData[col + row * fNRow]; } unsigned int Nrow() const { return fNRow; } private: unsigned int fNRow; std::vector fData; }; // compute outer product of two vector of same size to return a square matrix LASquareMatrix OuterProduct(const LAVector &v1, const LAVector &v2) { assert(v1.size() == v2.size()); LASquareMatrix a(v1.size()); for (unsigned int i = 0; i < v1.size(); ++i) { for (unsigned int j = 0; j < v2.size(); ++j) { a(i, j) = v1[i] * v2[j]; } } return a; } // compute product of symmetric matrix with square matrix LASquareMatrix MatrixProduct(const LASymMatrix &m1, const LASquareMatrix &m2) { unsigned int n = m1.Nrow(); assert(n == m2.Nrow()); LASquareMatrix a(n); for (unsigned int i = 0; i < n; ++i) { for (unsigned int j = 0; j < n; ++j) { a(i, j) = 0; for (unsigned int k = 0; k < n; ++k) { a(i, j) += m1(i, k) * m2(k, j); } } } return a; } MinimumError BFGSErrorUpdator::Update(const MinimumState &s0, const MinimumParameters &p1, const FunctionGradient &g1) const { // update of the covarianze matrix (BFGS formula, see Tutorial, par. 4.8 pag 26) // in case of delgam > gvg (PHI > 1) use rank one formula // see par 4.10 pag 30 const MnAlgebraicSymMatrix &v0 = s0.Error().InvHessian(); MnAlgebraicVector dx = p1.Vec() - s0.Vec(); MnAlgebraicVector dg = g1.Vec() - s0.Gradient().Vec(); double delgam = inner_product(dx, dg); // this is s^T y using wikipedia conventions double gvg = similarity(dg, v0); // this is y^T B^-1 y MnPrint print("BFGSErrorUpdator"); print.Debug("dx", dx, "dg", dg, "delgam", delgam, "gvg", gvg); if (delgam == 0) { print.Warn("delgam = 0 : cannot update - return same matrix"); return s0.Error(); } if (delgam < 0) { print.Warn("delgam < 0 : first derivatives increasing along search line"); } if (gvg <= 0) { // since v0 is pos def this gvg can be only = 0 if dg = 0 - should never be here print.Warn("gvg <= 0"); // return s0.Error(); } // compute update formula for BFGS // see wikipedia https://en.wikipedia.org/wiki/Broyden–Fletcher–Goldfarb–Shanno_algorithm // need to compute outer product dg . dx and it is not symmetric anymore LASquareMatrix a = OuterProduct(dg, dx); LASquareMatrix b = MatrixProduct(v0, a); unsigned int n = v0.Nrow(); MnAlgebraicSymMatrix v2(n); for (unsigned int i = 0; i < n; ++i) { for (unsigned int j = i; j < n; ++j) { v2(i, j) = (b(i, j) + b(j, i)) / (delgam); } } MnAlgebraicSymMatrix vUpd = (delgam + gvg) * Outer_product(dx) / (delgam * delgam); vUpd -= v2; double sum_upd = sum_of_elements(vUpd); vUpd += v0; double dcov = 0.5 * (s0.Error().Dcovar() + sum_upd / sum_of_elements(vUpd)); print.Debug("dcov", dcov); return MinimumError(vUpd, dcov); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/BasicMinimumError.cxx0000644000000000000000000000217114332717401021716 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/BasicMinimumError.h" #include "Minuit2/MnMatrix.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { MnAlgebraicSymMatrix BasicMinimumError::Hessian() const { // calculate Heassian: inverse of error matrix MnAlgebraicSymMatrix tmp(fMatrix); int ifail = Invert(tmp); if (ifail != 0) { MnPrint print("BasicMinimumError::Hessian"); print.Warn("Inversion fails; return diagonal matrix"); MnAlgebraicSymMatrix tmp2(fMatrix.Nrow()); for (unsigned int i = 0; i < fMatrix.Nrow(); i++) { tmp2(i, i) = 1. / fMatrix(i, i); } return tmp2; } return tmp; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/CMakeLists.txt0000644000000000000000000001225014332717401020342 0ustar00# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. # All rights reserved. # # For the licensing terms see $ROOTSYS/LICENSE. # For the list of contributors see $ROOTSYS/README/CREDITS. add_subdirectory(math) set(MINUIT2_HEADERS ABObj.h ABProd.h ABSum.h ABTypes.h AnalyticalGradientCalculator.h BFGSErrorUpdator.h CombinedMinimizer.h CombinedMinimumBuilder.h ContoursError.h DavidonErrorUpdator.h ExternalInternalGradientCalculator.h FCNAdapter.h FCNBase.h FCNGradAdapter.h FCNGradientBase.h FumiliBuilder.h FumiliChi2FCN.h FumiliErrorUpdator.h FumiliFCNAdapter.h FumiliFCNBase.h FumiliGradientCalculator.h FumiliMaximumLikelihoodFCN.h FumiliMinimizer.h FumiliStandardChi2FCN.h FumiliStandardMaximumLikelihoodFCN.h FunctionGradient.h FunctionMinimizer.h FunctionMinimum.h GenericFunction.h GradientCalculator.h HessianGradientCalculator.h InitialGradientCalculator.h LASymMatrix.h LAVector.h LaInverse.h LaOuterProduct.h LaProd.h LaSum.h MPIProcess.h MatrixInverse.h MinimumBuilder.h MinimumError.h MinimumErrorUpdator.h MinimumParameters.h MinimumSeed.h MinimumSeedGenerator.h MinimumState.h MinosError.h Minuit2Minimizer.h MinuitParameter.h MnApplication.h MnConfig.h MnContours.h MnCovarianceSqueeze.h MnCross.h MnEigen.h MnFcn.h MnFumiliMinimize.h MnFunctionCross.h MnGlobalCorrelationCoeff.h MnHesse.h MnLineSearch.h MnMachinePrecision.h MnMatrix.h MnMatrixfwd.h MnMigrad.h MnMinimize.h MnMinos.h MnParabola.h MnParabolaFactory.h MnParabolaPoint.h MnParameterScan.h MnPlot.h MnPosDef.h MnPrint.h MnScan.h MnSeedGenerator.h MnSimplex.h MnStrategy.h MnTiny.h MnTraceObject.h MnUserCovariance.h MnUserFcn.h MnUserParameterState.h MnUserParameters.h MnUserTransformation.h MnVectorTransform.h ModularFunctionMinimizer.h NegativeG2LineSearch.h Numerical2PGradientCalculator.h ParametricFunction.h ScanBuilder.h ScanMinimizer.h SimplexBuilder.h SimplexMinimizer.h SimplexParameters.h SimplexSeedGenerator.h SinParameterTransformation.h SqrtLowParameterTransformation.h SqrtUpParameterTransformation.h StackAllocator.h VariableMetricBuilder.h VariableMetricEDMEstimator.h VariableMetricMinimizer.h VectorOuterProduct.h ) set(MINUIT2_SOURCES AnalyticalGradientCalculator.cxx BFGSErrorUpdator.cxx CombinedMinimumBuilder.cxx DavidonErrorUpdator.cxx ExternalInternalGradientCalculator.cxx FumiliBuilder.cxx FumiliErrorUpdator.cxx FumiliGradientCalculator.cxx FumiliMinimizer.cxx FumiliStandardChi2FCN.cxx FumiliStandardMaximumLikelihoodFCN.cxx HessianGradientCalculator.cxx InitialGradientCalculator.cxx LaEigenValues.cxx LaInnerProduct.cxx LaInverse.cxx LaOuterProduct.cxx LaSumOfElements.cxx LaVtMVSimilarity.cxx MPIProcess.cxx MinimumBuilder.cxx Minuit2Minimizer.cxx MnApplication.cxx MnContours.cxx MnCovarianceSqueeze.cxx MnEigen.cxx MnFcn.cxx MnFumiliMinimize.cxx MnFunctionCross.cxx MnGlobalCorrelationCoeff.cxx MnHesse.cxx MnLineSearch.cxx MnMachinePrecision.cxx MnMinos.cxx MnParabolaFactory.cxx MnParameterScan.cxx MnPlot.cxx MnPosDef.cxx MnPrint.cxx MnPrintImpl.cxx MnScan.cxx MnSeedGenerator.cxx MnStrategy.cxx MnTiny.cxx MnTraceObject.cxx MnUserFcn.cxx MnUserParameterState.cxx MnUserParameters.cxx MnUserTransformation.cxx ModularFunctionMinimizer.cxx NegativeG2LineSearch.cxx Numerical2PGradientCalculator.cxx ParametricFunction.cxx ScanBuilder.cxx SimplexBuilder.cxx SimplexParameters.cxx SimplexSeedGenerator.cxx SinParameterTransformation.cxx SqrtLowParameterTransformation.cxx SqrtUpParameterTransformation.cxx VariableMetricBuilder.cxx VariableMetricEDMEstimator.cxx mnbins.cxx mndasum.cxx mndaxpy.cxx mnddot.cxx mndscal.cxx mndspmv.cxx mndspr.cxx mnlsame.cxx mnteigen.cxx mntplot.cxx mnvert.cxx mnxerbla.cxx ) prepend_path(MINUIT2_HEADERS "${Minuit2_SOURCE_DIR}/inc/Minuit2" ${MINUIT2_HEADERS}) prepend_path(MINUIT2_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}" ${MINUIT2_SOURCES}) add_library(Minuit2 ${MINUIT2_SOURCES} ${MINUIT2_HEADERS} ) # Add alias for direct inclusion with add_subdirectory add_library(Minuit2::Minuit2 ALIAS Minuit2) target_include_directories( Minuit2 PUBLIC $ $ ) target_compile_features(Minuit2 PUBLIC cxx_nullptr cxx_nonstatic_member_init) set_target_properties(Minuit2 PROPERTIES CXX_EXTENSIONS OFF) target_link_libraries(Minuit2 PUBLIC Minuit2Math Minuit2Common) install(TARGETS Minuit2 EXPORT Minuit2Targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES ${MINUIT2_HEADERS} DESTINATION include/Minuit2/Minuit2) iminuit-2.30.1/extern/root/math/minuit2/src/CombinedMinimumBuilder.cxx0000644000000000000000000000417314332717401022716 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/CombinedMinimumBuilder.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { FunctionMinimum CombinedMinimumBuilder::Minimum(const MnFcn &fcn, const GradientCalculator &gc, const MinimumSeed &seed, const MnStrategy &strategy, unsigned int maxfcn, double edmval) const { // find minimum using combined method // (Migrad then if fails try Simplex and then Migrad again) MnPrint print("CombinedMinimumBuilder"); FunctionMinimum min = fVMMinimizer.Builder().Minimum(fcn, gc, seed, strategy, maxfcn, edmval); if (!min.IsValid()) { print.Warn("Migrad method fails, will try with simplex method first"); MnStrategy str(2); FunctionMinimum min1 = fSimplexMinimizer.Builder().Minimum(fcn, gc, seed, str, maxfcn, edmval); if (!min1.IsValid()) { print.Warn("Both Migrad and Simplex methods failed"); return min1; } // check if gradient calculator is analytical auto agc = dynamic_cast(&gc); MinimumSeed seed1 = (agc) ? fVMMinimizer.SeedGenerator()(fcn, *agc, min1.UserState(), str) : fVMMinimizer.SeedGenerator()(fcn, gc, min1.UserState(), str); FunctionMinimum min2 = fVMMinimizer.Builder().Minimum(fcn, gc, seed1, str, maxfcn, edmval); if (!min2.IsValid()) { print.Warn("Both migrad and method failed also at 2nd attempt; return simplex Minimum"); return min1; } return min2; } return min; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/DavidonErrorUpdator.cxx0000644000000000000000000001605114332717401022266 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/DavidonErrorUpdator.h" #include "Minuit2/MinimumState.h" #include "Minuit2/LaSum.h" #include "Minuit2/LaProd.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { double inner_product(const LAVector &, const LAVector &); double similarity(const LAVector &, const LASymMatrix &); double sum_of_elements(const LASymMatrix &); MinimumError DavidonErrorUpdator::Update(const MinimumState &s0, const MinimumParameters &p1, const FunctionGradient &g1) const { // update of the covarianze matrix (Davidon formula, see Tutorial, par. 4.8 pag 26) // in case of delgam > gvg (PHI > 1) use rank one formula // see par 4.10 pag 30 // ( Tutorial: https://seal.web.cern.ch/seal/documents/minuit/mntutorial.pdf ) MnPrint print("DavidonErrorUpdator"); const MnAlgebraicSymMatrix &v0 = s0.Error().InvHessian(); MnAlgebraicVector dx = p1.Vec() - s0.Vec(); MnAlgebraicVector dg = g1.Vec() - s0.Gradient().Vec(); double delgam = inner_product(dx, dg); double gvg = similarity(dg, v0); print.Debug("\ndx", dx, "\ndg", dg, "\ndelgam", delgam, "gvg", gvg); if (delgam == 0) { print.Warn("delgam = 0 : cannot update - return same matrix (details in info log)"); print.Info("Explanation:\n" " The distance from the minimum cannot be estimated, since at two\n" " different points s0 and p1, the function gradient projected onto\n" " the difference of s0 and p1 is zero, where:\n" " * s0: ", s0.Vec(), "\n" " * p1: ", p1.Vec(), "\n" " * gradient at s0: ", s0.Gradient().Vec(), "\n" " * gradient at p1: ", g1.Vec(), "\n" " To understand whether this hints to an issue in the minimized function,\n" " the minimized function can be plotted along points between s0 and p1 to\n" " look for unexpected behavior."); return s0.Error(); } if (delgam < 0) { print.Warn("delgam < 0 : first derivatives increasing along search line (details in info log)"); print.Info("Explanation:\n" " The distance from the minimum cannot be estimated, since the minimized\n" " function seems not to be strictly convex in the space probed by the fit.\n" " That is expected if the starting parameters are e.g. close to a local maximum\n" " of the minimized function. If this function is expected to be fully convex\n" " in the probed range or Minuit is already close to the function minimum, this\n" " may hint to numerical or analytical issues with the minimized function.\n" " This was found by projecting the difference of gradients at two points, s0 and p1,\n" " onto the direction given by the difference of s0 and p1, where:\n" " * s0: ", s0.Vec(), "\n" " * p1: ", p1.Vec(), "\n" " * gradient at s0: ", s0.Gradient().Vec(), "\n" " * gradient at p1: ", g1.Vec(), "\n" " To understand whether this hints to an issue in the minimized function,\n" " the minimized function can be plotted along points between s0 and p1 to\n" " look for unexpected behavior."); } if (gvg <= 0) { // since v0 is pos def this gvg can be only = 0 if dg = 0 - should never be here print.Warn("gvg <= 0 : cannot update - return same matrix"); return s0.Error(); } MnAlgebraicVector vg = v0 * dg; // use rank 2 formula (Davidon) MnAlgebraicSymMatrix vUpd = Outer_product(dx) / delgam - Outer_product(vg) / gvg; if (delgam > gvg) { // use dual formula formula (BFGS) vUpd += gvg * Outer_product(MnAlgebraicVector(dx / delgam - vg / gvg)); print.Debug("delgam par_vec; par_vec.resize(par.Vec().size()); for (std::size_t ix = 0; ix < par.Vec().size(); ++ix) { par_vec[ix] = par.Vec()(ix); } std::vector grad = fGradFunc.Gradient(par_vec); assert(grad.size() == fTransformation.Parameters().size()); MnAlgebraicVector v(par.Vec().size()); for (unsigned int i = 0; i < par.Vec().size(); i++) { unsigned int ext = fTransformation.ExtOfInt(i); v(i) = grad[ext]; } MnPrint print("ExternalInternalGradientCalculator"); print.Debug("User given gradient in Minuit2", v); return FunctionGradient(v); } FunctionGradient ExternalInternalGradientCalculator::operator()(const MinimumParameters &par, const FunctionGradient &functionGradient) const { std::vector par_vec; par_vec.resize(par.Vec().size()); for (std::size_t ix = 0; ix < par.Vec().size(); ++ix) { par_vec[ix] = par.Vec()(ix); } std::vector previous_grad(functionGradient.Grad().Data(), functionGradient.Grad().Data() + functionGradient.Grad().size()); std::vector previous_g2(functionGradient.G2().Data(), functionGradient.G2().Data() + functionGradient.G2().size()); std::vector previous_gstep(functionGradient.Gstep().Data(), functionGradient.Gstep().Data() + functionGradient.Gstep().size()); std::vector grad = fGradFunc.GradientWithPrevResult(par_vec, previous_grad.data(), previous_g2.data(), previous_gstep.data()); assert(grad.size() == fTransformation.Parameters().size()); MnAlgebraicVector v(par.Vec().size()); MnAlgebraicVector v_g2(par.Vec().size()); MnAlgebraicVector v_gstep(par.Vec().size()); for (unsigned int i = 0; i < par.Vec().size(); i++) { unsigned int ext = fTransformation.ExtOfInt(i); v(i) = grad[ext]; v_g2(i) = previous_g2[ext]; v_gstep(i) = previous_gstep[ext]; } MnPrint print("ExternalInternalGradientCalculator"); print.Debug("User given gradient in Minuit2", v, "g2", v_g2, "step size", v_gstep); return FunctionGradient(v, v_g2, v_gstep); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/FumiliBuilder.cxx0000644000000000000000000003037314332717401021070 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/FumiliBuilder.h" #include "Minuit2/FumiliStandardMaximumLikelihoodFCN.h" #include "Minuit2/GradientCalculator.h" //#include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MinimumError.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnLineSearch.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnPosDef.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/LaSum.h" #include "Minuit2/LaProd.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnHesse.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { double inner_product(const LAVector &, const LAVector &); FunctionMinimum FumiliBuilder::Minimum(const MnFcn &fcn, const GradientCalculator &gc, const MinimumSeed &seed, const MnStrategy &strategy, unsigned int maxfcn, double edmval) const { // top level function to find minimum from a given initial seed // iterate on a minimum search in case of first attempt is not successful MnPrint print("FumiliBuilder", PrintLevel()); edmval *= 0.0001; // edmval *= 0.1; // use small factor for Fumili print.Debug("Convergence when edm <", edmval); if (seed.Parameters().Vec().size() == 0) { return FunctionMinimum(seed, fcn.Up()); } // double edm = Estimator().Estimate(seed.Gradient(), seed.Error()); double edm = seed.State().Edm(); FunctionMinimum min(seed, fcn.Up()); if (edm < 0.) { print.Warn("Initial matrix not pos.def."); return min; } std::vector result; // result.reserve(1); result.reserve(8); result.push_back(seed.State()); print.Info("Start iterating until Edm is <", edmval, '\n', "Initial state", MnPrint::Oneline(seed.State())); if (TraceIter()) TraceIteration(result.size() - 1, result.back()); // do actual iterations // try first with a maxfxn = 50% of maxfcn // Fumili in principle needs much less iterations int maxfcn_eff = int(0.5 * maxfcn); int ipass = 0; double edmprev = 1; do { min = Minimum(fcn, gc, seed, result, maxfcn_eff, edmval); // second time check for validity of function Minimum if (ipass > 0) { if (!min.IsValid()) { print.Warn("FunctionMinimum is invalid"); return min; } } // resulting edm of minimization edm = result.back().Edm(); print.Debug("Approximate Edm", edm, "npass", ipass); // call always Hesse (error matrix from Fumili is never accurate since is approximate) print.Debug("FumiliBuilder will verify convergence and Error matrix; " "dcov", min.Error().Dcovar()); // // recalculate the gradient using the numerical gradient calculator // Numerical2PGradientCalculator ngc(fcn, min.Seed().Trafo(), strategy); // FunctionGradient ng = ngc( min.State().Parameters() ); // MinimumState tmp( min.State().Parameters(), min.State().Error(), ng, min.State().Edm(), // min.State().NFcn() ); MinimumState st = MnHesse(strategy)(fcn, min.State(), min.Seed().Trafo(), maxfcn); result.push_back(st); print.Info("After Hessian"); if (TraceIter()) TraceIteration(result.size() - 1, result.back()); // check edm edm = st.Edm(); print.Debug("Edm", edm, "State", st); // break the loop if edm is NOT getting smaller if (ipass > 0 && edm >= edmprev) { print.Warn("Stop iterations, no improvements after Hesse; current Edm", edm, "previous value", edmprev); break; } if (edm > edmval) { print.Debug("Tolerance not sufficient, continue minimization; Edm", edm, "Requested", edmval); } else { // Case when edm < edmval after Heasse but min is flagged with a bad edm: // make then a new Function minimum since now edm is ok if (min.IsAboveMaxEdm()) { min = FunctionMinimum(min.Seed(), min.States(), min.Up()); break; } } // end loop on iterations // ? need a maximum here (or max of function calls is enough ? ) // continnue iteration (re-calculate function Minimum if edm IS NOT sufficient) // no need to check that hesse calculation is done (if isnot done edm is OK anyway) // count the pass to exit second time when function Minimum is invalid // increase by 20% maxfcn for doing some more tests if (ipass == 0) maxfcn_eff = maxfcn; ipass++; edmprev = edm; } while (edm > edmval); // Add latest state (Hessian calculation) min.Add(result.back()); return min; } FunctionMinimum FumiliBuilder::Minimum(const MnFcn &fcn, const GradientCalculator &gc, const MinimumSeed &seed, std::vector &result, unsigned int maxfcn, double edmval) const { // function performing the minimum searches using the FUMILI algorithm // after the modification when I iterate on this functions, so it can be called many times, // the seed is used here only to get precision and construct the returned FunctionMinimum object /* Three options were possible: 1) create two parallel and completely separate hierarchies, in which case the FumiliMinimizer would NOT inherit from ModularFunctionMinimizer, FumiliBuilder would not inherit from MinimumBuilder etc 2) Use the inheritance (base classes of ModularFunctionMinimizer, MinimumBuilder etc), but recreate the member functions Minimize() and Minimum() respectively (naming them for example minimize2() and minimum2()) so that they can take FumiliFCNBase as Parameter instead FCNBase (otherwise one wouldn't be able to call the Fumili-specific methods). 3) Cast in the daughter classes derived from ModularFunctionMinimizer, MinimumBuilder. The first two would mean to duplicate all the functionality already existent, which is a very bad practice and Error-prone. The third one is the most elegant and effective solution, where the only constraint is that the user must know that they have to pass a subclass of FumiliFCNBase to the FumiliMinimizer and not just a subclass of FCNBase. BTW, the first two solutions would have meant to recreate also a parallel structure for MnFcn... **/ // const FumiliFCNBase* tmpfcn = dynamic_cast(&(fcn.Fcn())); const MnMachinePrecision &prec = seed.Precision(); const MinimumState &initialState = result.back(); double edm = initialState.Edm(); MnPrint print("FumiliBuilder"); print.Debug("Initial State:", "\n Parameter", initialState.Vec(), "\n Gradient", initialState.Gradient().Vec(), "\n Inv Hessian", initialState.Error().InvHessian(), "\n edm", initialState.Edm(), "\n maxfcn", maxfcn, "\n tolerance", edmval); // iterate until edm is small enough or max # of iterations reached edm *= (1. + 3. * initialState.Error().Dcovar()); MnAlgebraicVector step(initialState.Gradient().Vec().size()); // initial lambda Value double lambda = 0.001; do { // const MinimumState& s0 = result.back(); MinimumState s0 = result.back(); step = -1. * s0.Error().InvHessian() * s0.Gradient().Vec(); print.Debug("Iteration -", result.size(), "\n Fval", s0.Fval(), "numOfCall", fcn.NumOfCalls(), "\n Internal Parameter values", s0.Vec(), "\n Newton step", step); double gdel = inner_product(step, s0.Gradient().Grad()); if (gdel > 0.) { print.Warn("Matrix not pos.def, gdel =", gdel, " > 0"); MnPosDef psdf; s0 = psdf(s0, prec); step = -1. * s0.Error().InvHessian() * s0.Gradient().Vec(); gdel = inner_product(step, s0.Gradient().Grad()); print.Warn("After correction, gdel =", gdel); if (gdel > 0.) { result.push_back(s0); return FunctionMinimum(seed, result, fcn.Up()); } } // MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec); // if(std::fabs(pp.Y() - s0.Fval()) < prec.Eps()) { // std::cout<<"FumiliBuilder: no improvement"<= s0.Fval()) { MnLineSearch lsearch; MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec); if (std::fabs(pp.Y() - s0.Fval()) < prec.Eps()) { // std::cout<<"FumiliBuilder: no improvement"< edmval) { if (edm < std::fabs(prec.Eps2() * result.back().Fval())) { print.Warn("Machine accuracy limits further improvement"); return FunctionMinimum(seed, result, fcn.Up()); } else if (edm < 10 * edmval) { return FunctionMinimum(seed, result, fcn.Up()); } else { print.Warn("No convergence; Edm", edm, "is above tolerance", 10 * edmval); return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnAboveMaxEdm); } } // std::cout<<"result.back().Error().Dcovar()= "< namespace ROOT { namespace Minuit2 { double sum_of_elements(const LASymMatrix &); MinimumError FumiliErrorUpdator::Update(const MinimumState &s0, const MinimumParameters &p1, const FunctionGradient &g1) const { // dummy methods to suppress unused variable warnings // this member function should never be called within // the Fumili method... s0.Fval(); p1.Fval(); g1.IsValid(); return MinimumError(2); } MinimumError FumiliErrorUpdator::Update(const MinimumState &s0, const MinimumParameters &p1, const GradientCalculator &gc, double lambda) const { // calculate the error matrix using approximation of Fumili // use only first derivatives (see tutorial par. 5.1,5.2) // The Fumili Hessian is provided by the FumiliGradientCalculator class // we apply also the Marquard lambda factor to increase weight of diagonal term // as suggester in Numerical Receipt for Marquard method // need to downcast to FumiliGradientCalculator FumiliGradientCalculator *fgc = dynamic_cast(const_cast(&gc)); assert(fgc != nullptr); MnPrint print("FumiliErrorUpdator"); // get Hessian from Gradient calculator MnAlgebraicSymMatrix h = fgc->GetHessian(); int nvar = p1.Vec().size(); // apply Marquard lambda factor double eps = 8 * std::numeric_limits::min(); for (int j = 0; j < nvar; j++) { h(j, j) *= (1. + lambda); // if h(j,j) is zero what to do ? if (std::fabs(h(j, j)) < eps) { // should use DBL_MIN // put a cut off to avoid zero on diagonals if (lambda > 1) h(j, j) = lambda * eps; else h(j, j) = eps; } } int ifail = Invert(h); if (ifail != 0) { print.Warn("inversion fails; return diagonal matrix"); for (unsigned int i = 0; i < h.Nrow(); i++) { h(i, i) = 1. / h(i, i); } } const MnAlgebraicSymMatrix &v0 = s0.Error().InvHessian(); // calculate by how much did the covariance matrix changed // (if it changed a lot since the last step, probably we // are not yet near the Minimum) double dcov = 0.5 * (s0.Error().Dcovar() + sum_of_elements(h - v0) / sum_of_elements(h)); return MinimumError(h, dcov); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/FumiliGradientCalculator.cxx0000644000000000000000000000771514332717401023255 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/FumiliGradientCalculator.h" #include "Minuit2/FumiliFCNBase.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/FumiliChi2FCN.h" #include "Minuit2/FumiliMaximumLikelihoodFCN.h" #include "Minuit2/MnPrint.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnUserFcn.h" namespace ROOT { namespace Minuit2 { FumiliGradientCalculator::FumiliGradientCalculator(const FumiliFCNBase &fcn, const MnUserTransformation &trafo, int n) : AnalyticalGradientCalculator(fcn, trafo), fFcn(fcn), fHessian(MnAlgebraicSymMatrix(n)) { } FunctionGradient FumiliGradientCalculator::operator()(const MinimumParameters &par) const { // Calculate gradient and Hessian for Fumili using the gradient and Hessian provided // by the FCN Fumili function // Need to apply internal to external for parameters and the external to int transformation // for the return gradient and Hessian int nvar = par.Vec().size(); std::vector extParam = fTransformation(par.Vec()); // eval Gradient FumiliFCNBase &fcn = const_cast(fFcn); // evaluate gradient and Hessian fcn.EvaluateAll(extParam); MnAlgebraicVector v(nvar); MnAlgebraicSymMatrix h(nvar); const std::vector &fcn_gradient = fFcn.Gradient(); assert(fcn_gradient.size() == extParam.size()); // transform gradient and Hessian from external to internal std::vector deriv(nvar); std::vector extIndex(nvar); for (int i = 0; i < nvar; ++i) { extIndex[i] = fTransformation.ExtOfInt(i); deriv[i] = 1; if (fTransformation.Parameter(extIndex[i]).HasLimits()) deriv[i] = fTransformation.DInt2Ext(i, par.Vec()(i)); v(i) = fcn_gradient[extIndex[i]] * deriv[i]; for (int j = 0; j <= i; ++j) { h(i, j) = deriv[i] * deriv[j] * fFcn.Hessian(extIndex[i], extIndex[j]); } } MnPrint print("FumiliGradientCalculator"); print.Debug([&](std::ostream &os) { // compare Fumili with Minuit gradient int plevel = MnPrint::SetGlobalLevel(MnPrint::GlobalLevel()-1); Numerical2PGradientCalculator gc(MnUserFcn(fFcn, fTransformation), fTransformation, MnStrategy(1)); FunctionGradient grd2 = gc(par); os << "Fumili Gradient:" << v << "\nMinuit Gradient" << grd2.Vec(); os << "\nFumili Hessian: " << h << std::endl; os << "Numerical g2 " << grd2.G2() << std::endl; MnPrint::SetGlobalLevel(plevel); }); // store calculated Hessian fHessian = h; // compute also g2 from diagonal Hessian MnAlgebraicVector g2(nvar); G2(par,g2); return FunctionGradient(v,g2); } FunctionGradient FumiliGradientCalculator::operator()(const MinimumParameters &par, const FunctionGradient &) const { // Needed for interface of base class. return this->operator()(par); } bool FumiliGradientCalculator::G2(const MinimumParameters &par, MnAlgebraicVector & g2) const { unsigned int n = par.Vec().size(); if (fHessian.Nrow() != n || g2.size() != n) { assert(false); return false; } for (unsigned int i = 0; i < n ; i++) { g2(i) = fHessian(i,i); } return true; } bool FumiliGradientCalculator::Hessian(const MinimumParameters &par, MnAlgebraicSymMatrix & h) const { unsigned int n = par.Vec().size(); if (fHessian.Nrow() != n ) { assert(false); return false; } h = fHessian; return true; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/FumiliMinimizer.cxx0000644000000000000000000000717214332717401021446 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnConfig.h" #include "Minuit2/FumiliMinimizer.h" #include "Minuit2/MinimumSeedGenerator.h" #include "Minuit2/FumiliGradientCalculator.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/MinimumBuilder.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnUserParameters.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnUserFcn.h" #include "Minuit2/FumiliFCNBase.h" #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { // for Fumili implement Minimize here because need downcast FunctionMinimum FumiliMinimizer::Minimize(const FCNBase &fcn, const MnUserParameterState &st, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // Minimize using Fumili. Create seed and Fumili gradient calculator. // The FCNBase passed must be a FumiliFCNBase type otherwise method will fail ! MnPrint print("FumiliMinimizer"); MnUserFcn mfcn(fcn, st.Trafo()); Numerical2PGradientCalculator gc(mfcn, st.Trafo(), strategy); unsigned int npar = st.VariableParameters(); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; // FUMILI needs much less function calls maxfcn = int(0.1 * maxfcn); MinimumSeed mnseeds = SeedGenerator()(mfcn, gc, st, strategy); // downcast fcn // std::cout << "FCN type " << typeid(&fcn).Name() << std::endl; FumiliFCNBase *fumiliFcn = dynamic_cast(const_cast(&fcn)); if (!fumiliFcn) { print.Error("Wrong FCN type; try to use default minimizer"); return FunctionMinimum(mnseeds, fcn.Up()); } FumiliGradientCalculator fgc(*fumiliFcn, st.Trafo(), npar); print.Debug("Using FumiliMinimizer"); return ModularFunctionMinimizer::Minimize(mfcn, fgc, mnseeds, strategy, maxfcn, toler); } FunctionMinimum FumiliMinimizer::Minimize(const FCNGradientBase &fcn, const MnUserParameterState &st, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { MnPrint print("FumiliMinimizer::Minimize"); // Minimize using Fumili. Case of interface is a FCNGradientBase. // Normally other method is used - probably this could be removed (t.b.i.) // need MnUserFcn MnUserFcn mfcn(fcn, st.Trafo()); AnalyticalGradientCalculator gc(fcn, st.Trafo()); unsigned int npar = st.VariableParameters(); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; MinimumSeed mnseeds = SeedGenerator()(mfcn, gc, st, strategy); // downcast fcn FumiliFCNBase *fumiliFcn = dynamic_cast(const_cast(&fcn)); if (!fumiliFcn) { print.Error("Wrong FCN type; try to use default minimizer"); return FunctionMinimum(mnseeds, fcn.Up()); } FumiliGradientCalculator fgc(*fumiliFcn, st.Trafo(), npar); print.Debug("Using FumiliMinimizer"); return ModularFunctionMinimizer::Minimize(mfcn, fgc, mnseeds, strategy, maxfcn, toler); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/FumiliStandardChi2FCN.cxx0000644000000000000000000000663314332717401022301 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/FumiliStandardChi2FCN.h" #include #include namespace ROOT { namespace Minuit2 { std::vector FumiliStandardChi2FCN::Elements(const std::vector &par) const { // Calculate the f(i) contribution to the Chi2. Chi2 = Sum[f(i)**2] std::vector result; double tmp1 = 0.0; unsigned int fPositionsSize = fPositions.size(); for (unsigned int i = 0; i < fPositionsSize; i++) { const std::vector ¤tPosition = fPositions[i]; // The commented line is the object-oriented way to do it // but it is faster to do a single function call... //(*(this->getModelFunction())).SetParameters(par); tmp1 = (*(this->ModelFunction()))(par, currentPosition) - fMeasurements[i]; result.push_back(tmp1 * fInvErrors[i]); // std::cout << "element " << i << " " << (*(this->getModelFunction()))(par, currentPosition) << " " << // fMeasurements[i] << " " << result[i] << std::endl; } return result; } const std::vector &FumiliStandardChi2FCN::GetMeasurement(int index) const { // Return the coordinate (position) values. return fPositions[index]; } int FumiliStandardChi2FCN::GetNumberOfMeasurements() const { // Return size return fPositions.size(); } void FumiliStandardChi2FCN::EvaluateAll(const std::vector &par) { // Evaluate chi2 value, gradient and hessian all in a single // loop on the measurements int nmeas = GetNumberOfMeasurements(); std::vector &grad = Gradient(); std::vector &h = Hessian(); int npar = par.size(); double chi2 = 0; grad.resize(npar); h.resize(static_cast(0.5 * npar * (npar + 1))); // reset Elements grad.assign(npar, 0.0); h.assign(static_cast(0.5 * npar * (npar + 1)), 0.0); const ParametricFunction &modelFunc = *ModelFunction(); for (int i = 0; i < nmeas; ++i) { // work for multi-dimensional points const std::vector ¤tPosition = fPositions[i]; modelFunc.SetParameters(currentPosition); double invError = fInvErrors[i]; double fval = modelFunc(par); double element = (fval - fMeasurements[i]) * invError; chi2 += element * element; // calc derivatives // this method should return a reference std::vector mfg = modelFunc.GetGradient(par); // grad is derivative of chi2 w.r.t to parameters for (int j = 0; j < npar; ++j) { double dfj = invError * mfg[j]; grad[j] += 2.0 * element * dfj; // in second derivative use Fumili approximation neglecting the term containing the // second derivatives of the model function for (int k = j; k < npar; ++k) { int idx = j + k * (k + 1) / 2; h[idx] += 2.0 * dfj * invError * mfg[k]; } } // end param loop } // end points loop // set Value in base class SetFCNValue(chi2); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/FumiliStandardMaximumLikelihoodFCN.cxx0000644000000000000000000001344314332717401025132 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/FumiliStandardMaximumLikelihoodFCN.h" #include #include #include namespace ROOT { namespace Minuit2 { std::vector FumiliStandardMaximumLikelihoodFCN::Elements(const std::vector &par) const { // calculate likelihood element f(i) = pdf(x(i)) std::vector result; double tmp1 = 0.0; unsigned int fPositionsSize = fPositions.size(); for (unsigned int i = 0; i < fPositionsSize; i++) { const std::vector ¤tPosition = fPositions[i]; // The commented line is the object-oriented way to do it // but it is faster to do a single function call... //(*(this->getModelFunction())).SetParameters(par); tmp1 = (*(this->ModelFunction()))(par, currentPosition); // std::cout << " i = " << i << " " << currentPosition[0] << " " << tmp1 << std::endl; result.push_back(tmp1); } return result; } const std::vector &FumiliStandardMaximumLikelihoodFCN::GetMeasurement(int index) const { // Return x(i). return fPositions[index]; } int FumiliStandardMaximumLikelihoodFCN::GetNumberOfMeasurements() const { // return size of positions (coordinates). return fPositions.size(); } void FumiliStandardMaximumLikelihoodFCN::EvaluateAll(const std::vector &par) { // Evaluate in one loop likelihood value, gradient and hessian const double minDouble = 8.0 * std::numeric_limits::min(); const double minDouble2 = std::sqrt(minDouble); const double maxDouble2 = 1.0 / minDouble2; // loop on the measurements int nmeas = GetNumberOfMeasurements(); std::vector &grad = Gradient(); std::vector &h = Hessian(); int npar = par.size(); double logLikelihood = 0; grad.resize(npar); h.resize(static_cast(0.5 * npar * (npar + 1))); grad.assign(npar, 0.0); h.assign(static_cast(0.5 * npar * (npar + 1)), 0.0); const ParametricFunction &modelFunc = *ModelFunction(); for (int i = 0; i < nmeas; ++i) { // work for one-dimensional points const std::vector ¤tPosition = fPositions[i]; modelFunc.SetParameters(currentPosition); double fval = modelFunc(par); if (fval < minDouble) fval = minDouble; // to avoid getting infinity and nan's logLikelihood -= std::log(fval); double invFval = 1.0 / fval; // this method should return a reference std::vector mfg = modelFunc.GetGradient(par); // calc derivatives for (int j = 0; j < npar; ++j) { if (std::fabs(mfg[j]) < minDouble) { // std::cout << "SMALL values: grad = " << mfg[j] << " " << minDouble << " f(x) = " << fval // << " params " << j << " p0 = " << par[0] << " p1 = " << par[1] << std::endl; if (mfg[j] < 0) mfg[j] = -minDouble; else mfg[j] = minDouble; } double dfj = invFval * mfg[j]; // to avoid summing infinite and nan later when calculating the Hessian if (std::fabs(dfj) > maxDouble2) { if (dfj > 0) dfj = maxDouble2; else dfj = -maxDouble2; } grad[j] -= dfj; // if ( ! ( dfj > 0) && ! ( dfj <= 0 ) ) // std::cout << " nan : dfj = " << dfj << " fval = " << fval << " invF = " << invFval << " grad = " << mfg[j] // << " par[j] = " << par[j] << std::endl; // std::cout << " x = " << currentPosition[0] << " par[j] = " << par[j] << " : dfj = " << dfj << " fval = " // << fval << " invF = " << invFval << " grad = " << mfg[j] << " deriv = " << grad[j] << std::endl; // in second derivative use Fumili approximation neglecting the term containing the // second derivatives of the model function for (int k = j; k < npar; ++k) { int idx = j + k * (k + 1) / 2; if (std::fabs(mfg[k]) < minDouble) { if (mfg[k] < 0) mfg[k] = -minDouble; else mfg[k] = minDouble; } double dfk = invFval * mfg[k]; // avoid that dfk*dfj are one small and one huge so I get a nan // to avoid summing infinite and nan later when calculating the Hessian if (std::fabs(dfk) > maxDouble2) { if (dfk > 0) dfk = maxDouble2; else dfk = -maxDouble2; } h[idx] += dfj * dfk; // if ( ( ! ( h[idx] > 0) && ! ( h[idx] <= 0 ) ) ) // std::cout << " nan : dfj = " << dfj << " fval = " << fval << " invF = " << invFval << " gradj = " << // mfg[j] // << " dfk = " << dfk << " gradk = "<< mfg[k] << " hess_jk = " << h[idx] << " par[k] = " << par[k] << // std::endl; } } // end param loop } // end points loop // std::cout <<"\nEVALUATED GRADIENT and HESSIAN " << std::endl; // for (int j = 0; j < npar; ++j) { // std::cout << " j = " << j << " grad = " << grad[j] << std::endl; // for (int k = j; k < npar; ++k) { // std::cout << " k = " << k << " hess = " << Hessian(j,k) << " " << h[ j + k*(k+1)/2] << std::endl; // } // } // set Value in base class SetFCNValue(logLikelihood); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/HessianGradientCalculator.cxx0000644000000000000000000001103314332717401023406 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/HessianGradientCalculator.h" #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnPrint.h" #include "Minuit2/MPIProcess.h" #include #include namespace ROOT { namespace Minuit2 { FunctionGradient HessianGradientCalculator::operator()(const MinimumParameters &par) const { // use initial gradient as starting point InitialGradientCalculator gc(fFcn, fTransformation); FunctionGradient gra = gc(par); return (*this)(par, gra); } FunctionGradient HessianGradientCalculator:: operator()(const MinimumParameters &par, const FunctionGradient &Gradient) const { // interface of the base class. Use DeltaGradient for op. std::pair mypair = DeltaGradient(par, Gradient); return mypair.first; } const MnMachinePrecision &HessianGradientCalculator::Precision() const { // return the precision return fTransformation.Precision(); } unsigned int HessianGradientCalculator::Ncycle() const { // return number of calculation cycles (defined in strategy) return Strategy().HessianGradientNCycles(); } std::pair HessianGradientCalculator::DeltaGradient(const MinimumParameters &par, const FunctionGradient &Gradient) const { // calculate gradient for Hessian assert(par.IsValid()); MnPrint print("HessianGradientCalculator"); MnAlgebraicVector x = par.Vec(); MnAlgebraicVector grd = Gradient.Grad(); const MnAlgebraicVector &g2 = Gradient.G2(); // const MnAlgebraicVector& gstep = Gradient.Gstep(); // update also gradient step sizes MnAlgebraicVector gstep = Gradient.Gstep(); double fcnmin = par.Fval(); // std::cout<<"fval: "< optstp) d = optstp; if (d < dmin) d = dmin; double chgold = 10000.; double dgmin = 0.; double grdold = 0.; double grdnew = 0.; for (unsigned int j = 0; j < Ncycle(); j++) { x(i) = xtf + d; double fs1 = Fcn()(x); x(i) = xtf - d; double fs2 = Fcn()(x); x(i) = xtf; // double sag = 0.5*(fs1+fs2-2.*fcnmin); // LM: should I calculate also here second derivatives ??? grdold = grd(i); grdnew = (fs1 - fs2) / (2. * d); dgmin = Precision().Eps() * (std::fabs(fs1) + std::fabs(fs2)) / d; // if(fabs(grdnew) < Precision().Eps()) break; if (grdnew == 0) break; double change = fabs((grdold - grdnew) / grdnew); if (change > chgold && j > 1) break; chgold = change; grd(i) = grdnew; // LM : update also the step sizes gstep(i) = d; if (change < 0.05) break; if (fabs(grdold - grdnew) < dgmin) break; if (d < dmin) break; d *= 0.2; } dgrd(i) = std::max(dgmin, std::fabs(grdold - grdnew)); print.Debug("HGC Param :", i, "\t new g1 =", grd(i), "gstep =", d, "dgrd =", dgrd(i)); } mpiproc.SyncVector(grd); mpiproc.SyncVector(gstep); mpiproc.SyncVector(dgrd); return std::pair(FunctionGradient(grd, g2, gstep), dgrd); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/InitialGradientCalculator.cxx0000644000000000000000000000643214332717401023414 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { FunctionGradient InitialGradientCalculator::operator()(const MinimumParameters &par) const { // initial rough estimate of the gradient using the parameter step size assert(par.IsValid()); unsigned int n = Trafo().VariableParameters(); assert(n == par.Vec().size()); MnPrint print("InitialGradientCalculator"); print.Debug("Calculating initial gradient at point", par.Vec()); MnAlgebraicVector gr(n), gr2(n), gst(n); for (unsigned int i = 0; i < n; i++) { unsigned int exOfIn = Trafo().ExtOfInt(i); double var = par.Vec()(i); double werr = Trafo().Parameter(exOfIn).Error(); double save1 = Trafo().Int2ext(i, var); double save2 = save1 + werr; if (Trafo().Parameter(exOfIn).HasLimits()) { if (Trafo().Parameter(exOfIn).HasUpperLimit() && save2 > Trafo().Parameter(exOfIn).UpperLimit()) save2 = Trafo().Parameter(exOfIn).UpperLimit(); } double var2 = Trafo().Ext2int(exOfIn, save2); double vplu = var2 - var; save2 = save1 - werr; if (Trafo().Parameter(exOfIn).HasLimits()) { if (Trafo().Parameter(exOfIn).HasLowerLimit() && save2 < Trafo().Parameter(exOfIn).LowerLimit()) save2 = Trafo().Parameter(exOfIn).LowerLimit(); } var2 = Trafo().Ext2int(exOfIn, save2); double vmin = var2 - var; double gsmin = 8. * Precision().Eps2() * (std::fabs(var) + Precision().Eps2()); // protect against very small step sizes which can cause dirin to zero and then nan values in grd double dirin = std::max(0.5 * (std::fabs(vplu) + std::fabs(vmin)), gsmin); double g2 = 2.0 * fFcn.ErrorDef() / (dirin * dirin); double gstep = std::max(gsmin, 0.1 * dirin); double grd = g2 * dirin; if (Trafo().Parameter(exOfIn).HasLimits()) { if (gstep > 0.5) gstep = 0.5; } gr(i) = grd; gr2(i) = g2; gst(i) = gstep; print.Debug("Computed initial gradient for parameter", Trafo().Name(exOfIn), "value", var, "[", vmin, ",", vplu, "]", "dirin", dirin, "grd", grd, "g2", g2); } return FunctionGradient(gr, gr2, gst); } FunctionGradient InitialGradientCalculator::operator()(const MinimumParameters &par, const FunctionGradient &) const { // Base class interface return (*this)(par); } const MnMachinePrecision &InitialGradientCalculator::Precision() const { // return precision (is set in transformation class) return fTransformation.Precision(); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/LaEigenValues.cxx0000644000000000000000000000250314332717401021012 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/LAVector.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { int mneigen(double *, unsigned int, unsigned int, unsigned int, double *, double); LAVector eigenvalues(const LASymMatrix &mat) { // calculate eigenvalues of symmetric matrices using mneigen function (translate from fortran Minuit) unsigned int nrow = mat.Nrow(); LAVector tmp(nrow * nrow); LAVector work(2 * nrow); for (unsigned int i = 0; i < nrow; i++) for (unsigned int j = 0; j <= i; j++) { tmp(i + j * nrow) = mat(i, j); tmp(i * nrow + j) = mat(i, j); } int info = mneigen(tmp.Data(), nrow, nrow, work.size(), work.Data(), 1.e-6); (void)info; assert(info == 0); LAVector result(nrow); for (unsigned int i = 0; i < nrow; i++) result(i) = work(i); return result; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/LaInnerProduct.cxx0000644000000000000000000000150614332717401021221 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/LAVector.h" namespace ROOT { namespace Minuit2 { double mnddot(unsigned int, const double *, int, const double *, int); double inner_product(const LAVector &v1, const LAVector &v2) { // calculate inner (dot) product of two vectors using mnddot function return mnddot(v1.size(), v1.Data(), 1, v2.Data(), 1); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/LaInverse.cxx0000644000000000000000000000201314332717401020212 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/LaInverse.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { int mnvert(LASymMatrix &t); // symmetric matrix (positive definite only) int Invert(LASymMatrix &t) { // function for inversion of symmetric matrices using mnvert function // (from Fortran Minuit) int ifail = 0; if (t.size() == 1) { double tmp = t.Data()[0]; if (!(tmp > 0.)) ifail = 1; else t.Data()[0] = 1. / tmp; } else { ifail = mnvert(t); } return ifail; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/LaOuterProduct.cxx0000644000000000000000000000513414332717401021245 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/LaOuterProduct.h" #include "Minuit2/LAVector.h" #include "Minuit2/LASymMatrix.h" namespace ROOT { namespace Minuit2 { int mndspr(const char *, unsigned int, double, const double *, int, double *); LASymMatrix::LASymMatrix(const ABObj, double>, double> &out) : fSize(0), fNRow(0), fData(nullptr) { // constructor from expression based on outer product of symmetric matrices // std::cout<<"LASymMatrix::LASymMatrix(const ABObj, double>, // double>& out)"<, double>, double> &out) { // assignment operator from expression based on outer product of symmetric matrices // std::cout<<"LASymMatrix& LASymMatrix::operator=(const ABObj, double>, double>& out)"< namespace ROOT { namespace Minuit2 { unsigned int MPIProcess::fgGlobalSize = 1; unsigned int MPIProcess::fgGlobalRank = 0; // By default all procs are for X unsigned int MPIProcess::fgCartSizeX = 0; unsigned int MPIProcess::fgCartSizeY = 0; unsigned int MPIProcess::fgCartDimension = 0; bool MPIProcess::fgNewCart = true; #ifdef MPIPROC MPI::Intracomm *MPIProcess::fgCommunicator = 0; int MPIProcess::fgIndexComm = -1; // -1 for no-initialization MPI::Intracomm *MPIProcess::fgCommunicators[2] = {0}; unsigned int MPIProcess::fgIndicesComm[2] = {0}; #endif MPIProcess::MPIProcess(unsigned int nelements, unsigned int indexComm) : fNelements(nelements), fSize(1), fRank(0) { // check local requested index for communicator, valid values are 0 and 1 indexComm = (indexComm == 0) ? 0 : 1; #ifdef MPIPROC StartMPI(); if (fgGlobalSize == fgCartDimension && fgCartSizeX != fgCartDimension && fgCartSizeY != fgCartDimension) { // declare the cartesian topology if (fgCommunicator == 0 && fgIndexComm < 0 && fgNewCart) { // first call, declare the topology std::cout << "Info --> MPIProcess::MPIProcess: Declare cartesian Topology (" << fgCartSizeX << "x" << fgCartSizeY << ")" << std::endl; int color = fgGlobalRank / fgCartSizeY; int key = fgGlobalRank % fgCartSizeY; fgCommunicators[0] = new MPI::Intracomm(MPI::COMM_WORLD.Split(key, color)); // rows for Minuit fgCommunicators[1] = new MPI::Intracomm(MPI::COMM_WORLD.Split(color, key)); // columns for NLL fgNewCart = false; } fgIndexComm++; if (fgIndexComm > 1 || fgCommunicator == (&(MPI::COMM_WORLD))) { // Remember, no more than 2 dimensions in the topology! std::cerr << "Error --> MPIProcess::MPIProcess: Requiring more than 2 dimensions in the topology!" << std::endl; MPI::COMM_WORLD.Abort(-1); } // requiring columns as first call. In this case use all nodes if (((unsigned int)fgIndexComm) < indexComm) fgCommunicator = &(MPI::COMM_WORLD); else { fgIndicesComm[fgIndexComm] = indexComm; fgCommunicator = fgCommunicators[fgIndicesComm[fgIndexComm]]; } } else { // no cartesian topology if (fgCartDimension != 0 && fgGlobalSize != fgCartDimension) { std::cout << "Warning --> MPIProcess::MPIProcess: Cartesian dimension doesn't correspond to # total procs!" << std::endl; std::cout << "Warning --> MPIProcess::MPIProcess: Ignoring topology, use all procs for X." << std::endl; std::cout << "Warning --> MPIProcess::MPIProcess: Resetting topology..." << std::endl; fgCartSizeX = fgGlobalSize; fgCartSizeY = 1; fgCartDimension = fgGlobalSize; } if (fgIndexComm < 0) { if (fgCartSizeX == fgCartDimension) { fgCommunicators[0] = &(MPI::COMM_WORLD); fgCommunicators[1] = 0; } else { fgCommunicators[0] = 0; fgCommunicators[1] = &(MPI::COMM_WORLD); } } fgIndexComm++; if (fgIndexComm > 1) { // Remember, no more than 2 nested MPI calls! std::cerr << "Error --> MPIProcess::MPIProcess: More than 2 nested MPI calls!" << std::endl; MPI::COMM_WORLD.Abort(-1); } fgIndicesComm[fgIndexComm] = indexComm; // require 2 nested communicators if (fgCommunicator != 0 && fgCommunicators[indexComm] != 0) { std::cout << "Warning --> MPIProcess::MPIProcess: Requiring 2 nested MPI calls!" << std::endl; std::cout << "Warning --> MPIProcess::MPIProcess: Ignoring second call." << std::endl; fgIndicesComm[fgIndexComm] = (indexComm == 0) ? 1 : 0; } fgCommunicator = fgCommunicators[fgIndicesComm[fgIndexComm]]; } // set size and rank if (fgCommunicator != 0) { fSize = fgCommunicator->Get_size(); fRank = fgCommunicator->Get_rank(); } else { // no MPI calls fSize = 1; fRank = 0; } if (fSize > fNelements) { std::cerr << "Error --> MPIProcess::MPIProcess: more processors than elements!" << std::endl; MPI::COMM_WORLD.Abort(-1); } #endif fNumElements4JobIn = fNelements / fSize; fNumElements4JobOut = fNelements % fSize; } MPIProcess::~MPIProcess() { // destructor #ifdef MPIPROC fgCommunicator = 0; fgIndexComm--; if (fgIndexComm == 0) fgCommunicator = fgCommunicators[fgIndicesComm[fgIndexComm]]; #endif } bool MPIProcess::SyncVector(ROOT::Minuit2::MnAlgebraicVector &mnvector) { // In case of just one job, don't need sync, just go if (fSize < 2) return false; if (mnvector.size() != fNelements) { std::cerr << "Error --> MPIProcess::SyncVector: # defined elements different from # requested elements!" << std::endl; std::cerr << "Error --> MPIProcess::SyncVector: no MPI synchronization is possible!" << std::endl; exit(-1); } #ifdef MPIPROC unsigned int numElements4ThisJob = NumElements4Job(fRank); unsigned int startElementIndex = StartElementIndex(); unsigned int endElementIndex = EndElementIndex(); double dvectorJob[numElements4ThisJob]; for (unsigned int i = startElementIndex; i < endElementIndex; i++) dvectorJob[i - startElementIndex] = mnvector(i); double dvector[fNelements]; MPISyncVector(dvectorJob, numElements4ThisJob, dvector); for (unsigned int i = 0; i < fNelements; i++) { mnvector(i) = dvector[i]; } return true; #else std::cerr << "Error --> MPIProcess::SyncVector: no MPI synchronization is possible!" << std::endl; exit(-1); #endif } bool MPIProcess::SyncSymMatrixOffDiagonal(ROOT::Minuit2::MnAlgebraicSymMatrix &mnmatrix) { // In case of just one job, don't need sync, just go if (fSize < 2) return false; if (mnmatrix.size() - mnmatrix.Nrow() != fNelements) { std::cerr << "Error --> MPIProcess::SyncSymMatrixOffDiagonal: # defined elements different from # requested elements!" << std::endl; std::cerr << "Error --> MPIProcess::SyncSymMatrixOffDiagonal: no MPI synchronization is possible!" << std::endl; exit(-1); } #ifdef MPIPROC unsigned int numElements4ThisJob = NumElements4Job(fRank); unsigned int startElementIndex = StartElementIndex(); unsigned int endElementIndex = EndElementIndex(); unsigned int nrow = mnmatrix.Nrow(); unsigned int offsetVect = 0; for (unsigned int i = 0; i < startElementIndex; i++) if ((i + offsetVect) % (nrow - 1) == 0) offsetVect += (i + offsetVect) / (nrow - 1); double dvectorJob[numElements4ThisJob]; for (unsigned int i = startElementIndex; i < endElementIndex; i++) { int x = (i + offsetVect) / (nrow - 1); if ((i + offsetVect) % (nrow - 1) == 0) offsetVect += x; int y = (i + offsetVect) % (nrow - 1) + 1; dvectorJob[i - startElementIndex] = mnmatrix(x, y); } double dvector[fNelements]; MPISyncVector(dvectorJob, numElements4ThisJob, dvector); offsetVect = 0; for (unsigned int i = 0; i < fNelements; i++) { int x = (i + offsetVect) / (nrow - 1); if ((i + offsetVect) % (nrow - 1) == 0) offsetVect += x; int y = (i + offsetVect) % (nrow - 1) + 1; mnmatrix(x, y) = dvector[i]; } return true; #else std::cerr << "Error --> MPIProcess::SyncMatrix: no MPI synchronization is possible!" << std::endl; exit(-1); #endif } #ifdef MPIPROC void MPIProcess::MPISyncVector(double *ivector, int svector, double *ovector) { int offsets[fSize]; int nconts[fSize]; nconts[0] = NumElements4Job(0); offsets[0] = 0; for (unsigned int i = 1; i < fSize; i++) { nconts[i] = NumElements4Job(i); offsets[i] = nconts[i - 1] + offsets[i - 1]; } fgCommunicator->Allgatherv(ivector, svector, MPI::DOUBLE, ovector, nconts, offsets, MPI::DOUBLE); } bool MPIProcess::SetCartDimension(unsigned int dimX, unsigned int dimY) { if (fgCommunicator != 0 || fgIndexComm >= 0) { std::cout << "Warning --> MPIProcess::SetCartDimension: MPIProcess already declared! Ignoring command..." << std::endl; return false; } if (dimX * dimY <= 0) { std::cout << "Warning --> MPIProcess::SetCartDimension: Invalid topology! Ignoring command..." << std::endl; return false; } StartMPI(); if (fgGlobalSize != dimX * dimY) { std::cout << "Warning --> MPIProcess::SetCartDimension: Cartesian dimension doesn't correspond to # total procs!" << std::endl; std::cout << "Warning --> MPIProcess::SetCartDimension: Ignoring command..." << std::endl; return false; } if (fgCartSizeX != dimX || fgCartSizeY != dimY) { fgCartSizeX = dimX; fgCartSizeY = dimY; fgCartDimension = fgCartSizeX * fgCartSizeY; fgNewCart = true; if (fgCommunicators[0] != 0 && fgCommunicators[1] != 0) { delete fgCommunicators[0]; fgCommunicators[0] = 0; fgIndicesComm[0] = 0; delete fgCommunicators[1]; fgCommunicators[1] = 0; fgIndicesComm[1] = 0; } } return true; } bool MPIProcess::SetDoFirstMPICall(bool doFirstMPICall) { StartMPI(); bool ret; if (doFirstMPICall) ret = SetCartDimension(fgGlobalSize, 1); else ret = SetCartDimension(1, fgGlobalSize); return ret; } #endif #ifdef MPIPROC MPITerminate dummyMPITerminate = MPITerminate(); #endif } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MinimumBuilder.cxx0000644000000000000000000000131314332717401021246 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MinimumBuilder.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { MinimumBuilder::MinimumBuilder() : fPrintLevel(MnPrint::GlobalLevel()), fStorageLevel(1), fTracer(nullptr) {} } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/Minuit2Minimizer.cxx0000644000000000000000000013057414332717401021553 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta Wed Oct 18 11:48:00 2006 /********************************************************************** * * * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT * * * * * **********************************************************************/ // Implementation file for class Minuit2Minimizer #include "Minuit2/Minuit2Minimizer.h" #include "Math/IFunction.h" #include "Math/IOptions.h" #include "Fit/ParameterSettings.h" #include "Minuit2/FCNAdapter.h" #include "Minuit2/FumiliFCNAdapter.h" #include "Minuit2/FCNGradAdapter.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnMigrad.h" #include "Minuit2/MnMinos.h" #include "Minuit2/MinosError.h" #include "Minuit2/MnHesse.h" #include "Minuit2/MinuitParameter.h" #include "Minuit2/MnUserFcn.h" #include "Minuit2/MnPrint.h" #include "Minuit2/VariableMetricMinimizer.h" #include "Minuit2/SimplexMinimizer.h" #include "Minuit2/CombinedMinimizer.h" #include "Minuit2/ScanMinimizer.h" #include "Minuit2/FumiliMinimizer.h" #include "Minuit2/MnParameterScan.h" #include "Minuit2/MnContours.h" #include "Minuit2/MnTraceObject.h" #include "Minuit2/MinimumBuilder.h" #include #include #include #include #ifdef USE_ROOT_ERROR #include "TError.h" #include "TROOT.h" #include "TMinuit2TraceObject.h" #endif namespace ROOT { namespace Minuit2 { // functions needed to control siwthc off of Minuit2 printing level #ifdef USE_ROOT_ERROR int TurnOffPrintInfoLevel() { // switch off Minuit2 printing of INFO message (cut off is 1001) int prevErrorIgnoreLevel = gErrorIgnoreLevel; if (prevErrorIgnoreLevel < 1001) { gErrorIgnoreLevel = 1001; return prevErrorIgnoreLevel; } return -2; // no op in this case } void RestoreGlobalPrintLevel(int value) { gErrorIgnoreLevel = value; } #else // dummy functions int TurnOffPrintInfoLevel() { return -1; } int ControlPrintLevel() { return -1; } void RestoreGlobalPrintLevel(int) {} #endif Minuit2Minimizer::Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type) : Minimizer(), fDim(0), fMinimizer(nullptr), fMinuitFCN(nullptr), fMinimum(nullptr) { // Default constructor implementation depending on minimizer type SetMinimizerType(type); } Minuit2Minimizer::Minuit2Minimizer(const char *type) : Minimizer(), fDim(0), fMinimizer(nullptr), fMinuitFCN(nullptr), fMinimum(nullptr) { // constructor from a string std::string algoname(type); // tolower() is not an std function (Windows) std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int (*)(int))tolower); EMinimizerType algoType = kMigrad; if (algoname == "simplex") algoType = kSimplex; if (algoname == "minimize") algoType = kCombined; if (algoname == "scan") algoType = kScan; if (algoname == "fumili" || algoname == "fumili2") algoType = kFumili; if (algoname == "bfgs") algoType = kMigradBFGS; SetMinimizerType(algoType); } void Minuit2Minimizer::SetMinimizerType(ROOT::Minuit2::EMinimizerType type) { // Set minimizer algorithm type fUseFumili = false; switch (type) { case ROOT::Minuit2::kMigrad: // std::cout << "Minuit2Minimizer: minimize using MIGRAD " << std::endl; SetMinimizer(new ROOT::Minuit2::VariableMetricMinimizer()); return; case ROOT::Minuit2::kMigradBFGS: // std::cout << "Minuit2Minimizer: minimize using MIGRAD " << std::endl; SetMinimizer(new ROOT::Minuit2::VariableMetricMinimizer(VariableMetricMinimizer::BFGSType())); return; case ROOT::Minuit2::kSimplex: // std::cout << "Minuit2Minimizer: minimize using SIMPLEX " << std::endl; SetMinimizer(new ROOT::Minuit2::SimplexMinimizer()); return; case ROOT::Minuit2::kCombined: SetMinimizer(new ROOT::Minuit2::CombinedMinimizer()); return; case ROOT::Minuit2::kScan: SetMinimizer(new ROOT::Minuit2::ScanMinimizer()); return; case ROOT::Minuit2::kFumili: SetMinimizer(new ROOT::Minuit2::FumiliMinimizer()); fUseFumili = true; return; default: // migrad minimizer SetMinimizer(new ROOT::Minuit2::VariableMetricMinimizer()); } } Minuit2Minimizer::~Minuit2Minimizer() { // Destructor implementation. if (fMinimizer) delete fMinimizer; if (fMinuitFCN) delete fMinuitFCN; if (fMinimum) delete fMinimum; } Minuit2Minimizer::Minuit2Minimizer(const Minuit2Minimizer &) : ROOT::Math::Minimizer() { // Implementation of copy constructor. } Minuit2Minimizer &Minuit2Minimizer::operator=(const Minuit2Minimizer &rhs) { // Implementation of assignment operator. if (this == &rhs) return *this; // time saving self-test return *this; } void Minuit2Minimizer::Clear() { // delete the state in case of consecutive minimizations fState = MnUserParameterState(); // clear also the function minimum if (fMinimum) delete fMinimum; fMinimum = nullptr; } // set variables bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string &name, double val, double step) { // set a free variable. // Add the variable if not existing otherwise set value if exists already // this is implemented in MnUserParameterState::Add // if index is wrong (i.e. variable already exists but with a different index return false) but // value is set for corresponding variable name // std::cout << " add parameter " << name << " " << val << " step " << step << std::endl; MnPrint print("Minuit2Minimizer::SetVariable", PrintLevel()); if (step <= 0) { print.Info("Parameter", name, "has zero or invalid step size - consider it as constant"); fState.Add(name, val); } else fState.Add(name, val, step); unsigned int minuit2Index = fState.Index(name); if (minuit2Index != ivar) { print.Warn("Wrong index", minuit2Index, "used for the variable", name); ivar = minuit2Index; return false; } fState.RemoveLimits(ivar); return true; } bool Minuit2Minimizer::SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower) { // add a lower bounded variable if (!SetVariable(ivar, name, val, step)) return false; fState.SetLowerLimit(ivar, lower); return true; } bool Minuit2Minimizer::SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper) { // add a upper bounded variable if (!SetVariable(ivar, name, val, step)) return false; fState.SetUpperLimit(ivar, upper); return true; } bool Minuit2Minimizer::SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower, double upper) { // add a double bound variable if (!SetVariable(ivar, name, val, step)) return false; fState.SetLimits(ivar, lower, upper); return true; } bool Minuit2Minimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val) { // add a fixed variable // need a step size otherwise treated as a constant // use 10% double step = (val != 0) ? 0.1 * std::abs(val) : 0.1; if (!SetVariable(ivar, name, val, step)) { ivar = fState.Index(name); } fState.Fix(ivar); return true; } std::string Minuit2Minimizer::VariableName(unsigned int ivar) const { // return the variable name if (ivar >= fState.MinuitParameters().size()) return std::string(); return fState.GetName(ivar); } int Minuit2Minimizer::VariableIndex(const std::string &name) const { // return the variable index // check if variable exist return fState.Trafo().FindIndex(name); } bool Minuit2Minimizer::SetVariableValue(unsigned int ivar, double val) { // set value for variable ivar (only for existing parameters) if (ivar >= fState.MinuitParameters().size()) return false; fState.SetValue(ivar, val); return true; } bool Minuit2Minimizer::SetVariableValues(const double *x) { // set value for variable ivar (only for existing parameters) unsigned int n = fState.MinuitParameters().size(); if (n == 0) return false; for (unsigned int ivar = 0; ivar < n; ++ivar) fState.SetValue(ivar, x[ivar]); return true; } bool Minuit2Minimizer::SetVariableStepSize(unsigned int ivar, double step) { // set the step-size of an existing variable // parameter must exist or return false if (ivar >= fState.MinuitParameters().size()) return false; fState.SetError(ivar, step); return true; } bool Minuit2Minimizer::SetVariableLowerLimit(unsigned int ivar, double lower) { // set the limits of an existing variable // parameter must exist or return false if (ivar >= fState.MinuitParameters().size()) return false; fState.SetLowerLimit(ivar, lower); return true; } bool Minuit2Minimizer::SetVariableUpperLimit(unsigned int ivar, double upper) { // set the limits of an existing variable // parameter must exist or return false if (ivar >= fState.MinuitParameters().size()) return false; fState.SetUpperLimit(ivar, upper); return true; } bool Minuit2Minimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) { // set the limits of an existing variable // parameter must exist or return false if (ivar >= fState.MinuitParameters().size()) return false; fState.SetLimits(ivar, lower, upper); return true; } bool Minuit2Minimizer::FixVariable(unsigned int ivar) { // Fix an existing variable if (ivar >= fState.MinuitParameters().size()) return false; fState.Fix(ivar); return true; } bool Minuit2Minimizer::ReleaseVariable(unsigned int ivar) { // Release an existing variable if (ivar >= fState.MinuitParameters().size()) return false; fState.Release(ivar); return true; } bool Minuit2Minimizer::IsFixedVariable(unsigned int ivar) const { // query if variable is fixed if (ivar >= fState.MinuitParameters().size()) { MnPrint print("Minuit2Minimizer", PrintLevel()); print.Error("Wrong variable index"); return false; } return (fState.Parameter(ivar).IsFixed() || fState.Parameter(ivar).IsConst()); } bool Minuit2Minimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const { // retrieve variable settings (all set info on the variable) if (ivar >= fState.MinuitParameters().size()) { MnPrint print("Minuit2Minimizer", PrintLevel()); print.Error("Wrong variable index"); return false; } const MinuitParameter &par = fState.Parameter(ivar); varObj.Set(par.Name(), par.Value(), par.Error()); if (par.HasLowerLimit()) { if (par.HasUpperLimit()) { varObj.SetLimits(par.LowerLimit(), par.UpperLimit()); } else { varObj.SetLowerLimit(par.LowerLimit()); } } else if (par.HasUpperLimit()) { varObj.SetUpperLimit(par.UpperLimit()); } if (par.IsConst() || par.IsFixed()) varObj.Fix(); return true; } void Minuit2Minimizer::SetFunction(const ROOT::Math::IMultiGenFunction &func) { // set function to be minimized if (fMinuitFCN) delete fMinuitFCN; fDim = func.NDim(); const bool hasGrad = func.HasGradient(); if (!fUseFumili) { fMinuitFCN = hasGrad ? static_cast(new ROOT::Minuit2::FCNGradAdapter(dynamic_cast(func), ErrorDef())) : static_cast(new ROOT::Minuit2::FCNAdapter(func, ErrorDef())); } else { if(hasGrad) { // for Fumili the fit method function interface is required auto fcnfunc = dynamic_cast(&func); if (!fcnfunc) { MnPrint print("Minuit2Minimizer", PrintLevel()); print.Error("Wrong Fit method function for Fumili"); return; } fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter(*fcnfunc, fDim, ErrorDef()); } else { // for Fumili the fit method function interface is required auto fcnfunc = dynamic_cast(&func); if (!fcnfunc) { MnPrint print("Minuit2Minimizer", PrintLevel()); print.Error("Wrong Fit method function for Fumili"); return; } fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter(*fcnfunc, fDim, ErrorDef()); } } } void Minuit2Minimizer::SetHessianFunction(std::function &, double *)> hfunc) { // for Fumili not supported for the time being if (fUseFumili) return; auto fcn = static_cast *>(fMinuitFCN); if (!fcn) return; fcn->SetHessianFunction(hfunc); } namespace { ROOT::Minuit2::MnStrategy customizedStrategy(unsigned int strategyLevel, ROOT::Math::MinimizerOptions const &options) { ROOT::Minuit2::MnStrategy st{strategyLevel}; // set strategy and add extra options if needed const ROOT::Math::IOptions *minuit2Opt = options.ExtraOptions(); if (!minuit2Opt) { minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault("Minuit2"); } if (!minuit2Opt) { return st; } auto customize = [&minuit2Opt](const char *name, auto val) { minuit2Opt->GetValue(name, val); return val; }; // set extra options st.SetGradientNCycles(customize("GradientNCycles", int(st.GradientNCycles()))); st.SetHessianNCycles(customize("HessianNCycles", int(st.HessianNCycles()))); st.SetHessianGradientNCycles(customize("HessianGradientNCycles", int(st.HessianGradientNCycles()))); st.SetGradientTolerance(customize("GradientTolerance", st.GradientTolerance())); st.SetGradientStepTolerance(customize("GradientStepTolerance", st.GradientStepTolerance())); st.SetHessianStepTolerance(customize("HessianStepTolerance", st.HessianStepTolerance())); st.SetHessianG2Tolerance(customize("HessianG2Tolerance", st.HessianG2Tolerance())); return st; } } // namespace bool Minuit2Minimizer::Minimize() { // perform the minimization // store a copy of FunctionMinimum MnPrint print("Minuit2Minimizer::Minimize", PrintLevel()); if (!fMinuitFCN) { print.Error("FCN function has not been set"); return false; } assert(GetMinimizer() != nullptr); // delete result of previous minimization if (fMinimum) delete fMinimum; fMinimum = nullptr; const int maxfcn = MaxFunctionCalls(); const double tol = Tolerance(); const int strategyLevel = Strategy(); fMinuitFCN->SetErrorDef(ErrorDef()); const int printLevel = PrintLevel(); if (PrintLevel() >= 1) { // print the real number of maxfcn used (defined in ModularFunctionMinimizer) int maxfcn_used = maxfcn; if (maxfcn_used == 0) { int nvar = fState.VariableParameters(); maxfcn_used = 200 + 100 * nvar + 5 * nvar * nvar; } std::cout << "Minuit2Minimizer: Minimize with max-calls " << maxfcn_used << " convergence for edm < " << tol << " strategy " << strategyLevel << std::endl; } // internal minuit messages fMinimizer->Builder().SetPrintLevel(printLevel); // switch off Minuit2 printing const int prev_level = (printLevel <= 0) ? TurnOffPrintInfoLevel() : -2; const int prevGlobalLevel = MnPrint::SetGlobalLevel(printLevel); // set the precision if needed if (Precision() > 0) fState.SetPrecision(Precision()); // add extra options if needed const ROOT::Math::IOptions *minuit2Opt = fOptions.ExtraOptions(); if (!minuit2Opt) { minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault("Minuit2"); } if (minuit2Opt) { // set extra options int storageLevel = 1; bool ret = minuit2Opt->GetValue("StorageLevel", storageLevel); if (ret) SetStorageLevel(storageLevel); if (printLevel > 0) { std::cout << "Minuit2Minimizer::Minuit - Changing default options" << std::endl; minuit2Opt->Print(); } } // set a minimizer tracer object (default for printlevel=10, from gROOT for printLevel=11) // use some special print levels MnTraceObject *traceObj = nullptr; #ifdef USE_ROOT_ERROR if (printLevel == 10 && gROOT) { TObject *obj = gROOT->FindObject("Minuit2TraceObject"); traceObj = dynamic_cast(obj); if (traceObj) { // need to remove from the list gROOT->Remove(obj); } } if (printLevel == 20 || printLevel == 30 || printLevel == 40 || (printLevel >= 20000 && printLevel < 30000)) { int parNumber = printLevel - 20000; if (printLevel == 20) parNumber = -1; if (printLevel == 30) parNumber = -2; if (printLevel == 40) parNumber = 0; traceObj = new TMinuit2TraceObject(parNumber); } #endif if (printLevel == 100 || (printLevel >= 10000 && printLevel < 20000)) { int parNumber = printLevel - 10000; traceObj = new MnTraceObject(parNumber); } if (traceObj) { traceObj->Init(fState); SetTraceObject(*traceObj); } const ROOT::Minuit2::MnStrategy strategy = customizedStrategy(strategyLevel, fOptions); const ROOT::Minuit2::FCNGradientBase *gradFCN = dynamic_cast(fMinuitFCN); if (gradFCN != nullptr) { // use gradient // SetPrintLevel(3); ROOT::Minuit2::FunctionMinimum min = GetMinimizer()->Minimize(*gradFCN, fState, strategy, maxfcn, tol); fMinimum = new ROOT::Minuit2::FunctionMinimum(min); } else { ROOT::Minuit2::FunctionMinimum min = GetMinimizer()->Minimize(*GetFCN(), fState, strategy, maxfcn, tol); fMinimum = new ROOT::Minuit2::FunctionMinimum(min); } // check if Hesse needs to be run. We do it when is requested (IsValidError() == true , set by SetParabError(true) in fitConfig) // (IsValidError() means the flag to get correct error from the Minimizer is set (Minimizer::SetValidError()) // AND when we have a valid minimum, // AND when the the current covariance matrix is estimated using the iterative approximation (Dcovar != 0 , i.e. Hesse has not computed before) if (fMinimum->IsValid() && IsValidError() && fMinimum->State().Error().Dcovar() != 0) { // run Hesse (Hesse will add results in the last state of fMinimum ROOT::Minuit2::MnHesse hesse(strategy); hesse(*fMinuitFCN, *fMinimum, maxfcn); } // -2 is the highest low invalid value for gErrorIgnoreLevel if (prev_level > -2) RestoreGlobalPrintLevel(prev_level); MnPrint::SetGlobalLevel(prevGlobalLevel); // copy minimum state (parameter values and errors) fState = fMinimum->UserState(); bool ok = ExamineMinimum(*fMinimum); // fMinimum = 0; // delete trace object if it was constructed if (traceObj) { delete traceObj; } return ok; } bool Minuit2Minimizer::ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min) { /// study the function minimum // debug ( print all the states) int debugLevel = PrintLevel(); if (debugLevel >= 3) { const std::vector &iterationStates = min.States(); std::cout << "Number of iterations " << iterationStates.size() << std::endl; for (unsigned int i = 0; i < iterationStates.size(); ++i) { // std::cout << iterationStates[i] << std::endl; const ROOT::Minuit2::MinimumState &st = iterationStates[i]; std::cout << "----------> Iteration " << i << std::endl; int pr = std::cout.precision(12); std::cout << " FVAL = " << st.Fval() << " Edm = " << st.Edm() << " Nfcn = " << st.NFcn() << std::endl; std::cout.precision(pr); if (st.HasCovariance()) std::cout << " Error matrix change = " << st.Error().Dcovar() << std::endl; if (st.HasParameters()) { std::cout << " Parameters : "; // need to transform from internal to external for (int j = 0; j < st.size(); ++j) std::cout << " p" << j << " = " << fState.Int2ext(j, st.Vec()(j)); std::cout << std::endl; } } } fStatus = 0; std::string txt; if (!min.HasPosDefCovar()) { // this happens normally when Hesse failed // it can happen in case MnSeed failed (see ROOT-9522) txt = "Covar is not pos def"; fStatus = 5; } if (min.HasMadePosDefCovar()) { txt = "Covar was made pos def"; fStatus = 1; } if (min.HesseFailed()) { txt = "Hesse is not valid"; fStatus = 2; } if (min.IsAboveMaxEdm()) { txt = "Edm is above max"; fStatus = 3; } if (min.HasReachedCallLimit()) { txt = "Reached call limit"; fStatus = 4; } MnPrint print("Minuit2Minimizer::Minimize", debugLevel); bool validMinimum = min.IsValid(); if (validMinimum) { // print a warning message in case something is not ok // this for example is case when Covar was made posdef and fStatus=3 if (fStatus != 0 && debugLevel > 0) print.Warn(txt); } else { // minimum is not valid when state is not valid and edm is over max or has passed call limits if (fStatus == 0) { // this should not happen txt = "unknown failure"; fStatus = 6; } print.Warn("Minimization did NOT converge,", txt); } if (debugLevel >= 1) PrintResults(); // set the minimum values in the fValues vector const std::vector ¶msObj = fState.MinuitParameters(); if (paramsObj.empty()) return false; assert(fDim == paramsObj.size()); // re-size vector if it has changed after a new minimization if (fValues.size() != fDim) fValues.resize(fDim); for (unsigned int i = 0; i < fDim; ++i) { fValues[i] = paramsObj[i].Value(); } return validMinimum; } void Minuit2Minimizer::PrintResults() { // print results of minimization if (!fMinimum) return; if (fMinimum->IsValid()) { // valid minimum std::cout << "Minuit2Minimizer : Valid minimum - status = " << fStatus << std::endl; int pr = std::cout.precision(18); std::cout << "FVAL = " << fState.Fval() << std::endl; std::cout << "Edm = " << fState.Edm() << std::endl; std::cout.precision(pr); std::cout << "Nfcn = " << fState.NFcn() << std::endl; for (unsigned int i = 0; i < fState.MinuitParameters().size(); ++i) { const MinuitParameter &par = fState.Parameter(i); std::cout << par.Name() << "\t = " << par.Value() << "\t "; if (par.IsFixed()) std::cout << "(fixed)" << std::endl; else if (par.IsConst()) std::cout << "(const)" << std::endl; else if (par.HasLimits()) std::cout << "+/- " << par.Error() << "\t(limited)" << std::endl; else std::cout << "+/- " << par.Error() << std::endl; } } else { std::cout << "Minuit2Minimizer : Invalid minimum - status = " << fStatus << std::endl; std::cout << "FVAL = " << fState.Fval() << std::endl; std::cout << "Edm = " << fState.Edm() << std::endl; std::cout << "Nfcn = " << fState.NFcn() << std::endl; } } const double *Minuit2Minimizer::Errors() const { // return error at minimum (set to zero for fixed and constant params) const std::vector ¶msObj = fState.MinuitParameters(); if (paramsObj.empty()) return nullptr; assert(fDim == paramsObj.size()); // be careful for multiple calls of this function. I will redo an allocation here // only when size of vectors has changed (e.g. after a new minimization) if (fErrors.size() != fDim) fErrors.resize(fDim); for (unsigned int i = 0; i < fDim; ++i) { const MinuitParameter &par = paramsObj[i]; if (par.IsFixed() || par.IsConst()) fErrors[i] = 0; else fErrors[i] = par.Error(); } return &fErrors.front(); } double Minuit2Minimizer::CovMatrix(unsigned int i, unsigned int j) const { // get value of covariance matrices (transform from external to internal indices) if (i >= fDim || j >= fDim) return 0; if (!fState.HasCovariance()) return 0; // no info available when minimization has failed if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) return 0; if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst()) return 0; unsigned int k = fState.IntOfExt(i); unsigned int l = fState.IntOfExt(j); return fState.Covariance()(k, l); } bool Minuit2Minimizer::GetCovMatrix(double *cov) const { // get value of covariance matrices if (!fState.HasCovariance()) return false; // no info available when minimization has failed for (unsigned int i = 0; i < fDim; ++i) { if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) { for (unsigned int j = 0; j < fDim; ++j) { cov[i * fDim + j] = 0; } } else { unsigned int l = fState.IntOfExt(i); for (unsigned int j = 0; j < fDim; ++j) { // could probably speed up this loop (if needed) int k = i * fDim + j; if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst()) cov[k] = 0; else { // need to transform from external to internal indices) // for taking care of the removed fixed row/columns in the Minuit2 representation unsigned int m = fState.IntOfExt(j); cov[k] = fState.Covariance()(l, m); } } } } return true; } bool Minuit2Minimizer::GetHessianMatrix(double *hess) const { // get value of Hessian matrix // this is the second derivative matrices if (!fState.HasCovariance()) return false; // no info available when minimization has failed for (unsigned int i = 0; i < fDim; ++i) { if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) { for (unsigned int j = 0; j < fDim; ++j) { hess[i * fDim + j] = 0; } } else { unsigned int l = fState.IntOfExt(i); for (unsigned int j = 0; j < fDim; ++j) { // could probably speed up this loop (if needed) int k = i * fDim + j; if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst()) hess[k] = 0; else { // need to transform from external to internal indices) // for taking care of the removed fixed row/columns in the Minuit2 representation unsigned int m = fState.IntOfExt(j); hess[k] = fState.Hessian()(l, m); } } } } return true; } double Minuit2Minimizer::Correlation(unsigned int i, unsigned int j) const { // get correlation between parameter i and j if (i >= fDim || j >= fDim) return 0; if (!fState.HasCovariance()) return 0; // no info available when minimization has failed if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) return 0; if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst()) return 0; unsigned int k = fState.IntOfExt(i); unsigned int l = fState.IntOfExt(j); double cij = fState.IntCovariance()(k, l); double tmp = std::sqrt(std::abs(fState.IntCovariance()(k, k) * fState.IntCovariance()(l, l))); if (tmp > 0) return cij / tmp; return 0; } double Minuit2Minimizer::GlobalCC(unsigned int i) const { // get global correlation coefficient for the parameter i. This is a number between zero and one which gives // the correlation between the i-th parameter and that linear combination of all other parameters which // is most strongly correlated with i. if (i >= fDim) return 0; // no info available when minimization has failed or has some problems if (!fState.HasGlobalCC()) return 0; if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) return 0; unsigned int k = fState.IntOfExt(i); return fState.GlobalCC().GlobalCC()[k]; } bool Minuit2Minimizer::GetMinosError(unsigned int i, double &errLow, double &errUp, int runopt) { // return the minos error for parameter i // if a minimum does not exist an error is returned // runopt is a flag which specifies if only lower or upper error needs to be run // if runopt = 0 both, = 1 only lower, + 2 only upper errors errLow = 0; errUp = 0; assert(fMinuitFCN); // need to know if parameter is const or fixed if (fState.Parameter(i).IsConst() || fState.Parameter(i).IsFixed()) { return false; } MnPrint print("Minuit2Minimizer::GetMinosError", PrintLevel()); // to run minos I need function minimum class // redo minimization from current state // ROOT::Minuit2::FunctionMinimum min = // GetMinimizer()->Minimize(*GetFCN(),fState, ROOT::Minuit2::MnStrategy(strategy), MaxFunctionCalls(), // Tolerance()); // fState = min.UserState(); if (fMinimum == nullptr) { print.Error("Failed - no function minimum existing"); return false; } if (!fMinimum->IsValid()) { print.Error("Failed - invalid function minimum"); return false; } fMinuitFCN->SetErrorDef(ErrorDef()); // if error def has been changed update it in FunctionMinimum if (ErrorDef() != fMinimum->Up()) fMinimum->SetErrorDef(ErrorDef()); int mstatus = RunMinosError(i, errLow, errUp, runopt); // run again the Minimization in case of a new minimum // bit 8 is set if ((mstatus & 8) != 0) { print.Info([&](std::ostream &os) { os << "Found a new minimum: run again the Minimization starting from the new point"; os << "\nFVAL = " << fState.Fval(); for (auto &par : fState.MinuitParameters()) { os << '\n' << par.Name() << "\t = " << par.Value(); } }); // release parameter that was fixed in the returned state from Minos ReleaseVariable(i); bool ok = Minimize(); if (!ok) return false; // run again Minos from new Minimum (also lower error needs to be re-computed) print.Info("Run now again Minos from the new found Minimum"); mstatus = RunMinosError(i, errLow, errUp, runopt); // do not reset new minimum bit to flag for other parameters mstatus |= 8; } fStatus += 10 * mstatus; fMinosStatus = mstatus; bool isValid = ((mstatus & 1) == 0) && ((mstatus & 2) == 0); return isValid; } int Minuit2Minimizer::RunMinosError(unsigned int i, double &errLow, double &errUp, int runopt) { bool runLower = runopt != 2; bool runUpper = runopt != 1; const int debugLevel = PrintLevel(); // switch off Minuit2 printing const int prev_level = (debugLevel <= 0) ? TurnOffPrintInfoLevel() : -2; const int prevGlobalLevel = MnPrint::SetGlobalLevel(debugLevel); // set the precision if needed if (Precision() > 0) fState.SetPrecision(Precision()); ROOT::Minuit2::MnMinos minos(*fMinuitFCN, *fMinimum); // run MnCross MnCross low; MnCross up; int maxfcn = MaxFunctionCalls(); double tol = Tolerance(); const char *par_name = fState.Name(i); // now input tolerance for migrad calls inside Minos (MnFunctionCross) // before it was fixed to 0.05 // cut off too small tolerance (they are not needed) tol = std::max(tol, 0.01); // get the real number of maxfcn used (defined in MnMinos) to be printed int maxfcn_used = maxfcn; if (maxfcn_used == 0) { int nvar = fState.VariableParameters(); maxfcn_used = 2 * (nvar + 1) * (200 + 100 * nvar + 5 * nvar * nvar); } if (runLower) { if (debugLevel >= 1) { std::cout << "************************************************************************************************" "******\n"; std::cout << "Minuit2Minimizer::GetMinosError - Run MINOS LOWER error for parameter #" << i << " : " << par_name << " using max-calls " << maxfcn_used << ", tolerance " << tol << std::endl; } low = minos.Loval(i, maxfcn, tol); } if (runUpper) { if (debugLevel >= 1) { std::cout << "************************************************************************************************" "******\n"; std::cout << "Minuit2Minimizer::GetMinosError - Run MINOS UPPER error for parameter #" << i << " : " << par_name << " using max-calls " << maxfcn_used << ", tolerance " << tol << std::endl; } up = minos.Upval(i, maxfcn, tol); } ROOT::Minuit2::MinosError me(i, fMinimum->UserState().Value(i), low, up); // restore global print level if (prev_level > -2) RestoreGlobalPrintLevel(prev_level); MnPrint::SetGlobalLevel(prevGlobalLevel); // debug result of Minos // print error message in Minos // Note that the only invalid condition can happen when the (npar-1) minimization fails // The error is also invalid when the maximum number of calls is reached or a new function minimum is found // in case of the parameter at the limit the error is not invalid. // When the error is invalid the returned error is the Hessian error. if (debugLevel > 0) { if (runLower) { if (!me.LowerValid()) std::cout << "Minos: Invalid lower error for parameter " << par_name << std::endl; if (me.AtLowerLimit()) std::cout << "Minos: Parameter : " << par_name << " is at Lower limit; error is " << me.Lower() << std::endl; if (me.AtLowerMaxFcn()) std::cout << "Minos: Maximum number of function calls exceeded when running for lower error for parameter " << par_name << std::endl; if (me.LowerNewMin()) std::cout << "Minos: New Minimum found while running Minos for lower error for parameter " << par_name << std::endl; if (debugLevel >= 1 && me.LowerValid()) std::cout << "Minos: Lower error for parameter " << par_name << " : " << me.Lower() << std::endl; } if (runUpper) { if (!me.UpperValid()) std::cout << "Minos: Invalid upper error for parameter " << par_name << std::endl; if (me.AtUpperLimit()) std::cout << "Minos: Parameter " << par_name << " is at Upper limit; error is " << me.Upper() << std::endl; if (me.AtUpperMaxFcn()) std::cout << "Minos: Maximum number of function calls exceeded when running for upper error for parameter " << par_name << std::endl; if (me.UpperNewMin()) std::cout << "Minos: New Minimum found while running Minos for upper error for parameter " << par_name << std::endl; if (debugLevel >= 1 && me.UpperValid()) std::cout << "Minos: Upper error for parameter " << par_name << " : " << me.Upper() << std::endl; } } MnPrint print("RunMinosError", PrintLevel()); bool lowerInvalid = (runLower && !me.LowerValid()); bool upperInvalid = (runUpper && !me.UpperValid()); // print message in case of invalid error also in printLevel0 if (lowerInvalid) { print.Warn("Invalid lower error for parameter", fMinimum->UserState().Name(i)); } if (upperInvalid) { print.Warn("Invalid upper error for parameter", fMinimum->UserState().Name(i)); } // print also case it is lower/upper limit if (me.AtLowerLimit()) { print.Warn("Lower error for parameter", fMinimum->UserState().Name(i), "is at the Lower limit!"); } if (me.AtUpperLimit()) { print.Warn("Upper error for parameter", fMinimum->UserState().Name(i), "is at the Upper limit!"); } int mstatus = 0; if (lowerInvalid || upperInvalid) { // set status according to bit // bit 1: lower invalid Minos errors // bit 2: upper invalid Minos error // bit 3: invalid because max FCN // bit 4 : invalid because a new minimum has been found if (lowerInvalid) { mstatus |= 1; if (me.AtLowerMaxFcn()) mstatus |= 4; if (me.LowerNewMin()) mstatus |= 8; } if (upperInvalid) { mstatus |= 2; if (me.AtUpperMaxFcn()) mstatus |= 4; if (me.UpperNewMin()) mstatus |= 8; } } // case upper/lower limit if (me.AtUpperLimit() || me.AtLowerLimit()) mstatus |= 16; if (runLower) errLow = me.Lower(); if (runUpper) errUp = me.Upper(); // in case of new minimum found update also the minimum state if ((runLower && me.LowerNewMin()) && (runUpper && me.UpperNewMin())) { // take state with lower function value fState = (low.State().Fval() < up.State().Fval()) ? low.State() : up.State(); } else if (runLower && me.LowerNewMin()) { fState = low.State(); } else if (runUpper && me.UpperNewMin()) { fState = up.State(); } return mstatus; } bool Minuit2Minimizer::Scan(unsigned int ipar, unsigned int &nstep, double *x, double *y, double xmin, double xmax) { // scan a parameter (variable) around the minimum value // the parameters must have been set before // if xmin=0 && xmax == 0 by default scan around 2 sigma of the error // if the errors are also zero then scan from min and max of parameter range MnPrint print("Minuit2Minimizer::Scan", PrintLevel()); if (!fMinuitFCN) { print.Error("Function must be set before using Scan"); return false; } if (ipar > fState.MinuitParameters().size()) { print.Error("Invalid number; minimizer variables must be set before using Scan"); return false; } // switch off Minuit2 printing const int prev_level = (PrintLevel() <= 0) ? TurnOffPrintInfoLevel() : -2; const int prevGlobalLevel = MnPrint::SetGlobalLevel(PrintLevel()); // set the precision if needed if (Precision() > 0) fState.SetPrecision(Precision()); MnParameterScan scan(*fMinuitFCN, fState.Parameters()); double amin = scan.Fval(); // fcn value of the function before scan // first value is param value std::vector> result = scan(ipar, nstep - 1, xmin, xmax); // restore global print level if (prev_level > -2) RestoreGlobalPrintLevel(prev_level); MnPrint::SetGlobalLevel(prevGlobalLevel); if (result.size() != nstep) { print.Error("Invalid result from MnParameterScan"); return false; } // sort also the returned points in x std::sort(result.begin(), result.end()); for (unsigned int i = 0; i < nstep; ++i) { x[i] = result[i].first; y[i] = result[i].second; } // what to do if a new minimum has been found ? // use that as new minimum if (scan.Fval() < amin) { print.Info("A new minimum has been found"); fState.SetValue(ipar, scan.Parameters().Value(ipar)); } return true; } bool Minuit2Minimizer::Contour(unsigned int ipar, unsigned int jpar, unsigned int &npoints, double *x, double *y) { // contour plot for parameter i and j // need a valid FunctionMinimum otherwise exits MnPrint print("Minuit2Minimizer::Contour", PrintLevel()); if (fMinimum == nullptr) { print.Error("No function minimum existing; must minimize function before"); return false; } if (!fMinimum->IsValid()) { print.Error("Invalid function minimum"); return false; } assert(fMinuitFCN); fMinuitFCN->SetErrorDef(ErrorDef()); // if error def has been changed update it in FunctionMinimum if (ErrorDef() != fMinimum->Up()) { fMinimum->SetErrorDef(ErrorDef()); } print.Info("Computing contours -", ErrorDef()); // switch off Minuit2 printing (for level of 0,1) const int prev_level = (PrintLevel() <= 1) ? TurnOffPrintInfoLevel() : -2; const int prevGlobalLevel = MnPrint::SetGlobalLevel(PrintLevel() - 1); // set the precision if needed if (Precision() > 0) fState.SetPrecision(Precision()); // eventually one should specify tolerance in contours MnContours contour(*fMinuitFCN, *fMinimum, Strategy()); // restore global print level if (prev_level > -2) RestoreGlobalPrintLevel(prev_level); MnPrint::SetGlobalLevel(prevGlobalLevel); // compute the contour std::vector> result = contour(ipar, jpar, npoints); if (result.size() != npoints) { print.Error("Invalid result from MnContours"); return false; } for (unsigned int i = 0; i < npoints; ++i) { x[i] = result[i].first; y[i] = result[i].second; } return true; } bool Minuit2Minimizer::Hesse() { // find Hessian (full second derivative calculations) // the contained state will be updated with the Hessian result // in case a function minimum exists and is valid the result will be // appended in the function minimum MnPrint print("Minuit2Minimizer::Hesse", PrintLevel()); if (!fMinuitFCN) { print.Error("FCN function has not been set"); return false; } const int maxfcn = MaxFunctionCalls(); print.Info("Using max-calls", maxfcn); // switch off Minuit2 printing const int prev_level = (PrintLevel() <= 0) ? TurnOffPrintInfoLevel() : -2; const int prevGlobalLevel = MnPrint::SetGlobalLevel(PrintLevel()); // set the precision if needed if (Precision() > 0) fState.SetPrecision(Precision()); ROOT::Minuit2::MnHesse hesse(customizedStrategy(Strategy(), fOptions)); // case when function minimum exists if (fMinimum) { // if (PrintLevel() >= 3) { // std::cout << "Minuit2Minimizer::Hesse - State before running Hesse " << std::endl; // std::cout << fState << std::endl; // } // run hesse and function minimum will be updated with Hesse result hesse(*fMinuitFCN, *fMinimum, maxfcn); // update user state fState = fMinimum->UserState(); } else { // run Hesse on point stored in current state (independent of function minimum validity) // (x == 0) fState = hesse(*fMinuitFCN, fState, maxfcn); } // restore global print level if (prev_level > -2) RestoreGlobalPrintLevel(prev_level); MnPrint::SetGlobalLevel(prevGlobalLevel); if (PrintLevel() >= 3) { std::cout << "Minuit2Minimizer::Hesse - State returned from Hesse " << std::endl; std::cout << fState << std::endl; } int covStatus = fState.CovarianceStatus(); std::string covStatusType = "not valid"; if (covStatus == 1) covStatusType = "approximate"; if (covStatus == 2) covStatusType = "full but made positive defined"; if (covStatus == 3) covStatusType = "accurate"; if (covStatus == 0) covStatusType = "full but not positive defined"; if (!fState.HasCovariance()) { // if false means error is not valid and this is due to a failure in Hesse // update minimizer error status int hstatus = 4; // information on error state can be retrieved only if fMinimum is available if (fMinimum) { if (fMinimum->Error().HesseFailed()) hstatus = 1; if (fMinimum->Error().InvertFailed()) hstatus = 2; else if (!(fMinimum->Error().IsPosDef())) hstatus = 3; } print.Warn("Hesse failed - matrix is", covStatusType); print.Warn(hstatus); fStatus += 100 * hstatus; return false; } print.Info("Hesse is valid - matrix is", covStatusType); return true; } int Minuit2Minimizer::CovMatrixStatus() const { // return status of covariance matrix //-1 - not available (inversion failed or Hesse failed) // 0 - available but not positive defined // 1 - covariance only approximate // 2 full matrix but forced pos def // 3 full accurate matrix if (fMinimum) { // case a function minimum is available if (fMinimum->HasAccurateCovar()) return 3; else if (fMinimum->HasMadePosDefCovar()) return 2; else if (fMinimum->HasValidCovariance()) return 1; else if (fMinimum->HasCovariance()) return 0; return -1; } else { // case fMinimum is not available - use state information return fState.CovarianceStatus(); } return 0; } void Minuit2Minimizer::SetTraceObject(MnTraceObject &obj) { // set trace object if (fMinimizer) fMinimizer->Builder().SetTraceObject(obj); } void Minuit2Minimizer::SetStorageLevel(int level) { // set storage level if (fMinimizer) fMinimizer->Builder().SetStorageLevel(level); } } // end namespace Minuit2 } // end namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnApplication.cxx0000644000000000000000000001463714332717401021077 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnApplication.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { // constructor from non-gradient functions MnApplication::MnApplication(const FCNBase &fcn, const MnUserParameterState &state, const MnStrategy &stra, unsigned int nfcn) : fFCN(fcn), fState(state), fStrategy(stra), fNumCall(nfcn), fUseGrad(false) { } // constructor from functions MnApplication::MnApplication(const FCNGradientBase &fcn, const MnUserParameterState &state, const MnStrategy &stra, unsigned int nfcn) : fFCN(fcn), fState(state), fStrategy(stra), fNumCall(nfcn), fUseGrad(true) { } FunctionMinimum MnApplication::operator()(unsigned int maxfcn, double toler) { // constructor from macfcn calls and tolerance MnPrint print("MnApplication"); assert(fState.IsValid()); unsigned int npar = VariableParameters(); // assert(npar > 0); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; const FCNBase &fcn = Fcnbase(); assert(!fUseGrad || dynamic_cast(&fcn) != nullptr); FunctionMinimum min = fUseGrad ? Minimizer().Minimize(static_cast(fcn), fState, fStrategy, maxfcn, toler) : Minimizer().Minimize(fcn, fState, fStrategy, maxfcn, toler); fNumCall += min.NFcn(); fState = min.UserState(); const std::vector &iterationStates = min.States(); print.Debug("State resulting from Migrad after", iterationStates.size(), "iterations:", fState); print.Debug([&](std::ostream &os) { for (unsigned int i = 0; i < iterationStates.size(); ++i) { // std::cout << iterationStates[i] << std::endl; const ROOT::Minuit2::MinimumState &st = iterationStates[i]; os << "\n----------> Iteration " << i << '\n'; int pr = os.precision(18); os << " FVAL = " << st.Fval() << " Edm = " << st.Edm() << " Nfcn = " << st.NFcn() << '\n'; os.precision(pr); os << " Error matrix change = " << st.Error().Dcovar() << '\n'; os << " Internal parameters : "; for (int j = 0; j < st.size(); ++j) os << " p" << j << " = " << st.Vec()(j); } }); return min; } // facade: forward interface of MnUserParameters and MnUserTransformation // via MnUserParameterState const std::vector &MnApplication::MinuitParameters() const { // access to parameters (row-wise) return fState.MinuitParameters(); } // access to parameters and errors in column-wise representation std::vector MnApplication::Params() const { return fState.Params(); } std::vector MnApplication::Errors() const { return fState.Errors(); } const MinuitParameter &MnApplication::Parameter(unsigned int i) const { // access to single Parameter return fState.Parameter(i); } void MnApplication::Add(const char *name, double val, double err) { // add free Parameter fState.Add(name, val, err); } void MnApplication::Add(const char *name, double val, double err, double low, double up) { // add limited Parameter fState.Add(name, val, err, low, up); } void MnApplication::Add(const char *name, double val) { // add const Parameter fState.Add(name, val); } // interaction via external number of Parameter void MnApplication::Fix(unsigned int i) { fState.Fix(i); } void MnApplication::Release(unsigned int i) { fState.Release(i); } void MnApplication::SetValue(unsigned int i, double val) { // set value for parameter i fState.SetValue(i, val); } void MnApplication::SetError(unsigned int i, double val) { // set parameter error fState.SetError(i, val); } void MnApplication::SetLimits(unsigned int i, double low, double up) { // set parameter limits fState.SetLimits(i, low, up); } void MnApplication::RemoveLimits(unsigned int i) { fState.RemoveLimits(i); } double MnApplication::Value(unsigned int i) const { return fState.Value(i); } double MnApplication::Error(unsigned int i) const { return fState.Error(i); } // interaction via Name of Parameter void MnApplication::Fix(const char *i) { fState.Fix(i); } void MnApplication::Release(const char *i) { fState.Release(i); } void MnApplication::SetValue(const char *i, double val) { fState.SetValue(i, val); } void MnApplication::SetError(const char *i, double val) { fState.SetError(i, val); } void MnApplication::SetLimits(const char *i, double low, double up) { fState.SetLimits(i, low, up); } void MnApplication::RemoveLimits(const char *i) { fState.RemoveLimits(i); } void MnApplication::SetPrecision(double eps) { fState.SetPrecision(eps); } double MnApplication::Value(const char *i) const { return fState.Value(i); } double MnApplication::Error(const char *i) const { return fState.Error(i); } unsigned int MnApplication::Index(const char *name) const { // convert name into external number of Parameter return fState.Index(name); } const char *MnApplication::Name(unsigned int i) const { // convert external number into name of Parameter return fState.Name(i); } double MnApplication::Int2ext(unsigned int i, double val) const { // transformation internal -> external return fState.Int2ext(i, val); } double MnApplication::Ext2int(unsigned int e, double val) const { // transformation external -> internal return fState.Ext2int(e, val); } unsigned int MnApplication::IntOfExt(unsigned int ext) const { // get internal index for external parameter with index ext return fState.IntOfExt(ext); } unsigned int MnApplication::ExtOfInt(unsigned int internal) const { // get external index for internal parameter with index internal return fState.ExtOfInt(internal); } unsigned int MnApplication::VariableParameters() const { // get number of variable parameters return fState.VariableParameters(); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnContours.cxx0000644000000000000000000002311314332717401020435 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnContours.h" #include "Minuit2/MnMinos.h" #include "Minuit2/MnMigrad.h" #include "Minuit2/MnFunctionCross.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/FCNBase.h" #include "Minuit2/MnCross.h" #include "Minuit2/MinosError.h" #include "Minuit2/ContoursError.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { std::vector> MnContours:: operator()(unsigned int px, unsigned int py, unsigned int npoints) const { // get contour as a pair of (x,y) points passing the parameter index (px, py) and the number of requested points // (>=4) ContoursError cont = Contour(px, py, npoints); return cont(); } ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int npoints) const { // calculate the contour passing the parameter index (px, py) and the number of requested points (>=4) // the fcn.UP() has to be set to the required value (see Minuit document on errors) assert(npoints > 3); unsigned int maxcalls = 100 * (npoints + 5) * (fMinimum.UserState().VariableParameters() + 1); unsigned int nfcn = 0; MnPrint print("MnContours"); print.Debug("MnContours: finding ",npoints," contours points for ",px,py," at level ",fFCN.Up()," from value ",fMinimum.Fval()); std::vector> result; result.reserve(npoints); std::vector states; // double edmmax = 0.5*0.05*fFCN.Up()*1.e-3; // double toler = 0.05; double toler = 0.1; // use same defaut value as in Minos // get first four points running Minos separately on the two parameters // and then finding the corresponding minimum in the other // P1( exlow, ymin1) where ymin1 is the parameter value (y) at the minimum of f when x is fixed to exlow // P2(xmin1, eylow) where xmin1 is the the parameter value (x) at the minimum of f when y is fixed to eylow // P3(exup, ymin2) // P4(xmin2, eyup) MnMinos minos(fFCN, fMinimum, fStrategy); double valx = fMinimum.UserState().Value(px); double valy = fMinimum.UserState().Value(py); print.Debug("Run Minos to find first 4 contour points. Current minimum is : ",valx,valy); MinosError mnex = minos.Minos(px); nfcn += mnex.NFcn(); if (!mnex.IsValid()) { print.Error("unable to find first two points"); return ContoursError(px, py, result, mnex, mnex, nfcn); } std::pair ex = mnex(); print.Debug("Minos error for p0: ",ex.first,ex.second); MinosError mney = minos.Minos(py); nfcn += mney.NFcn(); if (!mney.IsValid()) { print.Error("unable to find second two points"); return ContoursError(px, py, result, mnex, mney, nfcn); } std::pair ey = mney(); print.Debug("Minos error for p0: ",ey.first,ey.second); // if Minos is not at limits we can use migrad to find the other corresponding point coordinate MnMigrad migrad0(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); // start from minimizing in p1 and fixing p0 to Minos value migrad0.Fix(px); migrad0.SetValue(px, valx + ex.first); FunctionMinimum exy_lo = migrad0(); nfcn += exy_lo.NFcn(); if (!exy_lo.IsValid()) { print.Error("unable to find Lower y Value for x Parameter", px); return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_lo.UserState().Value(py),"fcn = ",exy_lo.Fval()); migrad0.SetValue(px, valx + ex.second); FunctionMinimum exy_up = migrad0(); nfcn += exy_up.NFcn(); if (!exy_up.IsValid()) { print.Error("unable to find Upper y Value for x Parameter", px); return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_up.UserState().Value(py),"fcn = ",exy_up.Fval()); MnMigrad migrad1(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); migrad1.Fix(py); migrad1.SetValue(py, valy + ey.second); FunctionMinimum eyx_up = migrad1(); nfcn += eyx_up.NFcn(); if (!eyx_up.IsValid()) { print.Error("unable to find Upper x Value for y Parameter", py); return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_up.UserState().Value(px),"fcn = ",eyx_up.Fval()); migrad1.SetValue(py, valy + ey.first); FunctionMinimum eyx_lo = migrad1(); nfcn += eyx_lo.NFcn(); if (!eyx_lo.IsValid()) { print.Error("unable to find Lower x Value for y Parameter", py); return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_lo.UserState().Value(px),"fcn = ",eyx_lo.Fval()); double scalx = 1. / (ex.second - ex.first); double scaly = 1. / (ey.second - ey.first); result.emplace_back(valx + ex.first, exy_lo.UserState().Value(py)); result.emplace_back(eyx_lo.UserState().Value(px), valy + ey.first); result.emplace_back(valx + ex.second, exy_up.UserState().Value(py)); result.emplace_back(eyx_up.UserState().Value(px), valy + ey.second); MnUserParameterState upar = fMinimum.UserState(); print.Debug("List of first 4 found contour points", '\n', " Parameter x is", upar.Name(px), '\n', " Parameter y is", upar.Name(py), '\n', result[0], '\n', result[1], '\n', result[2], '\n', result[3]); upar.Fix(px); upar.Fix(py); std::vector par(2); par[0] = px; par[1] = py; MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy); // find the remaining points of the contour for (unsigned int i = 4; i < npoints; i++) { // find the two neighbouring points with largest separation auto idist1 = result.end() - 1; auto idist2 = result.begin(); double dx = idist1->first - (idist2)->first; double dy = idist1->second - (idist2)->second; double bigdis = scalx * scalx * dx * dx + scaly * scaly * dy * dy; for (auto ipair = result.begin(); ipair != result.end() - 1; ++ipair) { double distx = ipair->first - (ipair + 1)->first; double disty = ipair->second - (ipair + 1)->second; double dist = scalx * scalx * distx * distx + scaly * scaly * disty * disty; if (dist > bigdis) { bigdis = dist; idist1 = ipair; idist2 = ipair + 1; } } double a1 = 0.5; double a2 = 0.5; double sca = 1.; L300: if (nfcn > maxcalls) { print.Error("maximum number of function calls exhausted"); return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (", idist2->first,", ",idist2->second,") with weights ",a1,a2); // find next point between the found 2 with max separation // start from point situated at the middle (a1,a2=0.5) // and direction double xmidcr = a1 * idist1->first + a2 * (idist2)->first; double ymidcr = a1 * idist1->second + a2 * (idist2)->second; // direction is the perpendicular one double xdir = (idist2)->second - idist1->second; double ydir = idist1->first - (idist2)->first; double scalfac = sca * std::max(std::fabs(xdir * scalx), std::fabs(ydir * scaly)); double xdircr = xdir / scalfac; double ydircr = ydir / scalfac; std::vector pmid(2); pmid[0] = xmidcr; pmid[1] = ymidcr; std::vector pdir(2); pdir[0] = xdircr; pdir[1] = ydircr; MnCross opt = cross(par, pmid, pdir, toler, maxcalls); nfcn += opt.NFcn(); if (!opt.IsValid()) { if(a1 > 0.5) { // LM 20/10/23 : remove switch of direction and look instead closer (this is what is done in TMinuit) // should we try again closer to P2 (e.g. a1=0.25, a2 = 0.75) if failing? //if (sca < 0.) { print.Error("unable to find point on Contour", i + 1, '\n', "found only", i, "points"); return ContoursError(px, py, result, mnex, mney, nfcn); } a1 = 0.75; a2 = 0.25; print.Debug("Unable to find point, try closer to p1 with weight values",a1,a2); //std::cout<<"*****switch direction"< 0); assert(n < cov.Nrow()); MnPrint print("MnCovarianceSqueeze"); MnAlgebraicSymMatrix hess(cov.Nrow()); for (unsigned int i = 0; i < cov.Nrow(); i++) { for (unsigned int j = i; j < cov.Nrow(); j++) { hess(i, j) = cov(i, j); } } int ifail = Invert(hess); if (ifail != 0) { print.Warn("inversion failed; return diagonal matrix;"); MnUserCovariance result(cov.Nrow() - 1); for (unsigned int i = 0, j = 0; i < cov.Nrow(); i++) { if (i == n) continue; result(j, j) = cov(i, i); j++; } return result; } MnAlgebraicSymMatrix squeezed = (*this)(hess, n); ifail = Invert(squeezed); if (ifail != 0) { print.Warn("back-inversion failed; return diagonal matrix;"); MnUserCovariance result(squeezed.Nrow()); for (unsigned int i = 0; i < squeezed.Nrow(); i++) { result(i, i) = 1. / squeezed(i, i); } return result; } return MnUserCovariance(std::vector(squeezed.Data(), squeezed.Data() + squeezed.size()), squeezed.Nrow()); } MinimumError MnCovarianceSqueeze::operator()(const MinimumError &err, unsigned int n) const { MnPrint print("MnCovarianceSqueeze"); // squeeze the minimum error class // Remove index-row on the Hessian matrix and the get the new correct error matrix // (inverse of new Hessian) int ifail1 = 0; MnAlgebraicSymMatrix hess = MinimumError::InvertMatrix(err.InvHessian(), ifail1); MnAlgebraicSymMatrix squeezed = (*this)(hess, n); int ifail2 = Invert(squeezed); if (ifail1 != 0 && ifail2 == 0){ print.Warn("MinimumError inversion fails; return diagonal matrix."); return MinimumError(squeezed, MinimumError::MnInvertFailed); } if (ifail2 != 0) { print.Warn("MinimumError back-inversion fails; return diagonal matrix."); MnAlgebraicSymMatrix tmp(squeezed.Nrow()); for (unsigned int i = 0; i < squeezed.Nrow(); i++) { tmp(i, i) = 1. / squeezed(i, i); } return MinimumError(tmp, MinimumError::MnInvertFailed); } return MinimumError(squeezed, err.Dcovar()); } MnAlgebraicSymMatrix MnCovarianceSqueeze::operator()(const MnAlgebraicSymMatrix &hess, unsigned int n) const { // squeeze a symmetric matrix (remove entire row and column n) assert(hess.Nrow() > 0); assert(n < hess.Nrow()); MnAlgebraicSymMatrix hs(hess.Nrow() - 1); for (unsigned int i = 0, j = 0; i < hess.Nrow(); i++) { if (i == n) continue; for (unsigned int k = i, l = j; k < hess.Nrow(); k++) { if (k == n) continue; hs(j, l) = hess(i, k); l++; } j++; } return hs; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnEigen.cxx0000644000000000000000000000220314332717401017645 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnEigen.h" #include "Minuit2/MnUserCovariance.h" #include "Minuit2/MnMatrix.h" namespace ROOT { namespace Minuit2 { LAVector eigenvalues(const LASymMatrix &); std::vector MnEigen::operator()(const MnUserCovariance &covar) const { // wrapper to calculate eigenvalues of the covariance matrix using mneigen function LASymMatrix cov(covar.Nrow()); for (unsigned int i = 0; i < covar.Nrow(); i++) for (unsigned int j = i; j < covar.Nrow(); j++) cov(i, j) = covar(i, j); LAVector eigen = eigenvalues(cov); std::vector result(eigen.Data(), eigen.Data() + covar.Nrow()); return result; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnFcn.cxx0000644000000000000000000000215014332717401017325 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnFcn.h" #include "Minuit2/FCNBase.h" #include "Minuit2/MnVectorTransform.h" namespace ROOT { namespace Minuit2 { MnFcn::~MnFcn() { // std::cout<<"Total number of calls to FCN: "<& par) const { // return fFCN(par); // } double MnFcn::ErrorDef() const { return fFCN.Up(); } double MnFcn::Up() const { return fFCN.Up(); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnFumiliMinimize.cxx0000644000000000000000000000221114332717401021544 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnFumiliMinimize.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/FumiliMinimizer.h" namespace ROOT { namespace Minuit2 { FunctionMinimum MnFumiliMinimize::operator()(unsigned int maxfcn, double toler) { // minimize using Fumili // need to reimplement otherwise base class method is done assert(fState.IsValid()); unsigned int npar = VariableParameters(); // assert(npar > 0); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; FunctionMinimum min = Minimizer().Minimize(Fcnbase(), fState, fStrategy, maxfcn, toler); fNumCall += min.NFcn(); fState = min.UserState(); return min; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnFunctionCross.cxx0000644000000000000000000004144314332717401021426 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnFunctionCross.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnMigrad.h" #include "Minuit2/FCNBase.h" #include "Minuit2/MnParabola.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/MnParabolaFactory.h" #include "Minuit2/MnCross.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { MnCross MnFunctionCross::operator()(const std::vector &par, const std::vector &pmid, const std::vector &pdir, double tlr, unsigned int maxcalls) const { // evaluate crossing point where function is equal to MIN + UP, // with direction pdir from values pmid // tlr indicate tolerance and maxcalls maximum number of calls // double edmmax = 0.5*0.001*toler*fFCN.Up(); unsigned int npar = par.size(); unsigned int nfcn = 0; const MnMachinePrecision &prec = fState.Precision(); // tolerance used when calling Migrad double mgr_tlr = 0.5 * tlr; // to be consistent with F77 version (for default values of tlr which is 0.1) // other olerance values are fixed at 0.01 tlr = 0.01; // convergence when F is within tlf of aim and next prediction // of aopt is within tla of previous value of aopt double up = fFCN.Up(); // for finding the point : double tlf = tlr * up; double tla = tlr; unsigned int maxitr = 15; unsigned int ipt = 0; double aminsv = fFval; double aim = aminsv + up; // std::cout<<"aim= "< alsb(3, 0.), flsb(3, 0.); MnPrint print("MnFunctionCross"); print.Debug([&](std::ostream &os) { for (unsigned int i = 0; i < par.size(); ++i) os << "Parameter " << par[i] << " value " << pmid[i] << " dir " << pdir[i] << " function min = " << aminsv << " contour value aim = (fmin + up) = " << aim; }); // find the largest allowed aulim double aulim = 100.; for (unsigned int i = 0; i < par.size(); i++) { unsigned int kex = par[i]; if (fState.Parameter(kex).HasLimits()) { double zmid = pmid[i]; double zdir = pdir[i]; // double zlim = 0.; if (zdir > 0. && fState.Parameter(kex).HasUpperLimit()) { double zlim = fState.Parameter(kex).UpperLimit(); if (std::fabs(zdir) < fState.Precision().Eps()) { // we have a limit if (std::fabs(zlim - zmid) < fState.Precision().Eps()) limset = true; continue; } aulim = std::min(aulim, (zlim - zmid) / zdir); } else if (zdir < 0. && fState.Parameter(kex).HasLowerLimit()) { double zlim = fState.Parameter(kex).LowerLimit(); if (std::fabs(zdir) < fState.Precision().Eps()) { // we have a limit if (std::fabs(zlim - zmid) < fState.Precision().Eps()) limset = true; continue; } aulim = std::min(aulim, (zlim - zmid) / zdir); } } } print.Debug("Largest allowed aulim", aulim); // case of a single parameter and we are at limit if (limset && npar == 1) { print.Warn("Parameter is at limit", pmid[0], "delta", pdir[0]); return MnCross(fState, nfcn, MnCross::CrossParLimit()); } if (aulim < aopt + tla) limset = true; MnMigrad migrad(fFCN, fState, MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); print.Info([&](std::ostream &os) { os << "Run Migrad with fixed parameters:"; for (unsigned i = 0; i < npar; ++i) os << "\n Pos " << par[i] << ": " << fState.Name(par[i]) << " = " << pmid[i]; }); for (unsigned int i = 0; i < npar; i++) migrad.SetValue(par[i], pmid[i]); // find minimum with respect all the other parameters (n- npar) (npar are the fixed ones) FunctionMinimum min0 = migrad(maxcalls, mgr_tlr); nfcn += min0.NFcn(); print.Info("Result after Migrad", MnPrint::Oneline(min0), min0.UserState().Parameters()); // case a new minimum is found if (min0.Fval() < fFval - tlf) { // case of new minimum is found print.Warn("New minimum found while scanning parameter", par.front(), "new value =", min0.Fval(), "old value =", fFval); return MnCross(min0.UserState(), nfcn, MnCross::CrossNewMin()); } if (min0.HasReachedCallLimit()) return MnCross(min0.UserState(), nfcn, MnCross::CrossFcnLimit()); if (!min0.IsValid()) return MnCross(fState, nfcn); if (limset == true && min0.Fval() < aim) return MnCross(min0.UserState(), nfcn, MnCross::CrossParLimit()); ipt++; alsb[0] = 0.; flsb[0] = min0.Fval(); flsb[0] = std::max(flsb[0], aminsv + 0.1 * up); aopt = std::sqrt(up / (flsb[0] - aminsv)) - 1.; if (std::fabs(flsb[0] - aim) < tlf) return MnCross(aopt, min0.UserState(), nfcn); if (aopt > 1.) aopt = 1.; if (aopt < -0.5) aopt = -0.5; limset = false; if (aopt > aulim) { aopt = aulim; limset = true; } print.Debug("flsb[0]", flsb[0], "aopt", aopt); print.Info([&](std::ostream &os) { os << "Run Migrad again (2nd) with fixed parameters:"; for (unsigned i = 0; i < npar; ++i) os << "\n Pos " << par[i] << ": " << fState.Name(par[i]) << " = " << pmid[i] + (aopt)*pdir[i]; }); for (unsigned int i = 0; i < npar; i++) migrad.SetValue(par[i], pmid[i] + (aopt)*pdir[i]); FunctionMinimum min1 = migrad(maxcalls, mgr_tlr); nfcn += min1.NFcn(); print.Info("Result after 2nd Migrad", MnPrint::Oneline(min1), min1.UserState().Parameters()); if (min1.Fval() < fFval - tlf) // case of new minimum found return MnCross(min1.UserState(), nfcn, MnCross::CrossNewMin()); if (min1.HasReachedCallLimit()) return MnCross(min1.UserState(), nfcn, MnCross::CrossFcnLimit()); if (!min1.IsValid()) return MnCross(fState, nfcn); if (limset == true && min1.Fval() < aim) return MnCross(min1.UserState(), nfcn, MnCross::CrossParLimit()); ipt++; alsb[1] = aopt; flsb[1] = min1.Fval(); double dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]); print.Debug("aopt", aopt, "min1Val", flsb[1], "dfda", dfda); L300: if (dfda < 0.) { // looking for slope of the right sign print.Debug("dfda < 0 - iterate from", ipt, "to max of", maxitr); // iterate (max times is maxitr) incrementing aopt unsigned int maxlk = maxitr - ipt; for (unsigned int it = 0; it < maxlk; it++) { alsb[0] = alsb[1]; flsb[0] = flsb[1]; // LM: Add + 1, looking at Fortran code it starts from 1 ( see bug #8396) aopt = alsb[0] + 0.2 * (it + 1); limset = false; if (aopt > aulim) { aopt = aulim; limset = true; } print.Info([&](std::ostream &os) { os << "Run Migrad again (iteration " << it << " ) :"; for (unsigned i = 0; i < npar; ++i) os << "\n parameter " << par[i] << " (" << fState.Name(par[i]) << ") fixed to " << pmid[i] + (aopt)*pdir[i]; }); for (unsigned int i = 0; i < npar; i++) migrad.SetValue(par[i], pmid[i] + (aopt)*pdir[i]); min1 = migrad(maxcalls, mgr_tlr); nfcn += min1.NFcn(); print.Info("Result after Migrad", MnPrint::Oneline(min1), '\n', min1.UserState().Parameters()); if (min1.Fval() < fFval - tlf) // case of new minimum found return MnCross(min1.UserState(), nfcn, MnCross::CrossNewMin()); if (min1.HasReachedCallLimit()) return MnCross(min1.UserState(), nfcn, MnCross::CrossFcnLimit()); if (!min1.IsValid()) return MnCross(fState, nfcn); if (limset == true && min1.Fval() < aim) return MnCross(min1.UserState(), nfcn, MnCross::CrossParLimit()); ipt++; alsb[1] = aopt; flsb[1] = min1.Fval(); dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]); // if(dfda > 0.) goto L460; print.Debug("aopt", aopt, "min1Val", flsb[1], "dfda", dfda); if (dfda > 0.) break; } if (ipt > maxitr) return MnCross(fState, nfcn); } // if(dfda < 0.) L460: // dfda > 0: we have two points with the right slope aopt = alsb[1] + (aim - flsb[1]) / dfda; print.Debug("dfda > 0 : aopt", aopt); double fdist = std::min(std::fabs(aim - flsb[0]), std::fabs(aim - flsb[1])); double adist = std::min(std::fabs(aopt - alsb[0]), std::fabs(aopt - alsb[1])); tla = tlr; if (std::fabs(aopt) > 1.) tla = tlr * std::fabs(aopt); if (adist < tla && fdist < tlf) return MnCross(aopt, min1.UserState(), nfcn); if (ipt > maxitr) return MnCross(fState, nfcn); double bmin = std::min(alsb[0], alsb[1]) - 1.; if (aopt < bmin) aopt = bmin; double bmax = std::max(alsb[0], alsb[1]) + 1.; if (aopt > bmax) aopt = bmax; limset = false; if (aopt > aulim) { aopt = aulim; limset = true; } print.Info([&](std::ostream &os) { os << "Run Migrad again (3rd) with fixed parameters:"; for (unsigned i = 0; i < npar; ++i) os << "\n Pos " << par[i] << ": " << fState.Name(par[i]) << " = " << pmid[i] + (aopt)*pdir[i]; }); for (unsigned int i = 0; i < npar; i++) migrad.SetValue(par[i], pmid[i] + (aopt)*pdir[i]); FunctionMinimum min2 = migrad(maxcalls, mgr_tlr); nfcn += min2.NFcn(); print.Info("Result after Migrad (3rd):", MnPrint::Oneline(min2), min2.UserState().Parameters()); if (min2.Fval() < fFval - tlf) // case of new minimum found return MnCross(min2.UserState(), nfcn, MnCross::CrossNewMin()); if (min2.HasReachedCallLimit()) return MnCross(min2.UserState(), nfcn, MnCross::CrossFcnLimit()); if (!min2.IsValid()) return MnCross(fState, nfcn); if (limset == true && min2.Fval() < aim) return MnCross(min2.UserState(), nfcn, MnCross::CrossParLimit()); ipt++; alsb[2] = aopt; flsb[2] = min2.Fval(); // now we have three points, ask how many < AIM double ecarmn = std::fabs(flsb[2] - aim); double ecarmx = 0.; unsigned int ibest = 2; unsigned int iworst = 0; unsigned int noless = 0; for (unsigned int i = 0; i < 3; i++) { double ecart = std::fabs(flsb[i] - aim); if (ecart > ecarmx) { ecarmx = ecart; iworst = i; } if (ecart < ecarmn) { ecarmn = ecart; ibest = i; } if (flsb[i] < aim) noless++; } print.Debug("have three points : noless < aim; noless", noless, "ibest", ibest, "iworst", iworst); // std::cout<<"480"< 0.) print.Warn("Problem 1"); // find with root is the right one aopt = x1; double slope = s1; if (s2 > 0.) { aopt = x2; slope = s2; } print.Debug("Parabola fit: aopt", aopt, "slope", slope); // ask if converged tla = tlr; if (std::fabs(aopt) > 1.) tla = tlr * std::fabs(aopt); print.Debug("Delta(aopt)", std::fabs(aopt - alsb[ibest]), "tla", tla, "Delta(F)", std::fabs(flsb[ibest] - aim), "tlf", tlf); if (std::fabs(aopt - alsb[ibest]) < tla && std::fabs(flsb[ibest] - aim) < tlf) return MnCross(aopt, min2.UserState(), nfcn); // if(ipt > maxitr) return MnCross(); // see if proposed point is in acceptable zone between L and R // first find ileft, iright, iout and ibest unsigned int ileft = 3; unsigned int iright = 3; unsigned int iout = 3; ibest = 0; ecarmx = 0.; ecarmn = std::fabs(aim - flsb[0]); for (unsigned int i = 0; i < 3; i++) { double ecart = std::fabs(flsb[i] - aim); if (ecart < ecarmn) { ecarmn = ecart; ibest = i; } if (ecart > ecarmx) ecarmx = ecart; if (flsb[i] > aim) { if (iright == 3) iright = i; else if (flsb[i] > flsb[iright]) iout = i; else { iout = iright; iright = i; } } else if (ileft == 3) ileft = i; else if (flsb[i] < flsb[ileft]) iout = i; else { iout = ileft; ileft = i; } } print.Debug("ileft", ileft, "iright", iright, "iout", iout, "ibest", ibest); // avoid keeping a bad point nest time around if (ecarmx > 10. * std::fabs(flsb[iout] - aim)) aopt = 0.5 * (aopt + 0.5 * (alsb[iright] + alsb[ileft])); // knowing ileft and iright, get acceptable window double smalla = 0.1 * tla; if (slope * smalla > tlf) smalla = tlf / slope; double aleft = alsb[ileft] + smalla; double aright = alsb[iright] - smalla; // move proposed point AOPT into window if necessary if (aopt < aleft) aopt = aleft; if (aopt > aright) aopt = aright; if (aleft > aright) aopt = 0.5 * (aleft + aright); // see if proposed point outside limits (should be impossible) limset = false; if (aopt > aulim) { aopt = aulim; limset = true; } // evaluate at new point aopt print.Info([&](std::ostream &os) { os << "Run Migrad again at new point (#iter = " << ipt+1 << " ):"; for (unsigned i = 0; i < npar; ++i) os << "\n\t - parameter " << par[i] << " fixed to " << pmid[i] + (aopt)*pdir[i]; }); for (unsigned int i = 0; i < npar; i++) migrad.SetValue(par[i], pmid[i] + (aopt)*pdir[i]); min2 = migrad(maxcalls, mgr_tlr); nfcn += min2.NFcn(); print.Info("Result after new Migrad:", MnPrint::Oneline(min2), min2.UserState().Parameters()); if (min2.Fval() < fFval - tlf) // case of new minimum found return MnCross(min2.UserState(), nfcn, MnCross::CrossNewMin()); if (min2.HasReachedCallLimit()) return MnCross(min2.UserState(), nfcn, MnCross::CrossFcnLimit()); if (!min2.IsValid()) return MnCross(fState, nfcn); if (limset == true && min2.Fval() < aim) return MnCross(min2.UserState(), nfcn, MnCross::CrossParLimit()); ipt++; // replace odd point with new one (which is the best of three) alsb[iout] = aopt; flsb[iout] = min2.Fval(); ibest = iout; } while (ipt < maxitr); // goto L500; return MnCross(fState, nfcn); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnGlobalCorrelationCoeff.cxx0000644000000000000000000000254014332717401023167 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnGlobalCorrelationCoeff.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { MnGlobalCorrelationCoeff::MnGlobalCorrelationCoeff(const MnAlgebraicSymMatrix &cov) : fGlobalCC(std::vector()), fValid(true) { // constructor: calculate global correlation given a symmetric matrix MnPrint print("MnGlobalCorrelationCoeff"); MnAlgebraicSymMatrix inv(cov); int ifail = Invert(inv); if (ifail != 0) { print.Warn("inversion of matrix fails"); fValid = false; } else { unsigned int n = cov.Nrow(); fGlobalCC.reserve(n); for (unsigned int i = 0; i < n; i++) { double denom = inv(i, i) * cov(i, i); if (denom < 1. && denom > 0.) fGlobalCC.push_back(0.); else fGlobalCC.push_back(std::sqrt(1. - 1. / denom)); } } } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnHesse.cxx0000644000000000000000000004707014332717401017700 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnHesse.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnUserFcn.h" #include "Minuit2/FCNBase.h" #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnPosDef.h" #include "Minuit2/HessianGradientCalculator.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/ExternalInternalGradientCalculator.h" #include "Minuit2/MinimumState.h" #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnPrint.h" #include "Minuit2/MPIProcess.h" namespace ROOT { namespace Minuit2 { MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int maxcalls) const { // interface from vector of params and errors return (*this)(fcn, MnUserParameterState(par, err), maxcalls); } MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int maxcalls) const { // interface from vector of params and covariance return (*this)(fcn, MnUserParameterState(par, cov, nrow), maxcalls); } MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const std::vector &par, const MnUserCovariance &cov, unsigned int maxcalls) const { // interface from vector of params and covariance return (*this)(fcn, MnUserParameterState(par, cov), maxcalls); } MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const MnUserParameters &par, unsigned int maxcalls) const { // interface from MnUserParameters return (*this)(fcn, MnUserParameterState(par), maxcalls); } MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const MnUserParameters &par, const MnUserCovariance &cov, unsigned int maxcalls) const { // interface from MnUserParameters and MnUserCovariance return (*this)(fcn, MnUserParameterState(par, cov), maxcalls); } MnUserParameterState MnHesse::operator()(const FCNBase &fcn, const MnUserParameterState &state, unsigned int maxcalls) const { // interface from MnUserParameterState // create a new Minimum state and use that interface unsigned int n = state.VariableParameters(); MnUserFcn mfcn(fcn, state.Trafo(), state.NFcn()); MnAlgebraicVector x(n); for (unsigned int i = 0; i < n; i++) x(i) = state.IntParameters()[i]; double amin = mfcn(x); MinimumParameters par(x, amin); // check if we can use analytical gradient auto * gradFCN = dynamic_cast(&(fcn)); if (gradFCN) { // no need to compute gradient here MinimumState tmp = ComputeAnalytical(*gradFCN, MinimumState(par, MinimumError(MnAlgebraicSymMatrix(n), 1.), FunctionGradient(n), state.Edm(), state.NFcn()), state.Trafo()); return MnUserParameterState(tmp, fcn.Up(), state.Trafo()); } // case of numerical gradient Numerical2PGradientCalculator gc(mfcn, state.Trafo(), fStrategy); FunctionGradient gra = gc(par); MinimumState tmp = ComputeNumerical(mfcn, MinimumState(par, MinimumError(MnAlgebraicSymMatrix(n), 1.), gra, state.Edm(), state.NFcn()), state.Trafo(), maxcalls); return MnUserParameterState(tmp, fcn.Up(), state.Trafo()); } void MnHesse::operator()(const FCNBase &fcn, FunctionMinimum &min, unsigned int maxcalls) const { // interface from FunctionMinimum to be used after minimization // use last state from the minimization without the need to re-create a new state // do not reset function calls and keep updating them MnUserFcn mfcn(fcn, min.UserState().Trafo(), min.NFcn()); MinimumState st = (*this)(mfcn, min.State(), min.UserState().Trafo(), maxcalls); min.Add(st); } MinimumState MnHesse::operator()(const MnFcn &mfcn, const MinimumState &st, const MnUserTransformation &trafo, unsigned int maxcalls) const { // check first if we have an analytical gradient if (st.Gradient().IsAnalytical()) { // check if we can compute analytical Hessian auto * gradFCN = dynamic_cast(&(mfcn.Fcn())); if (gradFCN && gradFCN->HasHessian()) { return ComputeAnalytical(*gradFCN, st, trafo); } } // case of numerical computation or only analytical first derivatives return ComputeNumerical(mfcn, st, trafo, maxcalls); } MinimumState MnHesse::ComputeAnalytical(const FCNGradientBase & fcn, const MinimumState &st, const MnUserTransformation &trafo) const { unsigned int n = st.Parameters().Vec().size(); MnAlgebraicSymMatrix vhmat(n); MnPrint print("MnHesse"); const MnMachinePrecision &prec = trafo.Precision(); std::unique_ptr hc; if (fcn.gradParameterSpace() == GradientParameterSpace::Internal) { hc = std::unique_ptr (new ExternalInternalGradientCalculator(fcn,trafo)); } else { hc = std::make_unique(fcn,trafo); } bool ret = hc->Hessian(st.Parameters(), vhmat); if (!ret) { print.Error("Error computing analytical Hessian. MnHesse fails and will return a null matrix"); return MinimumState(st.Parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed), st.Gradient(), st.Edm(), st.NFcn()); } MnAlgebraicVector g2(n); for (unsigned int i = 0; i < n; i++) g2(i) = vhmat(i,i); // update Function gradient with new G2 found FunctionGradient gr(st.Gradient().Grad(), g2); // verify if matrix pos-def (still 2nd derivative) print.Debug("Original error matrix", vhmat); MinimumError tmpErr = MnPosDef()(MinimumError(vhmat, 1.), prec); vhmat = tmpErr.InvHessian(); print.Debug("PosDef error matrix", vhmat); int ifail = Invert(vhmat); if (ifail != 0) { print.Warn("Matrix inversion fails; will return diagonal matrix"); MnAlgebraicSymMatrix tmpsym(vhmat.Nrow()); for (unsigned int j = 0; j < n; j++) { tmpsym(j,j) = 1. / g2(j); } return MinimumState(st.Parameters(), MinimumError(tmpsym, MinimumError::MnInvertFailed), gr, st.Edm(), st.NFcn()); } VariableMetricEDMEstimator estim; // if matrix is made pos def returns anyway edm if (tmpErr.IsMadePosDef()) { MinimumError err(vhmat, MinimumError::MnMadePosDef); double edm = estim.Estimate(gr, err); return MinimumState(st.Parameters(), err, gr, edm, st.NFcn()); } // calculate edm for good errors MinimumError err(vhmat, 0.); // this use only grad values double edm = estim.Estimate(gr, err); print.Debug("Hessian is ACCURATE. New state:", "\n First derivative:", st.Gradient().Grad(), "\n Covariance matrix:", vhmat, "\n Edm:", edm); return MinimumState(st.Parameters(), err, gr, edm, st.NFcn()); } MinimumState MnHesse::ComputeNumerical(const MnFcn &mfcn, const MinimumState &st, const MnUserTransformation &trafo, unsigned int maxcalls) const { // internal interface from MinimumState and MnUserTransformation // Function who does the real Hessian calculations MnPrint print("MnHesse"); const MnMachinePrecision &prec = trafo.Precision(); // make sure starting at the right place double amin = mfcn(st.Vec()); double aimsag = std::sqrt(prec.Eps2()) * (std::fabs(amin) + mfcn.Up()); // diagonal Elements first unsigned int n = st.Parameters().Vec().size(); if (maxcalls == 0) maxcalls = 200 + 100 * n + 5 * n * n; MnAlgebraicSymMatrix vhmat(n); MnAlgebraicVector g2 = st.Gradient().G2(); MnAlgebraicVector gst = st.Gradient().Gstep(); MnAlgebraicVector grd = st.Gradient().Grad(); MnAlgebraicVector dirin = st.Gradient().Gstep(); MnAlgebraicVector yy(n); // case gradient is not numeric (could be analytical or from FumiliGradientCalculator) if (st.Gradient().IsAnalytical()) { print.Info("Using analytical gradient but a numerical Hessian calculator - it could be not optimal"); Numerical2PGradientCalculator igc(mfcn, trafo, fStrategy); // should we check here if numerical gradient is compatible with analytical one ? FunctionGradient tmp = igc(st.Parameters()); gst = tmp.Gstep(); dirin = tmp.Gstep(); g2 = tmp.G2(); print.Warn("Analytical calculator ",grd," numerical ",tmp.Grad()," g2 ",g2); } MnAlgebraicVector x = st.Parameters().Vec(); print.Debug("Gradient is", st.Gradient().IsAnalytical() ? "analytical" : "numerical", "\n point:", x, "\n fcn :", amin, "\n grad :", grd, "\n step :", gst, "\n g2 :", g2); for (unsigned int i = 0; i < n; i++) { double xtf = x(i); double dmin = 8. * prec.Eps2() * (std::fabs(xtf) + prec.Eps2()); double d = std::fabs(gst(i)); if (d < dmin) d = dmin; print.Debug("Derivative parameter", i, "d =", d, "dmin =", dmin); for (unsigned int icyc = 0; icyc < Ncycles(); icyc++) { double sag = 0.; double fs1 = 0.; double fs2 = 0.; for (unsigned int multpy = 0; multpy < 5; multpy++) { x(i) = xtf + d; fs1 = mfcn(x); x(i) = xtf - d; fs2 = mfcn(x); x(i) = xtf; sag = 0.5 * (fs1 + fs2 - 2. * amin); print.Debug("cycle", icyc, "mul", multpy, "\tsag =", sag, "d =", d); // Now as F77 Minuit - check that sag is not zero if (sag != 0) goto L30; // break if (trafo.Parameter(i).HasLimits()) { if (d > 0.5) goto L26; d *= 10.; if (d > 0.5) d = 0.51; continue; } d *= 10.; } L26: // get parameter name for i // (need separate scope for avoiding compl error when declaring name) print.Warn("2nd derivative zero for parameter", trafo.Name(trafo.ExtOfInt(i)), "; MnHesse fails and will return diagonal matrix"); for (unsigned int j = 0; j < n; j++) { double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j); vhmat(j, j) = tmp < prec.Eps2() ? 1. : tmp; } return MinimumState(st.Parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed), st.Gradient(), st.Edm(), mfcn.NumOfCalls()); L30: double g2bfor = g2(i); g2(i) = 2. * sag / (d * d); grd(i) = (fs1 - fs2) / (2. * d); gst(i) = d; dirin(i) = d; yy(i) = fs1; double dlast = d; d = std::sqrt(2. * aimsag / std::fabs(g2(i))); if (trafo.Parameter(i).HasLimits()) d = std::min(0.5, d); if (d < dmin) d = dmin; print.Debug("g1 =", grd(i), "g2 =", g2(i), "step =", gst(i), "d =", d, "diffd =", std::fabs(d - dlast) / d, "diffg2 =", std::fabs(g2(i) - g2bfor) / g2(i)); // see if converged if (std::fabs((d - dlast) / d) < Tolerstp()) break; if (std::fabs((g2(i) - g2bfor) / g2(i)) < TolerG2()) break; d = std::min(d, 10. * dlast); d = std::max(d, 0.1 * dlast); } vhmat(i, i) = g2(i); if (mfcn.NumOfCalls() > maxcalls) { // std::cout<<"maxcalls " << maxcalls << " " << mfcn.NumOfCalls() << " " << st.NFcn() << std::endl; print.Warn("Maximum number of allowed function calls exhausted; will return diagonal matrix"); for (unsigned int j = 0; j < n; j++) { double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j); vhmat(j, j) = tmp < prec.Eps2() ? 1. : tmp; } return MinimumState(st.Parameters(), MinimumError(vhmat, MinimumError::MnReachedCallLimit), st.Gradient(), st.Edm(), mfcn.NumOfCalls()); } } print.Debug("Second derivatives", g2); if (fStrategy.Strategy() > 0) { // refine first derivative HessianGradientCalculator hgc(mfcn, trafo, fStrategy); FunctionGradient gr = hgc(st.Parameters(), FunctionGradient(grd, g2, gst)); // update gradient and step values grd = gr.Grad(); gst = gr.Gstep(); } // off-diagonal Elements // initial starting values bool doCentralFD = fStrategy.HessianCentralFDMixedDerivatives(); if (n > 0) { MPIProcess mpiprocOffDiagonal(n * (n - 1) / 2, 0); unsigned int startParIndexOffDiagonal = mpiprocOffDiagonal.StartElementIndex(); unsigned int endParIndexOffDiagonal = mpiprocOffDiagonal.EndElementIndex(); unsigned int offsetVect = 0; for (unsigned int in = 0; in < startParIndexOffDiagonal; in++) if ((in + offsetVect) % (n - 1) == 0) offsetVect += (in + offsetVect) / (n - 1); for (unsigned int in = startParIndexOffDiagonal; in < endParIndexOffDiagonal; in++) { int i = (in + offsetVect) / (n - 1); if ((in + offsetVect) % (n - 1) == 0) offsetVect += i; int j = (in + offsetVect) % (n - 1) + 1; if ((i + 1) == j || in == startParIndexOffDiagonal) x(i) += dirin(i); x(j) += dirin(j); double fs1 = mfcn(x); if(!doCentralFD) { double elem = (fs1 + amin - yy(i) - yy(j)) / (dirin(i) * dirin(j)); vhmat(i, j) = elem; x(j) -= dirin(j); } else { // three more function evaluations required for central fd x(i) -= dirin(i); x(i) -= dirin(i);double fs3 = mfcn(x); x(j) -= dirin(j); x(j) -= dirin(j);double fs4 = mfcn(x); x(i) += dirin(i); x(i) += dirin(i);double fs2 = mfcn(x); x(j) += dirin(j); double elem = (fs1 - fs2 - fs3 + fs4)/(4.*dirin(i)*dirin(j)); vhmat(i, j) = elem; } if (j % (n - 1) == 0 || in == endParIndexOffDiagonal - 1) x(i) -= dirin(i); } mpiprocOffDiagonal.SyncSymMatrixOffDiagonal(vhmat); } // verify if matrix pos-def (still 2nd derivative) // Note that for cases of extreme spread of eigenvalues, numerical precision // can mean the hessian is computed as being not pos-def // but the inverse of it is. print.Debug("Original error matrix", vhmat); MinimumError tmpErr = MnPosDef()(MinimumError(vhmat, 1.), prec); // pos-def version of hessian if(fStrategy.HessianForcePosDef()) { vhmat = tmpErr.InvHessian(); } print.Debug("PosDef error matrix", vhmat); int ifail = Invert(vhmat); if (ifail != 0) { print.Warn("Matrix inversion fails; will return diagonal matrix"); MnAlgebraicSymMatrix tmpsym(vhmat.Nrow()); for (unsigned int j = 0; j < n; j++) { double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j); tmpsym(j, j) = tmp < prec.Eps2() ? 1. : tmp; } return MinimumState(st.Parameters(), MinimumError(tmpsym, MinimumError::MnInvertFailed), st.Gradient(), st.Edm(), mfcn.NumOfCalls()); } FunctionGradient gr(grd, g2, gst); VariableMetricEDMEstimator estim; // if matrix is made pos def returns anyway edm if (tmpErr.IsMadePosDef()) { MinimumError err(vhmat, fStrategy.HessianForcePosDef() ? MinimumError::MnMadePosDef : MinimumError::MnNotPosDef); double edm = estim.Estimate(gr, err); return MinimumState(st.Parameters(), err, gr, edm, mfcn.NumOfCalls()); } // calculate edm for good errors MinimumError err(vhmat, 0.); double edm = estim.Estimate(gr, err); print.Debug("Hessian is ACCURATE. New state:", "\n First derivative:", grd, "\n Second derivative:", g2, "\n Gradient step:", gst, "\n Covariance matrix:", vhmat, "\n Edm:", edm); return MinimumState(st.Parameters(), err, gr, edm, mfcn.NumOfCalls()); } /* MinimumError MnHesse::Hessian(const MnFcn& mfcn, const MinimumState& st, const MnUserTransformation& trafo) const { const MnMachinePrecision& prec = trafo.Precision(); // make sure starting at the right place double amin = mfcn(st.Vec()); // if(std::fabs(amin - st.Fval()) > prec.Eps2()) std::cout<<"function Value differs from amin by "< prec.Eps2()) break; if(trafo.Parameter(i).HasLimits()) { if(d > 0.5) { std::cout<<"second derivative zero for Parameter "< 0.5) d = 0.51; continue; } d *= 10.; } if(sag < prec.Eps2()) { std::cout<<"MnHesse: internal loop exhausted, return diagonal matrix."< #include #ifdef USE_OTHER_LS #include "Math/SMatrix.h" #include "Math/SVector.h" #include "Math/IFunction.h" #include "Math/Minimizer1D.h" #endif namespace ROOT { namespace Minuit2 { /** Perform a line search from position defined by the vector st along the direction step, where the length of vector step gives the expected position of Minimum. fcn is Value of function at the starting position , gdel (if non-zero) is df/dx along step at st. Return a parabola point containing Minimum x position and y (function Value) - add a flag to control the debug */ MnParabolaPoint MnLineSearch::operator()(const MnFcn &fcn, const MinimumParameters &st, const MnAlgebraicVector &step, double gdel, const MnMachinePrecision &prec) const { //*-*-*-*-*-*-*-*-*-*Perform a line search from position st along step *-*-*-*-*-*-*-* //*-* ========================================= //*-* SLAMBG and ALPHA control the maximum individual steps allowed. //*-* The first step is always =1. The max length of second step is SLAMBG. //*-* The max size of subsequent steps is the maximum previous successful //*-* step multiplied by ALPHA + the size of most recent successful step, //*-* but cannot be smaller than SLAMBG. //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- MnPrint print("MnLineSearch"); print.Debug("gdel", gdel, "step", step); double overall = 1000.; double undral = -100.; double toler = 0.05; double slamin = 0.; double slambg = 5.; double alpha = 2.; int maxiter = 12; // start as in Fortran from 1 and count all the time we evaluate the function int niter = 1; for (unsigned int i = 0; i < step.size(); i++) { if (step(i) == 0) continue; double ratio = std::fabs(st.Vec()(i) / step(i)); if (slamin == 0) slamin = ratio; if (ratio < slamin) slamin = ratio; } if (std::fabs(slamin) < prec.Eps()) slamin = prec.Eps(); slamin *= prec.Eps2(); double f0 = st.Fval(); double f1 = fcn(st.Vec() + step); niter++; double fvmin = st.Fval(); double xvmin = 0.; if (f1 < f0) { fvmin = f1; xvmin = 1.; } double toler8 = toler; double slamax = slambg; double flast = f1; double slam = 1.; bool iterate = false; MnParabolaPoint p0(0., f0); MnParabolaPoint p1(slam, flast); double f2 = 0.; // quadratic interpolation using the two points p0,p1 and the slope at p0 do { // cut toler8 as function goes up iterate = false; // MnParabola pb = MnParabolaFactory()(p0, gdel, p1); print.Debug("flast", flast, "f0", f0, "flast-f0", flast - f0, "slam", slam); // double df = flast-f0; // if(std::fabs(df) < prec.Eps2()) { // if(flast-f0 < 0.) df = -prec.Eps2(); // else df = prec.Eps2(); // } // std::cout<<"df= "<= maxiter) { // exhausted max number of iterations return MnParabolaPoint(xvmin, fvmin); } print.Debug("after initial 2-point iter:", '\n', " x0, x1, x2:", p0.X(), p1.X(), slam, '\n', " f0, f1, f2:", p0.Y(), p1.Y(), f2); MnParabolaPoint p2(slam, f2); // do now the quadratic interpolation with 3 points do { slamax = std::max(slamax, alpha * std::fabs(xvmin)); MnParabola pb = MnParabolaFactory()(p0, p1, p2); print.Debug("Iteration", niter, '\n', " x0, x1, x2:", p0.X(), p1.X(), p2.X(), '\n', " f0, f1, f2:", p0.Y(), p1.Y(), p2.Y(), '\n', " slamax :", slamax, '\n', " p2-p0,p1 :", p2.Y() - p0.Y(), p2.Y() - p1.Y(), '\n', " a, b, c :", pb.A(), pb.B(), pb.C()); if (pb.A() < prec.Eps2()) { double slopem = 2. * pb.A() * xvmin + pb.B(); if (slopem < 0.) slam = xvmin + slamax; else slam = xvmin - slamax; print.Debug("xvmin", xvmin, "slopem", slopem, "slam", slam); } else { slam = pb.Min(); // std::cout<<"pb.Min() slam= "< xvmin + slamax) slam = xvmin + slamax; if (slam < xvmin - slamax) slam = xvmin - slamax; } if (slam > 0.) { if (slam > overall) slam = overall; } else { if (slam < undral) slam = undral; } print.Debug("slam", slam, "undral", undral, "overall", overall); double f3 = 0.; do { print.Debug("iterate on f3- slam", niter, "slam", slam, "xvmin", xvmin); iterate = false; double toler9 = std::max(toler8, std::fabs(toler8 * slam)); // min. of parabola at one point if (std::fabs(p0.X() - slam) < toler9 || std::fabs(p1.X() - slam) < toler9 || std::fabs(p2.X() - slam) < toler9) { // std::cout<<"f1, f2, f3= "< p0.Y() && f3 > p1.Y() && f3 > p2.Y()) { print.Debug("f3 worse than all three previous"); if (slam > xvmin) overall = std::min(overall, slam - toler8); if (slam < xvmin) undral = std::max(undral, slam + toler8); slam = 0.5 * (slam + xvmin); print.Debug("new slam", slam); iterate = true; niter++; } } while (iterate && niter < maxiter); if (niter >= maxiter) { // exhausted max number of iterations return MnParabolaPoint(xvmin, fvmin); } // find worst previous point out of three and replace MnParabolaPoint p3(slam, f3); if (p0.Y() > p1.Y() && p0.Y() > p2.Y()) p0 = p3; else if (p1.Y() > p0.Y() && p1.Y() > p2.Y()) p1 = p3; else p2 = p3; print.Debug("f3", f3, "fvmin", fvmin, "xvmin", xvmin); if (f3 < fvmin) { fvmin = f3; xvmin = slam; } else { if (slam > xvmin) overall = std::min(overall, slam - toler8); if (slam < xvmin) undral = std::max(undral, slam + toler8); } niter++; } while (niter < maxiter); print.Debug("f1, f2 =", p0.Y(), p1.Y(), '\n', "x1, x2 =", p0.X(), p1.X(), '\n', "x, f =", xvmin, fvmin); return MnParabolaPoint(xvmin, fvmin); } #ifdef USE_OTHER_LS /** Perform a line search using a cubic interpolation using x0, x1 , df/dx(x0) and d2/dx(x0) (second derivative) This is used at the beginning when the second derivative is known to be negative */ MnParabolaPoint MnLineSearch::CubicSearch(const MnFcn &fcn, const MinimumParameters &st, const MnAlgebraicVector &step, double gdel, double g2del, const MnMachinePrecision &prec) const { MnPrint print("MnLineSearch::CubicSearch"); print.Debug("gdel", gdel, "g2del", g2del, "step", step); // change of large values double overall = 100.; double undral = -100.; double toler = 0.05; double slamin = 0.; double slambg = 5.; double alpha = 2.; for (unsigned int i = 0; i < step.size(); i++) { if (step(i) == 0) continue; double ratio = std::fabs(st.Vec()(i) / step(i)); if (slamin == 0) slamin = ratio; if (ratio < slamin) slamin = ratio; } if (std::fabs(slamin) < prec.Eps()) slamin = prec.Eps(); slamin *= prec.Eps2(); double f0 = st.Fval(); double f1 = fcn(st.Vec() + step); double fvmin = st.Fval(); double xvmin = 0.; print.Debug("f0", f0, "f1", f1); if (f1 < f0) { fvmin = f1; xvmin = 1.; } double toler8 = toler; double slamax = slambg; double flast = f1; double slam = 1.; // MnParabolaPoint p0(0., f0); // MnParabolaPoint p1(slam, flast); ROOT::Math::SMatrix cubicMatrix; ROOT::Math::SVector cubicCoeff; // cubic coefficients to be found ROOT::Math::SVector bVec; // cubic coefficients to be found double x0 = 0; // cubic interpolation using the two points p0,p1 and the slope at p0 and the second derivative at p0 // cut toler8 as function goes up double x1 = slam; cubicMatrix(0, 0) = (x0 * x0 * x0 - x1 * x1 * x1) / 3.; cubicMatrix(0, 1) = (x0 * x0 - x1 * x1) / 2.; cubicMatrix(0, 2) = (x0 - x1); cubicMatrix(1, 0) = x0 * x0; cubicMatrix(1, 1) = x0; cubicMatrix(1, 2) = 1; cubicMatrix(2, 0) = 2. * x0; cubicMatrix(2, 1) = 1; cubicMatrix(2, 2) = 0; bVec(0) = f0 - f1; bVec(1) = gdel; bVec(2) = g2del; // if (debug) std::cout << "Matrix:\n " << cubicMatrix << std::endl; print.Debug("Vec:\n ", bVec); // find the minimum need to invert the matrix if (!cubicMatrix.Invert()) { print.Warn("Inversion failed - return"); return MnParabolaPoint(xvmin, fvmin); } cubicCoeff = cubicMatrix * bVec; print.Debug("Cubic:\n ", cubicCoeff); double ddd = cubicCoeff(1) * cubicCoeff(1) - 4 * cubicCoeff(0) * cubicCoeff(2); // b**2 - 4ac double slam1, slam2 = 0; // slam1 should be minimum and slam2 the maximum if (cubicCoeff(0) > 0) { slam1 = (-cubicCoeff(1) - std::sqrt(ddd)) / (2. * cubicCoeff(0)); slam2 = (-cubicCoeff(1) + std::sqrt(ddd)) / (2. * cubicCoeff(0)); } else if (cubicCoeff(0) < 0) { slam1 = (-cubicCoeff(1) + std::sqrt(ddd)) / (2. * cubicCoeff(0)); slam2 = (-cubicCoeff(1) - std::sqrt(ddd)) / (2. * cubicCoeff(0)); } else { // case == 0 (-b/c) slam1 = -gdel / g2del; slam2 = slam1; } print.Debug("slam1", slam1, "slam2", slam2); // this should be the minimum otherwise inversion failed and I should do something else if (slam2 < undral) slam2 = undral; if (slam2 > overall) slam2 = overall; // I am stack somewhere - take a large step if (std::fabs(slam2) < toler) slam2 = (slam2 >= 0) ? slamax : -slamax; double f2 = fcn(st.Vec() + slam2 * step); print.Debug("try with slam 2", slam2, "f2", f2); double fp; // use this as new minimum // bool noImpr = false; if (f2 < fvmin) { slam = slam2; xvmin = slam; fvmin = f2; fp = fvmin; } else { // try with slam2 if it is better if (slam1 < undral) slam1 = undral; if (slam1 > overall) slam1 = overall; if (std::fabs(slam1) < toler) slam1 = (slam1 >= 0) ? -slamax : slamax; double f3 = fcn(st.Vec() + slam1 * step); print.Debug("try with slam 1", slam1, "f3", f3); if (f3 < fvmin) { slam = slam1; fp = fvmin; xvmin = slam; fvmin = f3; } else { // case both f2 and f3 did not produce a better result if (f2 < f3) { slam = slam1; fp = f2; } else { slam = slam2; fp = f3; } } } bool iterate2 = false; int niter = 0; int maxiter = 10; do { iterate2 = false; print.Debug("iter", niter, "test approx deriv ad second deriv at", slam, "fp", fp); // estimate grad and second derivative at new point taking a step of 10-3 double h = 0.001 * slam; double fh = fcn(st.Vec() + (slam + h) * step); double fl = fcn(st.Vec() + (slam - h) * step); double df = (fh - fl) / (2. * h); double df2 = (fh + fl - 2. * fp) / (h * h); print.Debug("deriv", df, df2); // if I am in a point of still negative derivative if (std::fabs(df) < prec.Eps() && std::fabs(df2) < prec.Eps()) { // try in opposite direction with an opposite value slam = (slam >= 0) ? -slamax : slamax; slamax *= 10; fp = fcn(st.Vec() + slam * step); } else if (std::fabs(df2) <= 0) { // gradient is significative different than zero then redo a cubic interpolation // from new point return MnParabolaPoint(slam, fp); // should redo a cubic interpol. ?? // niter ++; // if (niter > maxiter) break; // MinimumParameters pa = MinimumParameters(st.Vec() + stepNew, fp); // gdel = stepNew(i) // MnParabolaPoint pp = CubicSearch(fcn, st, stepNew, df, df2 } else return MnParabolaPoint(slam, fp); niter++; } while (niter < maxiter); return MnParabolaPoint(xvmin, fvmin); } // class describing Fcn function in one dimension class ProjectedFcn : public ROOT::Math::IGenFunction { public: ProjectedFcn(const MnFcn &fcn, const MinimumParameters &pa, const MnAlgebraicVector &step) : fFcn(fcn), fPar(pa), fStep(step) { } ROOT::Math::IGenFunction *Clone() const { return new ProjectedFcn(*this); } private: double DoEval(double x) const { return fFcn(fPar.Vec() + x * fStep); } const MnFcn &fFcn; const MinimumParameters &fPar; const MnAlgebraicVector &fStep; }; MnParabolaPoint MnLineSearch::BrentSearch(const MnFcn &fcn, const MinimumParameters &st, const MnAlgebraicVector &step, double gdel, double g2del, const MnMachinePrecision &prec) const { MnPrint print("MnLineSearch::BrentSearch"); print.Debug("gdel", gdel, "g2del", g2del); print.Debug([&](std::ostream &os) { for (unsigned int i = 0; i < step.size(); ++i) { if (step(i) != 0) { os << "step(i) " << step(i) << '\n'; std::cout << "par(i) " << st.Vec()(i) << '\n'; break; } } }); ProjectedFcn func(fcn, st, step); // do first a cubic interpolation double f0 = st.Fval(); double f1 = fcn(st.Vec() + step); f0 = func(0.0); f1 = func(1.); double fvmin = st.Fval(); double xvmin = 0.; print.Debug("f0", f0, "f1", f1); if (f1 < f0) { fvmin = f1; xvmin = 1.; } // double toler8 = toler; // double slamax = slambg; // double flast = f1; double slam = 1.; double undral = -1000; double overall = 1000; double x0 = 0; // MnParabolaPoint p0(0., f0); // MnParabolaPoint p1(slam, flast); #ifdef USE_CUBIC ROOT::Math::SMatrix cubicMatrix; ROOT::Math::SVector cubicCoeff; // cubic coefficients to be found ROOT::Math::SVector bVec; // cubic coefficients to be found // cubic interpolation using the two points p0,p1 and the slope at p0 and the second derivative at p0 // cut toler8 as function goes up double x1 = slam; cubicMatrix(0, 0) = (x0 * x0 * x0 - x1 * x1 * x1) / 3.; cubicMatrix(0, 1) = (x0 * x0 - x1 * x1) / 2.; cubicMatrix(0, 2) = (x0 - x1); cubicMatrix(1, 0) = x0 * x0; cubicMatrix(1, 1) = x0; cubicMatrix(1, 2) = 1; cubicMatrix(2, 0) = 2. * x0; cubicMatrix(2, 1) = 1; cubicMatrix(2, 2) = 0; bVec(0) = f0 - f1; bVec(1) = gdel; bVec(2) = g2del; // if (debug) std::cout << "Matrix:\n " << cubicMatrix << std::endl; print.Debug("Vec:\n ", bVec); // find the minimum need to invert the matrix if (!cubicMatrix.Invert()) { print.Warn("Inversion failed - return"); return MnParabolaPoint(xvmin, fvmin); } cubicCoeff = cubicMatrix * bVec; print.Debug("Cubic:\n ", cubicCoeff); double ddd = cubicCoeff(1) * cubicCoeff(1) - 4 * cubicCoeff(0) * cubicCoeff(2); // b**2 - 4ac double slam1, slam2 = 0; // slam1 should be minimum and slam2 the maximum if (cubicCoeff(0) > 0) { slam1 = (-cubicCoeff(1) - std::sqrt(ddd)) / (2. * cubicCoeff(0)); slam2 = (-cubicCoeff(1) + std::sqrt(ddd)) / (2. * cubicCoeff(0)); } else if (cubicCoeff(0) < 0) { slam1 = (-cubicCoeff(1) + std::sqrt(ddd)) / (2. * cubicCoeff(0)); slam2 = (-cubicCoeff(1) - std::sqrt(ddd)) / (2. * cubicCoeff(0)); } else { // case == 0 (-b/c) slam1 = -gdel / g2del; slam2 = slam1; } if (slam1 < undral) slam1 = undral; if (slam1 > overall) slam1 = overall; if (slam2 < undral) slam2 = undral; if (slam2 > overall) slam2 = overall; double fs1 = func(slam1); double fs2 = func(slam2); print.Debug("slam1", slam1, "slam2", slam2, "f(slam1)", fs1, "f(slam2)", fs2); if (fs1 < fs2) { x0 = slam1; f0 = fs1; } else { x0 = slam2; f0 = fs2; } #else x0 = xvmin; f0 = fvmin; #endif double astart = 100; // do a Brent search in a large interval double a = x0 - astart; double b = x0 + astart; // double x0 = 1; int maxiter = 20; double absTol = 0.5; double relTol = 0.05; ROOT::Math::Minim1D::Type minType = ROOT::Math::Minim1D::BRENT; bool iterate = false; int iter = 0; print.Debug("f(0)", func(0.), "f1", func(1.0), "f(3)", func(3.0), "f(5)", func(5.0)); double fa = func(a); double fb = func(b); // double f0 = func(x0); double toler = 0.01; double delta0 = 5; double delta = delta0; bool enlarge = true; bool scanmin = false; double x2, f2 = 0; double dir = 1; int nreset = 0; do { print.Debug("iter", iter, "a", a, "b", b, "x0", x0, "fa", fa, "fb", fb, "f0", f0); if (fa <= f0 || fb <= f0) { scanmin = false; if (fa < fb) { if (fa < fvmin) { fvmin = fa; xvmin = a; } // double f2 = fa; // double x2 = a; if (enlarge) { x2 = a - 1000; // move lower f2 = func(x2); } if (std::fabs((fa - f2) / (a - x2)) > toler) { // significant change in f continue to enlarge interval x0 = a; f0 = fa; a = x2; fa = f2; enlarge = true; } else { // move direction of [a // values change a little, start from central point try with x0 = x0 - delta if (nreset == 0) dir = -1; enlarge = false; x0 = x0 + dir * delta; f0 = func(x0); // if reached limit try opposite direction , direction b] if (std::fabs((f0 - fa) / (x0 - a)) < toler) { delta = 10 * delta0 / (10. * (nreset + 1)); // decrease the delta if still not change observed a = x0; fa = f0; x0 = delta; f0 = func(x0); dir *= -1; nreset++; print.Info("A: Done a reset - scan in opposite direction!"); } delta *= 2; // double delta at next iteration if (x0 < b && x0 > a) scanmin = true; else { x0 = 0; f0 = st.Fval(); } } } else { // fb < fa if (fb < fvmin) { fvmin = fb; xvmin = b; } if (enlarge) { x2 = b + 1000; // move upper f2 = func(x2); } if (std::fabs((fb - f2) / (x2 - b)) > toler) { // significant change in f continue to enlarge interval f0 = fb; x0 = b; b = x2; // fb = f2; enlarge = true; } else { // here move direction b // values change a little, try with x0 = fa + delta if (nreset == 0) dir = 1; enlarge = false; x0 = x0 + dir * delta; f0 = func(x0); // if reached limit try other side if (std::fabs((f0 - fb) / (x0 - b)) < toler) { delta = 10 * delta0 / (10. * (nreset + 1)); // decrease the delta if still not change observed b = x0; fb = f0; x0 = -delta; f0 = func(x0); dir *= -1; nreset++; print.Info("B: Done a reset - scan in opposite direction!"); } delta *= 2; // double delta at next iteration if (x0 > a && x0 < b) scanmin = true; else { x0 = 0; f0 = st.Fval(); } } } if (f0 < fvmin) { x0 = xvmin; fvmin = f0; } print.Debug("new x0", x0, "f0", f0); // use golden section iterate = scanmin || enlarge; } else { // x0 is a min of [a,b] iterate = false; } iter++; } while (iterate && iter < maxiter); if (f0 > fa || f0 > fb) // skip minim 1d try Minuit LS // return (*this) (fcn, st, step, gdel, prec, debug); return MnParabolaPoint(xvmin, fvmin); print.Info("1D minimization using", minType); ROOT::Math::Minimizer1D min(minType); min.SetFunction(func, x0, a, b); int ret = min.Minimize(maxiter, absTol, relTol); MnPrint::info("result of GSL 1D minimization:", ret, "niter", min.Iterations(), "xmin", min.XMinimum(), "fmin", min.FValMinimum()); return MnParabolaPoint(min.XMinimum(), min.FValMinimum()); } #endif } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnMachinePrecision.cxx0000644000000000000000000000340314332717401022041 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnTiny.h" #include namespace ROOT { namespace Minuit2 { MnMachinePrecision::MnMachinePrecision() { // use double precision values from the numeric_limits standard // and do not determine it anymore using ComputePrecision // epsilon from stundard // note that there is a factor of 2 in the definition of // std::numeric_limitys::epsilon w.r.t DLAMCH epsilon fEpsMac = 4. * std::numeric_limits::epsilon(); fEpsMa2 = 2. * std::sqrt(fEpsMac); } void MnMachinePrecision::ComputePrecision() { fEpsMac = 4.0E-7; fEpsMa2 = 2. * std::sqrt(fEpsMac); // determine machine precision using // code similar to DLAMCH LAPACK Fortran function /* char e[] = {"e"}; fEpsMac = 8.*dlamch_(e); fEpsMa2 = 2.*std::sqrt(fEpsMac); */ MnTiny mytiny; // calculate machine precision double epstry = 0.5; double epsbak = 0.; volatile double epsp1 = 0.; // allow to run this method with fast-math double one = 1.0; for (int i = 0; i < 100; i++) { epstry *= 0.5; epsp1 = one + epstry; epsbak = mytiny(epsp1); if (epsbak < epstry) { fEpsMac = 8. * epstry; fEpsMa2 = 2. * std::sqrt(fEpsMac); break; } } } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnMinos.cxx0000644000000000000000000001605014332717401017710 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnMinos.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/FCNBase.h" #include "Minuit2/MnFunctionCross.h" #include "Minuit2/MnCross.h" #include "Minuit2/MinosError.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { MnMinos::MnMinos(const FCNBase &fcn, const FunctionMinimum &min, unsigned int stra) : fFCN(fcn), fMinimum(min), fStrategy(MnStrategy(stra)) { MnPrint print("MnMinos"); // construct from FCN + Minimum // check if Error definition has been changed, in case re-update errors if (fcn.Up() != min.Up()) { print.Warn("MnMinos: UP value has changed, need to update FunctionMinimum class"); } } MnMinos::MnMinos(const FCNBase &fcn, const FunctionMinimum &min, const MnStrategy &stra) : fFCN(fcn), fMinimum(min), fStrategy(stra) { MnPrint print("MnMinos"); // construct from FCN + Minimum // check if Error definition has been changed, in case re-update errors if (fcn.Up() != min.Up()) { print.Warn("UP value has changed, need to update FunctionMinimum class"); } } std::pair MnMinos::operator()(unsigned int par, unsigned int maxcalls, double toler) const { // do Minos analysis given the parameter index returning a pair for (lower,upper) errors MinosError mnerr = Minos(par, maxcalls, toler); return mnerr(); } double MnMinos::Lower(unsigned int par, unsigned int maxcalls, double toler) const { // get lower error for parameter par MnCross aopt = Loval(par, maxcalls, toler); MinosError mnerr(par, fMinimum.UserState().Value(par), aopt, MnCross()); return mnerr.Lower(); } double MnMinos::Upper(unsigned int par, unsigned int maxcalls, double toler) const { // upper error for parameter par MnCross aopt = Upval(par, maxcalls, toler); MinosError mnerr(par, fMinimum.UserState().Value(par), MnCross(), aopt); return mnerr.Upper(); } MinosError MnMinos::Minos(unsigned int par, unsigned int maxcalls, double toler) const { // do full minos error analysis (lower + upper) for parameter par MnPrint print("MnMinos"); MnCross up = Upval(par, maxcalls, toler); print.Debug("Function calls to find upper error", up.NFcn()); MnCross lo = Loval(par, maxcalls, toler); print.Debug("Function calls to find lower error", lo.NFcn()); print.Debug("return Minos error", lo.Value(), ",", up.Value()); return MinosError(par, fMinimum.UserState().Value(par), lo, up); } MnCross MnMinos::FindCrossValue(int direction, unsigned int par, unsigned int maxcalls, double toler) const { // get crossing value in the parameter direction : // direction = + 1 upper value // direction = -1 lower value // pass now tolerance used for Migrad minimizations assert(direction == 1 || direction == -1); MnPrint print("MnMinos"); print.Info("Determination of", direction == 1 ? "upper" : "lower", "Minos error for parameter", par); assert(fMinimum.IsValid()); assert(!fMinimum.UserState().Parameter(par).IsFixed()); assert(!fMinimum.UserState().Parameter(par).IsConst()); if (maxcalls == 0) { unsigned int nvar = fMinimum.UserState().VariableParameters(); maxcalls = 2 * (nvar + 1) * (200 + 100 * nvar + 5 * nvar * nvar); } std::vector para(1, par); MnUserParameterState upar = fMinimum.UserState(); double err = direction * upar.Error(par); double val = upar.Value(par) + err; // check if we do not cross limits if (direction == 1 && upar.Parameter(par).HasUpperLimit()) { val = std::min(val, upar.Parameter(par).UpperLimit()); } if (direction == -1 && upar.Parameter(par).HasLowerLimit()) { val = std::max(val, upar.Parameter(par).LowerLimit()); } // recompute err in case it was truncated for the limit err = val - upar.Value(par); std::vector xmid(1, val); std::vector xdir(1, err); double up = fFCN.Up(); unsigned int ind = upar.IntOfExt(par); // get error matrix (methods return a copy) MnAlgebraicSymMatrix m = fMinimum.Error().Matrix(); // get internal parameters const MnAlgebraicVector &xt = fMinimum.Parameters().Vec(); // LM: change to use err**2 (m(i,i) instead of err as in F77 version double xunit = std::sqrt(up / m(ind, ind)); // LM (29/04/08) bug: change should be done in internal variables // set the initial value for the other parameters that we are going to fit in MnCross for (unsigned int i = 0; i < m.Nrow(); i++) { if (i == ind) continue; double xdev = xunit * m(ind, i); double xnew = xt(i) + direction * xdev; // transform to external values unsigned int ext = upar.ExtOfInt(i); double unew = upar.Int2ext(i, xnew); // take into account limits if (upar.Parameter(ext).HasUpperLimit()) { unew = std::min(unew, upar.Parameter(ext).UpperLimit()); } if (upar.Parameter(ext).HasLowerLimit()) { unew = std::max(unew, upar.Parameter(ext).LowerLimit()); } print.Debug("Parameter", ext, "is set from", upar.Value(ext), "to", unew); upar.SetValue(ext, unew); } upar.Fix(par); upar.SetValue(par, val); print.Debug("Parameter", par, "is fixed and set from", fMinimum.UserState().Value(par), "to", val, "delta =", err); MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy); MnCross aopt = cross(para, xmid, xdir, toler, maxcalls); print.Debug("aopt value found from MnFunctionCross =", aopt.Value()); const char *par_name = upar.Name(par); if (aopt.AtMaxFcn()) print.Warn("maximum number of function calls exceeded for Parameter", par_name); if (aopt.NewMinimum()) print.Warn("new Minimum found while looking for Parameter", par_name); if (direction == 1) { if (aopt.AtLimit()) print.Warn("parameter", par_name, "is at Upper limit"); if (!aopt.IsValid()) print.Warn("could not find Upper Value for Parameter", par_name); } else { if (aopt.AtLimit()) print.Warn("parameter", par_name, "is at Lower limit"); if (!aopt.IsValid()) print.Warn("could not find Lower Value for Parameter", par_name); } print.Info("end of Minos scan for", direction == 1 ? "up" : "low", "interval for parameter", upar.Name(par)); return aopt; } MnCross MnMinos::Upval(unsigned int par, unsigned int maxcalls, double toler) const { // return crossing in the lower parameter direction return FindCrossValue(1, par, maxcalls, toler); } MnCross MnMinos::Loval(unsigned int par, unsigned int maxcalls, double toler) const { // return crossing in the lower parameter direction return FindCrossValue(-1, par, maxcalls, toler); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnParabolaFactory.cxx0000644000000000000000000000431014332717401021670 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnParabolaFactory.h" #include "Minuit2/MnParabola.h" #include "Minuit2/MnParabolaPoint.h" namespace ROOT { namespace Minuit2 { MnParabola MnParabolaFactory:: operator()(const MnParabolaPoint &p1, const MnParabolaPoint &p2, const MnParabolaPoint &p3) const { // construct the parabola from 3 points p1,p2,p3 double x1 = p1.X(); double x2 = p2.X(); double x3 = p3.X(); double dx12 = x1 - x2; double dx13 = x1 - x3; double dx23 = x2 - x3; // std::cout<<"MnParabolaFactory x1, x2, x3: "<> MnParameterScan:: operator()(unsigned int par, unsigned int maxsteps, double low, double high) { // do the scan for parameter par between low and high values // if(maxsteps > 101) maxsteps = 101; std::vector> result; result.reserve(maxsteps + 1); std::vector params = fParameters.Params(); result.push_back(std::pair(params[par], fAmin)); if (low > high) return result; if (maxsteps < 2) return result; if (low == 0. && high == 0.) { low = params[par] - 2. * fParameters.Error(par); high = params[par] + 2. * fParameters.Error(par); } if (low == 0. && high == 0. && fParameters.Parameter(par).HasLimits()) { if (fParameters.Parameter(par).HasLowerLimit()) low = fParameters.Parameter(par).LowerLimit(); if (fParameters.Parameter(par).HasUpperLimit()) high = fParameters.Parameter(par).UpperLimit(); } if (fParameters.Parameter(par).HasLimits()) { if (fParameters.Parameter(par).HasLowerLimit()) low = std::max(low, fParameters.Parameter(par).LowerLimit()); if (fParameters.Parameter(par).HasUpperLimit()) high = std::min(high, fParameters.Parameter(par).UpperLimit()); } double x0 = low; double stp = (high - low) / double(maxsteps - 1); for (unsigned int i = 0; i < maxsteps; i++) { params[par] = x0 + double(i) * stp; double fval = fFCN(params); if (fval < fAmin) { fParameters.SetValue(par, params[par]); fAmin = fval; } result.push_back(std::pair(params[par], fval)); } return result; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnPlot.cxx0000644000000000000000000000421514332717401017541 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnPlot.h" namespace ROOT { namespace Minuit2 { void mnplot(double *xpt, double *ypt, char *chpt, int nxypt, int npagwd, int npagln); void MnPlot::operator()(const std::vector> &points) const { // call routine from Fortran minuit (mnplot) to plot the vector of (x,y) points std::vector x; x.reserve(points.size()); std::vector y; y.reserve(points.size()); std::vector chpt; chpt.reserve(points.size()); for (std::vector>::const_iterator ipoint = points.begin(); ipoint != points.end(); ++ipoint) { x.push_back((*ipoint).first); y.push_back((*ipoint).second); chpt.push_back('*'); } mnplot(&(x.front()), &(y.front()), &(chpt.front()), points.size(), Width(), Length()); } void MnPlot::operator()(double xmin, double ymin, const std::vector> &points) const { // call routine from Fortran minuit (mnplot) to plot the vector of (x,y) points + minimum values std::vector x; x.reserve(points.size() + 2); x.push_back(xmin); x.push_back(xmin); std::vector y; y.reserve(points.size() + 2); y.push_back(ymin); y.push_back(ymin); std::vector chpt; chpt.reserve(points.size() + 2); chpt.push_back(' '); chpt.push_back('X'); for (std::vector>::const_iterator ipoint = points.begin(); ipoint != points.end(); ++ipoint) { x.push_back((*ipoint).first); y.push_back((*ipoint).second); chpt.push_back('*'); } mnplot(&(x.front()), &(y.front()), &(chpt.front()), points.size() + 2, Width(), Length()); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnPosDef.cxx0000644000000000000000000000643114332717401020005 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnPosDef.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { LAVector eigenvalues(const LASymMatrix &); MinimumState MnPosDef::operator()(const MinimumState &st, const MnMachinePrecision &prec) const { // interface from minimum state MinimumError err = (*this)(st.Error(), prec); return MinimumState(st.Parameters(), err, st.Gradient(), st.Edm(), st.NFcn()); } MinimumError MnPosDef::operator()(const MinimumError &e, const MnMachinePrecision &prec) const { MnPrint print("MnPosDef"); // make error matrix positive defined returning a new corrected minimum error state MnAlgebraicSymMatrix err(e.InvHessian()); if (err.size() == 1 && err(0, 0) < prec.Eps()) { err(0, 0) = 1.; return MinimumError(err, MinimumError::MnMadePosDef); } if (err.size() == 1 && err(0, 0) > prec.Eps()) { return e; } // std::cout<<"MnPosDef init matrix= "< #include #include #include #include constexpr int PRECISION = 10; constexpr int WIDTH = PRECISION + 7; namespace ROOT { namespace Minuit2 { // we don't use a std::vector or std::array here, because we want a mix of the two; // a stack-allocated container with fixed capacity but dynamic size, i.e. the equivalent // of static_vector from the Boost Container library template class PrefixStack { public: using const_pointer = const T *; using const_reference = const T &; void Push(T prefix) { if (fSize < fMaxSize) fData[fSize] = prefix; else { // crop the stack when it becomes too deep as a last resort, but this should not // happen, fMaxSize should be increased instead if this occurs fData[fMaxSize - 1] = prefix; fData[fMaxSize - 2] = "..."; } ++fSize; } void Pop() { assert(fSize > 0); --fSize; } const_pointer begin() const { return fData; } const_pointer end() const { return fData + (fSize < fMaxSize ? fSize : fMaxSize); } const_reference back() const { return *(end() - 1); } private: static constexpr unsigned fMaxSize = 10; // increase as needed T fData[fMaxSize]; unsigned fSize = 0; }; // gShowPrefixStack determines how messages are printed, it acts on all threads; // race conditions when writing to this do not cause failures bool gShowPrefixStack = false; // writing to gPrefixFilter is not thread-safe, should be done only from main thread std::vector gPrefixFilter; // gPrintLevel must be thread-local, because it may be manipulated by a thread to // temporarily turn logging on or off; Minuit2Minimizer does this, for example thread_local int gPrintLevel = 0; thread_local int gMaxNP = 10; // gPrefixStack must be thread-local thread_local PrefixStack gPrefixStack; MnPrint::MnPrint(const char *prefix, int level) : fLevel{level} { gPrefixStack.Push(prefix); } MnPrint::~MnPrint() { gPrefixStack.Pop(); } void MnPrint::ShowPrefixStack(bool yes) { gShowPrefixStack = yes; } void MnPrint::AddFilter(const char *filter) { gPrefixFilter.emplace_back(filter); } void MnPrint::ClearFilter() { gPrefixFilter.clear(); } int MnPrint::SetGlobalLevel(int level) { // should use std::exchange or boost::exchange std::swap(gPrintLevel, level); return level; } int MnPrint::GlobalLevel() { return gPrintLevel; } int MnPrint::SetLevel(int level) { // should use std::exchange or boost::exchange std::swap(fLevel, level); return level; } int MnPrint::Level() const { return fLevel; } int MnPrint::SetMaxNP(int value) { std::swap(gMaxNP, value); return value; } int MnPrint::MaxNP() { return gMaxNP; } void StreamFullPrefix(std::ostringstream &os) { const char *prev = ""; for (const auto cs : gPrefixStack) { // skip repeated prefixes; repetition happens when class method calls another // method of the same class and both set up a MnPrint instance if (std::strcmp(cs, prev) != 0) os << cs << ":"; prev = cs; } } void MnPrint::StreamPrefix(std::ostringstream &os) { if (gShowPrefixStack) { // show full prefix stack, useful to set sharp filters and to see what calls what StreamFullPrefix(os); } else { // show only the top of the prefix stack (the prefix of the innermost scope) os << gPrefixStack.back(); } } bool MnPrint::Hidden() { // Filtering is not implemented a very efficient way to keep it simple, but the // implementation ensures that the performance drop is opt-in. Only when filters are // used there is a performance loss. // The intended use case of filtering is for debugging, when highest performance // does not matter. Filtering is only every attempted if the message passes the // threshold level. // Filtering is very fast when the filter is empty. if (gPrefixFilter.empty()) return false; std::ostringstream os; os << "^"; StreamFullPrefix(os); std::string prefix = os.str(); // Filtering works like grep, the message is shown if any of the filter strings match. // To only match the beginning of the prefix, use "^". For example "^MnHesse" only // matches direct execution of MnHesse, but not MnHesse called by MnMigrad. for (const auto &s : gPrefixFilter) { if (prefix.find(s) != std::string::npos) return false; } return true; } MnPrint::Oneline::Oneline(double fcn, double edm, int ncalls, int iter) : fFcn(fcn), fEdm(edm), fNcalls(ncalls), fIter(iter) { } MnPrint::Oneline::Oneline(const MinimumState &state, int iter) : MnPrint::Oneline(state.Fval(), state.Edm(), state.NFcn(), iter) { } MnPrint::Oneline::Oneline(const FunctionMinimum &fmin, int iter) : MnPrint::Oneline(fmin.State(), iter) {} std::ostream &operator<<(std::ostream &os, const MnPrint::Oneline &x) { // print iteration, function value, edm and ncalls in one single line if (x.fIter >= 0) os << std::setw(4) << x.fIter << " - "; const int pr = os.precision(PRECISION); os << "FCN = " << std::setw(WIDTH) << x.fFcn << " Edm = " << std::setw(WIDTH) << x.fEdm << " NCalls = " << std::setw(6) << x.fNcalls; os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const LAVector &vec) { // print a vector const int pr = os.precision(PRECISION); const unsigned int nrow = vec.size(); const unsigned int np = std::min(nrow, static_cast( MnPrint::MaxNP()) ); os << "\t["; for (unsigned int i = 0; i < np; i++) { os.width(WIDTH); os << vec(i); } if (np < nrow) { os << ".... "; os.width(WIDTH); os << vec(nrow-1); } os << "]\t"; os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const LASymMatrix &matrix) { // print a matrix const int pr = os.precision(8); const unsigned int nrow = matrix.Nrow(); const unsigned int n = std::min(nrow, static_cast( MnPrint::MaxNP()) ); for (unsigned int i = 0; i < nrow; i++) { os << "\n"; if (i == 0) os << "[["; else { if (i >= n) { os << "....\n"; i = nrow-1; } os << " ["; } for (unsigned int j = 0; j < nrow; j++) { if (j >= n) { os << ".... "; j = nrow-1; } os.width(15); os << matrix(i, j); } os << "]"; } os << "]]"; os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MnUserParameters &par) { // print the MnUserParameter object os << "\n Pos | Name | type | Value | Error +/-"; int pr = os.precision(); const double eps2 = par.Precision().Eps2(); for (auto &&p : par.Parameters()) { os << "\n" << std::setw(5) << p.Number() << " | " << std::setw(10) << p.Name() << " |"; if (p.IsConst()) os << " const |"; else if (p.IsFixed()) os << " fixed |"; else if (p.HasLimits()) os << " limited |"; else os << " free |"; os.precision(PRECISION); os.width(WIDTH); os << p.Value() << " | " << std::setw(12); if (p.Error() > 0) { os << p.Error(); if (p.HasLimits()) { if (std::fabs(p.Value() - p.LowerLimit()) < eps2) { os << " (at lower limit)"; } else if (std::fabs(p.Value() - p.UpperLimit()) < eps2) { os << " (at upper limit)"; } } } } os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MnUserCovariance &matrix) { // print the MnUserCovariance const int pr = os.precision(6); unsigned int n = matrix.Nrow(); for (unsigned int i = 0; i < n; i++) { os << '\n'; for (unsigned int j = 0; j < n; j++) { os.width(13); os << matrix(i, j); } os << " | "; double di = matrix(i, i); for (unsigned int j = 0; j < n; j++) { double dj = matrix(j, j); os.width(13); os << matrix(i, j) / std::sqrt(std::fabs(di * dj)); } } os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MnGlobalCorrelationCoeff &coeff) { // print the global correlation coefficient const int pr = os.precision(6); for (auto &&x : coeff.GlobalCC()) { os << '\n'; os.width(6 + 7); os << x; } os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MnUserParameterState &state) { // print the MnUserParameterState const int pr = os.precision(PRECISION); os << "\n Valid : " << (state.IsValid() ? "yes" : "NO") << "\n Function calls: " << state.NFcn() << "\n Minimum value : " << state.Fval() << "\n Edm : " << state.Edm() << "\n Parameters : " << state.Parameters() << "\n CovarianceStatus: " << state.CovarianceStatus() << "\n Covariance and correlation matrix: "; if (state.HasCovariance()) os << state.Covariance(); else os << "matrix is not present or not valid"; if (state.HasGlobalCC()) os << "\n Global correlation coefficients: " << state.GlobalCC(); os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const FunctionMinimum &min) { // print the FunctionMinimum const int pr = os.precision(PRECISION); os << "\n Valid : " << (min.IsValid() ? "yes" : "NO") << "\n Function calls: " << min.NFcn() << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm() << "\n Internal parameters: " << min.Parameters().Vec(); if (min.HasValidCovariance()) os << "\n Internal covariance matrix: " << min.Error().Matrix(); os << "\n External parameters: " << min.UserParameters(); // os << min.UserCovariance() << '\n'; // os << min.UserState().GlobalCC() << '\n'; if (!min.IsValid()) { os << "\n FunctionMinimum is invalid:"; if (!min.State().IsValid()) os << "\n State is invalid"; if (min.IsAboveMaxEdm()) os << "\n Edm is above max"; if (min.HasReachedCallLimit()) os << "\n Reached call limit"; } os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MinimumState &min) { const int pr = os.precision(PRECISION); os << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm() << "\n Internal parameters:" << min.Vec() << "\n Internal gradient :" << min.Gradient().Vec(); if (min.HasCovariance()) os << "\n Internal covariance matrix:" << min.Error().Matrix(); os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MnMachinePrecision &prec) { // print the Precision int pr = os.precision(PRECISION); os << "MnMachinePrecision " << prec.Eps() << '\n'; os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const MinosError &me) { // print the Minos Error os << "Minos # of function calls: " << me.NFcn() << '\n'; if (!me.IsValid()) os << "Minos Error is not valid." << '\n'; if (!me.LowerValid()) os << "lower Minos Error is not valid." << '\n'; if (!me.UpperValid()) os << "upper Minos Error is not valid." << '\n'; if (me.AtLowerLimit()) os << "Minos Error is Lower limit of Parameter " << me.Parameter() << "." << '\n'; if (me.AtUpperLimit()) os << "Minos Error is Upper limit of Parameter " << me.Parameter() << "." << '\n'; if (me.AtLowerMaxFcn()) os << "Minos number of function calls for Lower Error exhausted." << '\n'; if (me.AtUpperMaxFcn()) os << "Minos number of function calls for Upper Error exhausted." << '\n'; if (me.LowerNewMin()) { os << "Minos found a new Minimum in negative direction." << '\n'; os << me.LowerState() << '\n'; } if (me.UpperNewMin()) { os << "Minos found a new Minimum in positive direction." << '\n'; os << me.UpperState() << '\n'; } int pr = os.precision(); os << "No |" << "| Name |" << "| Value@min |" << "| negative |" << "| positive " << '\n'; os << std::setw(4) << me.Parameter() << std::setw(5) << "||"; os << std::setw(10) << me.LowerState().Name(me.Parameter()) << std::setw(3) << "||"; os << std::setprecision(PRECISION) << std::setw(WIDTH) << me.Min() << " ||" << std::setprecision(PRECISION) << std::setw(WIDTH) << me.Lower() << " ||" << std::setw(WIDTH) << me.Upper() << '\n'; os << '\n'; os.precision(pr); return os; } std::ostream &operator<<(std::ostream &os, const ContoursError &ce) { // print the ContoursError os << "Contours # of function calls: " << ce.NFcn() << '\n'; os << "MinosError in x: " << '\n'; os << ce.XMinosError() << '\n'; os << "MinosError in y: " << '\n'; os << ce.YMinosError() << '\n'; MnPlot plot; plot(ce.XMin(), ce.YMin(), ce()); for (auto ipar = ce().begin(); ipar != ce().end(); ++ipar) { os << ipar - ce().begin() << " " << (*ipar).first << " " << (*ipar).second << '\n'; } os << '\n'; return os; } std::ostream &operator<<(std::ostream &os, const std::pair &point) { os << "\t x = " << point.first << " y = " << point.second << std::endl; return os; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnPrintImpl.cxx0000644000000000000000000000165414332717401020545 0ustar00#include "Minuit2/MnPrint.h" using ROOT::Minuit2::MnPrint; #ifndef USE_ROOT_ERROR #include #ifndef MN_OS #define MN_OS std::cerr #endif void MnPrint::Impl(MnPrint::Verbosity level, const std::string &s) { const char *label[4] = {"[Error]", "[Warn]", "[Info]", "[Debug]"}; const int ilevel = static_cast(level); MN_OS << label[ilevel] << " " << s << std::endl; } #else // use ROOT error reporting system #include "TError.h" #include void MnPrint::Impl(MnPrint::Verbosity level, const std::string &s) { switch (level) { case MnPrint::eError: ::Error("Minuit2", "%s", s.c_str()); break; case MnPrint::eWarn: ::Warning("Minuit2", "%s", s.c_str()); break; case MnPrint::eInfo: ::Info("Minuit2", "%s", s.c_str()); break; case MnPrint::eDebug: ::Info("Minuit2", "%s", s.c_str()); break; case MnPrint::eTrace: ::Info("Minuit2", "%s", s.c_str()); break; } } #endif // USE_ROOT_ERROR iminuit-2.30.1/extern/root/math/minuit2/src/MnScan.cxx0000644000000000000000000000210014332717401017476 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnScan.h" #include "Minuit2/MnParameterScan.h" namespace ROOT { namespace Minuit2 { std::vector> MnScan::Scan(unsigned int par, unsigned int maxsteps, double low, double high) { // perform a scan of the function in the parameter par MnParameterScan scan(fFCN, fState.Parameters()); double amin = scan.Fval(); std::vector> result = scan(par, maxsteps, low, high); if (scan.Fval() < amin) { fState.SetValue(par, scan.Parameters().Value(par)); amin = scan.Fval(); } return result; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnSeedGenerator.cxx0000644000000000000000000002267214332717401021361 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnSeedGenerator.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/MnFcn.h" #include "Minuit2/GradientCalculator.h" #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MinimumError.h" #include "Minuit2/MnMatrix.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MinuitParameter.h" #include "Minuit2/MnLineSearch.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnHesse.h" #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/NegativeG2LineSearch.h" #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/HessianGradientCalculator.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { MinimumSeed MnSeedGenerator:: operator()(const MnFcn &fcn, const GradientCalculator &gc, const MnUserParameterState &st, const MnStrategy &stra) const { MnPrint print("MnSeedGenerator"); // find seed (initial minimization point) using the calculated gradient const unsigned int n = st.VariableParameters(); const MnMachinePrecision &prec = st.Precision(); print.Info("Computing seed using NumericalGradient calculator"); print.Debug(n, "free parameters, FCN pointer", &fcn); // initial starting values MnAlgebraicVector x(n); for (unsigned int i = 0; i < n; i++) x(i) = st.IntParameters()[i]; double fcnmin = fcn(x); MinimumParameters pa(x, fcnmin); FunctionGradient dgrad = gc(pa); MnAlgebraicSymMatrix mat(n); double dcovar = 1.; if (st.HasCovariance()) { for (unsigned int i = 0; i < n; i++) for (unsigned int j = i; j < n; j++) mat(i, j) = st.IntCovariance()(i, j); dcovar = 0.; } else { for (unsigned int i = 0; i < n; i++) // if G2 is small better using an arbitrary value (e.g. 1) mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps() ? 1. / dgrad.G2()(i) : 1.0; } MinimumError err(mat, dcovar); double edm = VariableMetricEDMEstimator().Estimate(dgrad, err); MinimumState state(pa, err, dgrad, edm, fcn.NumOfCalls()); print.Info("Initial state:", MnPrint::Oneline(state)); NegativeG2LineSearch ng2ls; if (ng2ls.HasNegativeG2(dgrad, prec)) { print.Debug("Negative G2 Found", "\n point:", x, "\n grad :", dgrad.Grad(), "\n g2 :", dgrad.G2()); state = ng2ls(fcn, state, gc, prec); print.Info("Negative G2 found - new state:", state); } if (stra.Strategy() == 2 && !st.HasCovariance()) { // calculate full 2nd derivative print.Debug("calling MnHesse"); MinimumState tmp = MnHesse(stra)(fcn, state, st.Trafo()); print.Info("run Hesse - Initial seeding state:", tmp); return MinimumSeed(tmp, st.Trafo()); } print.Info("Initial state ",state); return MinimumSeed(state, st.Trafo()); } MinimumSeed MnSeedGenerator::operator()(const MnFcn &fcn, const AnalyticalGradientCalculator &gc, const MnUserParameterState &st, const MnStrategy &stra) const { MnPrint print("MnSeedGenerator"); // check gradient (slow: will require more function evaluations) //if (gc.CheckGradient()) { // //CheckGradient(st,trado,stra,grd) //} if (!gc.CanComputeG2()) { print.Info("Using analytical (external) gradient calculator but cannot compute G2 - use then numerical gradient for G2"); Numerical2PGradientCalculator ngc(fcn, st.Trafo(), stra); return this->operator()(fcn, ngc, st, stra); } if (gc.CanComputeHessian()) print.Info("Computing seed using analytical (external) gradients and Hessian calculator"); else print.Info("Computing seed using analytical (external) gradients and G2 calculator"); // find seed (initial point for minimization) using analytical gradient unsigned int n = st.VariableParameters(); const MnMachinePrecision &prec = st.Precision(); // initial starting values MnAlgebraicVector x(n); for (unsigned int i = 0; i < n; i++) x(i) = st.IntParameters()[i]; double fcnmin = fcn(x); MinimumParameters pa(x, fcnmin); // compute function gradient FunctionGradient grad = gc(pa); double dcovar = 0; MnAlgebraicSymMatrix mat(n); // if we can compute Hessian compute it and use it bool computedHessian = false; if (!grad.HasG2()) { assert(gc.CanComputeHessian()); MnAlgebraicSymMatrix hmat(n); bool ret = gc.Hessian(pa, hmat); if (!ret) { print.Error("Cannot compute G2 and Hessian"); assert(true); } // update gradient using G2 from Hessian calculation MnAlgebraicVector g2(n); for (unsigned int i = 0; i < n; i++) g2(i) = hmat(i,i); grad = FunctionGradient(grad.Grad(),g2); print.Debug("Computed analytical G2",g2); // when Hessian has been computed invert to get covariance // we prefer not using full Hessian in strategy 1 since we need to be sure that // is pos-defined. Uncomment following line if want to have seed with the full Hessian //computedHessian = true; if (computedHessian) { mat = MinimumError::InvertMatrix(hmat); print.Info("Use full Hessian as seed"); print.Debug("computed Hessian",hmat); print.Debug("computed Error matrix (H^-1)",mat); } } // do this only when we have not computed the Hessian or always ? if (!computedHessian) { // check if minimum state has covariance - if not use computed G2 // should maybe this an option, sometimes is not good to re-use existing covariance if (st.HasCovariance()) { print.Info("Using existing covariance matrix"); for (unsigned int i = 0; i < n; i++) for (unsigned int j = i; j < n; j++) mat(i, j) = st.IntCovariance()(i, j); dcovar = 0.; } else { for (unsigned int i = 0; i < n; i++) { // if G2 is very small, better using an arbitrary value (e.g. 1.) mat(i, i) = std::fabs(grad.G2()(i)) > prec.Eps() ? 1. / grad.G2()(i) : 1.0; } dcovar = 1.; } } else { print.Info("Computing seed using full Hessian"); } MinimumError err(mat, dcovar); double edm = VariableMetricEDMEstimator().Estimate(grad, err); if (!grad.HasG2()) { print.Error("Cannot compute seed because G2 is not computed"); } MinimumState state(pa, err, grad, edm, fcn.NumOfCalls()); NegativeG2LineSearch ng2ls; if (ng2ls.HasNegativeG2(grad, prec)) { // do a negative line search - can use current gradient calculator //Numerical2PGradientCalculator ngc(fcn, st.Trafo(), stra); state = ng2ls(fcn, state, gc, prec); } // compute Hessian above will not have posdef check as it is done if we call MnHesse if (stra.Strategy() == 2 && !st.HasCovariance() && !computedHessian) { // can calculate full 2nd derivative MinimumState tmpState = MnHesse(stra)(fcn, state, st.Trafo()); print.Info("Compute full Hessian: Initial seeding state is ",tmpState); return MinimumSeed(tmpState, st.Trafo()); } print.Info("Initial seeding state ",state); return MinimumSeed(state, st.Trafo()); } #if 0 bool CheckGradient(MinimumState & st, MnUserTransformation & trafo, MnStrategy & stra) { const MinimumParameters & pa = st.Parameters(); const FunctionGradient & grd = st.FunctionGradient(); // I think one should use Numerical2PGradientCalculator // since step sizes and G2 of initial gradient are wrong InitialGradientCalculator igc(fcn, trafo, stra); FunctionGradient tmp = igc(pa); // should also use G2 from grd (in case Analyticalgradient can compute Hessian ?) FunctionGradient dgrad(grd.Grad(), tmp.G2(), tmp.Gstep()); // do check computing gradient with HessianGradientCalculator which refines the gradient given an initial one bool good = true; HessianGradientCalculator hgc(fcn, trafo, MnStrategy(2)); std::pair hgrd = hgc.DeltaGradient(pa, dgrad); for (unsigned int i = 0; i < n; i++) { if (std::fabs(hgrd.first.Grad()(i) - grd.Grad()(i)) > hgrd.second(i)) { int externalParameterIndex = trafo.ExtOfInt(i); const char *parameter_name = trafo.Name(externalParameterIndex); print.Warn("Gradient discrepancy of external Parameter too large:" "parameter_name =", parameter_name, "externalParameterIndex =", externalParameterIndex, "internal =", i); good = false; } } if (!good) { print.Error("Minuit does not accept user specified Gradient. To force acceptance, override 'virtual bool " "CheckGradient() const' of FCNGradientBase.h in the derived class."); assert(good); } return good } #endif } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnStrategy.cxx0000644000000000000000000000463314332717401020431 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnStrategy.h" namespace ROOT { namespace Minuit2 { MnStrategy::MnStrategy() : fHessCFDG2(0), fHessForcePosDef(1), fStoreLevel(1) { // default strategy SetMediumStrategy(); } MnStrategy::MnStrategy(unsigned int stra) : fHessCFDG2(0), fHessForcePosDef(1), fStoreLevel(1) { // user defined strategy (0, 1, 2, >=3) if (stra == 0) SetLowStrategy(); else if (stra == 1) SetMediumStrategy(); else if (stra == 2) SetHighStrategy(); else SetVeryHighStrategy(); } void MnStrategy::SetLowStrategy() { // set low strategy (0) values fStrategy = 0; SetGradientNCycles(2); SetGradientStepTolerance(0.5); SetGradientTolerance(0.1); SetHessianNCycles(3); SetHessianStepTolerance(0.5); SetHessianG2Tolerance(0.1); SetHessianGradientNCycles(1); SetHessianCentralFDMixedDerivatives(0); } void MnStrategy::SetMediumStrategy() { // set minimum strategy (1) the default fStrategy = 1; SetGradientNCycles(3); SetGradientStepTolerance(0.3); SetGradientTolerance(0.05); SetHessianNCycles(5); SetHessianStepTolerance(0.3); SetHessianG2Tolerance(0.05); SetHessianGradientNCycles(2); SetHessianCentralFDMixedDerivatives(0); } void MnStrategy::SetHighStrategy() { // set high strategy (2) fStrategy = 2; SetGradientNCycles(5); SetGradientStepTolerance(0.1); SetGradientTolerance(0.02); SetHessianNCycles(7); SetHessianStepTolerance(0.1); SetHessianG2Tolerance(0.02); SetHessianGradientNCycles(6); SetHessianCentralFDMixedDerivatives(0); } void MnStrategy::SetVeryHighStrategy() { // set very high strategy (3) fStrategy = 3; SetGradientNCycles(5); SetGradientStepTolerance(0.1); SetGradientTolerance(0.02); SetHessianNCycles(7); SetHessianStepTolerance(0.); SetHessianG2Tolerance(0.); SetHessianGradientNCycles(6); SetHessianCentralFDMixedDerivatives(1); SetHessianForcePosDef(0); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnTiny.cxx0000644000000000000000000000141414332717401017544 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnTiny.h" namespace ROOT { namespace Minuit2 { double MnTiny::One() const { return fOne; } double MnTiny::operator()(double epsp1) const { // evaluate minimal difference between two floating points double result = epsp1 - One(); return result; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnTraceObject.cxx0000644000000000000000000000332114332717401021005 0ustar00// @(#)root/minuit2:$Id$ // Author: L. Moneta 2012 /********************************************************************** * * * Copyright (c) 2012 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnTraceObject.h" #include "Minuit2/MnPrint.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MinimumState.h" #include namespace ROOT { namespace Minuit2 { void MnTraceObject::operator()(int iter, const MinimumState &state) { MnPrint print("MnTraceObject"); print.Debug(MnPrint::Oneline(state, iter)); if (!fUserState) return; print.Debug([&](std::ostream &os) { // print also parameters and derivatives os << "\n\t" << std::setw(12) << " " << " " << std::setw(12) << " ext value " << " " << std::setw(12) << " int value " << " " << std::setw(12) << " gradient "; int firstPar = 0; int lastPar = state.Vec().size(); if (fParNumber >= 0 && fParNumber < lastPar) { firstPar = fParNumber; lastPar = fParNumber + 1; } for (int ipar = firstPar; ipar < lastPar; ++ipar) { int epar = fUserState->Trafo().ExtOfInt(ipar); double eval = fUserState->Trafo().Int2ext(ipar, state.Vec()(ipar)); os << "\n\t" << std::setw(12) << fUserState->Name(epar) << " " << std::setw(12) << eval << " " << std::setw(12) << state.Vec()(ipar) << " " << std::setw(12) << state.Gradient().Vec()(ipar); } }); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnUserFcn.cxx0000644000000000000000000000322114332717401020164 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnUserFcn.h" #include "Minuit2/FCNBase.h" #include "Minuit2/MnUserTransformation.h" namespace ROOT { namespace Minuit2 { double MnUserFcn::operator()(const MnAlgebraicVector &v) const { // call Fcn function transforming from a MnAlgebraicVector of internal values to a std::vector of external ones fNumCall++; // calling fTransform() like here was not thread safe because it was using a cached vector // return Fcn()( fTransform(v) ); // make a new thread-safe implementation creating a vector each time // a bit slower few% in stressFit and 10% in Rosenbrock function but it is negligible in big fits // get first initial values of parameter (in case some one is fixed) std::vector vpar(fTransform.InitialParValues().begin(), fTransform.InitialParValues().end()); const std::vector ¶meters = fTransform.Parameters(); unsigned int n = v.size(); for (unsigned int i = 0; i < n; i++) { int ext = fTransform.ExtOfInt(i); if (parameters[ext].HasLimits()) { vpar[ext] = fTransform.Int2ext(i, v(i)); } else { vpar[ext] = v(i); } } return Fcn()(vpar); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnUserParameterState.cxx0000644000000000000000000004354214332717401022411 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnCovarianceSqueeze.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { // // construct from user parameters (before minimization) // MnUserParameterState::MnUserParameterState(const std::vector &par, const std::vector &err) : fValid(true), fCovarianceValid(false), fGCCValid(false), fCovStatus(-1), fFVal(0.), fEDM(0.), fNFcn(0), fParameters(MnUserParameters(par, err)), fCovariance(MnUserCovariance()), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(par), fIntCovariance(MnUserCovariance()) { } MnUserParameterState::MnUserParameterState(const MnUserParameters &par) : fValid(true), fCovarianceValid(false), fGCCValid(false), fCovStatus(-1), fFVal(0.), fEDM(0.), fNFcn(0), fParameters(par), fCovariance(MnUserCovariance()), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(std::vector()), fIntCovariance(MnUserCovariance()) { // construct from user parameters (before minimization) for (std::vector::const_iterator ipar = MinuitParameters().begin(); ipar != MinuitParameters().end(); ++ipar) { if ((*ipar).IsConst() || (*ipar).IsFixed()) continue; if ((*ipar).HasLimits()) fIntParameters.push_back(Ext2int((*ipar).Number(), (*ipar).Value())); else fIntParameters.push_back((*ipar).Value()); } } // // construct from user parameters + errors (before minimization) // MnUserParameterState::MnUserParameterState(const std::vector &par, const std::vector &cov, unsigned int nrow) : fValid(true), fCovarianceValid(true), fGCCValid(false), fCovStatus(-1), fFVal(0.), fEDM(0.), fNFcn(0), fParameters(MnUserParameters()), fCovariance(MnUserCovariance(cov, nrow)), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(par), fIntCovariance(MnUserCovariance(cov, nrow)) { // construct from user parameters + errors (before minimization) using std::vector for parameter error and // an // std::vector of size n*(n+1)/2 for the covariance matrix and n (rank of cov matrix) std::vector err; err.reserve(par.size()); for (unsigned int i = 0; i < par.size(); i++) { assert(fCovariance(i, i) > 0.); err.push_back(std::sqrt(fCovariance(i, i))); } fParameters = MnUserParameters(par, err); assert(fCovariance.Nrow() == VariableParameters()); } MnUserParameterState::MnUserParameterState(const std::vector &par, const MnUserCovariance &cov) : fValid(true), fCovarianceValid(true), fGCCValid(false), fCovStatus(-1), fFVal(0.), fEDM(0.), fNFcn(0), fParameters(MnUserParameters()), fCovariance(cov), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(par), fIntCovariance(cov) { // construct from user parameters + errors (before minimization) using std::vector (params) and MnUserCovariance // class std::vector err; err.reserve(par.size()); for (unsigned int i = 0; i < par.size(); i++) { assert(fCovariance(i, i) > 0.); err.push_back(std::sqrt(fCovariance(i, i))); } fParameters = MnUserParameters(par, err); assert(fCovariance.Nrow() == VariableParameters()); } MnUserParameterState::MnUserParameterState(const MnUserParameters &par, const MnUserCovariance &cov) : fValid(true), fCovarianceValid(true), fGCCValid(false), fCovStatus(-1), fFVal(0.), fEDM(0.), fNFcn(0), fParameters(par), fCovariance(cov), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(std::vector()), fIntCovariance(cov) { // construct from user parameters + errors (before minimization) using // MnUserParameters and MnUserCovariance objects fIntCovariance.Scale(0.5); for (std::vector::const_iterator ipar = MinuitParameters().begin(); ipar != MinuitParameters().end(); ++ipar) { if ((*ipar).IsConst() || (*ipar).IsFixed()) continue; if ((*ipar).HasLimits()) fIntParameters.push_back(Ext2int((*ipar).Number(), (*ipar).Value())); else fIntParameters.push_back((*ipar).Value()); } assert(fCovariance.Nrow() == VariableParameters()); // // need to Fix that in case of limited parameters // fIntCovariance = MnUserCovariance(); // } // // MnUserParameterState::MnUserParameterState(const MinimumState &st, double up, const MnUserTransformation &trafo) : fValid(st.IsValid()), fCovarianceValid(false), fGCCValid(false), fCovStatus(-1), fFVal(st.Fval()), fEDM(st.Edm()), fNFcn(st.NFcn()), fParameters(MnUserParameters()), fCovariance(MnUserCovariance()), fGlobalCC(MnGlobalCorrelationCoeff()), fIntParameters(std::vector()), fIntCovariance(MnUserCovariance()) { // // construct from internal parameters (after minimization) // // std::cout << "build a MnUserParameterState after minimization.." << std::endl; for (std::vector::const_iterator ipar = trafo.Parameters().begin(); ipar != trafo.Parameters().end(); ++ipar) { if ((*ipar).IsConst()) { Add((*ipar).GetName(), (*ipar).Value()); } else if ((*ipar).IsFixed()) { Add((*ipar).GetName(), (*ipar).Value(), (*ipar).Error()); if ((*ipar).HasLimits()) { if ((*ipar).HasLowerLimit() && (*ipar).HasUpperLimit()) SetLimits((*ipar).GetName(), (*ipar).LowerLimit(), (*ipar).UpperLimit()); else if ((*ipar).HasLowerLimit() && !(*ipar).HasUpperLimit()) SetLowerLimit((*ipar).GetName(), (*ipar).LowerLimit()); else SetUpperLimit((*ipar).GetName(), (*ipar).UpperLimit()); } Fix((*ipar).GetName()); } else if ((*ipar).HasLimits()) { unsigned int i = trafo.IntOfExt((*ipar).Number()); double err = st.Error().IsValid() ? std::sqrt(2. * up * st.Error().InvHessian()(i, i)) : st.Parameters().Dirin()(i); Add((*ipar).GetName(), trafo.Int2ext(i, st.Vec()(i)), trafo.Int2extError(i, st.Vec()(i), err)); if ((*ipar).HasLowerLimit() && (*ipar).HasUpperLimit()) SetLimits((*ipar).GetName(), (*ipar).LowerLimit(), (*ipar).UpperLimit()); else if ((*ipar).HasLowerLimit() && !(*ipar).HasUpperLimit()) SetLowerLimit((*ipar).GetName(), (*ipar).LowerLimit()); else SetUpperLimit((*ipar).GetName(), (*ipar).UpperLimit()); } else { unsigned int i = trafo.IntOfExt((*ipar).Number()); double err = st.Error().IsValid() ? std::sqrt(2. * up * st.Error().InvHessian()(i, i)) : st.Parameters().Dirin()(i); Add((*ipar).GetName(), st.Vec()(i), err); } } // need to be set afterwards because becore the ::Add method set fCovarianceValid to false fCovarianceValid = st.Error().IsValid(); fCovStatus = -1; // when not available // if (st.Error().HesseFailed() || st.Error().InvertFailed() ) fCovStatus = -1; // when available if (st.Error().IsAvailable()) fCovStatus = 0; if (fCovarianceValid) { fCovariance = trafo.Int2extCovariance(st.Vec(), st.Error().InvHessian()); fIntCovariance = MnUserCovariance(std::vector(st.Error().InvHessian().Data(), st.Error().InvHessian().Data() + st.Error().InvHessian().size()), st.Error().InvHessian().Nrow()); fCovariance.Scale(2. * up); fGlobalCC = MnGlobalCorrelationCoeff(st.Error().InvHessian()); fGCCValid = fGlobalCC.IsValid(); assert(fCovariance.Nrow() == VariableParameters()); if (!st.Error().IsNotPosDef()) fCovStatus = 1; // when is valid and not NotPosDef } if (st.Error().IsMadePosDef()) fCovStatus = 2; if (st.Error().IsAccurate()) fCovStatus = 3; } MnUserCovariance MnUserParameterState::Hessian() const { // invert covariance matrix and return Hessian // need to copy in a MnSymMatrix MnPrint print("MnUserParameterState::Hessian"); MnAlgebraicSymMatrix mat(fCovariance.Nrow()); std::copy(fCovariance.Data().begin(), fCovariance.Data().end(), mat.Data()); int ifail = Invert(mat); if (ifail != 0) { print.Warn("Inversion failed; return diagonal matrix"); MnUserCovariance tmp(fCovariance.Nrow()); for (unsigned int i = 0; i < fCovariance.Nrow(); i++) { tmp(i, i) = 1. / fCovariance(i, i); } return tmp; } MnUserCovariance hessian(mat.Data(), fCovariance.Nrow()); return hessian; } // facade: forward interface of MnUserParameters and MnUserTransformation // via MnUserParameterState const std::vector &MnUserParameterState::MinuitParameters() const { // access to parameters (row-wise) return fParameters.Parameters(); } std::vector MnUserParameterState::Params() const { // access to parameters in column-wise representation return fParameters.Params(); } std::vector MnUserParameterState::Errors() const { // access to errors in column-wise representation return fParameters.Errors(); } const MinuitParameter &MnUserParameterState::Parameter(unsigned int i) const { // access to single Parameter i return fParameters.Parameter(i); } void MnUserParameterState::Add(const std::string &name, double val, double err) { MnPrint print("MnUserParameterState::Add"); // add free Parameter if (fParameters.Add(name, val, err)) { fIntParameters.push_back(val); fCovarianceValid = false; fGCCValid = false; fValid = true; } else { // redefine an existing parameter int i = Index(name); SetValue(i, val); if (Parameter(i).IsConst()) { print.Warn("Cannot modify status of constant parameter", name); return; } SetError(i, err); // release if it was fixed if (Parameter(i).IsFixed()) Release(i); } } void MnUserParameterState::Add(const std::string &name, double val, double err, double low, double up) { MnPrint print("MnUserParameterState::Add"); // add limited Parameter if (fParameters.Add(name, val, err, low, up)) { fCovarianceValid = false; fIntParameters.push_back(Ext2int(Index(name), val)); fGCCValid = false; fValid = true; } else { // Parameter already exist - just set values int i = Index(name); SetValue(i, val); if (Parameter(i).IsConst()) { print.Warn("Cannot modify status of constant parameter", name); return; } SetError(i, err); SetLimits(i, low, up); // release if it was fixed if (Parameter(i).IsFixed()) Release(i); } } void MnUserParameterState::Add(const std::string &name, double val) { // add const Parameter if (fParameters.Add(name, val)) fValid = true; else SetValue(name, val); } // interaction via external number of Parameter void MnUserParameterState::Fix(unsigned int e) { // fix parameter e (external index) if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) { unsigned int i = IntOfExt(e); if (fCovarianceValid) { // when covariance is valid remove fixed parameter row/column in covariance matrix // use squeeze to remove first from Hessian and obtain then new covariance fCovariance = MnCovarianceSqueeze()(fCovariance, i); fIntCovariance = MnCovarianceSqueeze()(fIntCovariance, i); } fIntParameters.erase(fIntParameters.begin() + i, fIntParameters.begin() + i + 1); } fParameters.Fix(e); fGCCValid = false; } void MnUserParameterState::Release(unsigned int e) { // release parameter e (external index) // no-op if parameter is const or if it is not fixed if (Parameter(e).IsConst() || !Parameter(e).IsFixed()) return; fParameters.Release(e); fCovarianceValid = false; fGCCValid = false; unsigned int i = IntOfExt(e); if (Parameter(e).HasLimits()) fIntParameters.insert(fIntParameters.begin() + i, Ext2int(e, Parameter(e).Value())); else fIntParameters.insert(fIntParameters.begin() + i, Parameter(e).Value()); } void MnUserParameterState::SetValue(unsigned int e, double val) { // set value for parameter e ( external index ) fParameters.SetValue(e, val); if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) { unsigned int i = IntOfExt(e); if (Parameter(e).HasLimits()) fIntParameters[i] = Ext2int(e, val); else fIntParameters[i] = val; } } void MnUserParameterState::SetError(unsigned int e, double val) { // set error for parameter e (external index) fParameters.SetError(e, val); } void MnUserParameterState::SetLimits(unsigned int e, double low, double up) { // set limits for parameter e (external index) fParameters.SetLimits(e, low, up); fCovarianceValid = false; fGCCValid = false; if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) { unsigned int i = IntOfExt(e); if (low < fIntParameters[i] && fIntParameters[i] < up) fIntParameters[i] = Ext2int(e, fIntParameters[i]); else if (low >= fIntParameters[i]) fIntParameters[i] = Ext2int(e, low + 0.1 * Parameter(e).Error()); else fIntParameters[i] = Ext2int(e, up - 0.1 * Parameter(e).Error()); } } void MnUserParameterState::SetUpperLimit(unsigned int e, double up) { // set upper limit for parameter e (external index) fParameters.SetUpperLimit(e, up); fCovarianceValid = false; fGCCValid = false; if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) { unsigned int i = IntOfExt(e); if (fIntParameters[i] < up) fIntParameters[i] = Ext2int(e, fIntParameters[i]); else fIntParameters[i] = Ext2int(e, up - 0.1 * Parameter(e).Error()); } } void MnUserParameterState::SetLowerLimit(unsigned int e, double low) { // set lower limit for parameter e (external index) fParameters.SetLowerLimit(e, low); fCovarianceValid = false; fGCCValid = false; if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) { unsigned int i = IntOfExt(e); if (low < fIntParameters[i]) fIntParameters[i] = Ext2int(e, fIntParameters[i]); else fIntParameters[i] = Ext2int(e, low + 0.1 * Parameter(e).Error()); } } void MnUserParameterState::RemoveLimits(unsigned int e) { // remove limit for parameter e (external index) fParameters.RemoveLimits(e); fCovarianceValid = false; fGCCValid = false; if (!Parameter(e).IsFixed() && !Parameter(e).IsConst()) fIntParameters[IntOfExt(e)] = Value(e); } double MnUserParameterState::Value(unsigned int i) const { // get value for parameter e (external index) return fParameters.Value(i); } double MnUserParameterState::Error(unsigned int i) const { // get error for parameter e (external index) return fParameters.Error(i); } // interaction via name of Parameter void MnUserParameterState::Fix(const std::string &name) { Fix(Index(name)); } void MnUserParameterState::Release(const std::string &name) { Release(Index(name)); } void MnUserParameterState::SetValue(const std::string &name, double val) { SetValue(Index(name), val); } void MnUserParameterState::SetError(const std::string &name, double val) { SetError(Index(name), val); } void MnUserParameterState::SetLimits(const std::string &name, double low, double up) { SetLimits(Index(name), low, up); } void MnUserParameterState::SetUpperLimit(const std::string &name, double up) { SetUpperLimit(Index(name), up); } void MnUserParameterState::SetLowerLimit(const std::string &name, double low) { SetLowerLimit(Index(name), low); } void MnUserParameterState::RemoveLimits(const std::string &name) { RemoveLimits(Index(name)); } double MnUserParameterState::Value(const std::string &name) const { return Value(Index(name)); } double MnUserParameterState::Error(const std::string &name) const { return Error(Index(name)); } unsigned int MnUserParameterState::Index(const std::string &name) const { // convert name into external number of Parameter return fParameters.Index(name); } const char *MnUserParameterState::Name(unsigned int i) const { // convert external number into name of Parameter (API returning a const char *) return fParameters.Name(i); } const std::string &MnUserParameterState::GetName(unsigned int i) const { // convert external number into name of Parameter (new interface returning a string) return fParameters.GetName(i); } // transformation internal <-> external (forward to transformation class) double MnUserParameterState::Int2ext(unsigned int i, double val) const { // internal to external value return fParameters.Trafo().Int2ext(i, val); } double MnUserParameterState::Ext2int(unsigned int e, double val) const { // external to internal value return fParameters.Trafo().Ext2int(e, val); } unsigned int MnUserParameterState::IntOfExt(unsigned int ext) const { // return internal index for external index ext return fParameters.Trafo().IntOfExt(ext); } unsigned int MnUserParameterState::ExtOfInt(unsigned int internal) const { // return external index for internal index internal return fParameters.Trafo().ExtOfInt(internal); } unsigned int MnUserParameterState::VariableParameters() const { // return number of variable parameters return fParameters.Trafo().VariableParameters(); } const MnMachinePrecision &MnUserParameterState::Precision() const { // return global parameter precision return fParameters.Precision(); } void MnUserParameterState::SetPrecision(double eps) { // set global parameter precision fParameters.SetPrecision(eps); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnUserParameters.cxx0000644000000000000000000001271014332717401021564 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnUserParameters.h" namespace ROOT { namespace Minuit2 { MnUserParameters::MnUserParameters(const std::vector &par, const std::vector &err) : fTransformation(par, err) { } // all implemented forwarding to MnUserTransformation class const std::vector &MnUserParameters::Parameters() const { // return vector of MinuitParameter objects return fTransformation.Parameters(); } std::vector MnUserParameters::Params() const { // return std::vector of double with parameter values return fTransformation.Params(); } std::vector MnUserParameters::Errors() const { // return std::vector of double with parameter errors return fTransformation.Errors(); } const MinuitParameter &MnUserParameters::Parameter(unsigned int n) const { // return the MinuitParameter object for index n (external) return fTransformation.Parameter(n); } bool MnUserParameters::Add(const std::string &name, double val, double err) { // add a new unlimited parameter giving name, value and err (step size) // return false if parameter already exists return fTransformation.Add(name, val, err); } bool MnUserParameters::Add(const std::string &name, double val, double err, double low, double up) { // add a new limited parameter giving name, value, err (step size) and lower/upper limits // return false if parameter already exists return fTransformation.Add(name, val, err, low, up); } bool MnUserParameters::Add(const std::string &name, double val) { // add a new unlimited parameter giving name and value // return false if parameter already exists return fTransformation.Add(name, val); } void MnUserParameters::Fix(unsigned int n) { // fix parameter n fTransformation.Fix(n); } void MnUserParameters::Release(unsigned int n) { // release parameter n fTransformation.Release(n); } void MnUserParameters::RemoveLimits(unsigned int n) { // remove limits for parameter n fTransformation.RemoveLimits(n); } void MnUserParameters::SetValue(unsigned int n, double val) { // set value for parameter n fTransformation.SetValue(n, val); } void MnUserParameters::SetError(unsigned int n, double err) { // set error for parameter n fTransformation.SetError(n, err); } void MnUserParameters::SetLimits(unsigned int n, double low, double up) { // set limits (lower/upper) for parameter n fTransformation.SetLimits(n, low, up); } void MnUserParameters::SetUpperLimit(unsigned int n, double up) { // set upper limit for parameter n fTransformation.SetUpperLimit(n, up); } void MnUserParameters::SetLowerLimit(unsigned int n, double low) { // set lower limit for parameter n fTransformation.SetLowerLimit(n, low); } void MnUserParameters::SetName(unsigned int n, const std::string &name) { // set name for parameter n fTransformation.SetName(n, name); } double MnUserParameters::Value(unsigned int n) const { // get value for parameter n return fTransformation.Value(n); } double MnUserParameters::Error(unsigned int n) const { // get error for parameter n return fTransformation.Error(n); } // interface using parameter name void MnUserParameters::Fix(const std::string &name) { // fix parameter Fix(Index(name)); } void MnUserParameters::Release(const std::string &name) { // release parameter Release(Index(name)); } void MnUserParameters::SetValue(const std::string &name, double val) { // set value for parameter SetValue(Index(name), val); } void MnUserParameters::SetError(const std::string &name, double err) { // set error SetError(Index(name), err); } void MnUserParameters::SetLimits(const std::string &name, double low, double up) { // set lower/upper limits SetLimits(Index(name), low, up); } void MnUserParameters::SetUpperLimit(const std::string &name, double up) { // set upper limit fTransformation.SetUpperLimit(Index(name), up); } void MnUserParameters::SetLowerLimit(const std::string &name, double low) { // set lower limit fTransformation.SetLowerLimit(Index(name), low); } void MnUserParameters::RemoveLimits(const std::string &name) { // remove limits RemoveLimits(Index(name)); } double MnUserParameters::Value(const std::string &name) const { // get parameter value return Value(Index(name)); } double MnUserParameters::Error(const std::string &name) const { // get parameter error return Error(Index(name)); } unsigned int MnUserParameters::Index(const std::string &name) const { // get index (external) corresponding to name return fTransformation.Index(name); } const std::string &MnUserParameters::GetName(unsigned int n) const { // get name corresponding to index (external) return fTransformation.GetName(n); } const char *MnUserParameters::Name(unsigned int n) const { // get name corresponding to index (external) return fTransformation.Name(n); } const MnMachinePrecision &MnUserParameters::Precision() const { // get global parameter precision return fTransformation.Precision(); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/MnUserTransformation.cxx0000644000000000000000000004161314332717401022473 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnUserCovariance.h" #include "Minuit2/MnMatrix.h" #include #include #include #include namespace ROOT { namespace Minuit2 { class MnParStr { public: MnParStr(const std::string &name) : fName(name) {} ~MnParStr() {} bool operator()(const MinuitParameter &par) const { // return (strcmp(par.Name(), fName) == 0); return par.GetName() == fName; } private: const std::string &fName; }; MnUserTransformation::MnUserTransformation(const std::vector &par, const std::vector &err) : fPrecision(MnMachinePrecision()), fParameters(std::vector()), fExtOfInt(std::vector()), fDoubleLimTrafo(SinParameterTransformation()), fUpperLimTrafo(SqrtUpParameterTransformation()), fLowerLimTrafo(SqrtLowParameterTransformation()), fCache(std::vector()) { // constructor from a vector of parameter values and a vector of errors (step sizes) // class has as data member the transformation objects (all of the types), // the std::vector of MinuitParameter objects and the vector with the index conversions from // internal to external (fExtOfInt) fParameters.reserve(par.size()); fExtOfInt.reserve(par.size()); fCache.reserve(par.size()); std::string parName; for (unsigned int i = 0; i < par.size(); i++) { std::ostringstream buf; buf << "p" << i; parName = buf.str(); Add(parName, par[i], err[i]); } } //#ifdef MINUIT2_THREAD_SAFE // this if a thread-safe implementation needed if want to share transformation object between the threads std::vector MnUserTransformation::operator()(const MnAlgebraicVector &pstates) const { // transform an internal Minuit vector of internal values in a std::vector of external values // fixed parameters will have their fixed values unsigned int n = pstates.size(); // need to initialize to the stored (initial values) parameter values for the fixed ones std::vector pcache(fCache); for (unsigned int i = 0; i < n; i++) { if (fParameters[fExtOfInt[i]].HasLimits()) { pcache[fExtOfInt[i]] = Int2ext(i, pstates(i)); } else { pcache[fExtOfInt[i]] = pstates(i); } } return pcache; } // #else // const std::vector & MnUserTransformation::operator()(const MnAlgebraicVector& pstates) const { // // transform an internal Minuit vector of internal values in a std::vector of external values // // std::vector Cache(pstates.size() ); // for(unsigned int i = 0; i < pstates.size(); i++) { // if(fParameters[fExtOfInt[i]].HasLimits()) { // fCache[fExtOfInt[i]] = Int2ext(i, pstates(i)); // } else { // fCache[fExtOfInt[i]] = pstates(i); // } // } // return fCache; // } // #endif double MnUserTransformation::Int2ext(unsigned int i, double val) const { // return external value from internal value for parameter i if (fParameters[fExtOfInt[i]].HasLimits()) { if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) return fDoubleLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit()); else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit()) return fUpperLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit()); else return fLowerLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].LowerLimit()); } return val; } double MnUserTransformation::Int2extError(unsigned int i, double val, double err) const { // return external error from internal error for parameter i // err = sigma Value == std::sqrt(cov(i,i)) double dx = err; if (fParameters[fExtOfInt[i]].HasLimits()) { double ui = Int2ext(i, val); double du1 = Int2ext(i, val + dx) - ui; double du2 = Int2ext(i, val - dx) - ui; if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) { // double al = fParameters[fExtOfInt[i]].Lower(); // double ba = fParameters[fExtOfInt[i]].Upper() - al; // double du1 = al + 0.5*(sin(val + dx) + 1.)*ba - ui; // double du2 = al + 0.5*(sin(val - dx) + 1.)*ba - ui; // if(dx > 1.) du1 = ba; if (dx > 1.) du1 = fParameters[fExtOfInt[i]].UpperLimit() - fParameters[fExtOfInt[i]].LowerLimit(); dx = 0.5 * (std::fabs(du1) + std::fabs(du2)); } else { dx = 0.5 * (std::fabs(du1) + std::fabs(du2)); } } return dx; } MnUserCovariance MnUserTransformation::Int2extCovariance(const MnAlgebraicVector &vec, const MnAlgebraicSymMatrix &cov) const { // return the external covariance matrix from the internal error matrix and the internal parameter value // the vector of internal parameter is needed for the derivatives (Jacobian of the transformation) // Vext(i,j) = Vint(i,j) * dPext(i)/dPint(i) * dPext(j)/dPint(j) MnUserCovariance result(cov.Nrow()); for (unsigned int i = 0; i < vec.size(); i++) { double dxdi = 1.; if (fParameters[fExtOfInt[i]].HasLimits()) { // dxdi = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() - // fParameters[fExtOfInt[i]].Lower())*cos(vec(i))); dxdi = DInt2Ext(i, vec(i)); } for (unsigned int j = i; j < vec.size(); j++) { double dxdj = 1.; if (fParameters[fExtOfInt[j]].HasLimits()) { // dxdj = 0.5*std::fabs((fParameters[fExtOfInt[j]].Upper() - // fParameters[fExtOfInt[j]].Lower())*cos(vec(j))); dxdj = DInt2Ext(j, vec(j)); } result(i, j) = dxdi * cov(i, j) * dxdj; } // double diag = Int2extError(i, vec(i), std::sqrt(cov(i,i))); // result(i,i) = diag*diag; } return result; } double MnUserTransformation::Ext2int(unsigned int i, double val) const { // return the internal value for parameter i with external value val if (fParameters[i].HasLimits()) { if (fParameters[i].HasUpperLimit() && fParameters[i].HasLowerLimit()) return fDoubleLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), fParameters[i].LowerLimit(), Precision()); else if (fParameters[i].HasUpperLimit() && !fParameters[i].HasLowerLimit()) return fUpperLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), Precision()); else return fLowerLimTrafo.Ext2int(val, fParameters[i].LowerLimit(), Precision()); } return val; } double MnUserTransformation::DInt2Ext(unsigned int i, double val) const { // return the derivative of the int->ext transformation: dPext(i) / dPint(i) // for the parameter i with value val double dd = 1.; if (fParameters[fExtOfInt[i]].HasLimits()) { if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() - // fParameters[fExtOfInt[i]].Lower())*cos(vec(i))); dd = fDoubleLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit()); else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit()) dd = fUpperLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit()); else dd = fLowerLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].LowerLimit()); } return dd; } /* double MnUserTransformation::dExt2Int(unsigned int, double) const { double dd = 1.; if(fParameters[fExtOfInt[i]].HasLimits()) { if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() - fParameters[fExtOfInt[i]].Lower())*cos(vec(i))); dd = fDoubleLimTrafo.dExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit()); else if(fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit()) dd = fUpperLimTrafo.dExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit()); else dd = fLowerLimTrafo.dExtInt(val, fParameters[fExtOfInt[i]].LowerLimit()); } return dd; } */ unsigned int MnUserTransformation::IntOfExt(unsigned int ext) const { // return internal index given external one ext assert(ext < fParameters.size()); assert(!fParameters[ext].IsFixed()); assert(!fParameters[ext].IsConst()); std::vector::const_iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), ext); assert(iind != fExtOfInt.end()); return (iind - fExtOfInt.begin()); } std::vector MnUserTransformation::Params() const { // return std::vector of double with parameter values unsigned int n = fParameters.size(); std::vector result(n); for (unsigned int i = 0; i < n; ++i) result[i] = fParameters[i].Value(); return result; } std::vector MnUserTransformation::Errors() const { // return std::vector of double with parameter errors std::vector result; result.reserve(fParameters.size()); for (std::vector::const_iterator ipar = Parameters().begin(); ipar != Parameters().end(); ++ipar) result.push_back((*ipar).Error()); return result; } const MinuitParameter &MnUserTransformation::Parameter(unsigned int n) const { // return the MinuitParameter object for index n (external) assert(n < fParameters.size()); return fParameters[n]; } // bool MnUserTransformation::Remove(const std::string & name) { // // remove parameter with name // // useful if want to re-define a parameter // // return false if parameter does not exist // std::vector::iterator itr = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name) // ); if (itr == fParameters.end() ) return false; int n = itr - fParameters.begin(); if (n < 0 || n >= // fParameters.size() ) return false; fParameters.erase(itr); fCache.erase( fExtOfInt.begin() + n); // std::vector::iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n); // if (iind != fExtOfInt.end()) fExtOfInt.erase(iind); // } bool MnUserTransformation::Add(const std::string &name, double val, double err) { // add a new unlimited parameter giving name, value and err (step size) // return false if parameter already exists if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end()) return false; fExtOfInt.push_back(fParameters.size()); fCache.push_back(val); fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err)); return true; } bool MnUserTransformation::Add(const std::string &name, double val, double err, double low, double up) { // add a new limited parameter giving name, value, err (step size) and lower/upper limits // return false if parameter already exists if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end()) return false; fExtOfInt.push_back(fParameters.size()); fCache.push_back(val); fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err, low, up)); return true; } bool MnUserTransformation::Add(const std::string &name, double val) { // add a new constant parameter giving name and value // return false if parameter already exists if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end()) return false; fCache.push_back(val); // constant parameter - do not add in list of internals (fExtOfInt) fParameters.push_back(MinuitParameter(fParameters.size(), name, val)); return true; } void MnUserTransformation::Fix(unsigned int n) { // fix parameter n (external index) assert(n < fParameters.size()); std::vector::iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n); if (iind != fExtOfInt.end()) fExtOfInt.erase(iind, iind + 1); fParameters[n].Fix(); } void MnUserTransformation::Release(unsigned int n) { // release parameter n (external index) assert(n < fParameters.size()); std::vector::const_iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n); if (iind == fExtOfInt.end()) { fExtOfInt.push_back(n); std::sort(fExtOfInt.begin(), fExtOfInt.end()); } fParameters[n].Release(); } void MnUserTransformation::SetValue(unsigned int n, double val) { // set value for parameter n (external index) assert(n < fParameters.size()); fParameters[n].SetValue(val); fCache[n] = val; } void MnUserTransformation::SetError(unsigned int n, double err) { // set error for parameter n (external index) assert(n < fParameters.size()); fParameters[n].SetError(err); } void MnUserTransformation::SetLimits(unsigned int n, double low, double up) { // set limits (lower/upper) for parameter n (external index) assert(n < fParameters.size()); assert(low != up); fParameters[n].SetLimits(low, up); } void MnUserTransformation::SetUpperLimit(unsigned int n, double up) { // set upper limit for parameter n (external index) assert(n < fParameters.size()); fParameters[n].SetUpperLimit(up); } void MnUserTransformation::SetLowerLimit(unsigned int n, double lo) { // set lower limit for parameter n (external index) assert(n < fParameters.size()); fParameters[n].SetLowerLimit(lo); } void MnUserTransformation::RemoveLimits(unsigned int n) { // remove limits for parameter n (external index) assert(n < fParameters.size()); fParameters[n].RemoveLimits(); } void MnUserTransformation::SetName(unsigned int n, const std::string &name) { // set name for parameter n (external index) assert(n < fParameters.size()); fParameters[n].SetName(name); } double MnUserTransformation::Value(unsigned int n) const { // get value for parameter n (external index) assert(n < fParameters.size()); return fParameters[n].Value(); } double MnUserTransformation::Error(unsigned int n) const { // get error for parameter n (external index) assert(n < fParameters.size()); return fParameters[n].Error(); } // interface by parameter name void MnUserTransformation::Fix(const std::string &name) { // fix parameter Fix(Index(name)); } void MnUserTransformation::Release(const std::string &name) { // release parameter Release(Index(name)); } void MnUserTransformation::SetValue(const std::string &name, double val) { // set value for parameter SetValue(Index(name), val); } void MnUserTransformation::SetError(const std::string &name, double err) { // set error SetError(Index(name), err); } void MnUserTransformation::SetLimits(const std::string &name, double low, double up) { // set lower/upper limits SetLimits(Index(name), low, up); } void MnUserTransformation::SetUpperLimit(const std::string &name, double up) { // set upper limit SetUpperLimit(Index(name), up); } void MnUserTransformation::SetLowerLimit(const std::string &name, double lo) { // set lower limit SetLowerLimit(Index(name), lo); } void MnUserTransformation::RemoveLimits(const std::string &name) { // remove limits RemoveLimits(Index(name)); } double MnUserTransformation::Value(const std::string &name) const { // get parameter value return Value(Index(name)); } double MnUserTransformation::Error(const std::string &name) const { // get parameter error return Error(Index(name)); } unsigned int MnUserTransformation::Index(const std::string &name) const { // get index (external) corresponding to name std::vector::const_iterator ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)); assert(ipar != fParameters.end()); // return (ipar - fParameters.begin()); return (*ipar).Number(); } int MnUserTransformation::FindIndex(const std::string &name) const { // find index (external) corresponding to name - return -1 if not found std::vector::const_iterator ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)); if (ipar == fParameters.end()) return -1; return (*ipar).Number(); } const std::string &MnUserTransformation::GetName(unsigned int n) const { // get name corresponding to index (external) assert(n < fParameters.size()); return fParameters[n].GetName(); } const char *MnUserTransformation::Name(unsigned int n) const { // get name corresponding to index (external) return GetName(n).c_str(); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/ModularFunctionMinimizer.cxx0000644000000000000000000002224314332717401023326 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/ModularFunctionMinimizer.h" #include "Minuit2/MinimumSeedGenerator.h" #include "Minuit2/AnalyticalGradientCalculator.h" #include "Minuit2/ExternalInternalGradientCalculator.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/MinimumBuilder.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnUserParameters.h" #include "Minuit2/MnUserCovariance.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnUserFcn.h" #include "Minuit2/FCNBase.h" #include "Minuit2/FCNGradientBase.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnHesse.h" #include "Minuit2/MnLineSearch.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { // #include "Minuit2/MnUserParametersPrint.h" FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra, unsigned int maxfcn, double toler) const { // minimize from FCNBase and std::vector of double's for parameter values and errors (step sizes) MnUserParameterState st(par, err); MnStrategy strategy(stra); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNGradientBase &fcn, const std::vector &par, const std::vector &err, unsigned int stra, unsigned int maxfcn, double toler) const { // minimize from FCNGradientBase (use analytical gradient provided in FCN) // and std::vector of double's for parameter values and errors (step sizes) MnUserParameterState st(par, err); MnStrategy strategy(stra); return Minimize(fcn, st, strategy, maxfcn, toler); } // move nrow before cov to avoid ambiguities when using default parameters FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra, unsigned int maxfcn, double toler) const { // minimize from FCNBase using std::vector for parameter error and // an std::vector of size n*(n+1)/2 for the covariance matrix and n (rank of cov matrix) MnUserParameterState st(par, cov, nrow); MnStrategy strategy(stra); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNGradientBase &fcn, const std::vector &par, unsigned int nrow, const std::vector &cov, unsigned int stra, unsigned int maxfcn, double toler) const { // minimize from FCNGradientBase (use analytical gradient provided in FCN) // using std::vector for parameter error and // an std::vector of size n*(n+1)/2 for the covariance matrix and n (rank of cov matrix) MnUserParameterState st(par, cov, nrow); MnStrategy strategy(stra); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNBase &fcn, const MnUserParameters &upar, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from FCNBase and MnUserParameters object MnUserParameterState st(upar); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNGradientBase &fcn, const MnUserParameters &upar, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from FCNGradientBase (use analytical gradient provided in FCN) and MnUserParameters object MnUserParameterState st(upar); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNBase &fcn, const MnUserParameters &upar, const MnUserCovariance &cov, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from FCNBase and MnUserParameters and MnUserCovariance objects MnUserParameterState st(upar, cov); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNGradientBase &fcn, const MnUserParameters &upar, const MnUserCovariance &cov, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from FCNGradientBase (use analytical gradient provided in FCN) and // MnUserParameters MnUserCovariance objects MnUserParameterState st(upar, cov); return Minimize(fcn, st, strategy, maxfcn, toler); } FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNBase &fcn, const MnUserParameterState &st, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from a FCNBase and a MnUserparameterState - interface used by all the previous ones // based on FCNBase. Create in this case a NumericalGradient calculator // Create the minuit FCN wrapper (MnUserFcn) containing the transformation (int<->ext) // need MnUserFcn for difference int-ext parameters MnUserFcn mfcn(fcn, st.Trafo()); Numerical2PGradientCalculator gc(mfcn, st.Trafo(), strategy); unsigned int npar = st.VariableParameters(); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; MinimumSeed mnseeds = SeedGenerator()(mfcn, gc, st, strategy); return Minimize(mfcn, gc, mnseeds, strategy, maxfcn, toler); } // use Gradient here FunctionMinimum ModularFunctionMinimizer::Minimize(const FCNGradientBase &fcn, const MnUserParameterState &st, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // minimize from a FCNGradientBase and a MnUserParameterState - // interface based on FCNGradientBase (external/analytical gradients) // Create in this case an AnalyticalGradient calculator // Create the minuit FCN wrapper (MnUserFcn) containing the transformation (int<->ext) MnUserFcn mfcn(fcn, st.Trafo()); std::unique_ptr gc; if (fcn.gradParameterSpace() == GradientParameterSpace::Internal) { // std::cout << "-- ModularFunctionMinimizer::Minimize: Internal parameter space" << std::endl; gc = std::unique_ptr(new ExternalInternalGradientCalculator(fcn, st.Trafo())); } else { // std::cout << "-- ModularFunctionMinimizer::Minimize: External parameter space" << std::endl; gc = std::make_unique(fcn, st.Trafo()); } unsigned int npar = st.VariableParameters(); if (maxfcn == 0) maxfcn = 200 + 100 * npar + 5 * npar * npar; // compute seed (will use internally numerical gradient in case calculator does not implement g2 computations) MinimumSeed mnseeds = SeedGenerator()(mfcn, *gc, st, strategy); auto minimum = Minimize(mfcn, *gc, mnseeds, strategy, maxfcn, toler); return minimum; } FunctionMinimum ModularFunctionMinimizer::Minimize(const MnFcn &mfcn, const GradientCalculator &gc, const MinimumSeed &seed, const MnStrategy &strategy, unsigned int maxfcn, double toler) const { // Interface used by all the others for the minimization using the base MinimumBuilder class // According to the contained type of MinimumBuilder the right type will be used MnPrint print("ModularFunctionMinimizer"); const MinimumBuilder &mb = Builder(); // std::cout << typeid(&mb).Name() << std::endl; double effective_toler = toler * mfcn.Up(); // scale tolerance with Up() // avoid tolerance too smalls (than limits) double eps = MnMachinePrecision().Eps2(); if (effective_toler < eps) effective_toler = eps; // check if maxfcn is already exhausted // case already reached call limit if (mfcn.NumOfCalls() >= maxfcn) { print.Warn("Stop before iterating - call limit already exceeded"); return FunctionMinimum(seed, std::vector(1, seed.State()), mfcn.Up(), FunctionMinimum::MnReachedCallLimit); } return mb.Minimum(mfcn, gc, seed, strategy, maxfcn, effective_toler); } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/NegativeG2LineSearch.cxx0000644000000000000000000001262314332717401022223 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/NegativeG2LineSearch.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MinimumState.h" #include "Minuit2/GradientCalculator.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnLineSearch.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/MnPrint.h" #include namespace ROOT { namespace Minuit2 { MinimumState NegativeG2LineSearch::operator()(const MnFcn &fcn, const MinimumState &st, const GradientCalculator &gc, const MnMachinePrecision &prec) const { // when the second derivatives are negative perform a line search along Parameter which gives // negative second derivative and magnitude equal to the Gradient step size. // Recalculate the gradients for all the Parameter after the correction and // continue iteration in case the second derivatives are still negative // MnPrint print("NegativeG2LineSearch"); bool negG2 = HasNegativeG2(st.Gradient(), prec); if (!negG2) return st; print.Info("Doing a NegativeG2LineSearch since one of the G2 component is negative"); unsigned int n = st.Parameters().Vec().size(); FunctionGradient dgrad = st.Gradient(); MinimumParameters pa = st.Parameters(); bool iterate = false; unsigned int iter = 0; // in case of analytical gradients we don't have step sizes bool hasGStep = !dgrad.IsAnalytical(); //print.Trace("Gradient ", dgrad.Vec(), "G2",dgrad.G2()); // gradient present in the state must have G2 otherwise something is wrong if (!dgrad.HasG2()) { print.Error("Input gradient to NG2LS must have G2 already computed"); return st; } do { iterate = false; for (unsigned int i = 0; i < n; i++) { if (dgrad.G2()(i) <= 0) { // check also the gradient (if it is zero ) I can skip the param) if (std::fabs(dgrad.Vec()(i)) < prec.Eps() && std::fabs(dgrad.G2()(i)) < prec.Eps()) continue; // if(dgrad.G2()(i) < prec.Eps()) { // do line search if second derivative negative MnAlgebraicVector step(n); MnLineSearch lsearch; // when using analytical gradient use as step size a dummy value of 1 // maybe could do better using user given parameter step sizes // tested using inverse of G2() gives worse behaviour if (dgrad.Vec()(i) < 0) step(i) = (hasGStep) ? dgrad.Gstep()(i) : 1; else step(i) = (hasGStep) ? -dgrad.Gstep()(i) : -1; double gdel = step(i) * dgrad.Vec()(i); // if using sec derivative information // double g2del = step(i)*step(i) * dgrad.G2()(i); print.Debug("Iter", iter, "param", i, pa.Vec()(i), "grad2", dgrad.G2()(i), "grad", dgrad.Vec()(i), "grad step", step(i), " gdel ", gdel); MnParabolaPoint pp = lsearch(fcn, pa, step, gdel, prec); print.Debug("Line search result", pp.X(), "f(0)", pa.Fval(), "f(1)", pp.Y()); step *= pp.X(); pa = MinimumParameters(pa.Vec() + step, pp.Y()); dgrad = gc(pa, dgrad); // re-compute also G2 if needed if (!dgrad.HasG2()) { //no need to compute Hessian here but only G2 print.Debug("Compute G2 at the new point", pa.Vec()); MnAlgebraicVector g2(n); bool ret = gc.G2(pa,g2); if (!ret) { print.Error("Cannot compute G2"); assert(false); return st; } dgrad = FunctionGradient(dgrad.Grad(), g2); } print.Debug("New result after Line search - iter", iter, "param", i, pa.Vec()(i), "step", step(i), "new grad2", dgrad.G2()(i), "new grad", dgrad.Vec()(i)); iterate = true; break; } } } while (iter++ < 2 * n && iterate); // even if we computed the Hessian it is still better to use the diagonal part, the G2 print.Debug("Approximate new covariance after NegativeG2LS using only G2"); MnAlgebraicSymMatrix mat(n); for (unsigned int i = 0; i < n; i++) { mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps() ? 1. / dgrad.G2()(i) : 1; // use an arbitrary value (e.g. 1) } MinimumError err(mat, 1.); double edm = VariableMetricEDMEstimator().Estimate(dgrad, err); if (edm < 0) { err = MinimumError(mat, MinimumError::MnNotPosDef); } return MinimumState(pa, err, dgrad, edm, fcn.NumOfCalls()); } bool NegativeG2LineSearch::HasNegativeG2(const FunctionGradient &grad, const MnMachinePrecision & /*prec */) const { // check if function gradient has any component which is negative for (unsigned int i = 0; i < grad.Vec().size(); i++) if (grad.G2()(i) <= 0) { return true; } return false; } } // namespace Minuit2 } // namespace ROOT iminuit-2.30.1/extern/root/math/minuit2/src/Numerical2PGradientCalculator.cxx0000644000000000000000000002065714332717401024151 0ustar00// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnUserTransformation.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MinimumParameters.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnPrint.h" #ifdef _OPENMP #include #endif #include #include #include #include "Minuit2/MPIProcess.h" namespace ROOT { namespace Minuit2 { FunctionGradient Numerical2PGradientCalculator::operator()(const MinimumParameters &par) const { // calculate gradient using Initial gradient calculator and from MinimumParameters object InitialGradientCalculator gc(fFcn, fTransformation); FunctionGradient gra = gc(par); return (*this)(par, gra); } // comment it, because it was added FunctionGradient Numerical2PGradientCalculator::operator()(const std::vector ¶ms) const { // calculate gradient from an std;:vector of paramteters int npar = params.size(); MnAlgebraicVector par(npar); for (int i = 0; i < npar; ++i) { par(i) = params[i]; } double fval = Fcn()(par); MinimumParameters minpars = MinimumParameters(par, fval); return (*this)(minpars); } FunctionGradient Numerical2PGradientCalculator:: operator()(const MinimumParameters &par, const FunctionGradient &Gradient) const { // calculate numerical gradient from MinimumParameters object // the algorithm takes correctly care when the gradient is approximately zero // std::cout<<"########### Numerical2PDerivative"< 0.5) step = 0.5; } double stpmax = 10. * std::fabs(gstep(i)); if (step > stpmax) step = stpmax; // std::cout<<" "< #include #include #include #include #include #include "Fit/ParameterSettings.h" #include // needed here because in Fitter is only a forward declaration namespace ROOT { namespace Minuit2 { NumericalDerivator::NumericalDerivator(bool always_exactly_mimic_minuit2) : fAlwaysExactlyMimicMinuit2(always_exactly_mimic_minuit2) { } NumericalDerivator::NumericalDerivator(double step_tolerance, double grad_tolerance, unsigned int ncycles, double error_level, bool always_exactly_mimic_minuit2) : fStepTolerance(step_tolerance), fGradTolerance(grad_tolerance), fUp(error_level), fNCycles(ncycles), fAlwaysExactlyMimicMinuit2(always_exactly_mimic_minuit2) { } NumericalDerivator::NumericalDerivator(const NumericalDerivator &/*other*/) = default; /// This function sets internal state based on input parameters. This state /// setup is used in the actual (partial) derivative calculations. void NumericalDerivator::SetupDifferentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *cx, const std::vector ¶meters) { assert(function != nullptr && "function is a nullptr"); fVx.resize(function->NDim()); fVxExternal.resize(function->NDim()); fVxFValCache.resize(function->NDim()); std::copy(cx, cx + function->NDim(), fVx.data()); // convert to Minuit external parameters for (unsigned i = 0; i < function->NDim(); i++) { fVxExternal[i] = Int2ext(parameters[i], fVx[i]); } if (fVx != fVxFValCache) { fVxFValCache = fVx; fVal = (*function)(fVxExternal.data()); // value of function at given points } fDfmin = 8. * fPrecision.Eps2() * (std::abs(fVal) + fUp); fVrysml = 8. * fPrecision.Eps() * fPrecision.Eps(); } DerivatorElement NumericalDerivator::PartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, DerivatorElement previous) { SetupDifferentiate(function, x, parameters); return FastPartialDerivative(function, parameters, i_component, previous); } // leaves the parameter setup to the caller DerivatorElement NumericalDerivator::FastPartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous) { DerivatorElement deriv{previous}; double xtf = fVx[i_component]; double epspri = fPrecision.Eps2() + std::abs(deriv.derivative * fPrecision.Eps2()); double step_old = 0.; for (unsigned int j = 0; j < fNCycles; ++j) { double optstp = std::sqrt(fDfmin / (std::abs(deriv.second_derivative) + epspri)); double step = std::max(optstp, std::abs(0.1 * deriv.step_size)); if (parameters[i_component].IsBound()) { if (step > 0.5) step = 0.5; } double stpmax = 10. * std::abs(deriv.step_size); if (step > stpmax) step = stpmax; double stpmin = std::max(fVrysml, 8. * std::abs(fPrecision.Eps2() * fVx[i_component])); if (step < stpmin) step = stpmin; if (std::abs((step - step_old) / step) < fStepTolerance) { break; } deriv.step_size = step; step_old = step; fVx[i_component] = xtf + step; fVxExternal[i_component] = Int2ext(parameters[i_component], fVx[i_component]); double fs1 = (*function)(fVxExternal.data()); fVx[i_component] = xtf - step; fVxExternal[i_component] = Int2ext(parameters[i_component], fVx[i_component]); double fs2 = (*function)(fVxExternal.data()); fVx[i_component] = xtf; fVxExternal[i_component] = Int2ext(parameters[i_component], fVx[i_component]); double fGrd_old = deriv.derivative; deriv.derivative = 0.5 * (fs1 - fs2) / step; deriv.second_derivative = (fs1 + fs2 - 2. * fVal) / step / step; if (std::abs(fGrd_old - deriv.derivative) / (std::abs(deriv.derivative) + fDfmin / step) < fGradTolerance) { break; } } return deriv; } DerivatorElement NumericalDerivator::operator()(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous) { return PartialDerivative(function, x, parameters, i_component, previous); } std::vector NumericalDerivator::Differentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *cx, const std::vector ¶meters, const std::vector &previous_gradient) { SetupDifferentiate(function, cx, parameters); std::vector gradient; gradient.reserve(function->NDim()); for (unsigned int ix = 0; ix < function->NDim(); ++ix) { gradient.emplace_back(FastPartialDerivative(function, parameters, ix, previous_gradient[ix])); } return gradient; } double NumericalDerivator::Int2ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const { // return external value from internal value for parameter i if (parameter.IsBound()) { if (parameter.IsDoubleBound()) { return fDoubleLimTrafo.Int2ext(val, parameter.UpperLimit(), parameter.LowerLimit()); } else if (parameter.HasUpperLimit() && !parameter.HasLowerLimit()) { return fUpperLimTrafo.Int2ext(val, parameter.UpperLimit()); } else { return fLowerLimTrafo.Int2ext(val, parameter.LowerLimit()); } } return val; } double NumericalDerivator::Ext2int(const ROOT::Fit::ParameterSettings ¶meter, double val) const { // return the internal value for parameter i with external value val if (parameter.IsBound()) { if (parameter.IsDoubleBound()) { return fDoubleLimTrafo.Ext2int(val, parameter.UpperLimit(), parameter.LowerLimit(), fPrecision); } else if (parameter.HasUpperLimit() && !parameter.HasLowerLimit()) { return fUpperLimTrafo.Ext2int(val, parameter.UpperLimit(), fPrecision); } else { return fLowerLimTrafo.Ext2int(val, parameter.LowerLimit(), fPrecision); } } return val; } double NumericalDerivator::DInt2Ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const { // return the derivative of the int->ext transformation: dPext(i) / dPint(i) // for the parameter i with value val double dd = 1.; if (parameter.IsBound()) { if (parameter.IsDoubleBound()) { dd = fDoubleLimTrafo.DInt2Ext(val, parameter.UpperLimit(), parameter.LowerLimit()); } else if (parameter.HasUpperLimit() && !parameter.HasLowerLimit()) { dd = fUpperLimTrafo.DInt2Ext(val, parameter.UpperLimit()); } else { dd = fLowerLimTrafo.DInt2Ext(val, parameter.LowerLimit()); } } return dd; } // MODIFIED: /// This function was not implemented as in Minuit2. Now it copies the behavior /// of InitialGradientCalculator. See https://github.com/roofit-dev/root/issues/10 void NumericalDerivator::SetInitialGradient(const ROOT::Math::IBaseFunctionMultiDim *, const std::vector ¶meters, std::vector &gradient) { // set an initial gradient using some given steps // (used in the first iteration) double eps2 = fPrecision.Eps2(); unsigned ix = 0; for (auto parameter = parameters.begin(); parameter != parameters.end(); ++parameter, ++ix) { // What Minuit2 calls "Error" is stepsize on the ROOT side. double werr = parameter->StepSize(); // Actually, extParVal in Minuit2 is the external parameter value, so that is // what we called var before and var is unnecessary here. double extParVal = parameter->Value(); // However, we do need var below, so let's calculate it using Ext2int: double var = Ext2int(*parameter, extParVal); if (fAlwaysExactlyMimicMinuit2) { // this transformation can lose a few bits, but Minuit2 does it too extParVal = Int2ext(*parameter, var); } double extParVal2 = extParVal + werr; if (parameter->HasUpperLimit() && extParVal2 > parameter->UpperLimit()) { extParVal2 = parameter->UpperLimit(); } double var2 = Ext2int(*parameter, extParVal2); double vplu = var2 - var; extParVal2 = extParVal - werr; if (parameter->HasLowerLimit() && extParVal2 < parameter->LowerLimit()) { extParVal2 = parameter->LowerLimit(); } var2 = Ext2int(*parameter, extParVal2); double vmin = var2 - var; double gsmin = 8. * eps2 * (std::abs(var) + eps2); // protect against very small step sizes which can cause dirin to zero and then nan values in grd double dirin = std::max(0.5 * (std::abs(vplu) + std::abs(vmin)), gsmin); double g2 = 2.0 * fUp / (dirin * dirin); double gstep = std::max(gsmin, 0.1 * dirin); double grd = g2 * dirin; if (parameter->IsBound()) { gstep = std::min(gstep, 0.5); } gradient[ix].derivative = grd; gradient[ix].second_derivative = g2; gradient[ix].step_size = gstep; } } std::ostream &operator<<(std::ostream &out, const DerivatorElement &value) { return out << "(derivative: " << value.derivative << ", second_derivative: " << value.second_derivative << ", step_size: " << value.step_size << ")"; } } // namespace Minuit2 } // namespace ROOT ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/ParametricFunction.cxx����������������������������������0000644�0000000�0000000�00000003072�14332717401�022125� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/ParametricFunction.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/Numerical2PGradientCalculator.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/MnVectorTransform.h" namespace ROOT { namespace Minuit2 { //#include "Minuit2/MnPrint.h" std::vector ParametricFunction::GetGradient(const std::vector &x) const { // calculate the numerical gradient (using Numerical2PGradientCalculator) // LM: this I believe is not very efficient MnFcn mfcn(*this); MnStrategy strategy(1); // ????????? how does it know the transformation???????? std::vector err(x.size()); err.assign(x.size(), 0.1); // need to use parameters MnUserParameterState st(x, err); Numerical2PGradientCalculator gc(mfcn, st.Trafo(), strategy); FunctionGradient g = gc(x); const MnAlgebraicVector &grad = g.Vec(); assert(grad.size() == x.size()); MnVectorTransform vt; // std::cout << "Param Function Gradient " << grad << std::endl; return vt(grad); } } // namespace Minuit2 } // namespace ROOT ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/ScanBuilder.cxx�����������������������������������������0000644�0000000�0000000�00000003541�14332717401�020524� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/ScanBuilder.h" #include "Minuit2/MnParameterScan.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnFcn.h" #include namespace ROOT { namespace Minuit2 { FunctionMinimum ScanBuilder::Minimum(const MnFcn &mfcn, const GradientCalculator &, const MinimumSeed &seed, const MnStrategy &, unsigned int, double) const { // find the function minimum performing a parameter scan (using MnParameterScan class) // function gradient is not used MnAlgebraicVector x = seed.Parameters().Vec(); MnUserParameterState upst(seed.State(), mfcn.Up(), seed.Trafo()); MnParameterScan scan(mfcn.Fcn(), upst.Parameters(), seed.Fval()); double amin = scan.Fval(); unsigned int n = seed.Trafo().VariableParameters(); MnAlgebraicVector dirin(n); for (unsigned int i = 0; i < n; i++) { unsigned int ext = seed.Trafo().ExtOfInt(i); scan(ext); if (scan.Fval() < amin) { amin = scan.Fval(); x(i) = seed.Trafo().Ext2int(ext, scan.Parameters().Value(ext)); } dirin(i) = std::sqrt(2. * mfcn.Up() * seed.Error().InvHessian()(i, i)); } MinimumParameters mp(x, dirin, amin); MinimumState st(mp, 0., mfcn.NumOfCalls()); return FunctionMinimum(seed, std::vector(1, st), mfcn.Up()); } } // namespace Minuit2 } // namespace ROOT ���������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/SimplexBuilder.cxx��������������������������������������0000644�0000000�0000000�00000017726�14332717401�021273� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/SimplexBuilder.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/SimplexParameters.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { class GradientCalculator; class MnStrategy; FunctionMinimum SimplexBuilder::Minimum(const MnFcn &mfcn, const GradientCalculator &, const MinimumSeed &seed, const MnStrategy &, unsigned int maxfcn, double minedm) const { // find the minimum using the Simplex method of Nelder and Mead (does not use function gradient) // method to find initial simplex is slightly different than in the original Fortran // Minuit since has not been proofed that one to be better // synchronize print levels MnPrint print("SimplexBuilder", PrintLevel()); print.Debug("Running with maxfcn", maxfcn, "minedm", minedm); const MnMachinePrecision &prec = seed.Precision(); MnAlgebraicVector x = seed.Parameters().Vec(); MnAlgebraicVector step = 10. * seed.Gradient().Gstep(); const unsigned int n = x.size(); // If there are no parameters, we just return a minimum state if (n == 0) { MinimumState st(MinimumParameters(MnAlgebraicVector{0}, MnAlgebraicVector{0}, mfcn(x)), 0.0, mfcn.NumOfCalls()); return FunctionMinimum(seed, {st}, mfcn.Up()); } const double wg = 1. / double(n); const double alpha = 1.; const double beta = 0.5; const double gamma = 2.; const double rhomin = 4.; const double rhomax = 8.; const double rho1 = 1. + alpha; // double rho2 = rho1 + alpha*gamma; // change proposed by david sachs (fnal) const double rho2 = 1. + alpha * gamma; std::vector> simpl; simpl.reserve(n + 1); simpl.emplace_back(seed.Fval(), x); unsigned int jl = 0; unsigned int jh = 0; double amin = seed.Fval(); double aming = seed.Fval(); for (unsigned int i = 0; i < n; i++) { double dmin = 8. * prec.Eps2() * (std::abs(x(i)) + prec.Eps2()); if (step(i) < dmin) step(i) = dmin; x(i) += step(i); double tmp = mfcn(x); if (tmp < amin) { amin = tmp; jl = i + 1; } if (tmp > aming) { aming = tmp; jh = i + 1; } simpl.emplace_back(tmp, x); x(i) -= step(i); } SimplexParameters simplex(simpl, jh, jl); print.Debug([&](std::ostream &os) { os << "Initial parameters - min " << jl << " " << amin << " max " << jh << " " << aming << '\n'; for (unsigned int i = 0; i < simplex.Simplex().size(); ++i) os << " i = " << i << " x = " << simplex(i).second << " fval(x) = " << simplex(i).first << '\n'; }); double edmPrev = simplex.Edm(); int niterations = 0; do { jl = simplex.Jl(); jh = simplex.Jh(); amin = simplex(jl).first; edmPrev = simplex.Edm(); print.Debug("iteration: edm =", simplex.Edm(), '\n', "--> Min Param is", jl, "pmin", simplex(jl).second, "f(pmin)", amin, '\n', "--> Max param is", jh, simplex(jh).first); // std::cout << "ALL SIMPLEX PARAMETERS: "<< std::endl; // for (unsigned int i = 0; i < simplex.Simplex().size(); ++i) // std::cout << " i = " << i << " x = " << simplex(i).second << " fval(x) = " << simplex(i).first << // std::endl; // trace the iterations (need to create a MinimumState although errors and gradient are not existing) if (TraceIter()) TraceIteration(niterations, MinimumState(MinimumParameters(simplex(jl).second, simplex(jl).first), simplex.Edm(), mfcn.NumOfCalls())); print.Info(MnPrint::Oneline(simplex(jl).first, simplex.Edm(), mfcn.NumOfCalls(), niterations)); niterations++; MnAlgebraicVector pbar(n); for (unsigned int i = 0; i < n + 1; i++) { if (i == jh) continue; pbar += (wg * simplex(i).second); } MnAlgebraicVector pstar = (1. + alpha) * pbar - alpha * simplex(jh).second; const double ystar = mfcn(pstar); print.Debug("pbar", pbar, "pstar", pstar, "f(pstar)", ystar); if (ystar > amin) { if (ystar < simplex(jh).first) { simplex.Update(ystar, pstar); if (jh != simplex.Jh()) continue; } MnAlgebraicVector pstst = beta * simplex(jh).second + (1. - beta) * pbar; double ystst = mfcn(pstst); print.Debug("Reduced simplex pstst", pstst, "f(pstst)", ystst); if (ystst > simplex(jh).first) break; simplex.Update(ystst, pstst); continue; } MnAlgebraicVector pstst = gamma * pstar + (1. - gamma) * pbar; double ystst = mfcn(pstst); print.Debug("pstst", pstst, "f(pstst)", ystst); const double y1 = (ystar - simplex(jh).first) * rho2; const double y2 = (ystst - simplex(jh).first) * rho1; double rho = 0.5 * (rho2 * y1 - rho1 * y2) / (y1 - y2); if (rho < rhomin) { if (ystst < simplex(jl).first) simplex.Update(ystst, pstst); else simplex.Update(ystar, pstar); continue; } if (rho > rhomax) rho = rhomax; MnAlgebraicVector prho = rho * pbar + (1. - rho) * simplex(jh).second; double yrho = mfcn(prho); print.Debug("prho", prho, "f(prho)", yrho); if (yrho < simplex(jl).first && yrho < ystst) { simplex.Update(yrho, prho); continue; } if (ystst < simplex(jl).first) { simplex.Update(ystst, pstst); continue; } if (yrho > simplex(jl).first) { if (ystst < simplex(jl).first) simplex.Update(ystst, pstst); else simplex.Update(ystar, pstar); continue; } if (ystar > simplex(jh).first) { pstst = beta * simplex(jh).second + (1. - beta) * pbar; ystst = mfcn(pstst); if (ystst > simplex(jh).first) break; simplex.Update(ystst, pstst); } print.Debug("End loop : Edm", simplex.Edm(), "pstst", pstst, "f(pstst)", ystst); } while ((simplex.Edm() > minedm || edmPrev > minedm) && mfcn.NumOfCalls() < maxfcn); jl = simplex.Jl(); jh = simplex.Jh(); amin = simplex(jl).first; MnAlgebraicVector pbar(n); for (unsigned int i = 0; i < n + 1; i++) { if (i == jh) continue; pbar += (wg * simplex(i).second); } double ybar = mfcn(pbar); if (ybar < amin) simplex.Update(ybar, pbar); else { pbar = simplex(jl).second; ybar = simplex(jl).first; } MnAlgebraicVector dirin = simplex.Dirin(); // Scale to sigmas on parameters werr^2 = dirin^2 * (up/edm) dirin *= std::sqrt(mfcn.Up() / simplex.Edm()); print.Debug("End simplex edm =", simplex.Edm(), "pbar =", pbar, "f(p) =", ybar); MinimumState st(MinimumParameters(pbar, dirin, ybar), simplex.Edm(), mfcn.NumOfCalls()); print.Info("Final iteration", MnPrint::Oneline(st)); if (TraceIter()) TraceIteration(niterations, st); if (mfcn.NumOfCalls() > maxfcn) { print.Warn("Simplex did not converge, #fcn calls exhausted"); return FunctionMinimum(seed, {st}, mfcn.Up(), FunctionMinimum::MnReachedCallLimit); } if (simplex.Edm() > minedm) { print.Warn("Simplex did not converge, edm > minedm"); return FunctionMinimum(seed, {st}, mfcn.Up(), FunctionMinimum::MnAboveMaxEdm); } return FunctionMinimum(seed, {st}, mfcn.Up()); } } // namespace Minuit2 } // namespace ROOT ������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/SimplexParameters.cxx�����������������������������������0000644�0000000�0000000�00000003307�14332717401�021776� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/SimplexParameters.h" namespace ROOT { namespace Minuit2 { void SimplexParameters::Update(double y, const MnAlgebraicVector &p) { // update the SimplexParameter object with a new value y = FCN(p) fSimplexParameters[Jh()] = std::pair(y, p); if (y < fSimplexParameters[Jl()].first) fJLow = Jh(); unsigned int jh = 0; for (unsigned int i = 1; i < fSimplexParameters.size(); i++) { if (fSimplexParameters[i].first > fSimplexParameters[jh].first) jh = i; } fJHigh = jh; return; } MnAlgebraicVector SimplexParameters::Dirin() const { // find simplex direction (vector from big to smaller parameter points) MnAlgebraicVector dirin(fSimplexParameters.size() - 1); for (unsigned int i = 0; i < fSimplexParameters.size() - 1; i++) { double pbig = fSimplexParameters[0].second(i), plit = pbig; for (unsigned int j = 0; j < fSimplexParameters.size(); j++) { if (fSimplexParameters[j].second(i) < plit) plit = fSimplexParameters[j].second(i); if (fSimplexParameters[j].second(i) > pbig) pbig = fSimplexParameters[j].second(i); } dirin(i) = pbig - plit; } return dirin; } } // namespace Minuit2 } // namespace ROOT �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/SimplexSeedGenerator.cxx��������������������������������0000644�0000000�0000000�00000004260�14332717401�022421� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/SimplexSeedGenerator.h" #include "Minuit2/MnUserParameterState.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/InitialGradientCalculator.h" #include "Minuit2/VariableMetricEDMEstimator.h" namespace ROOT { namespace Minuit2 { MinimumSeed SimplexSeedGenerator:: operator()(const MnFcn &fcn, const GradientCalculator &, const MnUserParameterState &st, const MnStrategy &) const { // create starting state for Simplex, which corresponds to the initial parameter values // using the simple Initial gradient calculator (does not use any FCN function calls) unsigned int n = st.VariableParameters(); const MnMachinePrecision &prec = st.Precision(); // initial starting values MnAlgebraicVector x(n); for (unsigned int i = 0; i < n; i++) x(i) = st.IntParameters()[i]; double fcnmin = fcn(x); MinimumParameters pa(x, fcnmin); InitialGradientCalculator igc(fcn, st.Trafo()); FunctionGradient dgrad = igc(pa); MnAlgebraicSymMatrix mat(n); double dcovar = 1.; for (unsigned int i = 0; i < n; i++) mat(i, i) = (std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : 1.); MinimumError err(mat, dcovar); double edm = VariableMetricEDMEstimator().Estimate(dgrad, err); MinimumState state(pa, err, dgrad, edm, fcn.NumOfCalls()); return MinimumSeed(state, st.Trafo()); } MinimumSeed SimplexSeedGenerator::operator()(const MnFcn &fcn, const AnalyticalGradientCalculator &gc, const MnUserParameterState &st, const MnStrategy &stra) const { // base class interface return (*this)(fcn, (const GradientCalculator &)(gc), st, stra); } } // namespace Minuit2 } // namespace ROOT ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/SinParameterTransformation.cxx��������������������������0000644�0000000�0000000�00000004166�14332717401�023656� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei, E.G.P. Bos 2003-2017 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/SinParameterTransformation.h" #include "Minuit2/MnMachinePrecision.h" #include namespace ROOT { namespace Minuit2 { long double SinParameterTransformation::Int2ext(long double Value, long double Upper, long double Lower) const { // transformation from to internal (unlimited) to external values (limited by Lower/Upper ) return Lower + 0.5 * (Upper - Lower) * (std::sin(Value) + 1.); } long double SinParameterTransformation::Ext2int(long double Value, long double Upper, long double Lower, const MnMachinePrecision &prec) const { // transformation from external (limited by Lower/Upper ) to internal (unlimited) values given the lower/upper // limits long double piby2 = 2. * std::atan(1.); long double distnn = 8. * std::sqrt(prec.Eps2()); long double vlimhi = piby2 - distnn; long double vlimlo = -piby2 + distnn; long double yy = 2. * (Value - Lower) / (Upper - Lower) - 1.; long double yy2 = yy * yy; if (yy2 > (1. - prec.Eps2())) { if (yy < 0.) { // Lower limit // std::cout<<"SinParameterTransformation warning: is at its Lower allowed limit. "<GetEntries() + 0.5); fHistoFval->GetXaxis()->SetRange(1, niter); } if (fHistoEdm) fHistoEdm->GetXaxis()->SetRange(1, niter); if (fHistoParList) { for (int i = 0; i < fHistoParList->GetSize(); ++i) { TH1 *h1 = (TH1 *)fHistoParList->At(i); if (h1) h1->GetXaxis()->SetRange(1, niter); } } } void TMinuit2TraceObject::Init(const ROOT::Minuit2::MnUserParameterState &state) { ROOT::Minuit2::MnTraceObject::Init(state); fIterOffset = 0; // build debug histogram if (fHistoFval) delete fHistoFval; if (fHistoEdm) delete fHistoEdm; if (fHistoParList) { fHistoParList->Delete(); delete fHistoParList; } if (fMinuitPad) delete fMinuitPad; fHistoFval = new TH1D("minuit2_hist_fval", "Function Value/iteration", 2, 0, 1); fHistoEdm = new TH1D("minuit2_hist_edm", "Edm/iteration", 2, 0, 1); fHistoFval->SetCanExtend(TH1::kAllAxes); fHistoEdm->SetCanExtend(TH1::kAllAxes); // create histos for all parameters fHistoParList = new TList(); for (unsigned int ipar = 0; ipar < state.Params().size(); ++ipar) { if (state.Parameter(ipar).IsFixed() || state.Parameter(ipar).IsConst()) continue; TH1D *h1 = new TH1D(TString::Format("minuit2_hist_par%d", ipar), TString::Format("Value of %s/iteration", state.Name(ipar)), 2, 0, 1); h1->SetCanExtend(TH1::kAllAxes); fHistoParList->Add(h1); } if (gPad) fOldPad = gPad; // fMinuitPad = new TCanvas("c1_minuit2","TMinuit2 Progress",2); // fMinuitPad->Divide(1,3); // fMinuitPad->cd(1); fHistoFval->Draw(); // fMinuitPad->cd(2); fHistoEdm->Draw(); // fMinuitPad->cd(3); fHistoPar->Draw(); fHistoFval->Draw("hist"); fMinuitPad = gPad; } void TMinuit2TraceObject::operator()(int iter, const ROOT::Minuit2::MinimumState &state) { // action for each iteration: fill histograms // if iteration number is < 0 add at the end of current histograms // if offset is > 0 start filling from end of previous histogram int lastIter = int(fHistoFval->GetEntries() + 0.5); if (iter < 0) iter = lastIter; else { if (iter == 0 && lastIter > 0) fIterOffset = lastIter; iter += fIterOffset; } ROOT::Minuit2::MnTraceObject::operator()(iter, state); fHistoFval->SetBinContent(iter + 1, state.Fval()); fHistoEdm->SetBinContent(iter + 1, state.Edm()); for (unsigned int ipar = 0; ipar < state.Vec().size(); ++ipar) { double eval = UserState().Trafo().Int2ext(ipar, state.Vec()(ipar)); TH1 *histoPar = (TH1 *)fHistoParList->At(ipar); histoPar->SetBinContent(iter + 1, eval); } if (fMinuitPad) { if (ParNumber() == -2) fHistoEdm->Draw(); else if (ParNumber() >= 0 && ParNumber() < fHistoParList->GetSize()) { fHistoParList->At(ParNumber())->Draw(); } else fHistoFval->Draw(); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/VariableMetricBuilder.cxx�������������������������������0000644�0000000�0000000�00000033114�14332717401�022530� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/VariableMetricBuilder.h" #include "Minuit2/GradientCalculator.h" #include "Minuit2/MinimumState.h" #include "Minuit2/MinimumError.h" #include "Minuit2/FunctionGradient.h" #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnLineSearch.h" #include "Minuit2/MinimumSeed.h" #include "Minuit2/MnFcn.h" #include "Minuit2/MnMachinePrecision.h" #include "Minuit2/MnPosDef.h" #include "Minuit2/MnParabolaPoint.h" #include "Minuit2/LaSum.h" #include "Minuit2/LaProd.h" #include "Minuit2/MnStrategy.h" #include "Minuit2/MnHesse.h" #include "Minuit2/MnPrint.h" #include #include namespace ROOT { namespace Minuit2 { double inner_product(const LAVector &, const LAVector &); void VariableMetricBuilder::AddResult(std::vector &result, const MinimumState &state) const { // // if (!store) store = StorageLevel(); // // store |= (result.size() == 0); // if (store) result.push_back(state); // else { // result.back() = state; // } if (TraceIter()) TraceIteration(result.size() - 1, result.back()); else { MnPrint print("VariableMetricBuilder", PrintLevel()); print.Info(MnPrint::Oneline(result.back(), result.size() - 1)); } } FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn &fcn, const GradientCalculator &gc, const MinimumSeed &seed, const MnStrategy &strategy, unsigned int maxfcn, double edmval) const { MnPrint print("VariableMetricBuilder", PrintLevel()); // top level function to find minimum from a given initial seed // iterate on a minimum search in case of first attempt is not successful // to be consistent with F77 Minuit // in Minuit2 edm is correct and is ~ a factor of 2 smaller than F77Minuit // There are also a check for convergence if (edm < 0.1 edmval for exiting the loop) // LM: change factor to 2E-3 to be consistent with F77Minuit edmval *= 0.002; // set global printlevel to the local one so all calls to MN_INFO_MSG can be controlled in the same way // at exit of this function the BuilderPrintLevelConf object is destructed and automatically the // previous level will be restored // double edm = Estimator().Estimate(seed.Gradient(), seed.Error()); double edm = seed.State().Edm(); FunctionMinimum min(seed, fcn.Up()); if (seed.Parameters().Vec().size() == 0) { print.Warn("No free parameters."); return min; } if (!seed.IsValid()) { print.Error("Minimum seed invalid."); return min; } if (edm < 0.) { print.Error("Initial matrix not pos.def."); // assert(!seed.Error().IsPosDef()); return min; } std::vector result; if (StorageLevel() > 0) result.reserve(10); else result.reserve(2); // do actual iterations print.Info("Start iterating until Edm is <", edmval, "with call limit =", maxfcn); AddResult(result, seed.State()); // try first with a maxfxn = 80% of maxfcn int maxfcn_eff = maxfcn; int ipass = 0; bool iterate = false; do { iterate = false; print.Debug(ipass > 0 ? "Continue" : "Start", "iterating..."); min = Minimum(fcn, gc, seed, result, maxfcn_eff, edmval); // if max function call reached exits if (min.HasReachedCallLimit()) { print.Warn("FunctionMinimum is invalid, reached function call limit"); return min; } // second time check for validity of function Minimum if (ipass > 0) { if (!min.IsValid()) { print.Warn("FunctionMinimum is invalid after second try"); return min; } } // resulting edm of minimization edm = result.back().Edm(); // need to correct again for Dcovar: edm *= (1. + 3. * e.Dcovar()) ??? if ((strategy.Strategy() >= 2) || (strategy.Strategy() == 1 && min.Error().Dcovar() > 0.05)) { print.Debug("MnMigrad will verify convergence and Error matrix; dcov =", min.Error().Dcovar()); MnStrategy strat(strategy); strat.SetHessianForcePosDef(1); // ensure no matter what strategy is used, we force the result positive-definite if required MinimumState st = MnHesse(strat)(fcn, min.State(), min.Seed().Trafo(), maxfcn); print.Info("After Hessian"); AddResult(result, st); if (!st.IsValid()) { print.Warn("Invalid Hessian - exit the minimization"); break; } // check new edm edm = st.Edm(); print.Debug("New Edm", edm, "Requested", edmval); if (edm > edmval) { // be careful with machine precision and avoid too small edm double machineLimit = std::fabs(seed.Precision().Eps2() * result.back().Fval()); if (edm >= machineLimit) { iterate = true; print.Info("Tolerance not sufficient, continue minimization; " "Edm", edm, "Required", edmval); } else { print.Warn("Reached machine accuracy limit; Edm", edm, "is smaller than machine limit", machineLimit, "while", edmval, "was requested"); } } } // end loop on iterations // ? need a maximum here (or max of function calls is enough ? ) // continnue iteration (re-calculate function Minimum if edm IS NOT sufficient) // no need to check that hesse calculation is done (if isnot done edm is OK anyway) // count the pass to exit second time when function Minimum is invalid // increase by 20% maxfcn for doing some more tests if (ipass == 0) maxfcn_eff = int(maxfcn * 1.3); ipass++; } while (iterate); // Add latest state (Hessian calculation) const MinimumState &latest = result.back(); // check edm (add a factor of 10 in tolerance ) if (edm > 10 * edmval) { min.Add(latest, FunctionMinimum::MnAboveMaxEdm); print.Warn("No convergence; Edm", edm, "is above tolerance", 10 * edmval); } else if (latest.Error().HasReachedCallLimit()) { // communicate to user that call limit was reached in MnHesse min.Add(latest, FunctionMinimum::MnReachedCallLimit); } else if (latest.Error().IsAvailable()) { // check if minimum had edm above max before if (min.IsAboveMaxEdm()) print.Info("Edm has been re-computed after Hesse; Edm", edm, "is now within tolerance"); min.Add(latest); } print.Debug("Minimum found", min); return min; } FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn &fcn, const GradientCalculator &gc, const MinimumSeed &seed, std::vector &result, unsigned int maxfcn, double edmval) const { // function performing the minimum searches using the Variable Metric algorithm (MIGRAD) // perform first a line search in the - Vg direction and then update using the Davidon formula (Davidon Error // updator) stop when edm reached is less than required (edmval) // after the modification when I iterate on this functions, so it can be called many times, // the seed is used here only to get precision and construct the returned FunctionMinimum object MnPrint print("VariableMetricBuilder", PrintLevel()); const MnMachinePrecision &prec = seed.Precision(); // result.push_back(MinimumState(seed.Parameters(), seed.Error(), seed.Gradient(), edm, fcn.NumOfCalls())); const MinimumState &initialState = result.back(); double edm = initialState.Edm(); print.Debug("Initial State:", "\n Parameter:", initialState.Vec(), "\n Gradient:", initialState.Gradient().Vec(), "\n InvHessian:", initialState.Error().InvHessian(), "\n Edm:", initialState.Edm()); // iterate until edm is small enough or max # of iterations reached edm *= (1. + 3. * initialState.Error().Dcovar()); MnLineSearch lsearch; MnAlgebraicVector step(initialState.Gradient().Vec().size()); // keep also prevStep MnAlgebraicVector prevStep(initialState.Gradient().Vec().size()); MinimumState s0 = result.back(); do { // MinimumState s0 = result.back(); step = -1. * s0.Error().InvHessian() * s0.Gradient().Vec(); print.Debug("Iteration", result.size(), "Fval", s0.Fval(), "numOfCall", fcn.NumOfCalls(), "\n Internal parameters", s0.Vec(), "\n Newton step", step); // check if derivatives are not zero if (inner_product(s0.Gradient().Vec(), s0.Gradient().Vec()) <= 0) { print.Debug("all derivatives are zero - return current status"); break; } // gdel = s^T * g = -g^T H g (since s = - Hg) so it must be negative double gdel = inner_product(step, s0.Gradient().Grad()); if (gdel > 0.) { print.Warn("Matrix not pos.def, gdel =", gdel, "> 0"); MnPosDef psdf; s0 = psdf(s0, prec); step = -1. * s0.Error().InvHessian() * s0.Gradient().Vec(); // #ifdef DEBUG // std::cout << "After MnPosdef - Error " << s0.Error().InvHessian() << " Gradient " << // s0.Gradient().Vec() << " step " << step << std::endl; // #endif gdel = inner_product(step, s0.Gradient().Grad()); print.Warn("gdel =", gdel); if (gdel > 0.) { AddResult(result, s0); return FunctionMinimum(seed, result, fcn.Up()); } } MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec); // <= needed for case 0 <= 0 if (std::fabs(pp.Y() - s0.Fval()) <= std::fabs(s0.Fval()) * prec.Eps()) { print.Warn("No improvement in line search"); // no improvement exit (is it really needed LM ? in vers. 1.22 tried alternative ) // add new state when only fcn changes if (result.size() <= 1) AddResult(result, MinimumState(s0.Parameters(), s0.Error(), s0.Gradient(), s0.Edm(), fcn.NumOfCalls())); else // no need to re-store the state AddResult(result, MinimumState(pp.Y(), s0.Edm(), fcn.NumOfCalls())); break; } print.Debug("Result after line search :", "\n x =", pp.X(), "\n Old Fval =", s0.Fval(), "\n New Fval =", pp.Y(), "\n NFcalls =", fcn.NumOfCalls()); MinimumParameters p(s0.Vec() + pp.X() * step, pp.Y()); FunctionGradient g = gc(p, s0.Gradient()); edm = Estimator().Estimate(g, s0.Error()); if (std::isnan(edm)) { print.Warn("Edm is NaN; stop iterations"); AddResult(result, s0); return FunctionMinimum(seed, result, fcn.Up()); } if (edm < 0.) { print.Warn("Matrix not pos.def., try to make pos.def."); MnPosDef psdf; s0 = psdf(s0, prec); edm = Estimator().Estimate(g, s0.Error()); if (edm < 0.) { print.Warn("Matrix still not pos.def.; stop iterations"); AddResult(result, s0); return FunctionMinimum(seed, result, fcn.Up()); } } MinimumError e = ErrorUpdator().Update(s0, p, g); // avoid print Hessian that will invert the matrix print.Debug("Updated new point:", "\n Parameter:", p.Vec(), "\n Gradient:", g.Vec(), "\n InvHessian:", e.Matrix(), "\n Edm:", edm); // update the state s0 = MinimumState(p, e, g, edm, fcn.NumOfCalls()); if (StorageLevel() || result.size() <= 1) AddResult(result, s0); else // use a reduced state for not-final iterations AddResult(result, MinimumState(p.Fval(), edm, fcn.NumOfCalls())); // correct edm edm *= (1. + 3. * e.Dcovar()); print.Debug("Dcovar =", e.Dcovar(), "\tCorrected edm =", edm); } while (edm > edmval && fcn.NumOfCalls() < maxfcn); // end of iteration loop // save last result in case of no complete final states // when the result is filled above (reduced storage) the resulting state will not be valid // since they will not have parameter values and error // the line above will fill as last element a valid state if (!result.back().IsValid()) result.back() = s0; if (fcn.NumOfCalls() >= maxfcn) { print.Warn("Call limit exceeded"); return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnReachedCallLimit); } if (edm > edmval) { if (edm < 10 * edmval) { print.Info("Edm is close to limit - return current minimum"); return FunctionMinimum(seed, result, fcn.Up()); } else if (edm < std::fabs(prec.Eps2() * result.back().Fval())) { print.Warn("Edm is limited by Machine accuracy - return current minimum"); return FunctionMinimum(seed, result, fcn.Up()); } else { print.Warn("Iterations finish without convergence; Edm", edm, "Requested", edmval); return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnAboveMaxEdm); } } // std::cout<<"result.back().Error().Dcovar()= "< edm = 0.5 g^T V g if (e.InvHessian().size() == 1) return 0.5 * g.Grad()(0) * g.Grad()(0) * e.InvHessian()(0, 0); double rho = similarity(g.Grad(), e.InvHessian()); return 0.5 * rho; } } // namespace Minuit2 } // namespace ROOT ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/math/CMakeLists.txt�������������������������������������0000644�0000000�0000000�00000004603�14332717401�021276� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. # All rights reserved. # # For the licensing terms see $ROOTSYS/LICENSE. # For the list of contributors see $ROOTSYS/README/CREDITS. set(FIT_HEADERS ParameterSettings.h ) set(MATH_HEADERS Error.h FitMethodFunction.h Functor.h GenAlgoOptions.h IFunction.h IFunctionfwd.h IOptions.h Minimizer.h MinimizerOptions.h Util.h WrappedFunction.h WrappedParamFunction.h ) set(MATH_SOURCES GenAlgoOptions.cxx IOptions.cxx Minimizer.cxx MinimizerOptions.cxx ParameterSettings.cxx ) copy_standalone(SOURCE ../../../mathcore/inc/Fit DESTINATION ../../inc/Fit OUTPUT FIT_HEADERS FILES ${FIT_HEADERS}) copy_standalone(SOURCE ../../../mathcore/inc/Math DESTINATION ../../inc/Math OUTPUT MATH_HEADERS FILES ${MATH_HEADERS}) copy_standalone(SOURCE ../../../mathcore/src DESTINATION . OUTPUT MATH_SOURCES FILES ${MATH_SOURCES}) # Adding the headers helps IDEs show the correct headers on targets add_library(Minuit2Math ${MATH_SOURCES} ${MATH_HEADERS} ${FIT_HEADERS} ) # Add alias for direct inclusion add_library(Minuit2::Math ALIAS Minuit2Math) # Build and install directories are different, using CMake Generator expression target_include_directories( Minuit2Math PUBLIC $ $ ) # We need to add the ROOT mathcore directories if build inside of ROOT without standalone) if(minuit2_inroot AND NOT minuit2_standalone) target_include_directories( Minuit2Math PUBLIC $ ) endif() target_compile_definitions( Minuit2Math PRIVATE MATH_NO_PLUGIN_MANAGER ) target_compile_definitions( Minuit2Math PUBLIC ROOT_Math_VecTypes MATHCORE_STANDALONE ) target_link_libraries(Minuit2Math PUBLIC Minuit2Common) target_compile_features(Minuit2Math PUBLIC cxx_auto_type cxx_static_assert) set_target_properties(Minuit2Math PROPERTIES CXX_EXTENSIONS OFF) install(TARGETS Minuit2Math EXPORT Minuit2Targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES ${FIT_HEADERS} DESTINATION include/Minuit2/Fit) install(FILES ${MATH_HEADERS} DESTINATION include/Minuit2/Math) �����������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mnbins.cxx����������������������������������������������0000644�0000000�0000000�00000005320�14332717401�017614� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include namespace ROOT { namespace Minuit2 { void mnbins(double a1, double a2, int naa, double &bl, double &bh, int &nb, double &bwid) { //*-*-*-*-*-*-*-*-*-*-*Compute reasonable histogram intervals*-*-*-*-*-*-*-*-* //*-* ====================================== //*-* Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS //*-* GIVEN ABSOLUTE UPPER AND LOWER BOUNDS A1 AND A2 //*-* AND DESIRED MAXIMUM NUMBER OF BINS NAA //*-* PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID //*-* F. JAMES, AUGUST, 1974 , stolen for Minuit, 1988 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* /* Local variables */ double awid, ah, al, sigfig, sigrnd, alb; int kwid, lwid, na = 0, log_; al = a1 < a2 ? a1 : a2; // al = std::min(a1,a2); // ah = std::max(a1,a2); ah = a1 > a2 ? a1 : a2; if (al == ah) ah = al + 1; //*-*- IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE if (naa == -1) goto L150; L10: na = naa - 1; if (na < 1) na = 1; //*-*- GET NOMINAL BIN WIDTH IN EXPON FORM L20: awid = (ah - al) / double(na); log_ = int(log10(awid)); if (awid <= 1) --log_; sigfig = awid * pow(10.0, -log_); //*-*- ROUND MANTISSA UP TO 2, 2.5, 5, OR 10 if (sigfig > 2) goto L40; sigrnd = 2; goto L100; L40: if (sigfig > 2.5) goto L50; sigrnd = 2.5; goto L100; L50: if (sigfig > 5) goto L60; sigrnd = 5; goto L100; L60: sigrnd = 1; ++log_; L100: bwid = sigrnd * pow(10.0, log_); goto L200; //*-*- GET NEW BOUNDS FROM NEW WIDTH BWID L150: if (bwid <= 0) goto L10; L200: alb = al / bwid; lwid = int(alb); if (alb < 0) --lwid; bl = bwid * double(lwid); alb = ah / bwid + 1; kwid = int(alb); if (alb < 0) --kwid; bh = bwid * double(kwid); nb = kwid - lwid; if (naa > 5) goto L240; if (naa == -1) return; //*-*- REQUEST FOR ONE BIN IS DIFFICULT CASE if (naa > 1 || nb == 1) return; bwid *= 2; nb = 1; return; L240: if (nb << 1 != naa) return; ++na; goto L20; } /* mnbins_ */ } // namespace Minuit2 } // namespace ROOT ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mndasum.cxx���������������������������������������������0000644�0000000�0000000�00000004542�14332717401�017777� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* dasum.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include namespace ROOT { namespace Minuit2 { double mndasum(unsigned int n, const double *dx, int incx) { /* System generated locals */ int i__1, i__2; double ret_val, d__1, d__2, d__3, d__4, d__5, d__6; /* Local variables */ int i__, m; double dtemp; int nincx, mp1; /* takes the sum of the absolute values. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 3/93 to return if incx .le. 0. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --dx; /* Function Body */ ret_val = 0.; dtemp = 0.; if (n <= 0 || incx <= 0) { return ret_val; } if (incx == 1) { goto L20; } /* code for increment not equal to 1 */ nincx = n * incx; i__1 = nincx; i__2 = incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { dtemp += (d__1 = dx[i__], std::fabs(d__1)); /* L10: */ } ret_val = dtemp; return ret_val; /* code for increment equal to 1 */ /* clean-up loop */ L20: m = n % 6; if (m == 0) { goto L40; } i__2 = m; for (i__ = 1; i__ <= i__2; ++i__) { dtemp += (d__1 = dx[i__], std::fabs(d__1)); /* L30: */ } if (n < 6) { goto L60; } L40: mp1 = m + 1; i__2 = n; for (i__ = mp1; i__ <= i__2; i__ += 6) { dtemp = dtemp + (d__1 = dx[i__], std::fabs(d__1)) + (d__2 = dx[i__ + 1], std::fabs(d__2)) + (d__3 = dx[i__ + 2], std::fabs(d__3)) + (d__4 = dx[i__ + 3], std::fabs(d__4)) + (d__5 = dx[i__ + 4], std::fabs(d__5)) + (d__6 = dx[i__ + 5], std::fabs(d__6)); /* L50: */ } L60: ret_val = dtemp; return ret_val; } /* dasum_ */ } // namespace Minuit2 } // namespace ROOT ��������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mndaxpy.cxx���������������������������������������������0000644�0000000�0000000�00000004400�14332717401�020004� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* daxpy.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ namespace ROOT { namespace Minuit2 { int Mndaxpy(unsigned int n, double da, const double *dx, int incx, double *dy, int incy) { /* System generated locals */ int i__1; /* Local variables */ int i__, m, ix, iy, mp1; /* constant times a vector plus a vector. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ if (n <= 0) { return 0; } if (da == 0.) { return 0; } if (incx == 1 && incy == 1) { goto L20; } /* code for unequal increments or equal increments */ /* not equal to 1 */ ix = 1; iy = 1; if (incx < 0) { ix = (-static_cast(n) + 1) * incx + 1; } if (incy < 0) { iy = (-static_cast(n) + 1) * incy + 1; } i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { dy[iy] += da * dx[ix]; ix += incx; iy += incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = n % 4; if (m == 0) { goto L40; } i__1 = m; for (i__ = 1; i__ <= i__1; ++i__) { dy[i__] += da * dx[i__]; /* L30: */ } if (n < 4) { return 0; } L40: mp1 = m + 1; i__1 = n; for (i__ = mp1; i__ <= i__1; i__ += 4) { dy[i__] += da * dx[i__]; dy[i__ + 1] += da * dx[i__ + 1]; dy[i__ + 2] += da * dx[i__ + 2]; dy[i__ + 3] += da * dx[i__ + 3]; /* L50: */ } return 0; } /* daxpy_ */ } // namespace Minuit2 } // namespace ROOT ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mnddot.cxx����������������������������������������������0000644�0000000�0000000�00000004562�14332717401�017622� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* ddot.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ namespace ROOT { namespace Minuit2 { double mnddot(unsigned int n, const double *dx, int incx, const double *dy, int incy) { /* System generated locals */ int i__1; double ret_val; /* Local variables */ int i__, m; double dtemp; int ix, iy, mp1; /* forms the dot product of two vectors. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ ret_val = 0.; dtemp = 0.; if (n <= 0) { return ret_val; } if (incx == 1 && incy == 1) { goto L20; } /* code for unequal increments or equal increments */ /* not equal to 1 */ ix = 1; iy = 1; if (incx < 0) { ix = (-static_cast(n) + 1) * incx + 1; } if (incy < 0) { iy = (-static_cast(n) + 1) * incy + 1; } i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { dtemp += dx[ix] * dy[iy]; ix += incx; iy += incy; /* L10: */ } ret_val = dtemp; return ret_val; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = n % 5; if (m == 0) { goto L40; } i__1 = m; for (i__ = 1; i__ <= i__1; ++i__) { dtemp += dx[i__] * dy[i__]; /* L30: */ } if (n < 5) { goto L60; } L40: mp1 = m + 1; i__1 = n; for (i__ = mp1; i__ <= i__1; i__ += 5) { dtemp = dtemp + dx[i__] * dy[i__] + dx[i__ + 1] * dy[i__ + 1] + dx[i__ + 2] * dy[i__ + 2] + dx[i__ + 3] * dy[i__ + 3] + dx[i__ + 4] * dy[i__ + 4]; /* L50: */ } L60: ret_val = dtemp; return ret_val; } /* ddot_ */ } // namespace Minuit2 } // namespace ROOT ����������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mndscal.cxx���������������������������������������������0000644�0000000�0000000�00000004110�14332717401�017743� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* dscal.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ namespace ROOT { namespace Minuit2 { int Mndscal(unsigned int n, double da, double *dx, int incx) { /* System generated locals */ int i__1, i__2; /* Local variables */ int i__, m, nincx, mp1; /* scales a vector by a constant. */ /* uses unrolled loops for increment equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 3/93 to return if incx .le. 0. */ /* modified 12/3/93, array(1) declarations changed to array(*) */ /* Parameter adjustments */ --dx; /* Function Body */ if (n <= 0 || incx <= 0) { return 0; } if (incx == 1) { goto L20; } /* code for increment not equal to 1 */ nincx = n * incx; i__1 = nincx; i__2 = incx; for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { dx[i__] = da * dx[i__]; /* L10: */ } return 0; /* code for increment equal to 1 */ /* clean-up loop */ L20: m = n % 5; if (m == 0) { goto L40; } i__2 = m; for (i__ = 1; i__ <= i__2; ++i__) { dx[i__] = da * dx[i__]; /* L30: */ } if (n < 5) { return 0; } L40: mp1 = m + 1; i__2 = n; for (i__ = mp1; i__ <= i__2; i__ += 5) { dx[i__] = da * dx[i__]; dx[i__ + 1] = da * dx[i__ + 1]; dx[i__ + 2] = da * dx[i__ + 2]; dx[i__ + 3] = da * dx[i__ + 3]; dx[i__ + 4] = da * dx[i__ + 4]; /* L50: */ } return 0; } /* dscal_ */ } // namespace Minuit2 } // namespace ROOT ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mndspmv.cxx���������������������������������������������0000644�0000000�0000000�00000022037�14332717401�020016� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* dspmv.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ namespace ROOT { namespace Minuit2 { bool mnlsame(const char *, const char *); int mnxerbla(const char *, int); int Mndspmv(const char *uplo, unsigned int n, double alpha, const double *ap, const double *x, int incx, double beta, double *y, int incy) { /* System generated locals */ int i__1, i__2; /* Local variables */ int info; double temp1, temp2; int i__, j, k; int kk, ix, iy, jx, jy, kx, ky; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPMV performs the matrix-vector operation */ /* y := alpha*A*x + beta*y, */ /* where alpha and beta are scalars, x and y are n element vectors and */ /* A is an n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the Upper or Lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The Upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The Lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the Upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the Lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the Elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* BETA - DOUBLE PRECISION. */ /* On entry, BETA specifies the scalar beta. When BETA is */ /* supplied as zero then Y need not be set on input. */ /* Unchanged on exit. */ /* Y - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCY ) ). */ /* Before entry, the incremented array Y must contain the n */ /* element vector y. On exit, Y is overwritten by the updated */ /* vector y. */ /* INCY - INTEGER. */ /* On entry, INCY specifies the increment for the Elements of */ /* Y. INCY must not be zero. */ /* Unchanged on exit. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --y; --x; --ap; /* Function Body */ info = 0; if (!mnlsame(uplo, "U") && !mnlsame(uplo, "L")) { info = 1; } // else if (n < 0) { // info = 2; // } else if (incx == 0) { info = 6; } else if (incy == 0) { info = 9; } if (info != 0) { mnxerbla("DSPMV ", info); return 0; } /* Quick return if possible. */ if ((n == 0) || (alpha == 0. && beta == 1.)) { return 0; } /* Set up the start points in X and Y. */ if (incx > 0) { kx = 1; } else { kx = 1 - (n - 1) * incx; } if (incy > 0) { ky = 1; } else { ky = 1 - (n - 1) * incy; } /* Start the operations. In this version the Elements of the array AP */ /* are accessed sequentially with one pass through AP. */ /* First form y := beta*y. */ if (beta != 1.) { if (incy == 1) { if (beta == 0.) { i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = 0.; /* L10: */ } } else { i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = beta * y[i__]; /* L20: */ } } } else { iy = ky; if (beta == 0.) { i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = 0.; iy += incy; /* L30: */ } } else { i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { y[iy] = beta * y[iy]; iy += incy; /* L40: */ } } } } if (alpha == 0.) { return 0; } kk = 1; if (mnlsame(uplo, "U")) { /* Form y when AP contains the Upper triangle. */ if (incx == 1 && incy == 1) { i__1 = n; for (j = 1; j <= i__1; ++j) { temp1 = alpha * x[j]; temp2 = 0.; k = kk; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L50: */ } y[j] = y[j] + temp1 * ap[kk + j - 1] + alpha * temp2; kk += j; /* L60: */ } } else { jx = kx; jy = ky; i__1 = n; for (j = 1; j <= i__1; ++j) { temp1 = alpha * x[jx]; temp2 = 0.; ix = kx; iy = ky; i__2 = kk + j - 2; for (k = 0; k <= i__2 - kk; ++k) { y[iy] += temp1 * ap[k + kk]; temp2 += ap[k + kk] * x[ix]; ix += incx; iy += incy; /* L70: */ } y[jy] = y[jy] + temp1 * ap[kk + j - 1] + alpha * temp2; jx += incx; jy += incy; kk += j; /* L80: */ } } } else { /* Form y when AP contains the Lower triangle. */ if (incx == 1 && incy == 1) { i__1 = n; for (j = 1; j <= i__1; ++j) { temp1 = alpha * x[j]; temp2 = 0.; y[j] += temp1 * ap[kk]; k = kk + 1; i__2 = n; for (i__ = j + 1; i__ <= i__2; ++i__) { y[i__] += temp1 * ap[k]; temp2 += ap[k] * x[i__]; ++k; /* L90: */ } y[j] += alpha * temp2; kk += n - j + 1; /* L100: */ } } else { jx = kx; jy = ky; i__1 = n; for (j = 1; j <= i__1; ++j) { temp1 = alpha * x[jx]; temp2 = 0.; y[jy] += temp1 * ap[kk]; ix = jx; iy = jy; i__2 = kk + n - j; for (k = kk + 1; k <= i__2; ++k) { ix += incx; iy += incy; y[iy] += temp1 * ap[k]; temp2 += ap[k] * x[ix]; /* L110: */ } y[jy] += alpha * temp2; jx += incx; jy += incy; kk += n - j + 1; /* L120: */ } } } return 0; /* End of DSPMV . */ } /* dspmv_ */ } // namespace Minuit2 } // namespace ROOT �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mndspr.cxx����������������������������������������������0000644�0000000�0000000�00000015757�14332717401�017650� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* dspr.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ namespace ROOT { namespace Minuit2 { bool mnlsame(const char *, const char *); int mnxerbla(const char *, int); int mndspr(const char *uplo, unsigned int n, double alpha, const double *x, int incx, double *ap) { /* System generated locals */ int i__1, i__2; /* Local variables */ int info; double temp; int i__, j, k; int kk, ix, jx, kx = 0; /* .. Scalar Arguments .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPR performs the symmetric rank 1 operation */ /* A := alpha*x*x' + A, */ /* where alpha is a real scalar, x is an n element vector and A is an */ /* n by n symmetric matrix, supplied in packed form. */ /* Parameters */ /* ========== */ /* UPLO - CHARACTER*1. */ /* On entry, UPLO specifies whether the Upper or Lower */ /* triangular part of the matrix A is supplied in the packed */ /* array AP as follows: */ /* UPLO = 'U' or 'u' The Upper triangular part of A is */ /* supplied in AP. */ /* UPLO = 'L' or 'l' The Lower triangular part of A is */ /* supplied in AP. */ /* Unchanged on exit. */ /* N - INTEGER. */ /* On entry, N specifies the order of the matrix A. */ /* N must be at least zero. */ /* Unchanged on exit. */ /* ALPHA - DOUBLE PRECISION. */ /* On entry, ALPHA specifies the scalar alpha. */ /* Unchanged on exit. */ /* X - DOUBLE PRECISION array of dimension at least */ /* ( 1 + ( n - 1 )*abs( INCX ) ). */ /* Before entry, the incremented array X must contain the n */ /* element vector x. */ /* Unchanged on exit. */ /* INCX - INTEGER. */ /* On entry, INCX specifies the increment for the Elements of */ /* X. INCX must not be zero. */ /* Unchanged on exit. */ /* AP - DOUBLE PRECISION array of DIMENSION at least */ /* ( ( n*( n + 1 ) )/2 ). */ /* Before entry with UPLO = 'U' or 'u', the array AP must */ /* contain the Upper triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 1, 2 ) */ /* and a( 2, 2 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the Upper triangular part of the */ /* updated matrix. */ /* Before entry with UPLO = 'L' or 'l', the array AP must */ /* contain the Lower triangular part of the symmetric matrix */ /* packed sequentially, column by column, so that AP( 1 ) */ /* contains a( 1, 1 ), AP( 2 ) and AP( 3 ) contain a( 2, 1 ) */ /* and a( 3, 1 ) respectively, and so on. On exit, the array */ /* AP is overwritten by the Lower triangular part of the */ /* updated matrix. */ /* Level 2 Blas routine. */ /* -- Written on 22-October-1986. */ /* Jack Dongarra, Argonne National Lab. */ /* Jeremy Du Croz, Nag Central Office. */ /* Sven Hammarling, Nag Central Office. */ /* Richard Hanson, Sandia National Labs. */ /* .. Parameters .. */ /* .. Local Scalars .. */ /* .. External Functions .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --x; /* Function Body */ info = 0; if (!mnlsame(uplo, "U") && !mnlsame(uplo, "L")) { info = 1; } // else if (n < 0) { // info = 2; // } else if (incx == 0) { info = 5; } if (info != 0) { mnxerbla("DSPR ", info); return 0; } /* Quick return if possible. */ if (n == 0 || alpha == 0.) { return 0; } /* Set the start point in X if the increment is not unity. */ if (incx <= 0) { kx = 1 - (n - 1) * incx; } else if (incx != 1) { kx = 1; } /* Start the operations. In this version the Elements of the array AP */ /* are accessed sequentially with one pass through AP. */ kk = 1; if (mnlsame(uplo, "U")) { /* Form A when Upper triangle is stored in AP. */ if (incx == 1) { i__1 = n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = alpha * x[j]; k = kk; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L10: */ } } kk += j; /* L20: */ } } else { jx = kx; i__1 = n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = alpha * x[jx]; ix = kx; i__2 = kk + j - 1; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += incx; /* L30: */ } } jx += incx; kk += j; /* L40: */ } } } else { /* Form A when Lower triangle is stored in AP. */ if (incx == 1) { i__1 = n; for (j = 1; j <= i__1; ++j) { if (x[j] != 0.) { temp = alpha * x[j]; k = kk; i__2 = n; for (i__ = j; i__ <= i__2; ++i__) { ap[k] += x[i__] * temp; ++k; /* L50: */ } } kk = kk + n - j + 1; /* L60: */ } } else { jx = kx; i__1 = n; for (j = 1; j <= i__1; ++j) { if (x[jx] != 0.) { temp = alpha * x[jx]; ix = jx; i__2 = kk + n - j; for (k = kk; k <= i__2; ++k) { ap[k] += x[ix] * temp; ix += incx; /* L70: */ } } jx += incx; kk = kk + n - j + 1; /* L80: */ } } } return 0; /* End of DSPR . */ } /* dspr_ */ } // namespace Minuit2 } // namespace ROOT �����������������iminuit-2.30.1/extern/root/math/minuit2/src/mnlsame.cxx���������������������������������������������0000644�0000000�0000000�00000003515�14332717401�017766� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* lsame.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include namespace ROOT { namespace Minuit2 { bool mnlsame(const char *ca, const char *cb) { /* System generated locals */ bool ret_val = false; /* Local variables */ // integer inta, intb, zcode; /* -- LAPACK auxiliary routine (version 2.0) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* January 31, 1994 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* LSAME returns .TRUE. if CA is the same letter as CB regardless of */ /* case. */ /* Arguments */ /* ========= */ /* CA (input) CHARACTER*1 */ /* CB (input) CHARACTER*1 */ /* CA and CB specify the single characters to be compared. */ /* ===================================================================== */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Executable Statements .. */ /* Test if the characters are equal */ int comp = std::strcmp(ca, cb); if (comp == 0) ret_val = true; return ret_val; } /* lsame_ */ } // namespace Minuit2 } // namespace ROOT �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mnteigen.cxx��������������������������������������������0000644�0000000�0000000�00000015446�14332717401�020146� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* mneig.F -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include namespace ROOT { namespace Minuit2 { int mneigen(double *a, unsigned int ndima, unsigned int n, unsigned int mits, double *work, double precis) { // compute matrix eignevalues (translation from mneig.F of Minuit) /* System generated locals */ unsigned int a_dim1, a_offset, i__1, i__2, i__3; double r__1, r__2; /* Local variables */ double b, c__, f, h__; unsigned int i__, j, k, l, m = 0; double r__, s; unsigned int i0, i1, j1, m1, n1; double hh, gl, pr, pt; /* PRECIS is the machine precision EPSMAC */ /* Parameter adjustments */ a_dim1 = ndima; a_offset = 1 + a_dim1 * 1; a -= a_offset; --work; /* Function Body */ int ifault = 1; i__ = n; i__1 = n; for (i1 = 2; i1 <= i__1; ++i1) { l = i__ - 2; f = a[i__ + (i__ - 1) * a_dim1]; gl = (double)0.; if (l < 1) { goto L25; } i__2 = l; for (k = 1; k <= i__2; ++k) { /* Computing 2nd power */ r__1 = a[i__ + k * a_dim1]; gl += r__1 * r__1; } L25: /* Computing 2nd power */ r__1 = f; h__ = gl + r__1 * r__1; if (gl > (double)1e-35) { goto L30; } work[i__] = (double)0.; work[n + i__] = f; goto L65; L30: ++l; gl = std::sqrt(h__); if (f >= (double)0.) { gl = -gl; } work[n + i__] = gl; h__ -= f * gl; a[i__ + (i__ - 1) * a_dim1] = f - gl; f = (double)0.; i__2 = l; for (j = 1; j <= i__2; ++j) { a[j + i__ * a_dim1] = a[i__ + j * a_dim1] / h__; gl = (double)0.; i__3 = j; for (k = 1; k <= i__3; ++k) { gl += a[j + k * a_dim1] * a[i__ + k * a_dim1]; } if (j >= l) { goto L47; } j1 = j + 1; i__3 = l; for (k = j1; k <= i__3; ++k) { gl += a[k + j * a_dim1] * a[i__ + k * a_dim1]; } L47: work[n + j] = gl / h__; f += gl * a[j + i__ * a_dim1]; } hh = f / (h__ + h__); i__2 = l; for (j = 1; j <= i__2; ++j) { f = a[i__ + j * a_dim1]; gl = work[n + j] - hh * f; work[n + j] = gl; i__3 = j; for (k = 1; k <= i__3; ++k) { a[j + k * a_dim1] = a[j + k * a_dim1] - f * work[n + k] - gl * a[i__ + k * a_dim1]; } } work[i__] = h__; L65: --i__; } work[1] = (double)0.; work[n + 1] = (double)0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { l = i__ - 1; if (work[i__] == (double)0. || l == 0) { goto L100; } i__3 = l; for (j = 1; j <= i__3; ++j) { gl = (double)0.; i__2 = l; for (k = 1; k <= i__2; ++k) { gl += a[i__ + k * a_dim1] * a[k + j * a_dim1]; } i__2 = l; for (k = 1; k <= i__2; ++k) { a[k + j * a_dim1] -= gl * a[k + i__ * a_dim1]; } } L100: work[i__] = a[i__ + i__ * a_dim1]; a[i__ + i__ * a_dim1] = (double)1.; if (l == 0) { goto L110; } i__2 = l; for (j = 1; j <= i__2; ++j) { a[i__ + j * a_dim1] = (double)0.; a[j + i__ * a_dim1] = (double)0.; } L110:; } n1 = n - 1; i__1 = n; for (i__ = 2; i__ <= i__1; ++i__) { i0 = n + i__ - 1; work[i0] = work[i0 + 1]; } work[n + n] = (double)0.; b = (double)0.; f = (double)0.; i__1 = n; for (l = 1; l <= i__1; ++l) { j = 0; h__ = precis * ((r__1 = work[l], std::fabs(r__1)) + (r__2 = work[n + l], std::fabs(r__2))); if (b < h__) { b = h__; } i__2 = n; for (m1 = l; m1 <= i__2; ++m1) { m = m1; if ((r__1 = work[n + m], std::fabs(r__1)) <= b) { goto L150; } } L150: if (m == l) { goto L205; } L160: if (j == mits) { return ifault; } ++j; pt = (work[l + 1] - work[l]) / (work[n + l] * (double)2.); r__ = std::sqrt(pt * pt + (double)1.); pr = pt + r__; if (pt < (double)0.) { pr = pt - r__; } h__ = work[l] - work[n + l] / pr; i__2 = n; for (i__ = l; i__ <= i__2; ++i__) { work[i__] -= h__; } f += h__; pt = work[m]; c__ = (double)1.; s = (double)0.; m1 = m - 1; i__ = m; i__2 = m1; for (i1 = l; i1 <= i__2; ++i1) { j = i__; --i__; gl = c__ * work[n + i__]; h__ = c__ * pt; if (std::fabs(pt) >= (r__1 = work[n + i__], std::fabs(r__1))) { goto L180; } c__ = pt / work[n + i__]; r__ = std::sqrt(c__ * c__ + (double)1.); work[n + j] = s * work[n + i__] * r__; s = (double)1. / r__; c__ /= r__; goto L190; L180: c__ = work[n + i__] / pt; r__ = std::sqrt(c__ * c__ + (double)1.); work[n + j] = s * pt * r__; s = c__ / r__; c__ = (double)1. / r__; L190: pt = c__ * work[i__] - s * gl; work[j] = h__ + s * (c__ * gl + s * work[i__]); i__3 = n; for (k = 1; k <= i__3; ++k) { h__ = a[k + j * a_dim1]; a[k + j * a_dim1] = s * a[k + i__ * a_dim1] + c__ * h__; a[k + i__ * a_dim1] = c__ * a[k + i__ * a_dim1] - s * h__; } } work[n + l] = s * pt; work[l] = c__ * pt; if ((r__1 = work[n + l], std::fabs(r__1)) > b) { goto L160; } L205: work[l] += f; } i__1 = n1; for (i__ = 1; i__ <= i__1; ++i__) { k = i__; pt = work[i__]; i1 = i__ + 1; i__3 = n; for (j = i1; j <= i__3; ++j) { if (work[j] >= pt) { goto L220; } k = j; pt = work[j]; L220:; } if (k == i__) { goto L240; } work[k] = work[i__]; work[i__] = pt; i__3 = n; for (j = 1; j <= i__3; ++j) { pt = a[j + i__ * a_dim1]; a[j + i__ * a_dim1] = a[j + k * a_dim1]; a[j + k * a_dim1] = pt; } L240:; } ifault = 0; return ifault; } /* mneig_ */ } // namespace Minuit2 } // namespace ROOT ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mntplot.cxx���������������������������������������������0000644�0000000�0000000�00000014377�14332717401�020037� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* mnplot.F -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include #include #include namespace ROOT { namespace Minuit2 { void mnbins(double, double, int, double &, double &, int &, double &); void mnplot(double *xpt, double *ypt, char *chpt, int nxypt, int npagwd, int npagln) { //*-*-*-*Plots points in array xypt onto one page with labelled axes*-*-*-*-* //*-* =========================================================== //*-* NXYPT is the number of points to be plotted //*-* XPT(I) = x-coord. of ith point //*-* YPT(I) = y-coord. of ith point //*-* CHPT(I) = character to be plotted at this position //*-* the input point arrays XPT, YPT, CHPT are destroyed. //*-* //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* // char cdot[] = "."; // char cslash[] = "/"; /* Local variables */ double xmin, ymin, xmax, ymax, saveX, saveY, yprt; double bwidx, bwidy, xbest, ybest, ax, ay, bx, by; double xvalus[12], any, dxx, dyy; int iTen, i, j, k, maxnx, maxny, iquit, ni, linodd; int nxbest, nybest, km1, ibk, isp1, nx, ny, ks, ix; char ctemp[120]; bool overpr; char cline[120]; char chsav, chbest; /* Function Body */ //*-* Computing MIN maxnx = npagwd - 20 < 100 ? npagwd - 20 : 100; if (maxnx < 10) maxnx = 10; maxny = npagln; if (maxny < 10) maxny = 10; if (nxypt <= 1) return; xbest = xpt[0]; ybest = ypt[0]; chbest = chpt[0]; //*-*- order the points by decreasing y km1 = nxypt - 1; for (i = 1; i <= km1; ++i) { iquit = 0; ni = nxypt - i; for (j = 1; j <= ni; ++j) { if (ypt[j - 1] > ypt[j]) continue; saveX = xpt[j - 1]; xpt[j - 1] = xpt[j]; xpt[j] = saveX; saveY = ypt[j - 1]; ypt[j - 1] = ypt[j]; ypt[j] = saveY; chsav = chpt[j - 1]; chpt[j - 1] = chpt[j]; chpt[j] = chsav; iquit = 1; } if (iquit == 0) break; } //*-*- find extreme values xmax = xpt[0]; xmin = xmax; for (i = 1; i <= nxypt; ++i) { if (xpt[i - 1] > xmax) xmax = xpt[i - 1]; if (xpt[i - 1] < xmin) xmin = xpt[i - 1]; } dxx = (xmax - xmin) * .001; xmax += dxx; xmin -= dxx; mnbins(xmin, xmax, maxnx, xmin, xmax, nx, bwidx); ymax = ypt[0]; ymin = ypt[nxypt - 1]; if (ymax == ymin) ymax = ymin + 1; dyy = (ymax - ymin) * .001; ymax += dyy; ymin -= dyy; mnbins(ymin, ymax, maxny, ymin, ymax, ny, bwidy); any = (double)ny; //*-*- if first point is blank, it is an 'origin' if (chbest == ' ') goto L50; xbest = (xmax + xmin) * .5; ybest = (ymax + ymin) * .5; L50: //*-*- find Scale constants ax = 1 / bwidx; ay = 1 / bwidy; bx = -ax * xmin + 2; by = -ay * ymin - 2; //*-*- convert points to grid positions for (i = 1; i <= nxypt; ++i) { xpt[i - 1] = ax * xpt[i - 1] + bx; ypt[i - 1] = any - ay * ypt[i - 1] - by; } nxbest = int((ax * xbest + bx)); nybest = int((any - ay * ybest - by)); //*-*- print the points ny += 2; nx += 2; isp1 = 1; linodd = 1; overpr = false; for (i = 1; i <= ny; ++i) { for (ibk = 1; ibk <= nx; ++ibk) { cline[ibk - 1] = ' '; } cline[nx] = '\0'; cline[nx + 1] = '\0'; cline[0] = '.'; // not needed - but to avoid a wrongly reported compiler warning (see ROOT-6496) if (nx > 0) cline[nx - 1] = '.'; cline[nxbest - 1] = '.'; if (i != 1 && i != nybest && i != ny) goto L320; for (j = 1; j <= nx; ++j) { cline[j - 1] = '.'; } L320: yprt = ymax - double(i - 1) * bwidy; if (isp1 > nxypt) goto L350; //*-*- find the points to be plotted on this line for (k = isp1; k <= nxypt; ++k) { ks = int(ypt[k - 1]); if (ks > i) goto L345; ix = int(xpt[k - 1]); if (cline[ix - 1] == '.') goto L340; if (cline[ix - 1] == ' ') goto L340; if (cline[ix - 1] == chpt[k - 1]) continue; overpr = true; //*-*- OVERPR is true if one or more positions contains more than //*-*- one point cline[ix - 1] = '&'; continue; L340: cline[ix - 1] = chpt[k - 1]; } isp1 = nxypt + 1; goto L350; L345: isp1 = k; L350: if (linodd == 1 || i == ny) goto L380; linodd = 1; memcpy(ctemp, cline, 120); printf(" %s", (const char *)ctemp); goto L400; L380: // ctemp = cline; memcpy(ctemp, cline, 120); printf(" %14.7g ..%s", yprt, (const char *)ctemp); linodd = 0; L400: printf("\n"); } //*-*- print labels on x-axis every ten columns for (ibk = 1; ibk <= nx; ++ibk) { cline[ibk - 1] = ' '; if (ibk % 10 == 1) cline[ibk - 1] = '/'; } printf(" %s", cline); printf("\n"); for (ibk = 1; ibk <= 12; ++ibk) { xvalus[ibk - 1] = xmin + double(ibk - 1) * 10 * bwidx; } printf(" "); iTen = (nx + 9) / 10; for (ibk = 1; ibk <= iTen; ++ibk) { printf(" %9.4g", xvalus[ibk - 1]); } printf("\n"); if (overpr) { char chmess[] = " Overprint character is &"; printf(" ONE COLUMN=%13.7g%s", bwidx, (const char *)chmess); } else { char chmess[] = " "; printf(" ONE COLUMN=%13.7g%s", bwidx, (const char *)chmess); } printf("\n"); } /* mnplot_ */ } // namespace Minuit2 } // namespace ROOT �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mnvert.cxx����������������������������������������������0000644�0000000�0000000�00000004014�14332717401�017640� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #include "Minuit2/MnMatrix.h" #include namespace ROOT { namespace Minuit2 { /** Inverts a symmetric matrix. Matrix is first scaled to have all ones on the diagonal (equivalent to change of units) but no pivoting is done since matrix is positive-definite. */ int mnvert(MnAlgebraicSymMatrix &a) { unsigned int nrow = a.Nrow(); MnAlgebraicVector s(nrow); MnAlgebraicVector q(nrow); MnAlgebraicVector pp(nrow); for (unsigned int i = 0; i < nrow; i++) { double si = a(i, i); if (si < 0.) return 1; s(i) = 1. / std::sqrt(si); } for (unsigned int i = 0; i < nrow; i++) for (unsigned int j = i; j < nrow; j++) a(i, j) *= (s(i) * s(j)); for (unsigned i = 0; i < nrow; i++) { unsigned int k = i; if (a(k, k) == 0.) return 1; q(k) = 1. / a(k, k); pp(k) = 1.; a(k, k) = 0.; unsigned int kp1 = k + 1; if (k != 0) { for (unsigned int j = 0; j < k; j++) { pp(j) = a(j, k); q(j) = a(j, k) * q(k); a(j, k) = 0.; } } if (k != nrow - 1) { for (unsigned int j = kp1; j < nrow; j++) { pp(j) = a(k, j); q(j) = -a(k, j) * q(k); a(k, j) = 0.; } } for (unsigned int j = 0; j < nrow; j++) for (k = j; k < nrow; k++) a(j, k) += (pp(j) * q(k)); } for (unsigned int j = 0; j < nrow; j++) for (unsigned int k = j; k < nrow; k++) a(j, k) *= (s(j) * s(k)); return 0; } } // namespace Minuit2 } // namespace ROOT ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/extern/root/math/minuit2/src/mnxerbla.cxx��������������������������������������������0000644�0000000�0000000�00000004370�14332717401�020142� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ /* xerbla.f -- translated by f2c (version 20010320). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include "Minuit2/MnConfig.h" #include "Minuit2/MnPrint.h" namespace ROOT { namespace Minuit2 { /* Table of constant values */ // static integer c__1 = 1; int mnxerbla(const char *srname, int info) { /* Format strings */ // static char fmt_9999[] = "(\002 ** On entry to \002,a6,\002 Parameter nu\// mber \002,i2,\002 had \002,\002an // illegal Value\002)"; /* -- LAPACK auxiliary routine (version 3.0) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* September 30, 1994 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* XERBLA is an Error handler for the LAPACK routines. */ /* It is called by an LAPACK routine if an input Parameter has an */ /* invalid Value. A message is printed and execution stops. */ /* Installers may consider modifying the STOP statement in order to */ /* call system-specific exception-handling facilities. */ /* Arguments */ /* ========= */ /* SRNAME (input) CHARACTER*6 */ /* The Name of the routine which called XERBLA. */ /* INFO (input) INTEGER */ /* The position of the invalid Parameter in the Parameter list */ /* of the calling routine. */ /* ===================================================================== */ /* .. Executable Statements .. */ MnPrint print("mnxerbla"); print.Warn("On entry to", srname, "Parameter number", info, "had an illegal Value"); /* End of XERBLA */ return 0; } /* xerbla_ */ } // namespace Minuit2 } // namespace ROOT ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/noxfile.py���������������������������������������������������������������������������0000644�0000000�0000000�00000005724�14332717401�012231� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Noxfile for iminuit. Pass extra arguments to pytest after -- """ import nox import sys sys.path.append(".") import python_releases nox.needs_version = ">=2024.3.2" nox.options.default_venv_backend = "uv|virtualenv" ENV = { "JUPYTER_PLATFORM_DIRS": "1", # Hides warnings in Jupyter "COVERAGE_CORE": "sysmon", # faster coverage on Python 3.12 } PYPROJECT = nox.project.load_toml("pyproject.toml") MINIMUM_PYTHON = PYPROJECT["project"]["requires-python"].strip(">=") LATEST_PYTHON = str(python_releases.latest()) nox.options.sessions = ["test", "mintest", "maxtest"] @nox.session(reuse_venv=True) def test(session: nox.Session) -> None: """Run all tests.""" session.install("--only-binary=:all:", "-e.[test]") extra_args = session.posargs if session.posargs else ("-n=auto",) session.run("pytest", *extra_args, env=ENV) @nox.session(python=MINIMUM_PYTHON, venv_backend="uv") def mintest(session: nox.Session) -> None: """Run tests on the minimum python version.""" session.install("--only-binary=:all:", "-e.", "--resolution=lowest-direct") session.install("pytest", "pytest-xdist") extra_args = session.posargs if session.posargs else ("-n=auto",) session.run("pytest", *extra_args) @nox.session(python=LATEST_PYTHON) def maxtest(session: nox.Session) -> None: """Run the unit and regular tests.""" session.install( "--only-binary=:all:", "-e.", "scipy", "matplotlib", "pytest", "pytest-xdist", "--pre", ) extra_args = session.posargs if session.posargs else ("-n=auto",) session.run("pytest", *extra_args, env=ENV) @nox.session(python="pypy3.9") def pypy(session: nox.Session) -> None: """Run the unit and regular tests.""" session.install("-e.") session.install("pytest", "pytest-xdist") session.run("pytest", "-n=auto", *session.posargs) # Python-3.12 provides coverage info faster @nox.session(python="3.12", venv_backend="uv", reuse_venv=True) def cov(session: nox.Session) -> None: """Run covage and place in 'htmlcov' directory.""" session.install("--only-binary=:all:", "-e.[test,doc]") session.run("coverage", "run", "-m", "pytest", env=ENV) session.run("coverage", "html", "-d", "build/htmlcov") session.run("coverage", "report", "-m") # 3.11 needed by Cython notebook @nox.session(python="3.11", reuse_venv=True) def doc(session: nox.Session) -> None: """Build html documentation.""" session.install("--only-binary=:all:", "-e.[test,doc]") # link check session.run( "sphinx-build", "-T", # full tracebacks "-v", "-b=html", "doc", "build/html", ) @nox.session(python="3.11", reuse_venv=True) def links(session: nox.Session) -> None: """Check all links in the documentation.""" session.install("--only-binary=:all:", "-e.[test,doc]") # link check session.run( "sphinx-build", "-b=linkcheck", "doc", "build/html", ) ��������������������������������������������iminuit-2.30.1/pyproject.toml�����������������������������������������������������������������������0000644�0000000�0000000�00000007611�14332717401�013124� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[build-system] requires = ["scikit-build-core[pyproject]>=0.5", "pybind11>=2.12"] build-backend = "scikit_build_core.build" [project] name = "iminuit" description = "Jupyter-friendly Python frontend for MINUIT2 in C++" version = "2.30.1" maintainers = [{ name = "Hans Dembinski", email = "hans.dembinski@gmail.com" }] readme = "README.rst" requires-python = ">=3.9" license = { file = "LICENSE" } classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "Programming Language :: C++", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development", "Topic :: Scientific/Engineering :: Physics", "Topic :: Scientific/Engineering :: Mathematics", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: Unix", "Operating System :: MacOS", ] dependencies = ["numpy >=1.21"] [project.urls] repository = "http://github.com/scikit-hep/iminuit" documentation = "https://scikit-hep.org/iminuit" [project.optional-dependencies] test = [ "coverage", # ipywidgets 8.0.5 and 8.0.6 are broken # see https://github.com/jupyter-widgets/ipywidgets/issues/3731 "ipywidgets", # needed by ipywidgets >= 8.0.6 "ipykernel", "joblib", "jacobi", "matplotlib", "numpy", "numba; platform_python_implementation=='CPython'", "numba-stats; platform_python_implementation=='CPython'", "pytest", "pytest-xdist", "scipy", "tabulate", "boost_histogram", "resample", "unicodeitplus", "pydantic", "annotated_types", ] doc = [ "sphinx-rtd-theme", # installs correct sphinx as well "nbsphinx", "nbconvert", "nbformat", "jupyter_client", "ipykernel", "jax", "jaxlib", "pytest-xdist", ] [tool.scikit-build] minimum-version = "0.5" build-dir = "build/{wheel_tag}" sdist.exclude = ["extern/root"] sdist.include = ["extern/root/math/minuit2/inc", "extern/root/math/minuit2/src"] [tool.pytest.ini_options] minversion = "6.0" addopts = ["-q", "-ra", "--ff", "--strict-config", "--strict-markers"] log_cli_level = "INFO" testpaths = ["tests"] xfail_strict = true filterwarnings = [ "error::PendingDeprecationWarning", "error::DeprecationWarning", "error::FutureWarning", ] [tool.ruff] src = ["src"] [tool.ruff.lint] extend-select = [ "D", # pydocstyle ] ignore = [ "D212", # multi-line-summary-first-line ] pydocstyle.convention = "numpy" [tool.ruff.lint.per-file-ignores] "test_*.py" = ["B", "D"] "*.ipynb" = ["D"] "automatic_differentiation.ipynb" = ["F821"] "cython.ipynb" = ["F821"] ".ci/*.py" = ["D"] "bench/*.py" = ["D"] "doc/*.py" = ["D"] [tool.mypy] ignore_missing_imports = true allow_redefinition = true plugins = "numpy.typing.mypy_plugin" pretty = true files = ["src"] no_implicit_optional = false [tool.cibuildwheel] build-frontend = "build[uv]" skip = ["cp39-musllinux_i686"] # no numpy wheel test-requires = "pytest" test-command = "python -m pytest {package}/tests" test-skip = ["*universal2:arm64"] # to match numpy, we use manylinux2014 for cp310+ manylinux-x86_64-image = "manylinux2014" manylinux-i686-image = "manylinux2014" free-threaded-support = true [tool.cibuildwheel.environment] # this makes sure that we build only on platforms that have a corresponding numpy wheel PIP_ONLY_BINARY = ":all:" [[tool.cibuildwheel.overrides]] # to match numpy, we use manylinux2010 for cp36 to cp39 select = "cp3?-manylinux*" manylinux-x86_64-image = "manylinux2010" manylinux-i686-image = "manylinux2010" build-frontend = "build" �����������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/python_releases.py�������������������������������������������������������������������0000644�0000000�0000000�00000003457�14332717401�013772� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Get the latest Python release which is online.""" import urllib.request import re from html.parser import HTMLParser import gzip class PythonVersionParser(HTMLParser): """Specialized HTMLParser to get Python version number.""" def __init__(self): super().__init__() self.versions = set() self.found_version = False def handle_starttag(self, tag, attrs): """Look for the right tag and store result in an attribute.""" if tag == "a": for attr in attrs: if attr[0] == "href" and "/downloads/release/python-" in attr[1]: self.found_version = True return def handle_data(self, data): """Extract Python version from entry.""" if self.found_version: self.found_version = False match = re.search(r"Python (\d+)\.(\d+)\.(\d+)?", data) if match: major = int(match.group(1)) minor = int(match.group(2)) bugfix = int(match.group(3)) self.versions.add((major, minor, bugfix)) def versions(): """Get all Python release versions.""" req = urllib.request.Request("https://www.python.org/downloads/") req.add_header("Accept-Encoding", "gzip") with urllib.request.urlopen(req) as response: raw = response.read() if response.info().get("Content-Encoding") == "gzip": raw = gzip.decompress(raw) html = raw.decode("utf-8") parser = PythonVersionParser() parser.feed(html) return parser.versions def latest(): """Return version of latest Python release.""" return max(versions()) def main(): """Print all discovered release versions.""" for x in sorted(versions()): print(x) if __name__ == "__main__": main() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/application.cpp������������������������������������������������������������������0000644�0000000�0000000�00000000740�14332717401�014002� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "pybind11.hpp" #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void bind_application(py::module m) { py::class_(m, "MnApplication") .def("__call__", &MnApplication::operator()) .def_property("precision", &MnApplication::Precision, &MnApplication::SetPrecision) .def_property_readonly("strategy", &MnApplication::Strategy) ; } ��������������������������������iminuit-2.30.1/src/contours.cpp���������������������������������������������������������������������0000644�0000000�0000000�00000001205�14332717401�013350� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "pybind11.hpp" #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void bind_contours(py::module m) { py::class_(m, "MnContours") .def(py::init()) .def("__call__", [](const MnContours& self, unsigned ix, unsigned iy, unsigned npoints) { const auto ce = self.Contour(ix, iy, npoints); return py::make_tuple(ce.XMinosError(), ce.YMinosError(), ce()); }) ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/equal.cpp������������������������������������������������������������������������0000644�0000000�0000000�00000000510�14332717401�012601� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "equal.hpp" #include #include #include bool nan_equal(double a, double b) { return std::isnan(a) == std::isnan(b) || a == b; } namespace std { bool operator==(const vector& a, const vector& b) { return equal(a.begin(), a.end(), b.begin(), b.end()); } } // namespace std ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/equal.hpp������������������������������������������������������������������������0000644�0000000�0000000�00000003050�14332717401�012610� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef IMINUIT_EQUAL_HPP #define IMINUIT_EQUAL_HPP #include bool nan_equal(double a, double b); namespace std { bool operator==(const vector& a, const vector& b); } // namespace std namespace ROOT { namespace Minuit2 { class MnStrategy; bool operator==(const MnStrategy& a, const MnStrategy& b); class MinuitParameter; bool operator==(const MinuitParameter& a, const MinuitParameter& b); class MnUserCovariance; bool operator==(const MnUserCovariance& a, const MnUserCovariance& b); class MnUserParameterState; bool operator==(const MnUserParameterState& a, const MnUserParameterState& b); class MnMachinePrecision; bool operator==(const MnMachinePrecision& a, const MnMachinePrecision& b); class MnUserTransformation; bool operator==(const MnUserTransformation& a, const MnUserTransformation& b); class LAVector; bool operator==(const LAVector& a, const LAVector& b); class LASymMatrix; bool operator==(const LASymMatrix& a, const LASymMatrix& b); class MinimumError; bool operator==(const MinimumError& a, const MinimumError& b); class FunctionGradient; bool operator==(const FunctionGradient& a, const FunctionGradient& b); class MinimumParameters; bool operator==(const MinimumParameters& a, const MinimumParameters& b); class MinimumState; bool operator==(const MinimumState& a, const MinimumState& b); class MinimumSeed; bool operator==(const MinimumSeed& a, const MinimumSeed& b); class FunctionMinimum; bool operator==(const FunctionMinimum& a, const FunctionMinimum& b); } // namespace Minuit2 } // namespace ROOT #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/fcn.cpp��������������������������������������������������������������������������0000644�0000000�0000000�00000007571�14332717401�012256� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "fcn.hpp" #include "pybind11.hpp" #include #include #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; FCN::FCN(py::object fcn, py::object grad, bool array_call, double errordef) : fcn_{fcn}, grad_{grad}, array_call_{array_call}, errordef_{errordef} { auto util = py::module_::import("iminuit.util"); auto address_of_cfunc = util.attr("_address_of_cfunc"); auto address = py::cast(address_of_cfunc(fcn_)); if (address) { MnPrint("FCN").Debug("using cfunc"); cfcn_ = reinterpret_cast(address); array_call_ = true; } } double FCN::operator()(const std::vector& x) const { ++nfcn_; if (array_call_) { if (cfcn_) { return cfcn_(x.size(), x.data()); } else { py::array_t a(static_cast(x.size()), x.data()); return check_value(py::cast(fcn_(a)), x); } } return check_value(py::cast(fcn_(*py::cast(x))), x); } std::vector FCN::Gradient(const std::vector& x) const { ++ngrad_; if (array_call_) { py::array_t a(static_cast(x.size()), x.data()); return check_vector(py::cast>(grad_(a)), x); } return check_vector(py::cast>(grad_(*py::cast(x))), x); } double FCN::Up() const { return errordef_; } void set_errordef(FCN& self, double value) { if (value > 0) { self.SetUp(value); } else throw std::invalid_argument("errordef must be a positive number"); } std::string error_message(const std::vector& x) { std::ostringstream msg; msg << "result is NaN for [ "; for (auto&& xi : x) msg << xi << " "; msg << "]"; return msg.str(); } double FCN::check_value(double r, const std::vector& x) const { if (std::isnan(r)) { if (throw_nan_) throw std::runtime_error(error_message(x)); else { MnPrint("FCN").Warn([&](std::ostream& os) { os << error_message(x); }); } } return r; } std::vector FCN::check_vector(std::vector r, const std::vector& x) const { bool has_nan = false; for (auto&& ri : r) has_nan |= std::isnan(ri); if (has_nan) { if (throw_nan_) throw std::runtime_error(error_message(x)); else { MnPrint("FCN::Gradient").Warn([&](std::ostream& os) { os << error_message(x); }); } } return r; } double FCN::ndata() const { if (py::hasattr(fcn_, "ndata")) return py::cast(fcn_.attr("ndata")); return std::numeric_limits::quiet_NaN(); } void bind_fcn(py::module m) { py::class_(m, "FCNBase"); py::class_(m, "FCN") .def(py::init()) .def("gradient", &FCN::Gradient) .def("_ndata", &FCN::ndata) .def_readwrite("_nfcn", &FCN::nfcn_) .def_readwrite("_ngrad", &FCN::ngrad_) .def_readwrite("_throw_nan", &FCN::throw_nan_) .def_property("_errordef", &FCN::Up, &set_errordef) .def_readonly("_array_call", &FCN::array_call_) .def_readonly("_fcn", &FCN::fcn_) .def_readonly("_grad", &FCN::grad_) .def("__call__", &FCN::operator()) .def(py::pickle( [](const FCN& self) { return py::make_tuple(self.fcn_, self.grad_, self.array_call_, self.errordef_, self.throw_nan_, self.nfcn_, self.ngrad_); }, [](py::tuple tp) { if (tp.size() != 7) throw std::runtime_error("invalid state"); FCN fcn{tp[0], tp[1], tp[2].cast(), tp[3].cast()}; fcn.throw_nan_ = tp[4].cast(); fcn.nfcn_ = tp[5].cast(); fcn.ngrad_ = tp[6].cast(); return fcn; })) ; } ���������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/fcn.hpp��������������������������������������������������������������������������0000644�0000000�0000000�00000002544�14332717401�012256� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "pybind11.hpp" #include #include #include namespace py = pybind11; /** Function interface for Minuit2. Calls the underlying Python function which computes the objective function. The interface of this class is defined by the abstract base class FCNGradientBase, which itself derives from FCNBase. It calls the function with the parameter vector converted into positional arguments or by passing a single Numpy array, depending on the value of array_call_. */ struct FCN : ROOT::Minuit2::FCNGradientBase { FCN(py::object fcn, py::object grad, bool array_call, double errordef); double operator()(const std::vector& x) const override; std::vector Gradient(const std::vector&) const override; bool CheckGradient() const override { return false; } double Up() const override; void SetUp(double x) { errordef_ = x; } double check_value(double r, const std::vector& x) const; std::vector check_vector(std::vector r, const std::vector& x) const; double ndata() const; py::object fcn_, grad_; bool array_call_; mutable double errordef_; using cfcn_t = double (*)(std::uint32_t, const double*); cfcn_t cfcn_ = nullptr; bool throw_nan_ = false; mutable unsigned nfcn_ = 0, ngrad_ = 0; }; ������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/functionminimum.cpp��������������������������������������������������������������0000644�0000000�0000000�00000005320�14332717401�014717� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "equal.hpp" #include "fcn.hpp" #include "pybind11.hpp" #include #include #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; FunctionMinimum init(const FCN& fcn, const MnUserParameterState& st, const MnStrategy& str, double edm_goal); FunctionMinimum init2(const MnUserTransformation& tr, py::sequence par, py::sequence cov, py::sequence grad, double fval, double up, double edm_goal, int nfcn, int max_nfcn, bool exact_hess_inv); py::tuple fmin_getstate(const FunctionMinimum&); FunctionMinimum fmin_setstate(py::tuple); bool hesse_failed_workaround(const FunctionMinimum& self) { // Calling FunctionMinimum::HesseFailed is not reliable. // It calls MinimumError::HesseFailed, but this is false if // there were the failures MinimumError::MnReachedCallLimit // or MinimumError::MnInvertFailed, which cannot be queried // from FunctionMinimum. // // As a workaround, we return true if covariance exists, but // is not accurate or made positive definite. return self.HasCovariance() && !(self.HasPosDefCovar() || self.HasMadePosDefCovar()); } void bind_functionminimum(py::module m) { py::class_(m, "FunctionMinimum") .def(py::init(&init)) .def(py::init(&init2)) .def_property_readonly("state", &FunctionMinimum::UserState) .def_property_readonly("edm", &FunctionMinimum::Edm) .def_property_readonly("fval", &FunctionMinimum::Fval) .def_property_readonly("is_valid", &FunctionMinimum::IsValid) // No need to wrap HasValidParameters // .def_property_readonly("has_valid_parameters", // &FunctionMinimum::HasValidParameters) .def_property_readonly("has_accurate_covar", &FunctionMinimum::HasAccurateCovar) .def_property_readonly("has_posdef_covar", &FunctionMinimum::HasPosDefCovar) .def_property_readonly("has_made_posdef_covar", &FunctionMinimum::HasMadePosDefCovar) .def_property_readonly("hesse_failed", hesse_failed_workaround) .def_property_readonly("has_covariance", &FunctionMinimum::HasCovariance) .def_property_readonly("is_above_max_edm", &FunctionMinimum::IsAboveMaxEdm) .def_property_readonly("has_reached_call_limit", &FunctionMinimum::HasReachedCallLimit) .def_property("errordef", &FunctionMinimum::Up, &FunctionMinimum::SetErrorDef) .def(py::self == py::self) .def(py::pickle(&fmin_getstate, &fmin_setstate)) ; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/functionminimum_extra.cpp��������������������������������������������������������0000644�0000000�0000000�00000013533�14332717401�016127� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "equal.hpp" #include "fcn.hpp" #include "pybind11.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; MinimumSeed make_seed(const FCN& fcn, const MnUserFcn& mfcn, const MnUserParameterState& st, const MnStrategy& str) { MnSeedGenerator gen; if (fcn.grad_.is_none()) { Numerical2PGradientCalculator gc(mfcn, st.Trafo(), str); return gen(mfcn, gc, st, str); } AnalyticalGradientCalculator gc(fcn, st.Trafo()); return gen(mfcn, gc, st, str); } FunctionMinimum init(const FCN& fcn, const MnUserParameterState& st, const MnStrategy& str, double edm_goal) { MnUserFcn mfcn(fcn, st.Trafo()); MinimumSeed seed = make_seed(fcn, mfcn, st, str); const auto& val = seed.Parameters().Vec(); const auto n = seed.Trafo().VariableParameters(); MnAlgebraicVector err(n); for (unsigned int i = 0; i < n; i++) { err(i) = std::sqrt(2. * mfcn.Up() * seed.Error().InvHessian()(i, i)); } MinimumParameters minp(val, err, seed.Fval()); std::vector minstv(1, MinimumState(minp, seed.Edm(), fcn.nfcn_)); if (minstv.back().Edm() < edm_goal) return FunctionMinimum(seed, minstv, fcn.Up()); return FunctionMinimum(seed, minstv, fcn.Up(), FunctionMinimum::MnAboveMaxEdm); } FunctionMinimum init2(const MnUserTransformation& trafo, py::sequence py_par, py::sequence py_hess_inv, py::sequence py_grad, double fval, double up, double edm_goal, int nfcn, int max_nfcn, bool exact_hess_inv) { // if parameters are fixed, py_par, py_cov, and py_grad only contain free parameters const auto n = trafo.VariableParameters(); MnAlgebraicVector val{n}, step{n}, g{n}, g2{n}; MnAlgebraicSymMatrix hess_inv{n}; for (unsigned i = 0; i < n; ++i) { const auto iext = trafo.ExtOfInt(i); val(i) = trafo.Ext2int(iext, py_par[i].cast()); const auto di = trafo.DInt2Ext(i, val(i)); for (unsigned k = 0; k <= i; ++k) { const auto py_hess_invi = py_hess_inv[i].cast(); const auto dk = trafo.DInt2Ext(k, val(k)); hess_inv(i, k) = py_hess_invi[k].cast() / di / dk; } step(i) = std::sqrt(hess_inv(i, i)); g(i) = py_grad[i].cast() / di; // TODO: use diagonal elements of inverted IntCovariance for G2 g2(i) = 1.0 / step(i); } MinimumParameters minp{val, step, fval}; MinimumError err{hess_inv, exact_hess_inv ? 0. : 1.}; FunctionGradient grad{g, g2, step}; const double edm = VariableMetricEDMEstimator().Estimate(grad, err); MinimumState st{minp, err, grad, edm, nfcn}; MinimumSeed seed{st, trafo}; FunctionMinimum fm(seed, {}, up); if (nfcn > max_nfcn) fm.Add(st, FunctionMinimum::MnReachedCallLimit); else if (edm < edm_goal) fm.Add(st, FunctionMinimum::MnValid); else fm.Add(st, FunctionMinimum::MnAboveMaxEdm); return fm; } py::tuple seed2py(const MinimumSeed& seed) { return py::make_tuple(seed.State(), seed.Trafo(), seed.IsValid()); } MinimumSeed py2seed(py::tuple tp) { static_assert(std::is_standard_layout(), ""); MinimumSeed seed(tp[0].cast(), tp[1].cast()); struct Layout { MinimumState fState; MnUserTransformation fTrafo; bool fValid; }; auto& ptr = reinterpret_cast&>(seed); auto d = ptr.get(); d->fValid = tp[2].cast(); return seed; } namespace ROOT { namespace Minuit2 { bool operator==(const MnUserTransformation& a, const MnUserTransformation& b) { return a.Precision() == b.Precision() && a.Parameters() == b.Parameters(); } bool operator==(const LAVector& a, const LAVector& b) { return std::equal(a.Data(), a.Data() + a.size(), b.Data(), b.Data() + b.size()); } bool operator==(const LASymMatrix& a, const LASymMatrix& b) { return std::equal(a.Data(), a.Data() + a.size(), b.Data(), b.Data() + b.size()); } bool operator==(const MinimumError& a, const MinimumError& b) { return a.InvHessian() == b.InvHessian() && a.Dcovar() == b.Dcovar() && a.IsValid() == b.IsValid() && a.IsPosDef() == b.IsPosDef() && a.IsMadePosDef() == b.IsMadePosDef() && a.HesseFailed() == b.HesseFailed() && a.InvertFailed() == b.InvertFailed() && a.IsAvailable() == b.IsAvailable(); } bool operator==(const FunctionGradient& a, const FunctionGradient& b) { return a.Grad() == b.Grad() && a.G2() == b.G2() && a.Gstep() == b.Gstep() && a.IsValid() == b.IsValid() && a.IsAnalytical() == b.IsAnalytical(); } bool operator==(const MinimumParameters& a, const MinimumParameters& b) { return a.Vec() == b.Vec() && a.Dirin() == b.Dirin() && a.Fval() == b.Fval() && a.IsValid() == b.IsValid() && a.HasStepSize() == b.HasStepSize(); } bool operator==(const MinimumState& a, const MinimumState& b) { return a.Parameters() == b.Parameters() && a.Error() == b.Error() && a.Gradient() == b.Gradient() && a.Fval() == b.Fval() && a.Edm() == b.Edm() && a.NFcn() == b.NFcn(); } bool operator==(const MinimumSeed& a, const MinimumSeed& b) { return a.State() == b.State() && a.Trafo() == b.Trafo() && a.IsValid() == b.IsValid(); } bool operator==(const FunctionMinimum& a, const FunctionMinimum& b) { return a.Seed() == b.Seed() && a.Up() == b.Up() && a.States() == b.States() && a.IsAboveMaxEdm() == b.IsAboveMaxEdm() && a.HasReachedCallLimit() == b.HasReachedCallLimit() && a.UserState() == b.UserState(); } } // namespace Minuit2 } // namespace ROOT ���������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/functionminimum_pickle.cpp�������������������������������������������������������0000644�0000000�0000000�00000002645�14332717401�016255� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "pybind11.hpp" #include #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; py::tuple seed2py(const MinimumSeed& seed); MinimumSeed py2seed(py::tuple tp); py::tuple fmin_getstate(const FunctionMinimum& self) { return py::make_tuple(seed2py(self.Seed()), self.Up(), self.States(), self.IsAboveMaxEdm(), self.HasReachedCallLimit(), self.UserState()); } FunctionMinimum fmin_setstate(py::tuple tp) { static_assert(std::is_standard_layout(), ""); if (tp.size() != 6) throw std::runtime_error("invalid state"); struct Layout { MinimumSeed fSeed; std::vector fStates; double fErrorDef; bool fAboveMaxEdm; bool fReachedCallLimit; mutable MnUserParameterState fUserState; }; auto seed = py2seed(tp[0]); auto up = tp[1].cast(); FunctionMinimum fm(seed, up); // evil workaround, will segfault or cause UB if source layout changes auto& ptr = reinterpret_cast&>(fm); auto d = ptr.get(); d->fStates = tp[2].cast>(); d->fAboveMaxEdm = tp[3].cast(); d->fReachedCallLimit = tp[4].cast(); d->fUserState = tp[5].cast(); return fm; } �������������������������������������������������������������������������������������������iminuit-2.30.1/src/hesse.cpp������������������������������������������������������������������������0000644�0000000�0000000�00000002261�14332717401�012606� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "pybind11.hpp" #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void update_fmin(MnHesse& self, const FCNBase& fcn, FunctionMinimum& min, unsigned maxcalls, float maxedm) { // We reset call counter here in contrast to MnHesse.cxx:83 MnUserFcn mfcn(fcn, min.UserState().Trafo(), 0); // Run Hesse MinimumState st = self(mfcn, min.State(), min.UserState().Trafo(), maxcalls); // Need to re-evalute status of minimum, EDM could now be over max EDM or // maxcalls could be exhausted, see MnMigrad.cxx:187 const auto edm = st.Edm(); if (edm > 10 * maxedm) min.Add(st, FunctionMinimum::MnAboveMaxEdm); else if (st.Error().HasReachedCallLimit()) // communicate to user that call limit was reached in MnHesse min.Add(st, FunctionMinimum::MnReachedCallLimit); else if (st.Error().IsAvailable()) min.Add(st); } void bind_hesse(py::module m) { py::class_(m, "MnHesse") .def(py::init()) .def("__call__", update_fmin) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/iminuit/__init__.py��������������������������������������������������������������0000644�0000000�0000000�00000001316�14332717401�014562� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Jupyter-friendly Python interface for the Minuit2 library in C++. Basic usage example:: from iminuit import Minuit def fcn(x, y, z): return (x - 2) ** 2 + (y - 3) ** 2 + (z - 4) ** 2 m = Minuit(fcn, x=0, y=0, z=0) m.migrad() m.hesse() print(m.values) # 'x': 2, 'y': 3, 'z': 4 print(m.errors) # 'x': 1, 'y': 1, 'z': 1 Further information: * Code: https://github.com/scikit-hep/iminuit * Docs: https://scikit-hep.org/iminuit """ from iminuit.minuit import Minuit from iminuit.minimize import minimize from iminuit.util import describe from importlib import metadata __version__ = metadata.version("iminuit") __all__ = ["Minuit", "minimize", "describe", "__version__"] ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/iminuit/_deprecated.py�����������������������������������������������������������0000644�0000000�0000000�00000003476�14332717401�015273� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������import warnings from typing import Callable, Any from importlib.metadata import version from iminuit._parse_version import parse_version CURRENT_VERSION = parse_version(version("iminuit")) class deprecated: def __init__(self, reason: str, removal: str = ""): self.reason = reason self.removal = parse_version(removal) if removal else None def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]: category: Any = FutureWarning extra = "" if self.removal: vstring = ".".join(str(x) for x in self.removal) extra = f" and will be removed in version {vstring}" if CURRENT_VERSION >= self.removal: category = DeprecationWarning msg = f"{func.__name__} is deprecated{extra}: {self.reason}" def decorated_func(*args: Any, **kwargs: Any) -> Any: warnings.warn(msg, category=category, stacklevel=2) return func(*args, **kwargs) decorated_func.__name__ = func.__name__ decorated_func.__doc__ = msg return decorated_func class deprecated_parameter: def __init__(self, **replacements: str): self.replacements = replacements def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]: def decorated_func(*args: Any, **kwargs: Any) -> Any: for new, old in self.replacements.items(): if old in kwargs: warnings.warn( f"keyword {old!r} is deprecated, please use {new!r}", category=FutureWarning, stacklevel=2, ) kwargs[new] = kwargs[old] del kwargs[old] return func(*args, **kwargs) decorated_func.__name__ = func.__name__ return decorated_func ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/iminuit/_hide_modules.py���������������������������������������������������������0000644�0000000�0000000�00000001740�14332717401�015624� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������import sys import contextlib from importlib.abc import MetaPathFinder class HiddenModules(MetaPathFinder): def __init__(self, modules): super().__init__() self.modules = modules def find_spec(self, fullname, path, target=None): if fullname in self.modules: raise ModuleNotFoundError( f"{fullname!r} is hidden", name=fullname, path=path ) @contextlib.contextmanager def hide_modules(*modules, reload=None): saved = {} for m in tuple(sys.modules): for to_hide in modules: if m.startswith(to_hide): saved[m] = sys.modules[m] del sys.modules[m] sys.meta_path.insert(0, HiddenModules(modules)) if reload and reload in sys.modules: del sys.modules[reload] yield if reload and reload in sys.modules: del sys.modules[reload] sys.meta_path = sys.meta_path[1:] for name, mod in saved.items(): sys.modules[name] = mod ��������������������������������iminuit-2.30.1/src/iminuit/_optional_dependencies.py������������������������������������������������0000644�0000000�0000000�00000001322�14332717401�017512� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������import contextlib import warnings from iminuit.warnings import OptionalDependencyWarning from typing import Dict, Optional @contextlib.contextmanager def optional_module_for( functionality: str, *, replace: Optional[Dict[str, str]] = None, stacklevel: int = 3 ): try: yield except ModuleNotFoundError as e: assert e.name is not None package = e.name.split(".")[0] if replace: package = replace.get(package, package) msg = ( f"{functionality} requires optional package {package!r}. " f"Install {package!r} manually to enable this functionality." ) warnings.warn(msg, OptionalDependencyWarning, stacklevel=stacklevel) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/iminuit/_parse_version.py��������������������������������������������������������0000644�0000000�0000000�00000002030�14332717401�016033� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import Tuple, Union def parse_version(s: str) -> Union[Tuple[int, int], Tuple[int, int, int]]: """ Parse version string and return tuple of integer parts to allow for comparison. This does not implement the full version spec for version parsing, see https://packaging.python.org/en/latest/specifications/version-specifiers/. It is a simplified approach, so we do not have to depend on the external packaging module. We only support correct ordering for major, mior, and micro segments, ie. version strings of the form X.Y and X.Y.Z. Versions with pre- and post-release segments are correctly parsed, but these segments are ignored, as well as development release segments. """ match = re.match(r"(\d+)\.(\d+)(?:\.(\d+))?", s) if not match: msg = f"could not parse version string {s}" raise ValueError(msg) if match.group(3): return int(match.group(1)), int(match.group(2)), int(match.group(3)) return int(match.group(1)), int(match.group(2)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������iminuit-2.30.1/src/iminuit/_repr_html.py������������������������������������������������������������0000644�0000000�0000000�00000020125�14332717401�015155� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������from ._repr_text import pdg_format, matrix_format, fmin_fields, _parse_latex good_style = "background-color:#92CCA6;color:black" bad_style = "background-color:#c15ef7;color:black" warn_style = "background-color:#FFF79A;color:black" class ColorGradient: """Color gradient.""" _steps = None def __init__(self, *steps): self._steps = steps def __call__(self, v): st = self._steps z = 0.0 if v < st[0][0]: z = 0.0 i = 0 elif v >= st[-1][0]: z = 1.0 i = -2 else: i = 0 for i in range(len(st) - 1): if st[i][0] <= v < st[i + 1][0]: break z = (v - st[i][0]) / (st[i + 1][0] - st[i][0]) az = 1.0 - z a = st[i] b = st[i + 1] return (az * a[1] + z * b[1], az * a[2] + z * b[2], az * a[3] + z * b[3]) def rgb(self, v): return "rgb(%.0f,%.0f,%.0f)" % self(v) def to_str(tag): lines = [] def visit(x, level): indent = " " * level if len(x) == 1: lines.append(indent + x[0]) else: b, *ch, e = x lines.append(indent + b) for x in ch: visit(x, level + 1) lines.append(indent + e) visit(tag, 0) return "\n".join(lines) def tag(name, *args, **kwargs): # sort keys so that order is same on all platforms head = "<" + name for k in sorted(kwargs): v = kwargs[k] head += f' {k}="{v}"' head += ">" tail = "" % name if len(args) == 0: return [head + tail] if len(args) == 1 and isinstance(args[0], str): return ["{} {} {}".format(head, args[0], tail)] return [head, *args, tail] def table(*args, **kwargs): return tag("table", *args, **kwargs) def tr(*args, **kwargs): return tag("tr", *args, **kwargs) def th(*args, **kwargs): return tag("th", *args, **kwargs) def td(*args, **kwargs): return tag("td", *args, **kwargs) def good(x, should_be, alt_style=bad_style): return good_style if x == should_be else alt_style def fmin(fm): ff = fmin_fields(fm) if fm.hesse_failed: cov_style = bad_style elif fm.has_accurate_covar: cov_style = good_style else: cov_style = warn_style return to_str( table( tr( th( ff[0], colspan=2, style="text-align:center", title="Minimizer", ), ), tr( td( ff[1], style="text-align:left", title="Minimum value of function", ), td( ff[2], style="text-align:center", title=( "Total number of function and (optional) gradient evaluations" ), ), ), tr( td( ff[3], style="text-align:left", title="Estimated distance to minimum and goal", ), td( ff[4], style="text-align:center", title="Total run time of algorithms", ), ), tr( td( ff[5], style="text-align:center;" + good(fm.is_valid, True), ), td( ff[6], style="text-align:center;" + good(fm.is_above_max_edm, False), ), ), tr( td( ff[7], style="text-align:center;" + good(fm.has_parameters_at_limit, False, warn_style), ), td( ff[8], style="text-align:center;" + good(fm.has_reached_call_limit, False), ), ), tr( td(ff[9], style="text-align:center;" + cov_style), td(ff[10], style="text-align:center;" + cov_style), ), ) ) def params(mps): # body rows = [] for i, mp in enumerate(mps): me = mp.merror if me: v, e, mem, mep = pdg_format(mp.value, mp.error, *me) else: v, e = pdg_format(mp.value, mp.error) mem = "" mep = "" rows.append( tr( th(str(i)), td(_parse_latex(mp.name)), td(v), td(e), td(mem), td(mep), td("%.3G" % mp.lower_limit if mp.lower_limit is not None else ""), td("%.3G" % mp.upper_limit if mp.upper_limit is not None else ""), td("yes" if mp.is_fixed else ("CONST" if mp.is_const else "")), ) ) return to_str( table( # header tr( td(), th("Name", title="Variable name"), th("Value", title="Value of parameter"), th("Hesse Error", title="Hesse error"), th("Minos Error-", title="Minos lower error"), th("Minos Error+", title="Minos upper error"), th("Limit-", title="Lower limit of the parameter"), th("Limit+", title="Upper limit of the parameter"), th("Fixed", title="Is the parameter fixed in the fit"), ), # body *rows, ) ) def merrors(mes): mes = mes.values() header = [td()] error = [th("Error", title="Lower and upper minos error of the parameter")] valid = [th("Valid", title="Validity of lower/upper minos error")] limit = [th("At Limit", title="Did scan hit limit of any parameter?")] maxfcn = [th("Max FCN", title="Did scan hit function call limit?")] newmin = [th("New Min", title="New minimum found when doing scan?")] for me in mes: header.append( th( _parse_latex(me.name), colspan=2, title="Parameter name", style="text-align:center", ) ) error += [td(x) for x in pdg_format(None, me.lower, me.upper)] valid += [ td(str(x), style=good(x, True)) for x in (me.lower_valid, me.upper_valid) ] limit += [ td(str(x), style=good(x, False)) for x in (me.at_lower_limit, me.at_upper_limit) ] maxfcn += [ td(str(x), style=good(x, False)) for x in (me.at_lower_max_fcn, me.at_upper_max_fcn) ] newmin += [ td(str(x), style=good(x, False)) for x in (me.lower_new_min, me.upper_new_min) ] return to_str( table( tr(*header), tr(*error), tr(*valid), tr(*limit), tr(*maxfcn), tr(*newmin), ) ) def matrix(arr): names = [_parse_latex(x) for x in arr._var2pos] n = len(names) nums = matrix_format(arr) grad = ColorGradient( (-1.0, 120.0, 120.0, 250.0), (0.0, 250.0, 250.0, 250.0), (1.0, 250.0, 100.0, 100.0), ) rows = [] for i, v in enumerate(names): cols = [th(v)] di = arr[i, i] ** 0.5 for j in range(len(names)): val = arr[i, j] dj = arr[j, j] ** 0.5 if i == j: t = td(nums[n * i + j]) else: corr = val / (di * dj + 1e-100) color = grad.rgb(corr) t = td( nums[n * i + j] + ( f" ({corr:.3f})" if abs(corr - val) > 1e-3 else "" ), style="background-color:" + color + ";color:black", ) cols.append(t) rows.append(tr(*cols)) return to_str(table(tr(td(), *[th(v) for v in names]), *rows)) iminuit-2.30.1/src/iminuit/_repr_text.py0000644000000000000000000001634614332717401015207 0ustar00from .pdg_format import _round, _strip from iminuit._optional_dependencies import optional_module_for import re import numpy as np def pdg_format(value, *errors): if value is None: strings, nexp = _round((0, *errors), None, None) strings = strings[1:] else: strings, nexp = _round((value, *errors), None, None) strings = _strip(strings) if nexp != 0: for i, s in enumerate(strings): if s[-1] in "fn": continue m = None if i == 0: m = re.match(r"(-?)0\.0+$", s) if m: s = m.group(1) + "0" suffix = "" if not m: suffix = "e%i" % nexp s += suffix strings[i] = s return strings def format_row(widths, *args) -> str: return ( "".join( ("│{0:^%i}" % w if w > 0 else "│ {0:%i}" % (-w - 1)).format(a) for (w, a) in zip(widths, args) ) + "│" ) def format_line(widths, edges): s = edges[0] for w, e in zip(widths, edges[1:]): s += "─" * abs(w) s += e return s def fmin_fields(fm): rc = fm.reduced_chi2 s_ncall = f"Nfcn = {fm.nfcn}" if fm.ngrad > 0: s_ncall += f", Ngrad = {fm.ngrad}" if fm.hesse_failed: covariance_msg1 = "Hesse FAILED" if fm.has_reached_call_limit: covariance_msg2 = "ABOVE call limit" else: assert not fm.has_posdef_covar covariance_msg2 = "Covariance NOT pos. def." else: if fm.has_covariance: covariance_msg1 = "Hesse ok" if fm.has_accurate_covar: covariance_msg2 = "Covariance accurate" elif fm.has_made_posdef_covar: covariance_msg2 = "Covariance FORCED pos. def." else: covariance_msg2 = "Covariance APPROXIMATE" else: covariance_msg1 = "Hesse not run" covariance_msg2 = "NO covariance" return [ f"{fm.algorithm}", f"FCN = {fm.fval:.4g}" + (f" (χ²/ndof = {rc:.1f})" if not np.isnan(rc) else ""), s_ncall, f"EDM = {fm.edm:.3g} (Goal: {fm.edm_goal:.3g})", f"time = {fm.time:.1f} sec" if fm.time >= 0.1 else "", f"{'Valid' if fm.is_valid else 'INVALID'} Minimum", f"{'ABOVE' if fm.is_above_max_edm else 'Below'} EDM threshold (goal x 10)", f"{'SOME' if fm.has_parameters_at_limit else 'No'} parameters at limit", f"{'ABOVE' if fm.has_reached_call_limit else 'Below'} call limit", covariance_msg1, covariance_msg2, ] def fmin(fm): ff = fmin_fields(fm) w = (73,) l1 = format_line(w, "┌â”") i1 = format_row(w, ff[0] + " ") w = (-34, 38) l2 = format_line(w, "├┬┤") i2 = format_row(w, *ff[1:3]) i3 = format_row(w, *ff[3:5]) w = (34, 38) l3 = format_line(w, "├┼┤") v1 = format_row(w, *ff[5:7]) l4 = format_line(w, "├┼┤") v2 = format_row(w, *ff[7:9]) l5 = format_line(w, "├┼┤") v3 = format_row(w, *ff[9:]) l6 = format_line(w, "└┴┘") return "\n".join((l1, i1, l2, i2, i3, l3, v1, l4, v2, l5, v3, l6)) def params(mps): vnames = [_parse_latex(mp.name) for mp in mps] name_width = max([4] + [len(x) for x in vnames]) num_width = max(2, len(f"{len(mps) - 1}")) ws = (-num_width - 1, -name_width - 2, 11, 11, 12, 12, 9, 9, 7) h = format_row( ws, "", "Name", "Value", "Hesse Err", "Minos Err-", "Minos Err+", "Limit-", "Limit+", "Fixed", ) ni = len(ws) - 1 l1 = format_line(ws, "┌" + "┬" * ni + "â”") l2 = format_line(ws, "├" + "┼" * ni + "┤") lines = [l1, h, l2] for i, mp in enumerate(mps): me = mp.merror if me: val, err, mel, meu = pdg_format(mp.value, mp.error, *me) else: val, err = pdg_format(mp.value, mp.error) mel = "" meu = "" lines.append( format_row( ws, str(i), vnames[i], val, err, mel, meu, "%g" % mp.lower_limit if mp.lower_limit is not None else "", "%g" % mp.upper_limit if mp.upper_limit is not None else "", "yes" if mp.is_fixed else "CONST" if mp.is_const else "", ) ) ln3 = format_line(ws, "â””" + "â”´" * ni + "┘") lines.append(ln3) return "\n".join(lines) def merrors(mes): mes = mes.values() n = len(mes) ws = [10] + [23] * n l1 = format_line(ws, "┌" + "┬" * n + "â”") header = format_row(ws, "", *(_parse_latex(m.name) for m in mes)) ws = [10] + [11] * (2 * n) l2 = format_line(ws, "├" + "┼┬" * n + "┤") l3 = format_line(ws, "â””" + "â”´" * n * 2 + "┘") x = [] for m in mes: mel, meu = pdg_format(None, m.lower, m.upper) x.append(mel) x.append(meu) error = format_row(ws, "Error", *x) x = [] for m in mes: x.append(str(m.lower_valid)) x.append(str(m.upper_valid)) valid = format_row(ws, "Valid", *x) x = [] for m in mes: x.append(str(m.at_lower_limit)) x.append(str(m.at_upper_limit)) at_limit = format_row(ws, "At Limit", *x) x = [] for m in mes: x.append(str(m.at_lower_max_fcn)) x.append(str(m.at_upper_max_fcn)) max_fcn = format_row(ws, "Max FCN", *x) x = [] for m in mes: x.append(str(m.lower_new_min)) x.append(str(m.upper_new_min)) new_min = format_row(ws, "New Min", *x) return "\n".join((l1, header, l2, error, valid, at_limit, max_fcn, new_min, l3)) def matrix(arr): names = [_parse_latex(x) for x in arr._var2pos] n = len(arr) nums = matrix_format(arr) def row_fmt(args): s = "│ " + args[0] + " │" for x in args[1:]: s += " " + x s += " │" return s first_row_width = max(len(v) for v in names) row_width = max(first_row_width, max(len(v) for v in nums)) v_names = [("{:>%is}" % first_row_width).format(x) for x in names] h_names = [("{:>%is}" % row_width).format(x) for x in names] val_fmt = ("{:>%is}" % row_width).format w = (first_row_width + 2, (row_width + 1) * len(names) + 1) l1 = format_line(w, "┌┬â”") l2 = format_line(w, "├┼┤") l3 = format_line(w, "└┴┘") header = row_fmt([" " * first_row_width] + h_names) lines = [l1, header, l2] for i, vn in enumerate(v_names): lines.append(row_fmt([vn] + [val_fmt(nums[n * i + j]) for j in range(n)])) lines.append(l3) return "\n".join(lines) def matrix_format(matrix): r = [] for i in range(matrix.shape[0]): for j in range(matrix.shape[1]): if i == j: r.append(f"{matrix[i, i]:.3g}") else: x = pdg_format(matrix[i, j], matrix[i, i], matrix[j, j])[0] r.append(x) return r def _parse_latex(s): if s.startswith("$") and s.endswith("$"): with optional_module_for("rendering simple LaTeX"): import unicodeitplus return unicodeitplus.parse(s) return s iminuit-2.30.1/src/iminuit/cost.py0000644000000000000000000026505514332717401014007 0ustar00""" Standard cost functions to minimize for statistical fits. We provide these for convenience, so that you do not have to write your own for standard fits. The cost functions optionally use Numba to accelerate some calculations, if Numba is installed. **There is no need** to set :attr:`iminuit.Minuit.errordef` manually for any of these cost functions. :class:`iminuit.Minuit` automatically uses the correct value, which is provided by each cost function with the attribute ``Cost.errordef``. What to use when ---------------- - Fit a normalised probability density to data - Data are not binned: :class:`UnbinnedNLL` - Data are binned: :class:`BinnedNLL`, also supports histogram of weighted samples - Fit a density to data, density is not normalised - Data are not binned: :class:`ExtendedUnbinnedNLL` - Data are binned: :class:`ExtendedBinnedNLL`, also supports histogram of weighted samples - Fit a template to binned data with bin-wise uncertainties on the template - :class:`Template`, also supports weighted data and weighted template histograms - Fit of a function f(x) to (x, y, yerror) pairs with normal-distributed fluctuations. x is one- or multi-dimensional, y is one-dimensional. - y values contain no outliers: :class:`LeastSquares` - y values contain outliers: :class:`LeastSquares` with loss function set to "soft_l1" - Include constraints from external fits or apply regularisation - :class:`NormalConstraint` Combining cost functions ------------------------ All cost functions can be added, which generates a new combined cost function. Parameters with the same name are shared between component cost functions. Use this to constrain one or several parameters with different data sets and using different statistical models for each data set. Gaussian penalty terms can also be added to the cost function to introduce external knowledge about a parameter. Model parameter limits ---------------------- The Minuit algorithms support box constrains in parameter space. A user-defined model can declare that a parameter is only valid over an interval on the real line with the ``Annotated`` type annotation, see :class:`iminuit.Minuit` for details. A typical example is the sigma parameter of a normal distribution, which must be positive. The cost functions defined here propagate this information to :class:`iminuit.Minuit`. Note: The :class:`Template` declares that the template amplitudes must be non-negative, which is usually the right choice, however, it may be desirable to fit templates which can have negative amplitudes. To achieve this, simply reset the limits with :attr:`iminuit.Minuit.limits` after creating the Minuit instance. User-defined gradients ---------------------- If the user provides a model gradient, the cost functions defined here except :class:`Template` will then also make their gradient available, which is then automatically used by :class:`iminuit.Minuit` (see the constructor for details) to potentially improve the fit (improve convergence or robustness). Note that it is perfectly normal to use Minuit without a user-defined gradient, and Minuit does not always benefit from a user-defined gradient. If the gradient is expensive to compute, the time to converge may increase. If you have trouble with the fitting process, it is unlikely that the issues are resolved by a user-defined gradient. Notes ----- The cost functions defined here have been optimized with knowledge about implementation details of Minuit to give the highest accucary and the most robust results, so they should perform well. If you have trouble with your own implementations, try these. The binned versions of the log-likelihood fits support weighted samples. For each bin of the histogram, the sum of weights and the sum of squared weights is needed then, see class documentation for details. """ from __future__ import annotations from .util import ( describe, merge_signatures, PerformanceWarning, _smart_sampling, _detect_log_spacing, is_positive_definite, ) from .typing import Model, ModelGradient, LossFunction import numpy as np from numpy.typing import NDArray, ArrayLike from collections.abc import Sequence as ABCSequence import abc from typing import ( List, Tuple, Union, Sequence, Collection, Dict, Any, Iterable, Optional, TypeVar, Callable, cast, ) import warnings from ._deprecated import deprecated_parameter __all__ = [ "CHISQUARE", "NEGATIVE_LOG_LIKELIHOOD", "chi2", "multinomial_chi2", "poisson_chi2", "template_chi2_jsc", "template_chi2_da", "template_nll_asy", "Cost", "CostSum", "Constant", "BinnedNLL", "UnbinnedNLL", "ExtendedBinnedNLL", "ExtendedUnbinnedNLL", "Template", "LeastSquares", ] T = TypeVar("T", float, NDArray) CHISQUARE = 1.0 NEGATIVE_LOG_LIKELIHOOD = 0.5 _TINY_FLOAT = np.finfo(float).tiny def log_or_zero(x): """ Evaluate to log(x) for x > 0 and to 0 otherwise. Parameters ---------- x : array Argument. Returns ------- array Elementwise contains log(x) for x > 0 and zero otherwise. """ # return 0 for x <= 0 r = np.zeros_like(x) ma = x > 0 r[ma] = np.log(x[ma]) return r def _unbinned_nll(x): # sorting makes sum more accurate, protect against x = 0 return -np.sum(np.sort(np.log(x + _TINY_FLOAT))) def _z_squared(y, ye, ym): z = (y - ym) / ye return z * z def _replace_none(x, replacement): if x is None: return replacement return x def chi2(y: ArrayLike, ye: ArrayLike, ym: ArrayLike) -> float: """ Compute (potentially) chi2-distributed cost. The value returned by this function is chi2-distributed, if the observed values are normally distributed around the expected values with the provided standard deviations. Parameters ---------- y : array-like with shape (N,) Observed values. ye : array-like with shape (N,) Uncertainties of values. ym : array-like with shape (N,) Expected values. Returns ------- float Value of cost function. """ y, ye, ym = np.atleast_1d(y, ye, ym) assert y.ndim == 1 return np.sum(_z_squared(y, ye, ym)) def _chi2_grad(y: ArrayLike, ye: ArrayLike, ym: ArrayLike, gym: ArrayLike) -> NDArray: """ Compute gradient of :func:`chi2`. Parameters ---------- y : array-like with shape (N,) Observed values. ye : array-like with shape (N,) Uncertainties of values. ym : array-like with shape (N,) Expected values. gym : array-like with shape (K, N) Gradient of ym with respect to K model parameters. Returns ------- array with shape (K,) Gradient of cost function with respect to model parameters. """ y, ye, ym, gym = np.atleast_1d(y, ye, ym, gym) assert y.ndim == 1 assert gym.ndim == 2 return -2 * np.sum((y - ym) * gym * ye**-2, axis=1) def _soft_l1_cost(y: NDArray, ye: NDArray, ym: NDArray) -> float: z_sqr = _z_squared(y, ye, ym) return 2 * np.sum(np.sqrt(1 + z_sqr) - 1) def _soft_l1_cost_grad(y: NDArray, ye: NDArray, ym: NDArray, gym: NDArray) -> NDArray: inv_ye = 1 / ye z = (y - ym) * inv_ye f = (1 + z**2) ** -0.5 return -2 * np.sum(z * inv_ye * f * gym, axis=tuple(range(1, gym.ndim))) def poisson_chi2(n: ArrayLike, mu: ArrayLike) -> float: """ Compute asymptotically chi2-distributed cost for Poisson-distributed data. See Baker & Cousins, NIM 221 (1984) 437-442. Parameters ---------- n : array-like Observed counts. mu : array-like Expected counts per bin. Must satisfy sum(mu) == sum(n). Returns ------- float Cost function value. Notes ----- The implementation makes the result asymptotically chi2-distributed, which helps to maximise the numerical accuracy for Minuit. """ n, mu = np.atleast_1d(n, mu) return 2 * np.sum(n * (log_or_zero(n) - log_or_zero(mu)) + mu - n) def _poisson_chi2_grad(n: NDArray, mu: NDArray, gmu: NDArray) -> NDArray: assert gmu.ndim == 2 return 2 * np.sum((1.0 - n / mu) * gmu, axis=1) def multinomial_chi2(n: ArrayLike, mu: ArrayLike) -> float: """ Compute asymptotically chi2-distributed cost for multinomially-distributed data. See Baker & Cousins, NIM 221 (1984) 437-442. Parameters ---------- n : array-like Observed counts. mu : array-like Expected counts. Returns ------- float Cost function value. Notes ----- The implementation makes the result asymptotically chi2-distributed, which helps to maximise the numerical accuracy for Minuit. """ n, mu = np.atleast_1d(n, mu) return 2 * np.sum(n * (log_or_zero(n) - log_or_zero(mu))) def _multinomial_chi2_grad(n: NDArray, mu: NDArray, gmu: NDArray) -> NDArray: assert gmu.ndim == 2 return -2 * np.sum(n / mu * gmu, axis=1) def template_chi2_jsc(n: ArrayLike, mu: ArrayLike, mu_var: ArrayLike) -> float: """ Compute asymptotically chi2-distributed cost for a template fit. J.S. Conway, PHYSTAT 2011, https://doi.org/10.48550/arXiv.1103.0354 Parameters ---------- n : array-like Observed counts. mu : array-like Expected counts. This is the sum of the normalised templates scaled with the component yields. Must be positive everywhere. mu_var : array-like Expected variance of mu. Must be positive everywhere. Returns ------- float Asymptotically chi-square-distributed test statistic. Notes ----- The implementation deviates slightly from the paper by making the result asymptotically chi2-distributed, which helps to maximise the numerical accuracy for Minuit. """ n, mu, mu_var = np.atleast_1d(n, mu, mu_var) beta_var = mu_var / mu**2 # Eq. 15 from https://doi.org/10.48550/arXiv.2206.12346 p = 0.5 - 0.5 * mu * beta_var beta = p + np.sqrt(p**2 + n * beta_var) return poisson_chi2(n, mu * beta) + np.sum((beta - 1) ** 2 / beta_var) def template_chi2_da(n: ArrayLike, mu: ArrayLike, mu_var: ArrayLike) -> float: """ Compute asymptotically chi2-distributed cost for a template fit. H.P. Dembinski, A. Abdelmotteleb, https://doi.org/10.48550/arXiv.2206.12346 Parameters ---------- n : array-like Observed counts. mu : array-like Expected counts. This is the sum of the normalised templates scaled with the component yields. mu_var : array-like Expected variance of mu. Must be positive everywhere. Returns ------- float Asymptotically chi-square-distributed test statistic. """ n, mu, mu_var = np.atleast_1d(n, mu, mu_var) k = mu**2 / mu_var # avoid divide by zero beta = (n + k) / (mu + k + _TINY_FLOAT) return poisson_chi2(n, mu * beta) + poisson_chi2(k, k * beta) def template_nll_asy(n: ArrayLike, mu: ArrayLike, mu_var: ArrayLike) -> float: """ Compute marginalized negative log-likelikihood for a template fit. This is the negative logarithm of equation 3.15 of the paper by C.A. Argüelles, A. Schneider, T. Yuan, https://doi.org/10.1007/JHEP06(2019)030. The authors use a Bayesian approach and integrate over the nuisance parameters. Like the other Barlow-Beeston-lite methods, this is an approximation. The resulting likelihood cannot be turned into an asymptotically chi-square distributed test statistic as detailed in Baker & Cousins, NIM 221 (1984) 437-442. Parameters ---------- n : array-like Observed counts. mu : array-like Expected counts. This is the sum of the normalised templates scaled with the component yields. mu_var : array-like Expected variance of mu. Must be positive everywhere. Returns ------- float Negative log-likelihood function value. """ from scipy.special import loggamma as lg n, mu, mu_var = np.atleast_1d(n, mu, mu_var) alpha = mu**2 / mu_var + 1 beta = mu / mu_var return -np.sum( alpha * np.log(beta) + lg(n + alpha) - (lg(n + 1) + (n + alpha) * np.log(1 + beta) + lg(alpha)) ) # If numba is available, use it to accelerate computations in float32 and float64 # precision. Fall back to plain numpy for float128 which is not currently supported # by numba. try: from numba import njit from numba.extending import overload as nb_overload jit = njit(nogil=True, cache=True, error_model="numpy") @nb_overload(log_or_zero, inline="always") def _ol_log_or_zero(x): return log_or_zero # pragma: no cover @nb_overload(_z_squared, inline="always") def _ol_z_squared(y, ye, ym): return _z_squared # pragma: no cover _unbinned_nll_np = _unbinned_nll _unbinned_nll_nb = jit(_unbinned_nll_np) def _unbinned_nll(x): if x.dtype in (np.float32, np.float64): return _unbinned_nll_nb(x) # fallback to numpy for float128 return _unbinned_nll_np(x) _multinomial_chi2_np = multinomial_chi2 _multinomial_chi2_nb = jit(_multinomial_chi2_np) def multinomial_chi2(n: ArrayLike, mu: ArrayLike) -> float: # noqa n, mu = np.atleast_1d(n, mu) if mu.dtype in (np.float32, np.float64): return _multinomial_chi2_nb(n, mu) # fallback to numpy for float128 return _multinomial_chi2_np(n, mu) multinomial_chi2.__doc__ = _multinomial_chi2_np.__doc__ _poisson_chi2_np = poisson_chi2 _poisson_chi2_nb = jit(_poisson_chi2_np) def poisson_chi2(n: ArrayLike, mu: ArrayLike) -> float: # noqa n, mu = np.atleast_1d(n, mu) if mu.dtype in (np.float32, np.float64): return _poisson_chi2_nb(n, mu) # fallback to numpy for float128 return _poisson_chi2_np(n, mu) poisson_chi2.__doc__ = _poisson_chi2_np.__doc__ _chi2_np = chi2 _chi2_nb = jit(_chi2_np) def chi2(y: ArrayLike, ye: ArrayLike, ym: ArrayLike) -> float: # noqa y, ye, ym = np.atleast_1d(y, ye, ym) if ym.dtype in (np.float32, np.float64): return _chi2_nb(y, ye, ym) # fallback to numpy for float128 return _chi2_np(y, ye, ym) chi2.__doc__ = _chi2_np.__doc__ _soft_l1_cost_np = _soft_l1_cost _soft_l1_cost_nb = jit(_soft_l1_cost_np) def _soft_l1_cost(y: NDArray, ye: NDArray, ym: NDArray) -> float: if ym.dtype in (np.float32, np.float64): return _soft_l1_cost_nb(y, ye, ym) # fallback to numpy for float128 return _soft_l1_cost_np(y, ye, ym) except ModuleNotFoundError: pass class Cost(abc.ABC): """ Base class for all cost functions. :meta private: """ __slots__ = ("_parameters", "_verbose") _parameters: Dict[str, Optional[Tuple[float, float]]] _verbose: int @property def errordef(self): """ For internal use. :meta private: """ return self._errordef() def _errordef(self): return CHISQUARE @property def ndata(self): """ Return number of points in least-squares fits or bins in a binned fit. Infinity is returned if the cost function is unbinned. This is used by Minuit to compute the reduced chi2, a goodness-of-fit estimate. """ return self._ndata() @property def npar(self): """Return total number of model parameters.""" return len(self._parameters) @abc.abstractmethod def _ndata(self): NotImplemented # pragma: no cover @property def verbose(self): """ Access verbosity level. Set this to 1 to print all function calls with input and output. """ return self._verbose @verbose.setter def verbose(self, value: int): self._verbose = value def __init__( self, parameters: Dict[str, Optional[Tuple[float, float]]], verbose: int ): """For internal use.""" self._parameters = parameters self._verbose = verbose def __add__(self, rhs): """ Add two cost functions to form a combined cost function. Returns ------- CostSum """ return CostSum(self, rhs) def __radd__(self, lhs): """ Add two cost functions to form a combined cost function. Returns ------- CostSum """ return CostSum(lhs, self) def __call__(self, *args: float) -> float: """ Evaluate the cost function. If verbose >= 1, print arguments and result. Parameters ---------- *args : float Parameter values. Returns ------- float """ r = self._value(args) if self.verbose >= 1: print(args, "->", r) return r def grad(self, *args: float) -> NDArray: """ Compute gradient of the cost function. This requires that a model gradient is provided. Parameters ---------- *args : float Parameter values. Returns ------- ndarray of float The length of the array is equal to the length of args. """ return self._grad(args) @property def has_grad(self) -> bool: """Return True if cost function can compute a gradient.""" return self._has_grad() @abc.abstractmethod def _value(self, args: Sequence[float]) -> float: ... # pragma: no cover @abc.abstractmethod def _grad(self, args: Sequence[float]) -> NDArray: ... # pragma: no cover @abc.abstractmethod def _has_grad(self) -> bool: ... # pragma: no cover class Constant(Cost): """ Cost function that represents a constant. If your cost function produces results that are far away from O(1), adding a constant that brings the value closer to zero may improve the numerical stability. """ __slots__ = "value" def __init__(self, value: float): """Initialize constant with a value.""" self.value = value super().__init__({}, False) def _ndata(self): return 0 def _value(self, args: Sequence[float]) -> float: return self.value def _grad(self, args: Sequence[float]) -> NDArray: return np.zeros(0) @staticmethod def _has_grad(): return True class CostSum(Cost, ABCSequence): """ Sum of cost functions. Users do not need to create objects of this class themselves. They should just add cost functions, for example:: nll = UnbinnedNLL(...) lsq = LeastSquares(...) ncs = NormalConstraint(...) csum = nll + lsq + ncs CostSum is used to combine data from different experiments or to combine normal cost functions with penalty terms (see NormalConstraint). The parameters of CostSum are the union of all parameters of its constituents. Supports the sequence protocol to access the constituents. Warnings -------- CostSum does not support cost functions that accept a parameter array, because the function signature does not allow one to determine how many parameters are accepted by the function and which parameters overlap between different cost functions. """ __slots__ = "_items", "_maps" def __init__(self, *items: Union[Cost, float]): """ Initialize with cost functions. Parameters ---------- *items : Cost Cost functions. May also be other CostSum functions. """ self._items: List[Cost] = [] for item in items: if isinstance(item, CostSum): self._items += item._items elif isinstance(item, (int, float)): if item != 0: self._items.append(Constant(item)) else: self._items.append(item) signatures, self._maps = merge_signatures(self._items, annotations=True) super().__init__(signatures, max(c.verbose for c in self._items)) def _split(self, args: Sequence[float]): for component, cmap in zip(self._items, self._maps): component_args = tuple(args[i] for i in cmap) yield component, component_args def _value(self, args: Sequence[float]) -> float: r = 0.0 for component, component_args in self._split(args): r += component._value(component_args) / component.errordef return r def _grad(self, args: Sequence[float]) -> NDArray: r = np.zeros(self.npar) for component, indices in zip(self._items, self._maps): component_args = tuple(args[i] for i in indices) r[indices] += component._grad(component_args) / component.errordef return r def _has_grad(self) -> bool: return all(component.has_grad for component in self._items) def _ndata(self): return sum(c.ndata for c in self._items) def __len__(self): """Return number of constituent cost functions.""" return self._items.__len__() def __getitem__(self, key): """Get constituent cost function by index.""" return self._items.__getitem__(key) def visualize( self, args: Sequence[float], component_kwargs: Dict[int, Dict[str, Any]] = None ): """ Visualize data and model agreement (requires matplotlib). The visualization is drawn with matplotlib.pyplot into the current figure. Subplots are created to visualize each part of the cost function, the figure height is increased accordingly. Parts without a visualize method are silently ignored. Parameters ---------- args : array-like Parameter values. component_kwargs : dict of dicts, optional Dict that maps an index to dict of keyword arguments. This can be used to pass keyword arguments to a visualize method of a component with that index. **kwargs : Other keyword arguments are forwarded to all components. """ from matplotlib import pyplot as plt n = sum(hasattr(comp, "visualize") for comp in self) fig = plt.gcf() fig.set_figwidth(n * fig.get_figwidth() / 1.5) _, ax = plt.subplots(1, n, num=fig.number) if component_kwargs is None: component_kwargs = {} i = 0 for k, (comp, cargs) in enumerate(self._split(args)): if not hasattr(comp, "visualize"): continue kwargs = component_kwargs.get(k, {}) plt.sca(ax[i]) comp.visualize(cargs, **kwargs) i += 1 class MaskedCost(Cost): """ Base class for cost functions that support data masking. :meta private: """ __slots__ = "_data", "_mask", "_masked" _mask: Optional[NDArray] def __init__( self, parameters: Dict[str, Optional[Tuple[float, float]]], data: NDArray, verbose: int, ): """For internal use.""" self._data = data self._mask = None self._update_cache() Cost.__init__(self, parameters, verbose) @property def mask(self): """ Boolean array, array of indices, or None. If not None, only values selected by the mask are considered. The mask acts on the first dimension of a value array, i.e. values[mask]. Default is None. """ return self._mask @mask.setter def mask(self, mask: Optional[ArrayLike]): self._mask = None if mask is None else np.asarray(mask) self._update_cache() @property def data(self): """Return data samples.""" return self._data @data.setter def data(self, value: ArrayLike): self._data[...] = value self._update_cache() def _update_cache(self): self._masked = self._data[_replace_none(self._mask, ...)] class MaskedCostWithPulls(MaskedCost): """ Base class for cost functions with pulls. :meta private: """ def pulls(self, args: Sequence[float]) -> NDArray: """ Return studentized residuals (aka pulls). Parameters ---------- args : sequence of float Parameter values. Returns ------- array Array of pull values. If the cost function is masked, the array contains NaN values where the mask value is False. Notes ----- Pulls allow one to estimate how well a model fits the data. A pull is a value computed for each data point. It is given by (observed - predicted) / standard-deviation. If the model is correct, the expectation value of each pull is zero and its variance is one in the asymptotic limit of infinite samples. Under these conditions, the chi-square statistic is computed from the sum of pulls squared has a known probability distribution if the model is correct. It therefore serves as a goodness-of-fit statistic. Beware: the sum of pulls squared in general is not identical to the value returned by the cost function, even if the cost function returns a chi-square distributed test-statistic. The cost function is computed in a slightly differently way that makes the return value approach the asymptotic chi-square distribution faster than a test statistic based on sum of pulls squared. In summary, only use pulls for plots. Compute the chi-square test statistic directly from the cost function. """ return self._pulls(args) def _ndata(self): return np.prod(self._masked.shape[: self._ndim]) @abc.abstractmethod def _pulls(self, args: Sequence[float]) -> NDArray: ... # pragma: no cover class UnbinnedCost(MaskedCost): """ Base class for unbinned cost functions. :meta private: """ __slots__ = "_model", "_model_grad", "_log" def __init__( self, data, model: Model, verbose: int, log: bool, grad: Optional[ModelGradient], name: Optional[Sequence[str]], ): """For internal use.""" self._model = model self._log = log self._model_grad = grad super().__init__(_model_parameters(model, name), _norm(data), verbose) @abc.abstractproperty def pdf(self): """Get probability density model.""" ... # pragma: no cover @abc.abstractproperty def scaled_pdf(self): """Get number density model.""" ... # pragma: no cover def _ndata(self): # unbinned likelihoods have infinite degrees of freedom return np.inf def _npoints(self): # cannot use len(self._masked) because multi-dimensional data has format # (K, N) with K dimensions and N points return self._masked.shape[-1] @deprecated_parameter(bins="nbins") def visualize( self, args: Sequence[float], model_points: Union[int, Sequence[float]] = 0, bins: int = 50, ): """ Visualize data and model agreement (requires matplotlib). The visualization is drawn with matplotlib.pyplot into the current axes. Parameters ---------- args : array-like Parameter values. model_points : int or array-like, optional How many points to use to draw the model. Default is 0, in this case an smart sampling algorithm selects the number of points. If array-like, it is interpreted as the point locations. bins : int, optional number of bins. Default is 50 bins. """ from matplotlib import pyplot as plt x = np.sort(self.data) if x.ndim > 1: raise ValueError("visualize is not implemented for multi-dimensional data") # this implementation only works with a histogram with linear spacing if isinstance(model_points, Iterable): xm = np.array(model_points) ym = self.scaled_pdf(xm, *args) elif model_points > 0: if _detect_log_spacing(x): xm = np.geomspace(x[0], x[-1], model_points) else: xm = np.linspace(x[0], x[-1], model_points) ym = self.scaled_pdf(xm, *args) else: xm, ym = _smart_sampling(lambda x: self.scaled_pdf(x, *args), x[0], x[-1]) # use xm for range, which may be narrower or wider than x range n, xe = np.histogram(x, bins=bins, range=(xm[0], xm[-1])) cx = 0.5 * (xe[1:] + xe[:-1]) dx = xe[1] - xe[0] plt.errorbar(cx, n, n**0.5, fmt="ok") plt.fill_between(xm, 0, ym * dx, fc="C0") def fisher_information(self, *args: float) -> NDArray: """ Estimate Fisher information for model and sample. The estimated Fisher information is only meaningful if the arguments provided are estimates of the true values. Parameters ---------- *args: float Estimates of model parameters. """ g = self._pointwise_score(args) return np.einsum("ji,ki->jk", g, g) def covariance(self, *args: float) -> NDArray: """ Estimate covariance of the parameters with the sandwich estimator. This requires that the model gradient is provided, and that the arguments are the maximum-likelihood estimates. The sandwich estimator is only asymptotically correct. Parameters ---------- *args : float Maximum-likelihood estimates of the parameter values. Returns ------- ndarray of float The array has shape (K, K) for K arguments. """ return np.linalg.inv(self.fisher_information(*args)) @abc.abstractmethod def _pointwise_score( self, args: Sequence[float] ) -> NDArray: ... # pragma: no cover def _has_grad(self) -> bool: return self._model_grad is not None class UnbinnedNLL(UnbinnedCost): """ Unbinned negative log-likelihood. Use this if only the shape of the fitted PDF is of interest and the original unbinned data is available. The data can be one- or multi-dimensional. """ __slots__ = () @property def pdf(self): """Get probability density model.""" if self._log: return lambda *args: np.exp(self._model(*args)) return self._model @property def scaled_pdf(self): """Get number density model.""" scale = np.prod(self.data.shape) if self._log: return lambda *args: scale * np.exp(self._model(*args)) return lambda *args: scale * self._model(*args) def __init__( self, data: ArrayLike, pdf: Model, *, verbose: int = 0, log: bool = False, grad: Optional[ModelGradient] = None, name: Optional[Sequence[str]] = None, ): """ Initialize UnbinnedNLL with data and model. Parameters ---------- data : array-like Sample of observations. If the observations are multidimensional, data must have the shape (D, N), where D is the number of dimensions and N the number of data points. pdf : callable Probability density function of the form f(data, par0, [par1, ...]), where data is the data sample and par0, ... are model parameters. If the data are multivariate, data passed to f has shape (D, N), where D is the number of dimensions and N the number of data points. Must return an array with the shape (N,). verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. log : bool, optional Distributions of the exponential family (normal, exponential, poisson, ...) allow one to compute the logarithm of the pdf directly, which is more accurate and efficient than numerically computing ``log(pdf)``. Set this to True, if the model returns the logpdf instead of the pdf. Default is False. grad : callable or None, optional Optionally pass the gradient of the pdf. Has the same calling signature like the pdf, but must return an array with the shape (K, N), where N is the number of data points and K is the number of parameters. If `log` is True, the function must return the gradient of the logpdf instead of the pdf. The gradient can be used by Minuit to improve or speed up convergence and to compute the sandwich estimator for the variance of the parameter estimates. Default is None. name : sequence of str or None, optional Optional names for each parameter of the model (in order). Must have the same length as there are model parameters. Default is None. """ super().__init__(data, pdf, verbose, log, grad, name) def _value(self, args: Sequence[float]) -> float: f = self._eval_model(args) if self._log: return -2.0 * np.sum(f) return 2.0 * _unbinned_nll(f) def _grad(self, args: Sequence[float]) -> NDArray: g = self._pointwise_score(args) return -2.0 * np.sum(g, axis=1) def _pointwise_score(self, args: Sequence[float]) -> NDArray: g = self._eval_model_grad(args) if self._log: return g f = self._eval_model(args) return g / f def _eval_model(self, args: Sequence[float]) -> float: data = self._masked return _normalize_output(self._model(data, *args), "model", self._npoints()) def _eval_model_grad(self, args: Sequence[float]) -> NDArray: if self._model_grad is None: raise ValueError("no gradient available") # pragma: no cover data = self._masked return _normalize_output( self._model_grad(data, *args), "model gradient", self.npar, self._npoints() ) class ExtendedUnbinnedNLL(UnbinnedCost): """ Unbinned extended negative log-likelihood. Use this if shape and normalization of the fitted PDF are of interest and the original unbinned data is available. The data can be one- or multi-dimensional. """ __slots__ = () @property def pdf(self): """Get probability density model.""" if self._log: def fn(*args): n, x = self._model(*args) return np.exp(x) / n else: def fn(*args): n, x = self._model(*args) return x / n return fn @property def scaled_pdf(self): """Get density model.""" if self._log: return lambda *args: np.exp(self._model(*args)[1]) return lambda *args: self._model(*args)[1] def __init__( self, data: ArrayLike, scaled_pdf: Model, *, verbose: int = 0, log: bool = False, grad: Optional[ModelGradient] = None, name: Optional[Sequence[str]] = None, ): """ Initialize cost function with data and model. Parameters ---------- data : array-like Sample of observations. If the observations are multidimensional, data must have the shape (D, N), where D is the number of dimensions and N the number of data points. scaled_pdf : callable Density function of the form f(data, par0, [par1, ...]), where data is the sample and par0, ... are model parameters. Must return a tuple (, ). The first value is the density integrated over the data window, the interval that we consider for the fit. For example, if the data are exponentially distributed, but we fit only the interval (0, 5), then the first value is the density integrated from 0 to 5. If the data are multivariate, data passed to f has shape (D, N), where D is the number of dimensions and N the number of data points. verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. log : bool, optional Distributions of the exponential family (normal, exponential, poisson, ...) allow one to compute the logarithm of the pdf directly, which is more accurate and efficient than effectively doing ``log(exp(logpdf))``. Set this to True, if the model returns the logarithm of the density as the second argument instead of the density. Default is False. grad : callable or None, optional Optionally pass the gradient of the density function. Has the same calling signature like the density function, but must return two arrays. The first array has shape (K,) where K are the number of parameters, while the second has shape (K, N), where N is the number of data points. The first array is the gradient of the integrated density. The second array is the gradient of the density itself. If `log` is True, the second array must be the gradient of the log-density instead. The gradient can be used by Minuit to improve or speed up convergence and to compute the sandwich estimator for the variance of the parameter estimates. Default is None. name : sequence of str or None, optional Optional names for each parameter of the model (in order). Must have the same length as there are model parameters. Default is None. """ super().__init__(data, scaled_pdf, verbose, log, grad, name) def _value(self, args: Sequence[float]) -> float: fint, f = self._eval_model(args) if self._log: return 2 * (fint - np.sum(f)) return 2 * (fint + _unbinned_nll(f)) def _grad(self, args: Sequence[float]) -> NDArray: g = self._pointwise_score(args) return -2 * np.sum(g, axis=1) def _pointwise_score(self, args: Sequence[float]) -> NDArray: gint, g = self._eval_model_grad(args) m = self._npoints() if self._log: return g - (gint / m)[:, np.newaxis] _, f = self._eval_model(args) return g / f - (gint / m)[:, np.newaxis] def _eval_model(self, args: Sequence[float]) -> Tuple[float, float]: data = self._masked fint, f = self._model(data, *args) f = _normalize_output(f, "model", self._npoints(), msg="in second position") return fint, f def _eval_model_grad(self, args: Sequence[float]) -> Tuple[NDArray, NDArray]: if self._model_grad is None: raise ValueError("no gradient available") # pragma: no cover data = self._masked gint, g = self._model_grad(data, *args) gint = _normalize_output( gint, "model gradient", self.npar, msg="in first position" ) g = _normalize_output( g, "model gradient", self.npar, self._npoints(), msg="in second position" ) return gint, g class BinnedCost(MaskedCostWithPulls): """ Base class for binned cost functions to support histograms filled with weights. Histograms filled with weights are supported by applying the Bohm-Zech transform. The Bohm-Zech approach was further generalized to handle sums of weights which are negative. See Baker & Cousins, NIM 221 (1984) 437-442; Bohm and Zech, NIMA 748 (2014) 1-6; H. Dembinski, M. Schmelling, R. Waldi, Nucl.Instrum.Meth.A 940 (2019) 135-141. Bohm and Zech use the scaled Poisson distribution (SPD) as an approximate way to handle sums of weights instead of Poisson counts. This approach also works for multinomial distributions. The idea of the Bohm and Zech is to use the likelihood for Poisson distributed data also for weighted data. They show that one can match the first and second moment of the compound Poisson distribution for weighted data with a single Poisson distribution with a scaling factor s, that is multiplied with the predicted expectation and the observation. This scaling factor is computed as s = sum(wi) / sum(wi**2), wi are the weights in the current bin. Instead of the Baker & Cousins transformed log-likelihood l(n; mu) for Poisson-distributed data, where n is the observed count and mu is the expectation, we now compute l(sum(w) * s; mu * s), this can be further simplified: l(w * s, mu * s) = 2 * [(w * s) * (log(w * s) - log(mu * s)) - s * mu + s * w] = 2 * s * [w * (log(w) - log(mu)) - mu + w] = s * l(w, mu) For multinomially-distributed data and s = 1, sum(w-mu) = 0, which is why these terms can be omitted in the standard calculation without weights, but in case of weighted counts, sum(s * (w - m)) != 0 and the terms must be kept. The original formulas from Bohm and Zech are only applicable if w >= 0 (with the extra condition that w * log(w) evaluates to 0 for w = 0). One can generalize the formula to w < 0, which is relevant in practice for example in fits of sweighted samples, by computing s = abs(sum(wi)) / sum(wi ** 2) and replacing w * log(w) with 0 for w <= 0. This works, because this extension has the right gradient. The gradient should be equal to hat of the quadratic function s * (w - mu)**2/mu', where mu'=mu but fixed during the gradient computation, see D. Dembinski, M. Schmelling, R. Waldi. The minimum of this quadratic function yields an unbiased estimate of mu, even if some w are negative. Since the quadratic function and the original function have the same gradient, the minima of both functions are the same, and the original function also yields an unbiased estimate. The gradient is not affected by the particular choice of how to handle w * log(w) with w < 0, since this term drops out in the computation of the gradient. Other choices are possible. Our goal was to select an option which keeps the function minimum approximately chi-square distributed, although that property tends to dissolve when negative weights are involved. The minimum can even become negative. :meta private: """ __slots__ = "_xe", "_ndim", "_bohm_zech_n", "_bohm_zech_s" _xe: Union[NDArray, Tuple[NDArray, ...]] _ndim: int _bohm_zech_n: NDArray _bohm_zech_s: Optional[NDArray] n = MaskedCost.data @property def xe(self): """Access bin edges.""" return self._xe def __init__( self, parameters: Dict[str, Optional[Tuple[float, float]]], n: ArrayLike, xe: Union[ArrayLike, Sequence[ArrayLike]], verbose: int, ): """For internal use.""" if not isinstance(xe, Iterable): raise ValueError("xe must be iterable") shape = _shape_from_xe(xe) self._ndim = len(shape) if self._ndim == 1: self._xe = _norm(cast(ArrayLike, xe)) else: self._xe = tuple(_norm(xei) for xei in xe) n = _norm(n) is_weighted = n.ndim > self._ndim and n.shape[-1] == 2 if n.ndim != (self._ndim + int(is_weighted)): raise ValueError("n must either have same dimension as xe or one extra") xei: NDArray for i, xei in enumerate([self._xe] if self._ndim == 1 else self._xe): if len(xei) != n.shape[i] + 1: raise ValueError( f"n and xe have incompatible shapes along dimension {i}, " "xe must be longer by one element along each dimension" ) # _bohm_zech_s will be set properly when init of base class # is called, which in turn calls our _update_cache() override self._bohm_zech_s = np.zeros(0) if is_weighted else None super().__init__(parameters, n, verbose) def prediction( self, args: Sequence[float] ) -> Union[NDArray, Tuple[NDArray, NDArray]]: """ Return the bin-wise expectation for the fitted model. Parameters ---------- args : array-like Parameter values. Returns ------- NDArray Model prediction for each bin. The expectation is always returned for all bins, even if some bins are temporarily masked. """ return self._pred(args) def visualize(self, args: Sequence[float]) -> None: """ Visualize data and model agreement (requires matplotlib). The visualization is drawn with matplotlib.pyplot into the current axes. Parameters ---------- args : sequence of float Parameter values. Notes ----- The automatically provided visualization for multi-dimensional data set is often not very pretty, but still helps to judge whether the fit is reasonable. Since there is no obvious way to draw higher dimensional data with error bars in comparison to a model, the visualization shows all data bins as a single sequence. """ return self._visualize(args) def _visualize(self, args: Sequence[float]) -> None: from matplotlib import pyplot as plt n, ne = self._n_err() mu = self.prediction(args) assert not isinstance(mu, tuple) if self._ndim > 1: # flatten higher-dimensional data n = n.reshape(-1) ne = ne.reshape(-1) mu = mu.reshape(-1) # just use bin numbers instead of original values xe = np.arange(len(n) + 1) - 0.5 cx = np.arange(len(n)).astype(float) else: xe = self.xe cx = 0.5 * (xe[1:] + xe[:-1]) plt.errorbar(cx, n, ne, fmt="ok") plt.stairs(mu, xe, fill=True, color="C0") @abc.abstractmethod def _pred( self, args: Sequence[float] ) -> Union[NDArray, Tuple[NDArray, NDArray]]: ... # pragma: no cover def _n_err(self) -> Tuple[NDArray, NDArray]: d = self.data if self._bohm_zech_s is None: n = d.copy() err = d**0.5 else: n = d[..., 0].copy() err = d[..., 1] ** 0.5 # mask values where error is zero ma = err == 0 if self.mask is not None: ma = ~self.mask n[ma] = np.nan err[ma] = np.nan return n, err def _pulls(self, args: Sequence[float]) -> NDArray: mu = self.prediction(args) n, ne = self._n_err() return (n - mu) / ne def _update_cache(self): super()._update_cache() n = self._masked if self._bohm_zech_s is not None: val = n[..., 0] var = n[..., 1] s = np.zeros_like(val) ma = var > 0 s[ma] = np.abs(val[ma]) / var[ma] # Use median of s from bins with entries to bins which have zero entries. # This is arbitrary, but still better than other arbitrary choices. s[~ma] = np.median(s[ma]) self._bohm_zech_s = s self._bohm_zech_n = val * s else: self._bohm_zech_n = n def _transformed(self, val: NDArray) -> Tuple[NDArray, NDArray]: s = self._bohm_zech_s ma = self.mask if ma is not None: val = val[ma] n = self._bohm_zech_n if s is None: return n, val return n, val * s def _transformed2( self, val: NDArray, var: NDArray ) -> Tuple[NDArray, NDArray, NDArray]: s = self._bohm_zech_s ma = self.mask if ma is not None: val = val[ma] var = var[ma] n = self._bohm_zech_n if s is None: return n, val, var return n, val * s, var * s**2 def _counts(self): if self._bohm_zech_s is None: return self._masked return self._masked[..., 0] class BinnedCostWithModel(BinnedCost): """ Base class for binned cost functions with parametric model. :meta private: """ __slots__ = ( "_xe_shape", "_model", "_model_xe", "_model_xm", "_model_dx", "_model_len", "_model_grad", "_pred_impl", ) _model_xe: np.ndarray _xe_shape: Union[Tuple[int], Tuple[int, ...]] def __init__(self, n, xe, model, verbose, grad, use_pdf, name): """For internal use.""" self._model = model self._model_grad = grad if use_pdf and grad: raise ValueError("keywords use_pdf and grad cannot be used together") if use_pdf == "approximate": self._pred_impl = self._pred_approximate elif use_pdf == "numerical": self._pred_impl = self._pred_numerical elif use_pdf == "": self._pred_impl = self._pred_cdf else: msg = ( f"use_pdf={use_pdf} is not understood, " "allowed values are '', 'approximate', or 'numerical'" ) raise ValueError(msg) super().__init__(_model_parameters(model, name), n, xe, verbose) if self._ndim == 1: self._xe_shape = (len(self.xe),) self._model_xe = _norm(self.xe) if use_pdf: dx = np.diff(self._model_xe) self._model_dx = dx self._model_xm = self._model_xe[:-1] + 0.5 * dx else: self._xe_shape = tuple(len(xei) for xei in self.xe) self._model_xe = np.vstack( [x.flatten() for x in np.meshgrid(*self.xe, indexing="ij")] ) if use_pdf == "approximate": dx = [np.diff(xe) for xe in self.xe] xm = [xei[:-1] + 0.5 * dxi for (xei, dxi) in zip(self.xe, dx)] xm = np.meshgrid(*xm, indexing="ij") dx = np.meshgrid(*dx, indexing="ij") self._model_xm = np.array(xm) self._model_dx = np.prod(dx, axis=0) elif use_pdf == "numerical": raise ValueError( 'use_pdf="numerical" is not supported for ' "multidimensional histograms" ) self._model_len = np.prod(self._xe_shape) def _pred(self, args: Sequence[float]) -> NDArray: return self._pred_impl(args) def _pred_cdf(self, args: Sequence[float]) -> NDArray: d = self._model(self._model_xe, *args) d = _normalize_output(d, "model", self._model_len) if self._ndim > 1: d = d.reshape(self._xe_shape) for i in range(self._ndim): d = np.diff(d, axis=i) # differences can come out negative due to round-off error in subtraction, # we set negative values to zero d[d < 0] = 0 return d def _pred_approximate(self, args: Sequence[float]) -> NDArray: y = self._model(self._model_xm, *args) return y * self._model_dx def _pred_numerical(self, args: Sequence[float]) -> NDArray: from scipy.integrate import quad assert self._ndim == 1 d = np.empty(self._model_len - 1) for i in range(self._model_len - 1): a = self._model_xe[i] b = self._model_xe[i + 1] d[i] = quad(lambda x: self._model(x, *args), a, b)[0] return d def _pred_grad(self, args: Sequence[float]) -> NDArray: d = self._model_grad(self._model_xe, *args) d = _normalize_output(d, "model gradient", self.npar, self._model_len) if self._ndim > 1: d = d.reshape((self.npar, *self._xe_shape)) for i in range(1, self._ndim + 1): d = np.diff(d, axis=i) return d def _has_grad(self) -> bool: return self._model_grad is not None class Template(BinnedCost): """ Binned cost function for a template fit with uncertainties on the template. This cost function is for a mixture of components. Use this if the sample originate from two or more components and you are interested in estimating the yield that originates from one or more components. In high-energy physics, one component is often a peaking signal over a smooth background component. A component can be described by a parametric model or a template. A parametric model is accepted in form of a scaled cumulative density function, while a template is a non-parametric shape estimate obtained by histogramming a Monte-Carlo simulation. Even if the Monte-Carlo simulation is asymptotically correct, estimating the shape from a finite simulation sample introduces some uncertainty. This cost function takes that additional uncertainty into account. There are several ways to fit templates and take the sampling uncertainty into account. Barlow and Beeston [1]_ found an exact likelihood for this problem, with one nuisance parameter per component per bin. Solving this likelihood is somewhat challenging though. The Barlow-Beeston likelihood also does not handle the additional uncertainty in weighted templates unless the weights per bin are all equal. Other works [2]_ [3]_ [4]_ describe likelihoods that use only one nuisance parameter per bin, which is an approximation. Some marginalize over the nuisance parameters with some prior, while others profile over the nuisance parameter. This class implements several of these methods. The default method is the one which performs best under most conditions, according to current knowledge. The default may change if this assessment changes. The cost function returns an asymptotically chi-square distributed test statistic, except for the method "asy", where it is the negative logarithm of the marginalised likelihood instead. The standard transform [5]_ which we use convert likelihoods into test statistics only works for (profiled) likelihoods, not for likelihoods marginalized over a prior. All methods implemented here have been generalized to work with both weighted data and weighted templates, under the assumption that the weights are independent of the data. This is not the case for sWeights, and the uncertaintes for results obtained with sWeights will only be approximately correct [6]_. The methods have been further generalized to allow fitting a mixture of parametric models and templates. .. [1] Barlow and Beeston, Comput.Phys.Commun. 77 (1993) 219-228 .. [2] Conway, PHYSTAT 2011 proceeding, https://doi.org/10.48550/arXiv.1103.0354 .. [3] Argüelles, Schneider, Yuan, JHEP 06 (2019) 030 .. [4] Dembinski and Abdelmotteleb, https://doi.org/10.48550/arXiv.2206.12346 .. [5] Baker and Cousins, NIM 221 (1984) 437-442 .. [6] Langenbruch, Eur.Phys.J.C 82 (2022) 5, 393 """ __slots__ = "_model_data", "_model_xe", "_xe_shape", "_impl", "_model_len" _model_data: List[ Union[ Tuple[NDArray, NDArray], Tuple[Model, float], ] ] _model_xe: np.ndarray _xe_shape: Union[Tuple[int], Tuple[int, ...]] def __init__( self, n: ArrayLike, xe: Union[ArrayLike, Sequence[ArrayLike]], model_or_template: Collection[Union[Model, ArrayLike]], *, name: Optional[Sequence[str]] = None, verbose: int = 0, method: str = "da", ): """ Initialize cost function with data and model. Parameters ---------- n : array-like Histogram counts. If this is an array with dimension D+1, where D is the number of histogram axes, then the last dimension must have two elements and is interpreted as pairs of sum of weights and sum of weights squared. xe : array-like or collection of array-like Bin edge locations, must be len(n) + 1, where n is the number of bins. If the histogram has more than one axis, xe must be a collection of the bin edge locations along each axis. model_or_template : collection of array-like or callable Collection of models or arrays. An array represent the histogram counts of a template. The template histograms must use the same axes as the data histogram. If the counts are represented by an array with dimension D+1, where D is the number of histogram axes, then the last dimension must have two elements and is interpreted as pairs of sum of weights and sum of weights squared. Callables must return the model cdf evaluated as xe. name : sequence of str or None, optional Optional name for the yield of each template and the parameter of each model (in order). Must have the same length as there are templates and model parameters in templates_or_model. Default is None. verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. method : {"jsc", "asy", "da"}, optional Which method to use. "jsc": Conway's method [2]_. "asy": ASY method [3]_. "da": DA method [4]_. Default is "da", which to current knowledge offers the best overall performance. The default may change in the future, so please set this parameter explicitly in code that has to be stable. For all methods except the "asy" method, the minimum value is chi-square distributed. """ M = len(model_or_template) if M < 1: raise ValueError("at least one template or model is required") shape = _shape_from_xe(xe) ndim = len(shape) npar = 0 annotated: Dict[str, Optional[Tuple[float, float]]] = {} self._model_data = [] for i, t in enumerate(model_or_template): if isinstance(t, Collection): tt = _norm(t) if tt.ndim > ndim: # template is weighted if tt.ndim != ndim + 1 or tt.shape[:-1] != shape: raise ValueError("shapes of n and templates do not match") t1 = tt[..., 0].copy() t2 = tt[..., 1].copy() else: if tt.ndim != ndim or tt.shape != shape: raise ValueError("shapes of n and templates do not match") t1 = tt.copy() t2 = tt.copy() # normalize to unity f = 1 / np.sum(t1) t1 *= f t2 *= f**2 self._model_data.append((t1, t2)) annotated[f"x{i}"] = (0.0, np.inf) elif isinstance(t, Model): ann = _model_parameters(t, None) npar = len(ann) self._model_data.append((t, npar)) for k in ann: annotated[f"x{i}_{k}"] = ann[k] else: raise ValueError( "model_or_template must be a collection of array-likes " "and/or Model types" ) if name is not None: if len(annotated) != len(name): raise ValueError( "number of names must match number of templates and " "model parameters" ) annotated = {new: annotated[old] for (old, new) in zip(annotated, name)} known_methods = { "jsc": template_chi2_jsc, "asy": template_nll_asy, "hpd": template_chi2_da, "da": template_chi2_da, } try: self._impl = known_methods[method] except KeyError: raise ValueError( f"method {method} is not understood, allowed values: {known_methods}" ) if method == "hpd": warnings.warn( "key 'hpd' is deprecated, please use 'da' instead", category=FutureWarning, stacklevel=2, ) super().__init__(annotated, n, xe, verbose) if self._ndim == 1: self._xe_shape = (len(self.xe),) self._model_xe = _norm(self.xe) else: self._xe_shape = tuple(len(xei) for xei in self.xe) self._model_xe = np.vstack( [x.flatten() for x in np.meshgrid(*self.xe, indexing="ij")] ) self._model_len = np.prod(self._xe_shape) def _pred(self, args: Sequence[float]) -> Tuple[NDArray, NDArray]: mu: NDArray = 0 # type:ignore mu_var: NDArray = 0 # type:ignore i = 0 for t1, t2 in self._model_data: if isinstance(t1, np.ndarray) and isinstance(t2, np.ndarray): a = args[i] mu += a * t1 mu_var += a**2 * t2 i += 1 elif isinstance(t1, Model) and isinstance(t2, int): d = t1(self._model_xe, *args[i : i + t2]) d = _normalize_output(d, "model", self._model_len) if self._ndim > 1: d = d.reshape(self._xe_shape) for j in range(self._ndim): d = np.diff(d, axis=j) # differences can come out negative due to round-off error in # subtraction, we set negative values to zero d[d < 0] = 0 mu += d mu_var += np.ones_like(mu) * 1e-300 i += t2 else: # never arrive here assert False # pragma: no cover return mu, mu_var def _value(self, args: Sequence[float]) -> float: mu, mu_var = self._pred(args) n, mu, mu_var = self._transformed2(mu, mu_var) ma = mu > 0 return self._impl(n[ma].reshape(-1), mu[ma].reshape(-1), mu_var[ma].reshape(-1)) def _grad(self, args: Sequence[float]) -> NDArray: raise NotImplementedError # pragma: no cover def _has_grad(self) -> bool: return False def _errordef(self) -> float: return NEGATIVE_LOG_LIKELIHOOD if self._impl is template_nll_asy else CHISQUARE def prediction(self, args: Sequence[float]) -> Tuple[NDArray, NDArray]: """ Return the fitted template and its standard deviation. This returns the prediction from the templates, the sum over the products of the template yields with the normalized templates. The standard deviation is returned as the second argument, this is the estimated uncertainty of the fitted template alone. It is obtained via error propagation, taking the statistical uncertainty in the template into account, but regarding the yields as parameters without uncertainty. Parameters ---------- args : array-like Parameter values. Returns ------- y, yerr : NDArray, NDArray Template prediction and its standard deviation, based on the statistical uncertainty of the template only. """ mu, mu_var = self._pred(args) return mu, np.sqrt(mu_var) def _visualize(self, args: Sequence[float]) -> None: from matplotlib import pyplot as plt n, ne = self._n_err() mu, mue = self.prediction(args) # type: ignore # see implementation notes in BinnedCost.visualize if self._ndim > 1: n = n.reshape(-1) ne = ne.reshape(-1) mu = mu.reshape(-1) mue = mue.reshape(-1) xe = np.arange(len(n) + 1) - 0.5 cx = np.arange(len(n)).astype(float) else: xe = self.xe cx = 0.5 * (xe[1:] + xe[:-1]) plt.errorbar(cx, n, ne, fmt="ok") # need fill=True and fill=False so that bins with mue=0 show up for fill in (False, True): plt.stairs(mu + mue, xe, baseline=mu - mue, fill=fill, color="C0") def _pulls(self, args: Sequence[float]) -> NDArray: mu, mue = self.prediction(args) n, ne = self._n_err() return (n - mu) / (mue**2 + ne**2) ** 0.5 class BinnedNLL(BinnedCostWithModel): """ Binned negative log-likelihood. Use this if only the shape of the fitted PDF is of interest and the data is binned. This cost function works with normal and weighted histograms. The histogram can be one- or multi-dimensional. The cost function has a minimum value that is asymptotically chi2-distributed. It is constructed from the log-likelihood assuming a multivariate-normal distribution and using the saturated model as a reference, see :func:`multinomial_chi2` for details. When this class is used with weighted data, we use the Bohm-Zech transform for Poisson-distributed data and the :func:`poisson_chi2` cost function, because :func:`multinomial_chi2` yields biased results for weighted data. The reasoning for this choice is that :func:`multinomial_chi2` and :func:`poisson_chi2` yield the same result for a model which predicts probabilities and expected counts are computed by multiplying the probability with the total number of counts. Thus we can derive :func:`multinomial_chi2` as a special case of :func:`poisson_chi2` in case of unweighted data, but this mathematical equivalence is gone when data are weighted. The correct cost function is then :func:`poisson_chi2`. """ __slots__ = ("_chi2",) @property def cdf(self): """Get cumulative density function.""" return self._model def __init__( self, n: ArrayLike, xe: Union[ArrayLike, Sequence[ArrayLike]], cdf: Model, *, verbose: int = 0, grad: Optional[ModelGradient] = None, use_pdf: str = "", name: Optional[Sequence[str]] = None, ): """ Initialize cost function with data and model. Parameters ---------- n : array-like Histogram counts. If this is an array with dimension D+1, where D is the number of histogram axes, then the last dimension must have two elements and is interpreted as pairs of sum of weights and sum of weights squared. xe : array-like or collection of array-like Bin edge locations, must be len(n) + 1, where n is the number of bins. If the histogram has more than one axis, xe must be a collection of the bin edge locations along each axis. cdf : callable Cumulative density function of the form f(xe, par0, par1, ..., parN), where xe is a bin edge and par0, ... are model parameters. The corresponding density must be normalized to unity over the space covered by the histogram. If the model is multivariate, xe must be an array-like with shape (D, N), where D is the dimension and N is the number of points where the model is evaluated. verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. grad: callable or None, optional Optionally pass the gradient of the cdf (Default is None). Has the same calling signature like the cdf, but must return an array with the shape (K, N), where N is the number of data points and K is the number of parameters. The gradient can be used by Minuit to improve or speed up convergence. use_pdf: str, optional Either "", "numerical", or "approximate" (Default is ""). If the model cdf is not available, but the model pdf is, this option can be set to "numerical" or "approximate" to compute the integral of the pdf over the bin patch. The option "numerical" uses numerical integration, which is accurate but computationally expensive and only supported for 1D histograms. The option "approximate" uses the zero-order approximation of evaluating the pdf at the bin center, multiplied with the bin area. This is fast and works in higher dimensions, but can lead to biased results if the curvature of the pdf inside the bin is significant. name : sequence of str or None, optional Optional names for each parameter of the model (in order). Must have the same length as there are model parameters. Default is None. """ super().__init__(n, xe, cdf, verbose, grad, use_pdf, name) if self._bohm_zech_s is None: self._chi2 = multinomial_chi2 else: self._chi2 = poisson_chi2 def _pred(self, args: Sequence[float]) -> NDArray: # must return array of full length, mask not applied yet p = super()._pred(args) # normalise probability of remaining bins ma = self.mask if ma is not None: p /= np.sum(p[ma]) # scale probabilities with total number of entries of unmasked bins in histogram return p * np.sum(self._counts()) def _value(self, args: Sequence[float]) -> float: mu = self._pred(args) n, mu = self._transformed(mu) return self._chi2(n.reshape(-1), mu.reshape(-1)) def _grad(self, args: Sequence[float]) -> NDArray: # pg and p must be arrays of full length, mask not applied yet pg = super()._pred_grad(args) p = super()._pred(args) ma = self.mask # normalise probability of remaining bins if ma is not None: psum = np.sum(p[ma]) pg = pg / psum - p * np.sum(pg[:, ma]) / psum**2 p /= psum # scale probabilities with total number of entries of unmasked bins in histogram n = self._counts() ntot = np.sum(n) mu = p * ntot gmu = pg * ntot ma = self.mask if ma is not None: mu = mu[ma] gmu = gmu[:, ma] n = n.reshape(-1) mu = mu.reshape(-1) gmu = gmu.reshape(gmu.shape[0], -1) s = self._bohm_zech_s if s is None: return _multinomial_chi2_grad(n, mu, gmu) # use original n and mu because Bohm-Zech scale factor cancels s = s.reshape(-1) return _poisson_chi2_grad(n, mu, s * gmu) class ExtendedBinnedNLL(BinnedCostWithModel): """ Binned extended negative log-likelihood. Use this if shape and normalization of the fitted PDF are of interest and the data is binned. This cost function works with normal and weighted histograms. The histogram can be one- or multi-dimensional. The cost function works for both weighted data. The cost function assumes that the weights are independent of the data. This is not the case for sWeights, and the uncertaintes for results obtained with sWeights will only be approximately correct, see C. Langenbruch, Eur.Phys.J.C 82 (2022) 5, 393. The cost function has a minimum value that is asymptotically chi2-distributed. It is constructed from the log-likelihood assuming a poisson distribution and using the saturated model as a reference. """ __slots__ = () @property def scaled_cdf(self): """Get integrated density model.""" return self._model def __init__( self, n: ArrayLike, xe: Union[ArrayLike, Sequence[ArrayLike]], scaled_cdf: Model, *, verbose: int = 0, grad: Optional[ModelGradient] = None, use_pdf: str = "", name: Optional[Sequence[str]] = None, ): """ Initialize cost function with data and model. Parameters ---------- n : array-like Histogram counts. If this is an array with dimension D+1, where D is the number of histogram axes, then the last dimension must have two elements and is interpreted as pairs of sum of weights and sum of weights squared. xe : array-like or collection of array-like Bin edge locations, must be len(n) + 1, where n is the number of bins. If the histogram has more than one axis, xe must be a collection of the bin edge locations along each axis. scaled_cdf : callable Scaled Cumulative density function of the form f(xe, par0, [par1, ...]), where xe is a bin edge and par0, ... are model parameters. If the model is multivariate, xe must be an array-like with shape (D, N), where D is the dimension and N is the number of points where the model is evaluated. verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. grad: callable or None, optional Optionally pass the gradient of the cdf (Default is None). Has the same calling signature like the cdf, but must return an array with the shape (K, N), where N is the number of data points and K is the number of parameters. The gradient can be used by Minuit to improve or speed up convergence. use_pdf: str, optional Either "", "numerical", or "approximate". If the model cdf is not available, but the model pdf is, this option can be set to "numerical" or "approximate" to compute the integral of the pdf over the bin patch. The option "numerical" uses numerical integration, which is accurate but computationally expensive and only supported for 1D histograms. The option "approximate" uses the zero-order approximation of evaluating the pdf at the bin center, multiplied with the bin area. This is fast and works in higher dimensions, but can lead to biased results if the curvature of the pdf inside the bin is significant. name : sequence of str or None, optional Optional names for each parameter of the model (in order). Must have the same length as there are model parameters. Default is None. """ super().__init__(n, xe, scaled_cdf, verbose, grad, use_pdf, name) def _value(self, args: Sequence[float]) -> float: mu = self._pred(args) n, mu = self._transformed(mu) return poisson_chi2(n.reshape(-1), mu.reshape(-1)) def _grad(self, args: Sequence[float]) -> NDArray: mu = self._pred(args) gmu = self._pred_grad(args) ma = self.mask if ma is not None: mu = mu[ma] gmu = gmu[:, ma] mu = mu.reshape(-1) gmu = gmu.reshape(gmu.shape[0], -1) n = self._counts().reshape(-1) s = self._bohm_zech_s if s is None: return _poisson_chi2_grad(n, mu, gmu) # use original n and mu because Bohm-Zech scale factor cancels s = s.reshape(-1) return _poisson_chi2_grad(n, mu, s * gmu) class LeastSquares(MaskedCostWithPulls): """ Least-squares cost function (aka chisquare function). Use this if you have data of the form (x, y +/- yerror), where x can be one-dimensional or multi-dimensional, but y is always one-dimensional. See :meth:`__init__` for details on how to use a multivariate model. """ __slots__ = "_loss", "_cost", "_cost_grad", "_model", "_model_grad", "_ndim" _loss: Union[str, LossFunction] _cost: Callable[[ArrayLike, ArrayLike, ArrayLike], float] _cost_grad: Optional[Callable[[NDArray, NDArray, NDArray, NDArray], NDArray]] _model: Model _model_grad: Optional[ModelGradient] _ndim: int @property def x(self): """Get explanatory variables.""" if self._ndim == 1: return self.data[:, 0] return self.data.T[: self._ndim] @x.setter def x(self, value): if self._ndim == 1: self.data[:, 0] = _norm(value) else: self.data[:, : self._ndim] = _norm(value).T self._update_cache() @property def y(self): """Get samples.""" return self.data[:, self._ndim] @y.setter def y(self, value): self.data[:, self._ndim] = _norm(value) self._update_cache() @property def yerror(self): """Get sample uncertainties.""" return self.data[:, self._ndim + 1] @yerror.setter def yerror(self, value): self.data[:, self._ndim + 1] = _norm(value) self._update_cache() @property def model(self): """Get model of the form y = f(x, par0, [par1, ...]).""" if len(self._parameters) == 1: return lambda x, *args: ( self._model(x, args) if len(args) > 1 else self._model(x, *args) ) else: return self._model @property def loss(self): """Get loss function.""" return self._loss @loss.setter def loss(self, loss: Union[str, LossFunction]): self._loss = loss if isinstance(loss, str): if loss == "linear": self._cost = chi2 self._cost_grad = _chi2_grad elif loss == "soft_l1": self._cost = _soft_l1_cost # type: ignore self._cost_grad = _soft_l1_cost_grad else: raise ValueError(f"unknown loss {loss!r}") elif isinstance(loss, LossFunction): self._cost = lambda y, ye, ym: np.sum( loss(_z_squared(y, ye, ym)) # type:ignore ) self._cost_grad = None else: raise ValueError("loss must be str or LossFunction") def __init__( self, x: ArrayLike, y: ArrayLike, yerror: ArrayLike, model: Model, *, loss: Union[str, LossFunction] = "linear", verbose: int = 0, grad: Optional[ModelGradient] = None, name: Optional[Sequence[str]] = None, ): """ Initialize cost function with data and model. Parameters ---------- x : array-like Locations where the model is evaluated. If the model is multivariate, x must have shape (D, N), where D is the number of dimensions and N the number of data points. y : array-like Observed values. Must have the same length as x. yerror : array-like or float Estimated uncertainty of observed values. Must have same shape as y or be a scalar, which is then broadcasted to same shape as y. model : callable Function of the form f(x, par0, [par1, ...]) whose output is compared to observed values, where x is the location and par0, ... are model parameters. If the model is multivariate, x has shape (D, N), where D is the number of dimensions and N the number of data points. loss : str or callable, optional The loss function can be modified to make the fit robust against outliers, see scipy.optimize.least_squares for details. Only "linear" (default) and "soft_l1" are currently implemented, but users can pass any loss function as this argument. It should be a monotonic, twice differentiable function, which accepts the squared residual and returns a modified squared residual. verbose : int, optional Verbosity level. 0: is no output (default). 1: print current args and negative log-likelihood value. Notes ----- Alternative loss functions make the fit more robust against outliers by weakening the pull of outliers. The mechanical analog of a least-squares fit is a system with attractive forces. The points pull the model towards them with a force whose potential is given by :math:`rho(z)` for a squared-offset :math:`z`. The plot shows the standard potential in comparison with the weaker soft-l1 potential, in which outliers act with a constant force independent of their distance. .. plot:: plots/loss.py """ x = _norm(x) y = _norm(y) assert x.ndim >= 1 # guaranteed by _norm self._ndim = x.shape[0] if x.ndim > 1 else 1 self._model = model self._model_grad = grad self.loss = loss x = np.atleast_2d(x) data = np.column_stack(np.broadcast_arrays(*x, y, yerror)) super().__init__(_model_parameters(model, name), data, verbose) def _ndata(self): return len(self._masked) def visualize( self, args: ArrayLike, model_points: Union[int, Sequence[float]] = 0 ) -> Tuple[Tuple[NDArray, NDArray, NDArray], Tuple[NDArray, NDArray]]: """ Visualize data and model agreement (requires matplotlib). The visualization is drawn with matplotlib.pyplot into the current axes. Parameters ---------- args : array-like Parameter values. model_points : int or array-like, optional How many points to use to draw the model. Default is 0, in this case an smart sampling algorithm selects the number of points. If array-like, it is interpreted as the point locations. """ from matplotlib import pyplot as plt if self._ndim > 1: raise ValueError("visualize is not implemented for multi-dimensional data") x, y, ye = self._masked.T plt.errorbar(x, y, ye, fmt="ok") if isinstance(model_points, Iterable): xm = np.array(model_points) ym = self.model(xm, *args) elif model_points > 0: if _detect_log_spacing(x): xm = np.geomspace(x[0], x[-1], model_points) else: xm = np.linspace(x[0], x[-1], model_points) ym = self.model(xm, *args) else: xm, ym = _smart_sampling(lambda x: self.model(x, *args), x[0], x[-1]) plt.plot(xm, ym) return (x, y, ye), (xm, ym) def prediction(self, args: Sequence[float]) -> NDArray: """ Return the prediction from the fitted model. Parameters ---------- args : array-like Parameter values. Returns ------- NDArray Model prediction for each bin. """ return self.model(self.x, *args) def _pulls(self, args: Sequence[float]) -> NDArray: y = self.y.copy() ye = self.yerror.copy() ym = self.prediction(args) if self.mask is not None: ma = ~self.mask y[ma] = np.nan ye[ma] = np.nan return (y - ym) / ye def _pred(self, args: Sequence[float]) -> NDArray: x = self._masked.T[0] if self._ndim == 1 else self._masked.T[: self._ndim] ym = self._model(x, *args) return _normalize_output(ym, "model", self._ndata()) def _pred_grad(self, args: Sequence[float]) -> NDArray: if self._model_grad is None: raise ValueError("no gradient available") # pragma: no cover x = self._masked.T[0] if self._ndim == 1 else self._masked.T[: self._ndim] ymg = self._model_grad(x, *args) return _normalize_output(ymg, "model gradient", self.npar, self._ndata()) def _value(self, args: Sequence[float]) -> float: y, ye = self._masked.T[self._ndim :] ym = self._pred(args) return self._cost(y, ye, ym) def _grad(self, args: Sequence[float]) -> NDArray: if self._cost_grad is None: raise ValueError("no cost gradient available") # pragma: no cover y, ye = self._masked.T[self._ndim :] ym = self._pred(args) ymg = self._pred_grad(args) return self._cost_grad(y, ye, ym, ymg) def _has_grad(self) -> bool: return self._model_grad is not None and self._cost_grad is not None class NormalConstraint(Cost): """ Gaussian penalty for one or several parameters. The Gaussian penalty acts like a pseudo-measurement of the parameter itself, based on a (multi-variate) normal distribution. Penalties can be set for one or several parameters at once (which is more efficient). When several parameter are constrained, one can specify the full covariance matrix of the parameters. Notes ----- It is sometimes necessary to add a weak penalty on a parameter to avoid instabilities in the fit. A typical example in high-energy physics is the fit of a signal peak above some background. If the amplitude of the peak vanishes, the shape parameters of the peak become unconstrained and the fit becomes unstable. This can be avoided by adding weak (large uncertainty) penalty on the shape parameters whose pull is negligible if the peak amplitude is non-zero. This class can also be used to approximately include external measurements of some parameters, if the original cost function is not available or too costly to compute. If the external measurement was performed in the asymptotic limit with a large sample, a Gaussian penalty is an accurate statistical representation of the external result. """ __slots__ = "_expected", "_cov", "_covinv" def __init__( self, args: Union[str, Iterable[str]], value: ArrayLike, error: ArrayLike, ): """ Initialize the normal constraint with expected value(s) and error(s). Parameters ---------- args : str or sequence of str Parameter name(s). value : float or array-like Expected value(s). Must have same length as `args`. error : float or array-like Expected error(s). If 1D, must have same length as `args`. If 2D, must be the covariance matrix of the parameters. """ tp_args = (args,) if isinstance(args, str) else tuple(args) nargs = len(tp_args) self._expected = _norm(value) if self._expected.ndim > 1: raise ValueError("value must be a scalar or one-dimensional") # args can be a vector of values, in this case we have nargs == 1 if nargs > 1 and len(self._expected) != nargs: raise ValueError("size of value does not match size of args") self._cov = _norm(error) if len(self._cov) != len(self._expected): raise ValueError("size of error does not match size of value") if self._cov.ndim < 2: self._cov **= 2 elif self._cov.ndim == 2: if not is_positive_definite(self._cov): raise ValueError("covariance matrix is not positive definite") else: raise ValueError("covariance matrix cannot have more than two dimensions") self._covinv = _covinv(self._cov) super().__init__({k: None for k in tp_args}, False) @property def covariance(self): """ Get expected covariance of parameters. Can be 1D (diagonal of covariance matrix) or 2D (full covariance matrix). """ return self._cov @covariance.setter def covariance(self, value): value = np.asarray(value) if value.ndim == 2 and not is_positive_definite(value): raise ValueError("covariance matrix is not positive definite") self._cov[:] = value self._covinv = _covinv(self._cov) @property def value(self): """Get expected parameter values.""" return self._expected @value.setter def value(self, value): self._expected[:] = value def _value(self, args: Sequence[float]) -> float: delta = args - self._expected if self._covinv.ndim < 2: return np.sum(delta**2 * self._covinv) return np.einsum("i,ij,j", delta, self._covinv, delta) def _grad(self, args: Sequence[float]) -> NDArray: delta = args - self._expected if self._covinv.ndim < 2: return 2 * delta * self._covinv return 2 * self._covinv @ delta def _has_grad(self) -> bool: return True def _ndata(self): return len(self._expected) def visualize(self, args: ArrayLike): """ Visualize data and model agreement (requires matplotlib). The visualization is drawn with matplotlib.pyplot into the current axes. Parameters ---------- args : array-like Parameter values. """ from matplotlib import pyplot as plt args = np.atleast_1d(args) par = self._parameters val = self.value cov = self.covariance if cov.ndim == 2: cov = np.diag(cov) err = np.sqrt(cov) n = len(par) i = 0 max_pull = 0 for v, e, a in zip(val, err, args): pull = (a - v) / e max_pull = max(abs(pull), max_pull) plt.errorbar(pull, -i, 0, 1, fmt="o", color="C0") i += 1 plt.axvline(0, color="k") plt.xlim(-max_pull - 1.1, max_pull + 1.1) yaxis = plt.gca().yaxis yaxis.set_ticks(-np.arange(n)) yaxis.set_ticklabels(par) plt.ylim(-n + 0.5, 0.5) def _norm(value: ArrayLike) -> NDArray: value = np.atleast_1d(value) dtype = value.dtype if dtype.kind != "f": value = value.astype(np.float64) return value def _covinv(array): return np.linalg.inv(array) if array.ndim == 2 else 1.0 / array def _normalize_output(x, kind, *shape, msg=None): if not isinstance(x, np.ndarray): if msg is None: msg = f"{kind} should return numpy array, but returns {type(x)}" else: msg = f"{kind} should return numpy array {msg}, but returns {type(x)}" warnings.warn(msg, PerformanceWarning) x = np.array(x) if x.dtype.kind != "f": return x.astype(float) if x.ndim < len(shape): return x.reshape(*shape) elif x.shape != shape: # NumPy 2 uses a numpy int here pretty_shape = tuple(int(i) for i in shape) msg = ( f"output of {kind} has shape {x.shape!r}, but {pretty_shape!r} is required" ) raise ValueError(msg) return x def _shape_from_xe(xe): if isinstance(xe[0], Iterable): return tuple(len(xei) - 1 for xei in xe) return (len(xe) - 1,) def _model_parameters(model, name): # strip first argument from model ann = describe(model, annotations=True) args = iter(ann) next(args) params = {k: ann[k] for k in args} if name: if len(params) == len(name): params = {n: att for (n, att) in zip(name, params.values())} elif len(params) > 0: raise ValueError("length of name does not match number of model parameters") else: params = {n: None for n in name} return params _deprecated_content = { "BarlowBeestonLite": ("Template", Template), "barlow_beeston_lite_chi2_jsc": ("template_chi2_jsc", template_chi2_jsc), "barlow_beeston_lite_chi2_hpd": ("template_chi2_da", template_chi2_da), "multinominal_chi2": ("multinomial_chi2", multinomial_chi2), } def __getattr__(name: str) -> Any: if name in _deprecated_content: new_name, obj = _deprecated_content[name] warnings.warn( f"{name} was renamed to {new_name}, please import {new_name} instead", FutureWarning, stacklevel=2, ) return obj raise AttributeError iminuit-2.30.1/src/iminuit/experimental.py0000644000000000000000000000212214332717401015514 0ustar00""" Warning: As the name indicates, everything in this module is experimental. The API is not final, code here may be removed or altered in breaking ways without warning. Use at your own risk. """ from .util import merge_signatures def expanded(*callables): """ Return expanded callables with unified signatures. Uses :func:`merge_signatures` to unify the signatures and generates function wrappers that accept the merged signature and call the original function in the correct way. This is best explained by an example:: def f(x, y, z): ... def g(x, p): ... f2, g2 = expand_functions(f, g) # f2 is the equivalent of: def f2(x, y, z, p): return f(x, y, z) # g2 is the equivalent of: def g2(x, y, z, p): return g(x, p) """ varnames, mapping = merge_signatures(callables) total = ",".join(varnames) args = [",".join(varnames[i] for i in map) for map in mapping] lambdas = ",".join( f"lambda {total} : funcs[{i}]({arg})" for (i, arg) in enumerate(args) ) return eval(lambdas, {"funcs": callables}) iminuit-2.30.1/src/iminuit/ipywidget.py0000644000000000000000000002273614332717401015041 0ustar00"""Interactive fitting widget for Jupyter notebooks.""" import warnings import numpy as np from typing import Dict, Any, Callable import sys with warnings.catch_warnings(): # ipywidgets produces deprecation warnings through use of internal APIs :( warnings.simplefilter("ignore") try: import ipywidgets as widgets from ipywidgets.widgets.interaction import show_inline_matplotlib_plots from IPython.display import clear_output from matplotlib import pyplot as plt except ModuleNotFoundError as e: e.msg += ( "\n\nPlease install ipywidgets, IPython, and matplotlib to " "enable interactive" ) raise def make_widget( minuit: Any, plot: Callable[..., None], kwargs: Dict[str, Any], raise_on_exception: bool, ): """Make interactive fitting widget.""" # Implementations makes heavy use of closures, # we frequently use variables which are defined # near the end of the function. original_values = minuit.values[:] original_limits = minuit.limits[:] def plot_with_frame(from_fit, report_success): trans = plt.gca().transAxes try: with warnings.catch_warnings(): minuit.visualize(plot, **kwargs) except Exception: if raise_on_exception: raise import traceback plt.figtext( 0, 0.5, traceback.format_exc(limit=-1), fontdict={"family": "monospace", "size": "x-small"}, va="center", color="r", backgroundcolor="w", wrap=True, ) return fval = minuit.fmin.fval if from_fit else minuit._fcn(minuit.values) plt.text( 0.05, 1.05, f"FCN = {fval:.3f}", transform=trans, fontsize="x-large", ) if from_fit and report_success: plt.text( 0.95, 1.05, f"{'success' if minuit.valid and minuit.accurate else 'FAILURE'}", transform=trans, fontsize="x-large", ha="right", ) def fit(): if algo_choice.value == "Migrad": minuit.migrad() elif algo_choice.value == "Scipy": minuit.scipy() elif algo_choice.value == "Simplex": minuit.simplex() return False else: assert False # pragma: no cover, should never happen return True class OnParameterChange: # Ugly implementation notes: # We want the plot when the user moves the slider widget, but not when # we update the slider value manually from our code. Unfortunately, # the latter also calls OnParameterChange, which leads to superfluous plotting. # I could not find a nice way to prevent that (and I tried many), so as a workaround # we optionally skip a number of calls, when the slider is updated. def __init__(self, skip: int = 0): self.skip = skip def __call__(self, change: Dict[str, Any] = {}): if self.skip > 0: self.skip -= 1 return from_fit = change.get("from_fit", False) report_success = change.get("report_success", False) if not from_fit: for i, x in enumerate(parameters): minuit.values[i] = x.slider.value if any(x.fit.value for x in parameters): saved = minuit.fixed[:] for i, x in enumerate(parameters): minuit.fixed[i] = not x.fit.value from_fit = True report_success = do_fit(None) minuit.fixed = saved # Implementation like in ipywidegts.interaction.interactive_output with out: clear_output(wait=True) plot_with_frame(from_fit, report_success) with warnings.catch_warnings(): warnings.simplefilter("ignore") show_inline_matplotlib_plots() def do_fit(change): report_success = fit() for i, x in enumerate(parameters): x.reset(minuit.values[i]) if change is None: return report_success OnParameterChange()({"from_fit": True, "report_success": report_success}) def on_update_button_clicked(change): for x in parameters: x.slider.continuous_update = not x.slider.continuous_update def on_reset_button_clicked(change): minuit.reset() minuit.values = original_values minuit.limits = original_limits for i, x in enumerate(parameters): x.reset(minuit.values[i], minuit.limits[i]) OnParameterChange()() class Parameter(widgets.HBox): def __init__(self, minuit, par): val = minuit.values[par] vmin, vmax = minuit.limits[par] step = _guess_initial_step(val, vmin, vmax) vmin2 = vmin if np.isfinite(vmin) else val - 100 * step vmax2 = vmax if np.isfinite(vmax) else val + 100 * step tlabel = widgets.Label(par, layout=widgets.Layout(width=f"{longest_par}em")) tmin = widgets.BoundedFloatText( _round(vmin2), min=_make_finite(vmin), max=vmax2, step=1e-1 * (vmax2 - vmin2), layout=widgets.Layout(width="4.1em"), ) tmax = widgets.BoundedFloatText( _round(vmax2), min=vmin2, max=_make_finite(vmax), step=1e-1 * (vmax2 - vmin2), layout=widgets.Layout(width="4.1em"), ) self.slider = widgets.FloatSlider( val, min=vmin2, max=vmax2, step=step, continuous_update=True, readout_format=".3g", layout=widgets.Layout(min_width="50%"), ) self.slider.observe(OnParameterChange(), "value") def on_min_change(change): self.slider.min = change["new"] tmax.min = change["new"] lim = minuit.limits[par] minuit.limits[par] = (self.slider.min, lim[1]) def on_max_change(change): self.slider.max = change["new"] tmin.max = change["new"] lim = minuit.limits[par] minuit.limits[par] = (lim[0], self.slider.max) tmin.observe(on_min_change, "value") tmax.observe(on_max_change, "value") self.fix = widgets.ToggleButton( minuit.fixed[par], description="Fix", tooltip="Fix", layout=widgets.Layout(width="3.1em"), ) self.fit = widgets.ToggleButton( False, description="Fit", tooltip="Fit", layout=widgets.Layout(width="3.5em"), ) def on_fix_toggled(change): minuit.fixed[par] = change["new"] if change["new"]: self.fit.value = False def on_fit_toggled(change): self.slider.disabled = change["new"] if change["new"]: self.fix.value = False OnParameterChange()() self.fix.observe(on_fix_toggled, "value") self.fit.observe(on_fit_toggled, "value") super().__init__([tlabel, tmin, self.slider, tmax, self.fix, self.fit]) def reset(self, value, limits=None): self.slider.unobserve_all("value") self.slider.value = value if limits: self.slider.min, self.slider.max = limits # Installing the observer actually triggers a notification, # we skip it. See notes in OnParameterChange. self.slider.observe(OnParameterChange(1), "value") longest_par = max(len(par) for par in minuit.parameters) parameters = [Parameter(minuit, par) for par in minuit.parameters] button_layout = widgets.Layout(max_width="8em") fit_button = widgets.Button( description="Fit", button_style="primary", layout=button_layout, ) fit_button.on_click(do_fit) update_button = widgets.ToggleButton( True, description="Continuous", layout=button_layout, ) update_button.observe(on_update_button_clicked) reset_button = widgets.Button( description="Reset", button_style="danger", layout=button_layout, ) reset_button.on_click(on_reset_button_clicked) algo_choice = widgets.Dropdown( options=["Migrad", "Scipy", "Simplex"], value="Migrad", layout=button_layout, ) ui = widgets.VBox( [ widgets.HBox([fit_button, update_button, reset_button, algo_choice]), widgets.VBox(parameters), ] ) out = widgets.Output() OnParameterChange()() return widgets.HBox([out, ui]) def _make_finite(x: float) -> float: sign = -1 if x < 0 else 1 if abs(x) == np.inf: return sign * sys.float_info.max return x def _guess_initial_step(val: float, vmin: float, vmax: float) -> float: if np.isfinite(vmin) and np.isfinite(vmax): return 1e-2 * (vmax - vmin) return 1e-2 def _round(x: float) -> float: return float(f"{x:.1g}") iminuit-2.30.1/src/iminuit/minimize.py0000644000000000000000000001161214332717401014644 0ustar00"""Scipy interface for Minuit.""" from .minuit import Minuit import warnings import numpy as np def minimize( fun, x0, args=(), method="migrad", jac=None, hess=None, hessp=None, bounds=None, constraints=None, tol=None, callback=None, options=None, ): """ Interface to MIGRAD using the ``scipy.optimize.minimize`` API. This function provides the same interface as ``scipy.optimize.minimize``. If you are familiar with the latter, this allows you to use Minuit with a quick start. Eventually, you still may want to learn the interface of the :class:`Minuit` class, as it provides more functionality if you are interested in parameter uncertainties. For a general description of the arguments of this function, see ``scipy.optimize.minimize``. We list only a few in the following. Parameters ---------- method: str Allowed values are "migrad" or "simplex". Default: "migrad". options: dict Can be used to pass special settings to Minuit. All are optional. The following options are supported. *disp* (bool): Set to true to print convergence messages. Default: False. *stra* (int): Minuit strategy (0: fast/inaccurate, 1: balanced, 2: slow/accurate). Default: 1. *maxfun* (int): Maximum allowed number of iterations. Default: None. *maxfev* (int): Deprecated alias for *maxfun*. *eps* (sequence): Initial step size to numerical compute derivative. Minuit automatically refines this in subsequent iterations and is very insensitive to the initial choice. Default: 1. Returns ------- OptimizeResult Dict with attribute access that holds the result. It contains the following lists of fields. *x* (ndarray): Solution of optimization. *fun* (float): Value of objective function at minimum. *message* (str): Description of cause of termination. *hess_inv* (ndarray): Inverse of Hesse matrix at minimum (may not be exact). *nfev* (int): Number of function evaluations. *njev* (int): Number of jacobian evaluations. *minuit* (Minuit): Minuit object internally used to do the minimization. Use this to extract more information about the parameter errors. """ from scipy.optimize import OptimizeResult, Bounds x0 = np.atleast_1d(x0) if constraints is not None: raise ValueError("Constraints are not supported by Minuit, only bounds") if hess or hessp: warnings.warn("hess and hessp arguments cannot be handled and are ignored") def wrapped(func, args, callback=None): if callback is None: return lambda x: func(x, *args) def f(x): callback(x) return func(x, *args) return f wrapped_fun = wrapped(fun, args, callback) wrapped_fun.errordef = 0.5 # so that hesse is really second derivative if bool(jac): if jac is True: raise ValueError("jac=True is not supported, only jac=callable") assert callable(jac) wrapped_grad = wrapped(jac, args) else: wrapped_grad = None m = Minuit(wrapped_fun, x0, grad=wrapped_grad) if bounds is not None: if isinstance(bounds, Bounds): m.limits = [(a, b) for a, b in zip(bounds.lb, bounds.ub)] else: m.limits = bounds if tol: m.tol = tol ncall = 0 if options: m.print_level = 2 if options.get("disp", False) else 0 if "maxiter" in options: warnings.warn("maxiter not supported, acts like maxfun instead") if "maxfev" in options: warnings.warn( "maxfev is deprecated, use maxfun instead", DeprecationWarning ) ncall = options.get("maxfun", options.get("maxfev", options.get("maxiter", 0))) errors = options.get("eps", None) if errors is not None: m.errors = errors m.strategy = options.get("stra", 1) if method == "migrad": m.migrad(ncall=ncall) elif method == "simplex": m.simplex(ncall=ncall) else: raise ValueError(f"keyword method={method} not understood") if m.valid: message = "Optimization terminated successfully" if m.accurate: message += "." else: message += ", but uncertainties are unrealiable." else: message = "Optimization failed." fmin = m.fmin if fmin.has_reached_call_limit: message += " Call limit was reached." if fmin.is_above_max_edm: message += " Estimated distance to minimum too large." n = len(x0) return OptimizeResult( x=np.array(m.values), success=m.valid, fun=m.fval, hess_inv=m.covariance if m.covariance is not None else np.ones((n, n)), message=message, nfev=m.nfcn, njev=m.ngrad, minuit=m, ) iminuit-2.30.1/src/iminuit/minuit.py0000644000000000000000000030102514332717401014330 0ustar00"""Minuit class.""" from __future__ import annotations import warnings from iminuit import util as mutil from iminuit.util import _replace_none as replace_none from iminuit._core import ( FCN, MnContours, MnHesse, MnMachinePrecision, MnMigrad, MnMinos, MnPrint, MnSimplex, MnStrategy, MnUserParameterState, FunctionMinimum, ) from iminuit.warnings import ErrordefAlreadySetWarning import numpy as np from typing import ( Union, Optional, Callable, Tuple, List, Dict, Iterable, Any, Collection, Set, Sized, ) from iminuit.typing import UserBound, Cost, CostGradient from iminuit._optional_dependencies import optional_module_for from numpy.typing import ArrayLike MnPrint.global_level = 0 __all__ = ["Minuit"] class Minuit: """Function minimizer and error computer.""" __slots__ = ( "_fcn", "_strategy", "_tolerance", "_precision", "_values", "_errors", "_merrors", "_fixed", "_limits", "_fmin", "_covariance", "_var2pos", "_pos2var", "_init_state", "_last_state", ) _fmin: Optional[mutil.FMin] _covariance: Optional[mutil.Matrix] # Set errordef to this for a least-squares cost function. LEAST_SQUARES = 1.0 # Set errordef to this for a negated log-likelihood function. LIKELIHOOD = 0.5 @property def fcn(self) -> FCN: """Get cost function (usually a least-squares or likelihood function).""" return self._fcn @property def grad(self) -> Callable[[np.ndarray], np.ndarray]: """Get gradient function of the cost function.""" return self._fcn.gradient # type:ignore @property def pos2var(self) -> Tuple[str, ...]: """Map variable index to name.""" return self._pos2var @property def var2pos(self) -> Dict[str, int]: """Map variable name to index.""" return self._var2pos @property def parameters(self) -> Tuple[str, ...]: """ Get tuple of parameter names. This is an alias for :attr:`pos2var`. """ return self._pos2var @property def errordef(self) -> float: """ Access FCN increment above minimum that corresponds to one standard deviation. Default value is 1.0. `errordef` should be 1.0 for a least-squares cost function and 0.5 for a negative log-likelihood function. See section 1.5.1 on page 6 of the :download:`MINUIT2 User's Guide `. This parameter is also called *UP* in MINUIT documents. If FCN has an attribute ``errordef``, its value is used automatically and you should not set errordef by hand. Doing so will raise a ErrordefAlreadySetWarning. For the builtin cost functions in :mod:`iminuit.cost`, you don't need to set this value, because they all have the ``errordef`` attribute set. To make user code more readable, we provided two named constants:: m_lsq = Minuit(a_least_squares_function) m_lsq.errordef = Minuit.LEAST_SQUARES # == 1 m_nll = Minuit(a_likelihood_function) m_nll.errordef = Minuit.LIKELIHOOD # == 0.5 """ return self._fcn._errordef # type: ignore @errordef.setter def errordef(self, value: float) -> None: fcn_errordef = getattr(self._fcn._fcn, "errordef", None) if fcn_errordef is not None: msg = ( f"cost function has an errordef attribute equal to {fcn_errordef}, " "you should not override this with Minuit.errordef" ) warnings.warn(msg, ErrordefAlreadySetWarning) if value <= 0: raise ValueError(f"errordef={value} must be a positive number") self._fcn._errordef = value if self._fmin: self._fmin._src.errordef = value @property def precision(self) -> Optional[float]: """ Access estimated precision of the cost function. Default: None. If set to None, Minuit assumes the cost function is computed in double precision. If the precision of the cost function is lower (because it computes in single precision, for example) set this to some multiple of the smallest relative change of a parameter that still changes the function. """ return self._precision @precision.setter def precision(self, value: Optional[float]) -> None: if value is not None and not (value > 0): raise ValueError("precision must be a positive number or None") self._precision = value @property def tol(self) -> float: """ Access tolerance for convergence with the EDM criterion. Minuit detects converge with the EDM criterion. EDM stands for *Estimated Distance to Minimum*, it is mathematically described in the `MINUIT paper`_. The EDM criterion is well suited for statistical cost functions, since it stops the minimization when parameter improvements become small compared to parameter uncertainties. The convergence is detected when `edm < edm_max`, where `edm_max` is calculated as * Migrad: edm_max = 0.002 * tol * errordef * Simplex: edm_max = tol * errordef Users can set `tol` (default: 0.1) to a different value to either speed up convergence at the cost of a larger error on the fitted parameters and possibly invalid estimates for parameter uncertainties or smaller values to get more accurate parameter values, although this should never be necessary as the default is fine. If the tolerance is set to a very small value or zero, Minuit will use an internal lower limit for the tolerance. To restore the default use, one can assign `None`. Under some circumstances, Migrad is allowed to violate edm_max by a factor of 10. Users should not try to detect convergence by comparing edm with edm_max, but query :attr:`iminuit.util.FMin.is_above_max_edm`. """ return self._tolerance @tol.setter def tol(self, value: Optional[float]) -> None: if value is None: # used to reset tolerance value = 0.1 elif value < 0: raise ValueError("tolerance must be non-negative") self._tolerance = value @property def strategy(self) -> MnStrategy: """ Access current minimization strategy. You can assign an integer: - 0: Fast. Does not check a user-provided gradient. Does not improve Hesse matrix at minimum. Extra call to :meth:`hesse` after :meth:`migrad` is always needed for good error estimates. If you pass a user-provided gradient to MINUIT, convergence is **faster**. - 1: Default. Checks user-provided gradient against numerical gradient. Checks and usually improves Hesse matrix at minimum. Extra call to :meth:`hesse` after :meth:`migrad` is usually superfluous. If you pass a user-provided gradient to MINUIT, convergence is **slower**. - 2: Careful. Like 1, but does extra checks of intermediate Hessian matrix during minimization. The effect in benchmarks is a somewhat improved accuracy at the cost of more function evaluations. A similar effect can be achieved by reducing the tolerance :attr:`tol` for convergence at any strategy level. """ return self._strategy @strategy.setter def strategy(self, value: int) -> None: self._strategy.strategy = value @property def print_level(self) -> int: """ Access current print level. You can assign an integer: - 0: quiet (default) - 1: print minimal debug messages to terminal - 2: print more debug messages to terminal - 3: print even more debug messages to terminal Warnings -------- Setting print_level has the unwanted side-effect of setting the level globally for all Minuit instances in the current Python session. """ return MnPrint.global_level # type: ignore @print_level.setter def print_level(self, level: int) -> None: MnPrint.global_level = level @property def throw_nan(self) -> bool: """ Access whether to raise runtime error if the function evaluates to NaN. If you set this to True, an error is raised whenever the function evaluates to NaN. """ return self._fcn._throw_nan # type: ignore @throw_nan.setter def throw_nan(self, value: bool) -> None: self._fcn._throw_nan = value @property def values(self) -> mutil.ValueView: """ Access parameter values via an array-like view. Use to read or write current parameter values based on the parameter index or the parameter name as a string. If you change a parameter value and run :meth:`migrad`, the minimization will start from that value, similar for :meth:`hesse` and :meth:`minos`. See Also -------- errors, fixed, limits """ return self._values @values.setter def values(self, args: Iterable) -> None: self._values[:] = args @property def errors(self) -> mutil.ErrorView: """ Access parameter parabolic errors via an array-like view. Like :attr:`values`, but instead of reading or writing the values, you read or write the errors (which double as step sizes for MINUITs numerical gradient estimation). Only positive values are accepted when assigning to errors. See Also -------- values, fixed, limits """ return self._errors @errors.setter def errors(self, args: Iterable) -> None: self._errors[:] = args @property def fixed(self) -> mutil.FixedView: """ Access whether parameters are fixed via an array-like view. Use to read or write the fixation state of a parameter based on the parameter index or the parameter name as a string. If you change the state and run :meth:`migrad`, :meth:`hesse`, or :meth:`minos`, the new state is used. In case of complex fits, it can help to fix some parameters first and only minimize the function with respect to the other parameters, then release the fixed parameters and minimize again starting from that state. See Also -------- values, errors, limits """ return self._fixed @fixed.setter def fixed(self, args: Iterable) -> None: self._fixed[:] = args @property def limits(self) -> mutil.LimitView: """ Access parameter limits via a array-like view. Use to read or write the limits of a parameter based on the parameter index or the parameter name as a string. If you change the limits and run :meth:`migrad`, :meth:`hesse`, or :meth:`minos`, the new state is used. In case of complex fits, it can help to limit some parameters first, run Migrad, then remove the limits and run Migrad again. Limits will bias the result only if the best fit value is outside the limits, not if it is inside. Limits will affect the estimated Hesse uncertainties if the parameter is close to a limit. They do not affect the Minos uncertainties, because those are invariant to transformations and limits are implemented via a variable transformation. See Also -------- values, errors, fixed """ return self._limits @limits.setter def limits(self, args: Iterable) -> None: self._limits[:] = args @property def merrors(self) -> mutil.MErrors: """ Return a dict-like with Minos data objects. The Minos data objects contain the full status information of the Minos run. See Also -------- util.MError util.MErrors """ return self._merrors @property def covariance(self) -> Optional[mutil.Matrix]: r""" Return covariance matrix. The square-root of the diagonal elements of the covariance matrix correspond to a standard deviation for each parameter with 68 % coverage probability in the asymptotic limit (large samples). To get k standard deviations, multiply the covariance matrix with k^2. The submatrix formed by two parameters describes an ellipse. The asymptotic coverage probabilty of the standard ellipse is lower than 68 %. It can be computed from the :math:`\chi^2` distribution with 2 degrees of freedom. In general, to obtain a (hyper-)ellipsoid with coverage probability CL, one has to multiply the submatrix of the corresponding k parameters with a factor. For k = 1,2,3 and CL = 0.99 :: from scipy.stats import chi2 chi2(1).ppf(0.99) # 6.63... chi2(2).ppf(0.99) # 9.21... chi2(3).ppf(0.99) # 11.3... See Also -------- util.Matrix """ return self._covariance @property def npar(self) -> int: """Get number of parameters.""" return len(self._last_state) @property def nfit(self) -> int: """Get number of fitted parameters (fixed parameters not counted).""" return self.npar - sum(self.fixed) @property def ndof(self) -> int: """ Get number of degrees of freedom if cost function supports this. To support this feature, the cost function has to report the number of data points with a property called ``ndata``. Unbinned cost functions should return infinity. """ return self._fcn._ndata() - self.nfit # type: ignore @property def fmin(self) -> Optional[mutil.FMin]: """ Get function minimum data object. See Also -------- util.FMin """ return self._fmin @property def fval(self) -> Optional[float]: """ Get function value at minimum. This is an alias for :attr:`iminuit.util.FMin.fval`. See Also -------- util.FMin """ fm = self._fmin return fm.fval if fm else None @property def params(self) -> mutil.Params: """ Get list of current parameter data objects. See Also -------- init_params, util.Params """ return _get_params(self._last_state, self._merrors) @property def init_params(self) -> mutil.Params: """ Get list of current parameter data objects set to the initial fit state. See Also -------- params, util.Params """ return _get_params(self._init_state, mutil.MErrors()) @property def valid(self) -> bool: """ Return True if the function minimum is valid. This is an alias for :attr:`iminuit.util.FMin.is_valid`. See Also -------- util.FMin """ return self._fmin.is_valid if self._fmin else False @property def accurate(self) -> bool: """ Return True if the covariance matrix is accurate. This is an alias for :attr:`iminuit.util.FMin.has_accurate_covar`. See Also -------- util.FMin """ return self._fmin.has_accurate_covar if self._fmin else False @property def nfcn(self) -> int: """Get total number of function calls.""" return self._fcn._nfcn # type:ignore @property def ngrad(self) -> int: """Get total number of gradient calls.""" return self._fcn._ngrad # type:ignore def __init__( self, fcn: Cost, *args: Union[float, ArrayLike], grad: Union[CostGradient, bool, None] = None, name: Collection[str] = None, **kwds: float, ): """ Initialize Minuit object. This does not start the minimization or perform any other work yet. Algorithms are started by calling the corresponding methods. Parameters ---------- fcn : Function to minimize. See notes for details on what kind of functions are accepted. *args : Starting values for the minimization as positional arguments. See notes for details on how to set starting values. grad : callable, bool, or None, optional If grad is a callable, it must be a function that calculates the gradient and returns an iterable object with one entry for each parameter, which is the derivative of `fcn` for that parameter. If None (default), Minuit will call the function :func:`iminuit.util.gradient` on `fcn`. If this function returns a callable, it will be used, otherwise Minuit will internally compute the gradient numerically. Please see the documentation of :func:`iminuit.util.gradient` how gradients are detected. Passing a boolean override this detection. If grad=True is used, a ValueError is raised if no useable gradient is found. If grad=False, Minuit will internally compute the gradient numerically. name : sequence of str, optional If it is set, it overrides iminuit's function signature detection. **kwds : Starting values for the minimization as keyword arguments. See notes for details on how to set starting values. Notes ----- *Callables* By default, Minuit assumes that the callable `fcn` behaves like chi-square function, meaning that the function minimum in repeated identical random experiments is chi-square distributed up to an arbitrary additive constant. This is important for the correct error calculation. If `fcn` returns a log-likelihood, one should multiply the result with -2 to adapt it. If the function returns the negated log-likelihood, one can alternatively set the attribute `fcn.errordef` = :attr:`Minuit.LIKELIHOOD` or :attr:`Minuit.errordef` = :attr:`Minuit.LIKELIHOOD` after initialization to make Minuit calculate errors properly. Minuit reads the function signature of `fcn` to detect the number and names of the function parameters. Two kinds of function signatures are understood. a) Function with positional arguments. The function has positional arguments, one for each fit parameter. Example:: def fcn(a, b, c): ... The parameters a, b, c must accept a real number. iminuit automatically detects the parameters names in this case. More information about how the function signature is detected can be found in :func:`iminuit.util.describe`. b) Function with arguments passed as a single Numpy array. The function has a single argument which is a Numpy array. Example:: def fcn_np(x): ... To use this form, starting values need to be passed to Minuit in form as an array-like type, e.g. a numpy array, tuple or list. For more details, see "Parameter Keyword Arguments" further down. In some cases, the detection fails, for example, for a function like this:: def difficult_fcn(*args): ... To use such a function, set the `name` keyword as described further below. *Parameter initialization* Initial values for the minimization can be set with positional arguments or via keywords. This is best explained through an example:: def fcn(x, y): return (x - 2) ** 2 + (y - 3) ** 2 The following ways of passing starting values are equivalent:: Minuit(fcn, x=1, y=2) Minuit(fcn, y=2, x=1) # order is irrelevant when keywords are used ... Minuit(fcn, 1, 2) # ... but here the order matters Positional arguments can also be used if the function has no signature:: def fcn_no_sig(*args): # ... Minuit(fcn_no_sig, 1, 2) If the arguments are explicitly named with the `name` keyword described further below, keywords can be used for initialization:: Minuit(fcn_no_sig, x=1, y=2, name=("x", "y")) # this also works If the function accepts a single Numpy array, then the initial values must be passed as a single array-like object:: def fcn_np(x): return (x[0] - 2) ** 2 + (x[1] - 3) ** 2 Minuit(fcn_np, (1, 2)) Setting the values with keywords is not possible in this case. Minuit deduces the number of parameters from the length of the initialization sequence. See Also -------- migrad, hesse, minos, scan, simplex, iminuit.util.gradient """ array_call = False if len(args) == 1 and isinstance(args[0], Iterable): array_call = True start = np.array(args[0]) else: start = np.array(args) del args annotated = mutil.describe(fcn, annotations=True) if name is None: name = list(annotated) if len(name) == 0 or (array_call and len(name) == 1): name = tuple(f"x{i}" for i in range(len(start))) elif len(name) == len(annotated): annotated = {new: annotated[old] for (old, new) in zip(annotated, name)} if len(start) == 0 and len(kwds) == 0: raise RuntimeError( "starting value(s) are required" + (f" for [{' '.join(name)}]" if name else "") ) # Maintain two dictionaries to easily convert between # parameter names and position self._pos2var = tuple(name) self._var2pos = {k: i for i, k in enumerate(name)} # set self.tol to default value self.tol = None # type:ignore self._strategy = MnStrategy(1) if grad is None: grad = mutil.gradient(fcn) elif grad is True: grad = mutil.gradient(fcn) if grad is None: raise ValueError( "gradient enforced, but iminuit.util.gradient returned None" ) elif grad is False: grad = None if grad is not None and not isinstance(grad, CostGradient): raise ValueError("provided gradient is not a CostGradient") self._fcn = FCN( fcn, grad, array_call, getattr(fcn, "errordef", 1.0), ) self._init_state = _make_init_state(self._pos2var, start, kwds) self._values = mutil.ValueView(self) self._errors = mutil.ErrorView(self) self._fixed = mutil.FixedView(self) self._limits = mutil.LimitView(self) self.precision = getattr(fcn, "precision", None) self.reset() for k, lim in annotated.items(): if lim is not None: self.limits[k] = lim def fixto(self, key: mutil.Key, value: Union[float, Iterable[float]]) -> "Minuit": """ Fix parameter and set it to value. This is a convenience function to fix a parameter and set it to a value at the same time. It is equivalent to calling :attr:`fixed` and :attr:`values`. Parameters ---------- key : int, str, slice, list of int or str Key, which can be an index, name, slice, or list of indices or names. value : float or sequence of float Value(s) assigned to key(s). Returns ------- self """ index = mutil._key2index(self._var2pos, key) if isinstance(index, list): if mutil._ndim(value) == 0: # support basic broadcasting for i in index: self.fixto(i, value) else: assert isinstance(value, Iterable) assert isinstance(value, Sized) if len(value) != len(index): raise ValueError("length of argument does not match slice") for i, v in zip(index, value): self.fixto(i, v) else: self._last_state.fix(index) self._last_state.set_value(index, value) return self # return self for method chaining def reset(self) -> "Minuit": """ Reset minimization state to initial state. Leaves :attr:`strategy`, :attr:`precision`, :attr:`tol`, :attr:`errordef`, :attr:`print_level` unchanged. """ self._last_state = self._init_state self._fmin = None self._fcn._nfcn = 0 self._fcn._ngrad = 0 self._merrors = mutil.MErrors() self._covariance: mutil.Matrix = None return self # return self for method chaining and to autodisplay current state def migrad( self, ncall: Optional[int] = None, iterate: int = 5, use_simplex: bool = True, ) -> "Minuit": """ Run Migrad minimization. Migrad from the Minuit2 library is a robust minimisation algorithm which earned its reputation in 40+ years of almost exclusive usage in high-energy physics. How Migrad works is described in the `Minuit paper`_. It uses first and approximate second derivatives to achieve quadratic convergence near the minimum. Parameters ---------- ncall : int or None, optional Approximate maximum number of calls before minimization will be aborted. If set to None, use the adaptive heuristic from the Minuit2 library (Default: None). Note: The limit may be slightly violated, because the condition is checked only after a full iteration of the algorithm, which usually performs several function calls. iterate : int, optional Automatically call Migrad up to N times if convergence was not reached (Default: 5). This simple heuristic makes Migrad converge more often even if the numerical precision of the cost function is low. Setting this to 1 disables the feature. use_simplex: bool, optional If we have to iterate, set this to True to call the Simplex algorithm before each call to Migrad (Default: True). This may improve convergence in pathological cases (which we are in when we have to iterate). See Also -------- simplex, scan """ if iterate < 1: raise ValueError("iterate must be at least 1") t = mutil._Timer(self._fmin) with t: fm = _robust_low_level_fit( self._fcn, self._last_state, replace_none(ncall, 0), self._strategy, self._tolerance, self._precision, iterate, use_simplex, ) self._last_state = fm.state self._fmin = mutil.FMin( fm, "Migrad", self.nfcn, self.ngrad, self.ndof, self._edm_goal(migrad_factor=True), t.value, ) self._make_covariance() return self # return self for method chaining and to autodisplay current state def simplex(self, ncall: Optional[int] = None) -> "Minuit": """ Run Simplex minimization. Simplex from the Minuit2 C++ library is a variant of the Nelder-Mead algorithm to find the minimum of a function. It does not make use of derivatives. `The Wikipedia has a good article on the Nelder-Mead method `_. Parameters ---------- ncall : Approximate maximum number of calls before minimization will be aborted. If set to None, use the adaptive heuristic from the Minuit2 library (Default: None). Note: The limit may be slightly violated, because the condition is checked only after a full iteration of the algorithm, which usually performs several function calls. Notes ----- The Simplex method usually converges more slowly than Migrad, but performs better in certain cases, the Rosenbrock function is a notable example. Unlike Migrad, the Simplex method does not have quadratic convergence near the minimum, so it is a good approach to run Migrad after Simplex to obtain an accurate solution in fewer steps. Simplex may also be useful to get close to the minimum from an unsuitable starting point. The convergence criterion for Simplex is also based on EDM, but the threshold is much more lax than that of Migrad (see :attr:`Minuit.tol` for details). This was made so that Simplex stops early when getting near the minimum, to give the user a chance to switch to the more efficient Migrad algorithm to finish the minimization. Early stopping can be avoided by setting Minuit.tol to an accordingly smaller value, however. """ simplex = MnSimplex(self._fcn, self._last_state, self.strategy) if self._precision is not None: simplex.precision = self._precision t = mutil._Timer(self._fmin) with t: # ncall = 0 tells C++ Minuit to use its internal heuristic fm = simplex(replace_none(ncall, 0), self._tolerance) self._last_state = fm.state self._fmin = mutil.FMin( fm, "Simplex", self.nfcn, self.ngrad, self.ndof, self._edm_goal(), t.value, ) self._covariance = None self._merrors = mutil.MErrors() return self # return self for method chaining and to autodisplay current state def scan(self, ncall: Optional[int] = None) -> "Minuit": """ Brute-force minimization. Scans the function on a regular hypercube grid, whose bounds are defined either by parameter limits if present or by Minuit.values +/- Minuit.errors. Minuit.errors are initialized to very small values by default, too small for this scan. They should be increased before running scan or limits should be set. The scan evaluates the function exactly at the limit boundary, so the function should be defined there. Parameters ---------- ncall : Approximate number of function calls to spend on the scan. The actual number will be close to this, the scan uses ncall^(1/npar) steps per cube dimension. If no value is given, a heuristic is used to set ncall. Notes ----- The scan can return an invalid minimum, this is not a cause for alarm. It just minimizes the cost function, the EDM value is only computed after the scan found a best point. If the best point still has a bad EDM value, the minimum is considered invalid. But even if it is considered valid, it is probably not accurate, since the tolerance is very lax. One should always run :meth:`migrad` after the scan. This implementation here does a full scan of the hypercube in Python. Originally, this was supposed to use MnScan from C++ Minuit2, but MnScan is unsuitable. It does a 1D scan with 41 steps (not configurable) for each parameter in sequence, so it is not actually scanning the full hypercube. It first scans one parameter, then starts the scan of the second parameter from the best value of the first and so on. This fails easily when the parameters are correlated. """ # Implementation notes: # Returning a valid FunctionMinimum object was a major challenge, because C++ # Minuit2 does not allow one to initialize data objects with data, it forces one # to go through algorithm objects. Because of that design, the Minuit2 C++ # interface forces one to compute the gradient and second derivatives for the # starting values, even though these are not used in a scan. We turn a # disadvantage into an advantage here by tricking Minuit2 into computing updates # of the step sizes and to estimate the EDM value. # Running MnScan would look like this: # scan = MnScan(self._fcn, self._last_state, self.strategy) # fm = scan(0, 0) # args are ignored # self._last_state = fm.state # self._fmin = mutil.FMin(fm, self._fcn.nfcn, self._fcn.ngrad, self._tolerance) n = self.nfit if ncall is None: ncall = self._migrad_maxcall() nstep = int(ncall ** (1 / n)) if self._last_state == self._init_state: # avoid overriding initial state self._last_state = MnUserParameterState(self._last_state) x = np.empty(self.npar + 1) x[self.npar] = np.inf lims = list(self.limits) for i, (low, up) in enumerate(lims): v = self.values[i] e = self.errors[i] if self.fixed[i]: lims[i] = v, v else: lims[i] = ( v - e if low == -np.inf else low, v + e if up == np.inf else up, ) def run(ipar: int) -> None: if ipar == self.npar: r = self._fcn(x[: self.npar]) if r < x[self.npar]: x[self.npar] = r self.values[:] = x[: self.npar] return low, up = lims[ipar] if low == up: x[ipar] = low run(ipar + 1) else: for xi in np.linspace(low, up, nstep): x[ipar] = xi run(ipar + 1) t = mutil._Timer(self._fmin) with t: run(0) edm_goal = self._edm_goal() fm = FunctionMinimum(self._fcn, self._last_state, self.strategy, edm_goal) self._last_state = fm.state self._fmin = mutil.FMin( fm, "Scan", self.nfcn, self.ngrad, self.ndof, edm_goal, t.value, ) self._covariance = None self._merrors = mutil.MErrors() return self # return self for method chaining and to autodisplay current state def scipy( self, method: Union[str, Callable] = None, ncall: Optional[int] = None, hess: Any = None, hessp: Any = None, constraints: Iterable = None, ) -> "Minuit": """ Minimize with SciPy algorithms. Parameters ---------- method : str or Callable, optional Which scipy method to use. ncall : int, optional Function call limit. hess : Callable, optional Function that computes the Hessian matrix. It must use the exact same calling conversion as the original fcn (several arguments which are numbers or a single array argument). hessp : Callable, optional Function that computes the product of the Hessian matrix with a vector. It must use the same calling conversion as the original fcn (several arguments which are numbers or a single array argument) and end with another argument which is an arbitrary vector. constraints : scipy.optimize.LinearConstraint or scipy.optimize.NonlinearConstraint, optional Linear or non-linear constraints, see docs of :func:`scipy.optimize.minimize` look for the `constraints` parameter. The function used in the constraint must use the exact same calling convention as the original fcn, see hess parameter for details. No parameters may be omitted in the signature, even if those parameters are not used in the constraint. Notes ----- The call limit may be violated since many algorithms checks the call limit only after a full iteraction of their algorithm, which consists of several function calls. Some algorithms do not check the number of function calls at all, in this case the call limit acts on the number of iterations of the algorithm. This issue should be fixed in scipy. The SciPy minimizers use their own internal rule for convergence. The EDM criterion is evaluated only after the original algorithm already stopped. This means that usually SciPy minimizers will use more iterations than Migrad and the tolerance :attr:`tol` has no effect on SciPy minimizers. """ try: from scipy.optimize import ( minimize, Bounds, NonlinearConstraint, LinearConstraint, approx_fprime, ) except ModuleNotFoundError as exc: exc.msg += "\n\nPlease install scipy to use scipy minimizers in iminuit." raise if ncall is None: ncall = self._migrad_maxcall() cfree = ~np.array(self.fixed[:], dtype=bool) cpar = np.array(self.values[:]) no_fixed_parameters = np.all(cfree) if no_fixed_parameters: class Wrapped: __slots__ = ("fcn",) def __init__(self, fcn): self.fcn = fcn if self.fcn._array_call: def __call__(self, par): return self.fcn(par) else: def __call__(self, par): return self.fcn(*par) WrappedGrad = Wrapped WrappedHess = Wrapped class WrappedHessp: __slots__ = ("fcn",) def __init__(self, fcn): self.fcn = fcn if self.fcn._array_call: def __call__(self, par, v): return self.fcn(par, v) else: def __call__(self, par, v): return self.fcn(*par, v) else: class Wrapped: # type:ignore __slots__ = ("fcn", "free", "par") def __init__(self, fcn): self.fcn = fcn self.free = cfree self.par = cpar if self.fcn._array_call: def __call__(self, par): self.par[self.free] = par return self.fcn(self.par) else: def __call__(self, par): self.par[self.free] = par return self.fcn(*self.par) class WrappedGrad(Wrapped): # type:ignore def __call__(self, par): g = super().__call__(par) return np.atleast_1d(g)[self.free] class WrappedHess(Wrapped): # type:ignore def __init__(self, fcn): super().__init__(fcn) self.freem = np.outer(self.free, self.free) n = np.sum(self.free) self.shape = n, n def __call__(self, par): h = super().__call__(par) return np.atleast_2d(h)[self.freem].reshape(self.shape) class WrappedHessp: # type:ignore __slots__ = ("fcn", "free", "par", "vec") def __init__(self, fcn): self.fcn = fcn self.free = cfree self.par = cpar self.vec = np.zeros_like(self.par) if self.fcn._array_call: def __call__(self, par, v): self.par[self.free] = par self.vec[self.free] = v return self.fcn(self.par, self.vec)[self.free] else: def __call__(self, par, v): self.par[self.free] = par self.vec[self.free] = v return self.fcn(*self.par, self.vec)[self.free] fcn = Wrapped(self._fcn._fcn) grad = self._fcn._grad grad = WrappedGrad(grad) if grad else None if hess: hess = WrappedHess(hess) if hessp: hessp = WrappedHessp(hessp) if constraints is not None: if isinstance(constraints, dict): raise ValueError("setting constraints with dicts is not supported") if not isinstance(constraints, Iterable): constraints = [constraints] else: constraints = list(constraints) for i, c in enumerate(constraints): if isinstance(c, NonlinearConstraint): c.fun = Wrapped(c.fun) elif isinstance(c, LinearConstraint): if not no_fixed_parameters: x = cpar.copy() x[cfree] = 0 shift = np.dot(c.A, x) lb = c.lb - shift ub = c.ub - shift A = np.atleast_2d(c.A)[:, cfree] constraints[i] = LinearConstraint(A, lb, ub, c.keep_feasible) else: raise ValueError( "setting constraints with dicts is not supported, use " "LinearConstraint or NonlinearConstraint from scipy.optimize." ) pr = self._mnprecision() # Limits for scipy need to be a little bit tighter than the ones for Minuit # so that the Jacobian of the transformation is not zero or infinite. start = [] lower_bound = [] upper_bound = [] has_limits = False for p in self.params: if p.is_fixed: continue has_limits |= p.has_limits # ensure lower < x < upper for Minuit ai = -np.inf if p.lower_limit is None else p.lower_limit bi = np.inf if p.upper_limit is None else p.upper_limit if ai > 0: ai *= 1 + pr.eps2 elif ai < 0: ai *= 1 - pr.eps2 else: ai = pr.eps2 if bi > 0: bi *= 1 - pr.eps2 elif bi < 0: bi *= 1 + pr.eps2 else: bi = -pr.eps2 xi = np.clip(p.value, ai, bi) lower_bound.append(ai) upper_bound.append(bi) start.append(xi) if method is None: # like in scipy.optimize.minimize if constraints: method = "SLSQP" elif has_limits: method = "L-BFGS-B" else: method = "BFGS" # various workarounds for API inconsistencies in scipy.optimize.minimize options = {"maxiter": ncall} if method in ( "Nelder-Mead", "Powell", ): options["maxfev"] = ncall del options["maxiter"] if method in ("L-BFGS-B", "TNC"): options["maxfun"] = ncall del options["maxiter"] if method in ("COBYLA", "SLSQP", "trust-constr") and constraints is None: constraints = () t = mutil._Timer(self._fmin) with t: r = minimize( fcn, start, method=method, bounds=( Bounds(lower_bound, upper_bound, keep_feasible=True) if has_limits else None ), jac=grad, hess=hess, hessp=hessp, constraints=constraints, options=options, ) if self.print_level > 0: print(r) self._fcn._nfcn += r["nfev"] if grad: self._fcn._ngrad += r.get("njev", 0) # Get inverse Hesse matrix, working around many inconsistencies in scipy. # Try in order: # 1) If hess_inv is returned as full matrix as result, use that. # 2) If hess is returned as full matrix, invert it and use that. # - These two are approximations to the exact Hessian. - # 3) If externally computed hessian was passed to method, use that. # Hessian is considered accurate then. matrix = None needs_invert = False if "hess_inv" in r: matrix = r.hess_inv elif "hess" in r: matrix = r.hess needs_invert = True # hess_inv is a function, need to convert to full matrix if callable(matrix): assert matrix is not None # for mypy matrix = matrix(np.eye(self.nfit)) accurate_covar = bool(hess) or bool(hessp) # Newton-CG neither returns hessian nor inverted hessian if matrix is None: if accurate_covar: if hessp: matrix = [hessp(r.x, ei) for ei in np.eye(self.nfit)] else: matrix = hess(r.x) needs_invert = True if needs_invert: matrix = np.linalg.inv(matrix) # type:ignore # Last resort: use parameter step sizes as "errors" if matrix is None: matrix = np.zeros((self.nfit, self.nfit)) i = 0 for p in self.params: if p.is_fixed: continue matrix[i, i] = p.error**2 i += 1 if "grad" in r: # trust-constr has "grad" and "jac", but "grad" is "jac"! jac = r.grad elif "jac" in r: jac = r.jac else: dx = np.sqrt(np.diag(matrix) * 1e-10) jac = approx_fprime(r.x, fcn, epsilon=dx) edm_goal = self._edm_goal(migrad_factor=True) fm = FunctionMinimum( self._last_state.trafo, r.x, matrix, jac, r.fun, self.errordef, edm_goal, self.nfcn, ncall, accurate_covar, ) self._last_state = fm.state self._fmin = mutil.FMin( fm, f"SciPy[{method}]", self.nfcn, self.ngrad, self.ndof, edm_goal, t.value, ) if accurate_covar: self._make_covariance() else: if self.strategy.strategy > 0: self.hesse() return self def visualize(self, plot: Callable = None, **kwargs): """ Visualize agreement of current model with data (requires matplotlib). This generates a plot of the data/model agreement, using the current parameter values, if the likelihood function supports this, otherwise AttributeError is raised. Parameters ---------- plot : Callable, optional This function tries to call the visualize method on the cost function, which accepts the current model parameters as an array-like and potentially further keyword arguments, and draws a visualization into the current matplotlib axes. If the cost function does not provide a visualize method or if you want to override it, pass the function here. kwargs : Other keyword arguments are forwarded to the plot function. See Also -------- Minuit.interactive """ return self._visualize(plot)(self.values, **kwargs) def hesse(self, ncall: Optional[int] = None) -> "Minuit": """ Run Hesse algorithm to compute asymptotic errors. The Hesse method estimates the covariance matrix by inverting the matrix of `second derivatives (Hesse matrix) at the minimum `_. To get parameters correlations, you need to use this. The Minos algorithm is another way to estimate parameter uncertainties, see :meth:`minos`. Parameters ---------- ncall : Approximate upper limit for the number of calls made by the Hesse algorithm. If set to None, use the adaptive heuristic from the Minuit2 library (Default: None). Notes ----- The covariance matrix is asymptotically (in large samples) valid. By valid we mean that confidence intervals constructed from the errors contain the true value with a well-known coverage probability (68 % for each interval). In finite samples, this is likely to be true if your cost function looks like a hyperparabola around the minimum. In practice, the errors very likely have correct coverage if the results from Minos and Hesse methods agree. It is possible to construct artifical functions where this rule is violated, but in practice it should always work. See Also -------- minos """ # Should be fixed upstream: workaround for segfault in MnHesse when all # parameters are fixed if self.nfit == 0: warnings.warn( "Hesse called with all parameters fixed", mutil.IMinuitWarning, stacklevel=2, ) return self if self._fmin_does_not_exist_or_last_state_was_modified(): # create a seed minimum edm_goal = self._edm_goal(migrad_factor=True) fm = FunctionMinimum( self._fcn, self._last_state, self._strategy, edm_goal, ) self._fmin = mutil.FMin( fm, "External", self.nfcn, self.ngrad, self.ndof, edm_goal, 0 ) self._merrors = mutil.MErrors() assert self._fmin is not None fm = self._fmin._src # update _fmin with Hesse hesse = MnHesse(self.strategy) t = mutil._Timer(self._fmin) with t: # ncall = 0 tells C++ Minuit to use its internal heuristic hesse(self._fcn, fm, replace_none(ncall, 0), self._fmin.edm_goal) self._last_state = fm.state self._fmin = mutil.FMin( fm, self._fmin.algorithm, self.nfcn, self.ngrad, self.ndof, self._fmin.edm_goal, t.value, ) self._make_covariance() return self # return self for method chaining and to autodisplay current state def minos( self, *parameters: Union[int, str], cl: float = None, ncall: Optional[int] = None, ) -> "Minuit": """ Run Minos algorithm to compute confidence intervals. The Minos algorithm uses the profile likelihood method to compute (generally asymmetric) confidence intervals. It scans the negative log-likelihood or (equivalently) the least-squares cost function around the minimum to construct a confidence interval. Parameters ---------- *parameters : Names of parameters to generate Minos errors for. If no positional arguments are given, Minos is run for each parameter. cl : float or None, optional Confidence level of the interval. If not set or None, a standard 68 % interval is computed (default). If 0 < cl < 1, the value is interpreted as the confidence level (a probability). For convenience, values cl >= 1 are interpreted as the probability content of a central symmetric interval covering that many standard deviations of a normal distribution. For example, cl=1 is interpreted as 68.3 %, and cl=2 is 84.3 %, and so on. Using values other than 0.68, 0.9, 0.95, 0.99, 1, 2, 3, 4, 5 require the scipy module. ncall : int or None, optional Limit the number of calls made by Minos. If None, an adaptive internal heuristic of the Minuit2 library is used (Default: None). Notes ----- Asymptotically (large samples), the Minos interval has a coverage probability equal to the given confidence level. The coverage probability is the probability for the interval to contain the true value in repeated identical experiments. The interval is invariant to transformations and thus not distorted by parameter limits, unless the limits intersect with the confidence interval. As a rule-of-thumb: when the confidence intervals computed with the Hesse and Minos algorithms differ strongly, the Minos intervals are preferred. Otherwise, Hesse intervals are preferred. Running Minos is computationally expensive when there are many fit parameters. Effectively, it scans over one parameter in small steps and runs a full minimisation for all other parameters of the cost function for each scan point. This requires many more function evaluations than running the Hesse algorithm. """ factor = _cl_to_errordef(cl, 1, 1.0) if self._fmin_does_not_exist_or_last_state_was_modified(): self.hesse() # creates self._fmin assert self._fmin is not None fm = self._fmin._src if not self.valid: raise RuntimeError(f"Function minimum is not valid: {repr(self._fmin)}") if len(parameters) == 0: ipars = [ipar for ipar in range(self.npar) if not self.fixed[ipar]] else: ipars = [] for par in parameters: ip, pname = self._normalize_key(par) if self.fixed[ip]: warnings.warn( f"Cannot scan over fixed parameter {pname!r}", mutil.IMinuitWarning, ) else: ipars.append(ip) t = mutil._Timer(self._fmin) with t: with _TemporaryErrordef(self._fcn, factor): minos = MnMinos(self._fcn, fm, self.strategy) for ipar in ipars: par = self._pos2var[ipar] me = minos(ipar, replace_none(ncall, 0), self._tolerance) self._merrors[par] = mutil.MError( me.number, par, me.lower, me.upper, me.is_valid, me.lower_valid, me.upper_valid, me.at_lower_limit, me.at_upper_limit, me.at_lower_max_fcn, me.at_upper_max_fcn, me.lower_new_min, me.upper_new_min, me.nfcn, me.min, ) if self._fmin: self._fmin._nfcn = self.nfcn self._fmin._ngrad = self.ngrad self._fmin._time = t.value return self # return self for method chaining and to autodisplay current state def mnprofile( self, vname: Union[int, str], *, size: int = 30, bound: Union[float, UserBound] = 2, grid: ArrayLike = None, subtract_min: bool = False, ncall: int = 0, iterate: int = 5, use_simplex: bool = True, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: r""" Get Minos profile over a specified interval. Scans over one parameter and minimises the function with respect to all other parameters for each scan point. Parameters ---------- vname : int or str Parameter to scan over. size : int, optional Number of scanning points (Default: 100). Ignored if grid is set. bound : tuple of float or float, optional If bound is tuple, (left, right) scanning bound. If bound is a number, it specifies an interval of N :math:`\sigma` symmetrically around the minimum (Default: 2). Ignored if grid is set. grid : array-like, optional Parameter values on which to compute the profile. If grid is set, size and bound are ignored. subtract_min : bool, optional If true, subtract offset so that smallest value is zero (Default: False). ncall : int, optional Approximate maximum number of calls before minimization will be aborted. If set to 0, use the adaptive heuristic from the Minuit2 library (Default: 0). Note: The limit may be slightly violated, because the condition is checked only after a full iteration of the algorithm, which usually performs several function calls. iterate : int, optional Automatically call Migrad up to N times if convergence was not reached (Default: 5). This simple heuristic makes Migrad converge more often even if the numerical precision of the cost function is low. Setting this to 1 disables the feature. use_simplex: bool, optional If we have to iterate, set this to True to call the Simplex algorithm before each call to Migrad (Default: True). This may improve convergence in pathological cases (which we are in when we have to iterate). Returns ------- array of float Parameter values where the profile was computed. array of float Profile values. array of bool Whether minimisation in each point succeeded or not. See Also -------- profile, contour, mncontour """ ipar, pname = self._normalize_key(vname) del vname if grid is not None: x = np.array(grid, dtype=float) if x.ndim != 1: raise ValueError("grid must be 1D array-like") else: a, b = self._normalize_bound(pname, bound) x = np.linspace(a, b, size, dtype=float) y = np.empty_like(x) status = np.empty(len(x), dtype=bool) state = MnUserParameterState(self._last_state) # copy state.fix(ipar) # strategy 0 to avoid expensive computation of Hesse matrix strategy = MnStrategy(0) for i, v in enumerate(x): state.set_value(ipar, v) fm = _robust_low_level_fit( self._fcn, state, ncall, strategy, self._tolerance, self._precision, iterate, use_simplex, ) if not fm.is_valid: warnings.warn( f"MIGRAD fails to converge for {pname}={v}", mutil.IMinuitWarning ) status[i] = fm.is_valid y[i] = fm.fval if subtract_min: y -= np.min(y) return x, y, status def draw_mnprofile( self, vname: Union[int, str], *, band: bool = True, text: bool = True, **kwargs ) -> Tuple[np.ndarray, np.ndarray]: r""" Draw Minos profile over a specified interval (requires matplotlib). See :meth:`mnprofile` for details and shared arguments. The following additional arguments are accepted. Parameters ---------- vname: int or string Which variable to scan over, can be identified by index or name. band : bool, optional If true, show a band to indicate the Hesse error interval (Default: True). text : bool, optional If true, show text a title with the function value and the Hesse error (Default: True). **kwargs : Other keyword arguments are forwarded to :meth:`mnprofile`. Examples -------- .. plot:: plots/mnprofile.py :include-source: See Also -------- mnprofile, draw_profile, draw_contour, draw_mnmatrix """ ipar, pname = self._normalize_key(vname) del vname if "subtract_min" not in kwargs: kwargs["subtract_min"] = True x, y, _ = self.mnprofile(ipar, **kwargs) return self._draw_profile(ipar, x, y, band, text) def profile( self, vname: Union[int, str], *, size: int = 100, bound: Union[float, UserBound] = 2, grid: ArrayLike = None, subtract_min: bool = False, ) -> Tuple[np.ndarray, np.ndarray]: r""" Calculate 1D cost function profile over a range. A 1D scan of the cost function around the minimum, useful to inspect the minimum. For a fit with several free parameters this is not the same as the Minos profile computed by :meth:`mncontour`. Parameters ---------- vname : int or str Parameter to scan over. size : int, optional Number of scanning points (Default: 100). Ignored if grid is set. bound : tuple of float or float, optional If bound is tuple, (left, right) scanning bound. If bound is a number, it specifies an interval of N :math:`\sigma` symmetrically around the minimum (Default: 2). Ignored if grid is set. grid : array-like, optional Parameter values on which to compute the profile. If grid is set, size and bound are ignored. subtract_min : bool, optional If true, subtract offset so that smallest value is zero (Default: False). Returns ------- array of float Parameter values. array of float Function values. See Also -------- mnprofile, contour, mncontour """ ipar, par = self._normalize_key(vname) del vname if grid is not None: x = np.array(grid, dtype=float) if x.ndim != 1: raise ValueError("grid must be 1D array-like") else: a, b = self._normalize_bound(par, bound) x = np.linspace(a, b, size, dtype=float) y = np.empty_like(x) values = np.array(self.values) for i, vi in enumerate(x): values[ipar] = vi y[i] = self._fcn(values) if subtract_min: y -= np.min(y) return x, y def draw_profile( self, vname: Union[int, str], *, band: bool = True, text: bool = True, **kwargs ) -> Tuple[np.ndarray, np.ndarray]: """ Draw 1D cost function profile over a range (requires matplotlib). See :meth:`profile` for details and shared arguments. The following additional arguments are accepted. Parameters ---------- band : bool, optional If true, show a band to indicate the Hesse error interval (Default: True). text : bool, optional If true, show text a title with the function value and the Hesse error (Default: True). See Also -------- profile, draw_mnprofile, draw_contour, draw_mncontourprofile """ ipar, pname = self._normalize_key(vname) del vname if "subtract_min" not in kwargs: kwargs["subtract_min"] = True x, y = self.profile(ipar, **kwargs) return self._draw_profile(ipar, x, y, band, text) def _draw_profile( self, ipar: int, x: np.ndarray, y: np.ndarray, band: bool, text: bool, ) -> Tuple[np.ndarray, np.ndarray]: from matplotlib import pyplot as plt pname = self._pos2var[ipar] plt.plot(x, y) plt.xlabel(pname) plt.ylabel("FCN") v = self.values[ipar] plt.axvline(v, color="k", linestyle="--") vmin = None vmax = None if pname in self.merrors: vmin = v + self.merrors[pname].lower vmax = v + self.merrors[pname].upper else: vmin = v - self.errors[ipar] vmax = v + self.errors[ipar] if vmin is not None and band: plt.axvspan(vmin, vmax, facecolor="0.8") if text: plt.title( ( (f"{pname} = {v:.3g}") if vmin is None else ( "{} = {:.3g} - {:.3g} + {:.3g}".format( pname, v, v - vmin, vmax - v ) ) ), fontsize="large", ) return x, y def contour( self, x: Union[int, str], y: Union[int, str], *, size: int = 50, bound: Union[float, Iterable[Tuple[float, float]]] = 2, grid: Tuple[ArrayLike, ArrayLike] = None, subtract_min: bool = False, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: r""" Get a 2D contour of the function around the minimum. It computes the contour via a function scan over two parameters, while keeping all other parameters fixed. The related :meth:`mncontour` works differently: for each pair of parameter values in the scan, it minimises the function with the respect to all other parameters. This method is useful to inspect the function near the minimum to detect issues (the contours should look smooth). It is not a confidence region unless the function only has two parameters. Use :meth:`mncontour` to compute confidence regions. Parameters ---------- x : int or str First parameter for scan. y : int or str Second parameter for scan. size : int or tuple of int, optional Number of scanning points per parameter (Default: 50). A tuple is interpreted as the number of scanning points per parameter. Ignored if grid is set. bound : float or tuple of floats, optional If bound is 2x2 array, [[v1min,v1max],[v2min,v2max]]. If bound is a number, it specifies how many :math:`\sigma` symmetrically from minimum (minimum+- bound*:math:`\sigma`). (Default: 2). Ignored if grid is set. grid : tuple of array-like, optional Grid points to scan over. If grid is set, size and bound are ignored. subtract_min : Subtract minimum from return values (Default: False). Returns ------- array of float Parameter values of first parameter. array of float Parameter values of second parameter. 2D array of float Function values. See Also -------- mncontour, mnprofile, profile """ ix, xname = self._normalize_key(x) iy, yname = self._normalize_key(y) del x del y if grid is not None: xg, yg = grid xv = np.array(xg, dtype=float) yv = np.array(yg, dtype=float) if xv.ndim != 1 or yv.ndim != 1: raise ValueError("grid per parameter must be 1D array-like") else: if isinstance(bound, Iterable): xb, yb = bound xrange = self._normalize_bound(xname, xb) yrange = self._normalize_bound(yname, yb) else: n = float(bound) xrange = self._normalize_bound(xname, n) yrange = self._normalize_bound(yname, n) if isinstance(size, Iterable): xsize, ysize = size else: xsize = size ysize = size xv = np.linspace(xrange[0], xrange[1], xsize) yv = np.linspace(yrange[0], yrange[1], ysize) zv = np.empty((len(xv), len(yv)), dtype=float) values = np.array(self.values) for i, xi in enumerate(xv): values[ix] = xi for j, yi in enumerate(yv): values[iy] = yi zv[i, j] = self._fcn(values) if subtract_min: zv -= np.min(zv) return xv, yv, zv def draw_contour( self, x: Union[int, str], y: Union[int, str], **kwargs, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """ Draw 2D contour around minimum (requires matplotlib). See :meth:`contour` for details on parameters and interpretation. Please also read the docs of :meth:`mncontour` to understand the difference between the two. See Also -------- contour, draw_mncontour, draw_profile, draw_mnmatrix """ from matplotlib import pyplot as plt ix, xname = self._normalize_key(x) iy, yname = self._normalize_key(y) del x del y if "subtract_min" not in kwargs: kwargs["subtract_min"] = True vx, vy, vz = self.contour(ix, iy, **kwargs) v = [self.errordef * (i + 1) for i in range(4)] CS = plt.contour(vx, vy, vz.T, v) plt.clabel(CS, v) plt.xlabel(xname) plt.ylabel(yname) plt.axhline(self.values[iy], color="k", ls="--") plt.axvline(self.values[ix], color="k", ls="--") return vx, vy, vz def mncontour( self, x: Union[int, str], y: Union[int, str], *, cl: float = None, size: int = 100, interpolated: int = 0, experimental: bool = False, ncall: int = 0, iterate: int = 5, use_simplex: bool = True, ) -> np.ndarray: """ Get 2D Minos confidence region. This scans over two parameters and minimises all other free parameters for each scan point. This scan produces a statistical confidence region according to the `profile likelihood method `_ with a confidence level `cl`, which is asymptotically equal to the coverage probability of the confidence region according to `Wilks' theorem `. Note that 1D projections of the 2D confidence region are larger than 1D Minos intervals computed for the same confidence level. This is not an error, but a consequence of Wilks' theorem. The calculation is expensive since a numerical minimisation has to be performed at various points. Parameters ---------- x : str Variable name of the first parameter. y : str Variable name of the second parameter. cl : float or None, optional Confidence level of the contour. If not set or None, a standard 68 % contour is computed (default). If 0 < cl < 1, the value is interpreted as the confidence level (a probability). For convenience, values cl >= 1 are interpreted as the probability content of a central symmetric interval covering that many standard deviations of a normal distribution. For example, cl=1 is interpreted as 68.3 %, and cl=2 is 84.3 %, and so on. Using values other than 0.68, 0.9, 0.95, 0.99, 1, 2, 3, 4, 5 require the scipy module. size : int, optional Number of points on the contour to find (default: 100). Increasing this makes the contour smoother, but requires more computation time. interpolated : int, optional Number of interpolated points on the contour (default: 0). If you set this to a value larger than size, cubic spline interpolation is used to generate a smoother curve and the interpolated coordinates are returned. Values smaller than size are ignored. Good results can be obtained with size=20, interpolated=200. This requires scipy. experimental : bool, optional If true, use experimental implementation to compute contour, otherwise use MnContour from the Minuit2 library. The experimental implementation was found to succeed in cases where MnContour produced no reasonable result, but is slower and not yet well tested in practice. Use with caution and report back any issues via Github. ncall : int, optional This parameter only takes effect if ``experimental`` is True. Approximate maximum number of calls before minimization will be aborted. If set to 0, use the adaptive heuristic from the Minuit2 library (Default: 0). iterate : int, optional This parameter only takes effect if ``experimental`` is True. Automatically call Migrad up to N times if convergence was not reached (Default: 5). This simple heuristic makes Migrad converge more often even if the numerical precision of the cost function is low. Setting this to 1 disables the feature. use_simplex: bool, optional This parameter only takes effect if ``experimental`` is True. If we have to iterate, set this to True to call the Simplex algorithm before each call to Migrad (Default: True). This may improve convergence in pathological cases (which we are in when we have to iterate). Returns ------- array of float (N x 2) Contour points of the form [[x1, y1]...[xn, yn]]. Note that N = size + 1, the last point [xn, yn] is identical to [x1, y1]. This makes it easier to draw a closed contour. See Also -------- contour, mnprofile, profile """ ix, xname = self._normalize_key(x) iy, yname = self._normalize_key(y) del x del y factor = _cl_to_errordef(cl, 2, 0.68) if self._fmin_does_not_exist_or_last_state_was_modified(): self.hesse() # creates self._fmin if not self.valid: raise RuntimeError(f"Function minimum is not valid: {repr(self._fmin)}") pars = {xname, yname} - self._free_parameters() if pars: raise ValueError( f"mncontour can only be run on free parameters, not on {pars}" ) if experimental: ce = self._experimental_mncontour( factor, ix, iy, size, ncall, iterate, use_simplex ) else: with _TemporaryErrordef(self._fcn, factor): assert self._fmin is not None mnc = MnContours(self._fcn, self._fmin._src, self.strategy) ce = mnc(ix, iy, size)[2] pts = np.asarray(ce) # add starting point at end to close the contour pts = np.append(pts, pts[:1], axis=0) if interpolated > size: with optional_module_for("interpolation"): from scipy.interpolate import CubicSpline xg = np.linspace(0, 1, len(pts)) spl = CubicSpline(xg, pts, bc_type="periodic") pts = spl(np.linspace(0, 1, interpolated)) return pts def draw_mncontour( self, x: Union[int, str], y: Union[int, str], *, cl: Union[float, ArrayLike] = None, size: int = 100, interpolated: int = 0, experimental: bool = False, ) -> Any: """ Draw 2D Minos confidence region (requires matplotlib). See :meth:`mncontour` for details on the interpretation of the region and for the parameters accepted by this function. Examples -------- .. plot:: plots/mncontour.py :include-source: Returns ------- ContourSet Instance of a ContourSet class from matplot.contour. See Also -------- mncontour, draw_contour, draw_mnmatrix, draw_profile """ from matplotlib import __version__ as mpl_version_string from matplotlib import pyplot as plt from matplotlib.path import Path from matplotlib.contour import ContourSet from ._parse_version import parse_version ix, xname = self._normalize_key(x) iy, yname = self._normalize_key(y) mpl_version = parse_version(mpl_version_string) cls = [replace_none(x, 0.68) for x in mutil._iterate(cl)] c_val = [] c_pts = [] codes = [] for cl in cls: pts = self.mncontour( ix, iy, cl=cl, size=size, interpolated=interpolated, experimental=experimental, ) n_lineto = len(pts) - 2 if mpl_version < (3, 5): n_lineto -= 1 # pragma: no cover c_val.append(cl) c_pts.append([pts]) # level can have more than one contour in mpl codes.append([[Path.MOVETO] + [Path.LINETO] * n_lineto + [Path.CLOSEPOLY]]) assert len(c_val) == len(codes), f"{len(c_val)} {len(codes)}" cs = ContourSet(plt.gca(), c_val, c_pts, codes) plt.clabel(cs) plt.xlabel(xname) plt.ylabel(yname) return cs def draw_mnmatrix( self, *, cl: Union[float, ArrayLike] = None, size: int = 100, experimental: bool = False, figsize=None, ) -> Any: """ Draw matrix of Minos scans (requires matplotlib). This draws a matrix of Minos likelihood scans, meaning that the likelihood is minimized with respect to the parameters that are not scanned over. The diagonal cells of the matrix show the 1D scan, the off-diagonal cells show 2D scans for all unique pairs of parameters. The projected edges of the 2D contours do not align with the 1D intervals, because of Wilks' theorem. The levels for 2D confidence regions are higher. For more information on the interpretation of 2D confidence regions, see :meth:`mncontour`. Parameters ---------- cl : float or array-like of floats, optional See :meth:`mncontour`. size : int, optional See :meth:`mncontour` experimental : bool, optional See :meth:`mncontour` figsize : (float, float) or None, optional Width and height of figure in inches. Examples -------- .. plot:: plots/mnmatrix.py :include-source: Returns ------- fig, ax Figure and axes instances generated by matplotlib. See Also -------- mncontour, mnprofile, draw_mncontour, draw_contour, draw_profile """ if not self.valid: raise RuntimeError(f"Function minimum is not valid: {repr(self._fmin)}") pars = [p for p in self.parameters if not self.fixed[p]] npar = len(pars) if npar == 0: raise RuntimeError("all parameters are fixed") cls = [replace_none(x, 0.68) for x in mutil._iterate(cl)] if len(cls) == 0: raise ValueError("cl must have at least one value") from matplotlib import pyplot as plt fig, ax = plt.subplots( npar, npar, figsize=figsize, constrained_layout=True, squeeze=False, ) prange = {p: (np.inf, -np.inf) for p in pars} with mutil.ProgressBar( max_value=npar + (npar * (npar + 1) // 2 - npar) * len(cls) ) as bar: for i, par1 in enumerate(pars): plt.sca(ax[i, i]) fmax = 0 for k, cl in enumerate(cls): f = _cl_to_errordef(cl, 1, 0.68) fmax = max(fmax, f) plt.axhline(f, color=f"C{k}") bound = fmax**0.5 + 1 for iter in range(5): x, y, ok = self.mnprofile(par1, bound=bound, subtract_min=True) x = x[ok] y = y[ok] if y[0] > fmax and y[-1] > fmax: break bound *= 1.6 bar += 1 plt.plot(x, y, "k") a, b = prange[par1] extremes = [] for k, (xk, yk) in enumerate(zip(x, y)): if yk < fmax and y[k - 1] > fmax: extremes.append(x[k - 1]) if yk > fmax and y[k - 1] < fmax: extremes.append(xk) if extremes: a = min(*extremes, a) b = max(*extremes, b) prange[par1] = (a, b) plt.ylim(0, fmax + 0.5) for j in range(i): par2 = pars[j] plt.sca(ax[i, j]) plt.plot(self.values[par2], self.values[par1], "+", color="k") for k, cli in enumerate(cls): pts = self.mncontour( par1, par2, cl=cli, size=size, experimental=experimental ) bar += 1 if len(pts) > 0: x, y = np.transpose(pts) plt.plot(y, x, color=f"C{k}") for r, p in ((x, par1), (y, par2)): a, b = prange[p] a = min(np.min(r), a) b = max(np.max(r), b) prange[p] = (a, b) ax[j, i].set_visible(False) for i, par1 in enumerate(pars): ax[i, i].set_xlim(*prange[par1]) if i > 0: ax[i, 0].set_ylabel(par1) ax[-1, i].set_xlabel(par1) for j in range(i): par2 = pars[j] ax[j, i].set_xlim(*prange[par1]) ax[j, i].set_ylim(*prange[par2]) return fig, ax def interactive( self, plot: Callable = None, raise_on_exception=False, **kwargs, ): """ Return fitting widget (requires ipywidgets, IPython, matplotlib). A fitting widget is returned which can be displayed and manipulated in a Jupyter notebook to find good starting parameters and to debug the fit. Parameters ---------- plot : Callable, optional To visualize the fit, interactive tries to access the visualize method on the cost function, which accepts the current model parameters as an array-like and potentially further keyword arguments, and draws a visualization into the current matplotlib axes. If the cost function does not provide a visualize method or if you want to override it, pass the function here. raise_on_exception : bool, optional The default is to catch exceptions in the plot function and convert them into a plotted message. In unit tests, raise_on_exception should be set to True to allow detecting errors. **kwargs : Any other keyword arguments are forwarded to the plot function. Examples -------- .. plot:: plots/interactive.py :include-source: See Also -------- Minuit.visualize """ from iminuit.ipywidget import make_widget plot = self._visualize(plot) return make_widget(self, plot, kwargs, raise_on_exception) def _free_parameters(self) -> Set[str]: return set(mp.name for mp in self._last_state if not mp.is_fixed) def _mnprecision(self) -> MnMachinePrecision: pr = MnMachinePrecision() if self._precision is not None: pr.eps = self._precision return pr def _normalize_key(self, key: Union[int, str]) -> Tuple[int, str]: if isinstance(key, int): if key >= self.npar: raise ValueError(f"parameter {key} is out of range (max: {self.npar})") return key, self._pos2var[key] if key not in self._var2pos: raise ValueError(f"unknown parameter {key!r}") return self._var2pos[key], key def _normalize_bound( self, vname: str, bound: Union[float, UserBound, Tuple[float, float]] ) -> Tuple[float, float]: if isinstance(bound, Iterable): return mutil._normalize_limit(bound) if not self.accurate: warnings.warn( "Specified nsigma bound, but error matrix is not accurate", mutil.IMinuitWarning, ) start = self.values[vname] sigma = self.errors[vname] return (start - bound * sigma, start + bound * sigma) def _copy_state_if_needed(self): # If FunctionMinimum exists, _last_state may be a reference to its user state. # The state is read-only in C++, but mutable in Python. To not violate # invariants, we need to make a copy of the state when the user requests a # modification. If a copy was already made (_last_state is already a copy), # no further copy has to be made. # # If FunctionMinimum does not exist, we don't want to copy. We want to # implicitly modify _init_state; _last_state is an alias for _init_state, then. if self._fmin and self._last_state == self._fmin._src.state: self._last_state = MnUserParameterState(self._last_state) def _make_covariance(self) -> None: if self._last_state.has_covariance: cov = self._last_state.covariance m = mutil.Matrix(self._var2pos) n = len(m) if cov.nrow < self.npar: ext2int = {} k = 0 for mp in self._last_state: if not mp.is_fixed: ext2int[mp.number] = k k += 1 m.fill(0) for e, i in ext2int.items(): for f, j in ext2int.items(): m[e, f] = cov[i, j] else: n = len(m) for i in range(n): for j in range(n): m[i, j] = cov[i, j] self._covariance = m else: self._covariance = None def _edm_goal(self, migrad_factor=False) -> float: # EDM goal # - taken from the source code, see VariableMeticBuilder::Minimum and # ModularFunctionMinimizer::Minimize # - goal is used to detect convergence but violations by 10x are also accepted; # see VariableMetricBuilder.cxx:425 edm_goal = max( self.tol * self.errordef, self._mnprecision().eps2, # type:ignore ) if migrad_factor: edm_goal *= 2e-3 return edm_goal def _migrad_maxcall(self) -> int: n = self.nfit return 200 + 100 * n + 5 * n * n def _fmin_does_not_exist_or_last_state_was_modified(self) -> bool: return not self._fmin or self._fmin._src.state is not self._last_state def __repr__(self): """Get detailed text representation.""" s = [] if self.fmin is not None: s.append(repr(self.fmin)) s.append(repr(self.params)) if self.merrors: s.append(repr(self.merrors)) if self.covariance is not None: s.append(repr(self.covariance)) return "\n".join(s) def __str__(self): """Get user-friendly text representation.""" s = [] if self.fmin is not None: s.append(str(self.fmin)) s.append(str(self.params)) if self.merrors: s.append(str(self.merrors)) if self.covariance is not None: s.append(str(self.covariance)) return "\n".join(s) def _repr_html_(self): s = "" if self.fmin is not None: s += self.fmin._repr_html_() s += self.params._repr_html_() if self.merrors: s += self.merrors._repr_html_() if self.covariance is not None: s += self.covariance._repr_html_() if self.fmin is not None: try: import matplotlib.pyplot as plt import io with _TemporaryFigure(5, 4): self.visualize() with io.StringIO() as io: plt.savefig(io, format="svg", dpi=10) io.seek(0) s += io.read() except (ModuleNotFoundError, AttributeError, ValueError): pass return s def _repr_pretty_(self, p, cycle): if cycle: p.text("") else: p.text(str(self)) def _visualize(self, plot): pyfcn = self._fcn._fcn if plot is None: if hasattr(pyfcn, "visualize"): plot = pyfcn.visualize else: msg = ( f"class {pyfcn.__class__.__name__} has no visualize method, " "please use the 'plot' keyword to pass a visualization function" ) raise AttributeError(msg) return plot def _experimental_mncontour( self, factor: float, ix: int, iy: int, size: int, ncall: int, iterate: int, use_simplex: bool, ) -> List[Tuple[float, float]]: from scipy.optimize import root_scalar center = self.values[[ix, iy]] assert self.covariance is not None t, u = np.linalg.eig( [ [self.covariance[ix, ix], self.covariance[ix, iy]], [self.covariance[ix, iy], self.covariance[iy, iy]], ] ) s = (t * factor) ** 0.5 # strategy 0 to avoid expensive computation of Hesse matrix strategy = MnStrategy(0) ce = [] for phi in np.linspace(-np.pi, np.pi, size, endpoint=False): def args(z): r = u @ ( z * s[0] * np.cos(phi), z * s[1] * np.sin(phi), ) x = r[0] + center[0] lim = self.limits[ix] if lim is not None: x = max(lim[0], min(x, lim[1])) y = r[1] + center[1] if lim is not None: y = max(lim[0], min(y, lim[1])) return x, y def scan(z): state = MnUserParameterState(self._last_state) # copy state.fix(ix) state.fix(iy) xy = args(z) state.set_value(ix, xy[0]) state.set_value(iy, xy[1]) fm = _robust_low_level_fit( self._fcn, state, ncall, strategy, self._tolerance, self._precision, iterate, use_simplex, ) return fm.fval - self.fval - factor * self._fcn._errordef # find bracket a = 0.5 while scan(a) > 0 and a > 1e-7: a *= 0.5 # pragma: no cover if a < 1e-7: ce.append((np.nan, np.nan)) # pragma: no cover continue # pragma: no cover b = 1.2 while scan(b) < 0 and b < 8: b *= 1.1 if b > 8: ce.append(args(b)) continue # low xtol was found to be sufficient in experimental trials r = root_scalar(scan, bracket=(a, b), xtol=1e-3) ce.append(args(r.root) if r.converged else (np.nan, np.nan)) return ce def _make_init_state( pos2var: Tuple[str, ...], args: np.ndarray, kwds: Dict[str, float] ) -> MnUserParameterState: nargs = len(args) # check kwds if nargs: if kwds: raise RuntimeError( f"positional arguments cannot be mixed with " f"parameter keyword arguments {kwds}" ) else: for kw in kwds: if kw not in pos2var: raise RuntimeError( f"{kw} is not one of the parameters [{' '.join(pos2var)}]" ) nargs = len(kwds) if len(pos2var) != nargs: raise RuntimeError( f"{nargs} values given for {len(pos2var)} function parameter(s)" ) state = MnUserParameterState() for i, x in enumerate(pos2var): val = kwds[x] if kwds else args[i] err = mutil._guess_initial_step(val) state.add(x, val, err) return state def _get_params(mps: MnUserParameterState, merrors: mutil.MErrors) -> mutil.Params: def get_me(name: str) -> Optional[Tuple[float, float]]: if name in merrors: me = merrors[name] return me.lower, me.upper return None return mutil.Params( ( mutil.Param( mp.number, mp.name, mp.value, mp.error, get_me(mp.name), mp.is_const, mp.is_fixed, mp.lower_limit if mp.has_lower_limit else None, mp.upper_limit if mp.has_upper_limit else None, ) for mp in mps ), ) class _TemporaryErrordef: def __init__(self, fcn: FCN, factor: float): self.saved = fcn._errordef self.fcn = fcn self.fcn._errordef *= factor def __enter__(self) -> None: pass def __exit__(self, *args: object) -> None: self.fcn._errordef = self.saved class _TemporaryFigure: def __init__(self, w, h): from matplotlib import pyplot as plt self.plt = plt self.fig = self.plt.figure(figsize=(w, h), constrained_layout=True) def __enter__(self) -> None: pass def __exit__(self, *args: object) -> None: self.plt.close(self.fig) def _cl_to_errordef(cl, npar, default): assert 0 < npar < 3 cl = float(default if cl is None else cl) if cl <= 0: raise ValueError("cl must be positive") if npar == 1: if cl >= 1.0: factor = cl**2 else: factor = { 0.68: 0.988946481478023, # chi2(1).ppf(0.68) 0.90: 2.705543454095404, # chi2(1).ppf(0.9) 0.95: 3.841458820694124, # chi2(1).ppf(0.95) 0.99: 6.634896601021215, # chi2(1).ppf(0.99) }.get(cl, 0.0) else: factor = { 0.68: 2.27886856637673, # chi2(2).ppf(0.68) 0.90: 4.605170185988092, # chi2(2).ppf(0.9) 0.95: 5.991464547107979, # chi2(2).ppf(0.95) 0.99: 9.21034037197618, # chi2(2).ppf(0.99) 1.0: 2.295748928898636, # chi2(2).ppf(chi2(1).cdf(1)) 2.0: 6.180074306244168, # chi2(2).ppf(chi2(1).cdf(2 ** 2)) 3.0: 11.829158081900795, # chi2(2).ppf(chi2(1).cdf(3 ** 2)) 4.0: 19.333908611934685, # chi2(2).ppf(chi2(1).cdf(4 ** 2)) 5.0: 28.743702426935496, # chi2(2).ppf(chi2(1).cdf(5 ** 2)) }.get(cl, 0.0) if factor == 0.0: try: from scipy.stats import chi2 except ModuleNotFoundError as exc: exc.msg += ( "\n\n" "You set an uncommon cl value, " "scipy is needed to process it. Please install scipy." ) raise if cl >= 1.0: cl = chi2(1).cdf(cl**2) # convert sigmas into confidence level factor = chi2(npar).ppf(cl) # convert confidence level to errordef return factor def _robust_low_level_fit( fcn: FCN, state: MnUserParameterState, ncall: int, strategy: MnStrategy, tolerance: float, precision: Optional[float], iterate: int, use_simplex: bool, ) -> FunctionMinimum: # Automatically call Migrad up to `iterate` times if minimum is not valid. # This simple heuristic makes Migrad converge more often. Optionally, # one can interleave calls to Simplex and Migrad, which may also help. migrad = MnMigrad(fcn, state, strategy) if precision is not None: migrad.precision = precision fm = migrad(ncall, tolerance) strategy = MnStrategy(2) migrad = MnMigrad(fcn, fm.state, strategy) while not fm.is_valid and not fm.has_reached_call_limit and iterate > 1: # If we have to iterate, we have a pathological case. Increasing the # strategy to 2 in this case was found to be beneficial. if use_simplex: simplex = MnSimplex(fcn, fm.state, strategy) if precision is not None: simplex.precision = precision fm = simplex(ncall, tolerance) # recreate MnMigrad instance to start from updated state migrad = MnMigrad(fcn, fm.state, strategy) # workaround: precision must be set again after each call if precision is not None: migrad.precision = precision fm = migrad(ncall, tolerance) iterate -= 1 return fm iminuit-2.30.1/src/iminuit/pdg_format.py0000644000000000000000000002422514332717401015151 0ustar00# Copyright 2020 Hans Dembinski # 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. # 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 HOLDER 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. """ PDG formatting of numbers with uncertainties. The PDG uses a special rounding rule for quantities with uncertainties. The description quoted from M. Tanabashi et al. (Particle Data Group), Phys. Rev. D 98, 030001 (2018), https://doi.org/10.1103/PhysRevD.98.030001: "The basic rule states that if the three highest order digits of the error lie between 100 and 354, we round to two significant digits. If they lie between 355 and 949, we round to one significant digit. Finally, if they lie between 950 and 999, we round up to 1000 and keep two significant digits. In all cases, the central value is given with a precision that matches that of the error. So, for example, the result (coming from an average) 0.827 +- 0.119 would appear as 0.83 +- 0.12, while 0.827 +- 0.367 would turn into 0.8 +- 0.4." In addition, the LHCb Editorial Board declared that in case of several errors, the most precise one defines the number of digits shown. This module offers functions that convert values and errors into a string representation. Documentation follows these guidelines: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard """ import math from typing import List term = (" %s", " +%s", " ± %s", " (%s)", "(%s)E%+03i", True, None) latex = ( " {}_{%s}", "^{+%s}", r" \pm %s", r" (\mathrm{%s})", r"(%s) \times 10^{%i}", True, (r"\mathrm{NaN}", r"\infty"), ) def pdg_format(value, error, *errors, labels=None, format=term, leader=None, exp=None): r""" Return formatted value with uncertainties according to PDG rules. Examples -------- >>> pdg_format(2.3456, 0.123, 0.0123) '2.346 ± 0.123 ± 0.012' >>> pdg_format(2.3456, 0.123, 0.0123, leader=0) '2.35 ± 0.12 ± 0.01' >>> pdg_format(1.2, (0.1, 0.2), 0.3, format=latex) '1.2 {}_{-0.1}^{+0.2} \\pm 0.3' >>> pdg_format(2.3e-09, 0.354e-09, format=latex) '(2.30 \\pm 0.35) \\times 10^{-9}' >>> pdg_format(2.3e3, 0.1e3, 0.2e3, format=latex, labels=('stat', 'sys')) '(2.3 \\pm 0.1 (\\mathrm{stat}) \\pm 0.2 (\\mathrm{sys})) \\times 10^{3}' >>> pdg_format(1.234, -0.11, 0.22, 0.3, format=latex) '1.23 {}_{-0.11}^{+0.22} \\pm 0.30' Parameters ---------- value : float Estimated value. error : float or tuple of floats Uncertainty of value. A positive number is interpreted as a symmetric uncertainty (value +- error). Asymmetric uncertainties are passed as a tuple of positive numbers (x - xmin, xmax - x) OR as a negative number xmin - x immediately followed by a positive number xmax - x. *errors Optional further uncertainties. labels : sequence of str, optional Optional labels for the different uncertainties (e.g. 'sys', 'stat', 'lumi'). A label that starts with one of the characters '_\^<' is used verbatim, otherwise it is wrapped according to the format spec for labels. format : tuple, optional Formatting specification. Structure: ( , , , , , , ) leader : int, optional Index of uncertainty that should be used to determine the number of digits shown, if there are several uncertainties. Default is to use the smallest uncertainty. If asymmetric uncertainties are passed as tuples or subsequent pairs of negative and positive numbers, the index is that of the pair. exp : int, optional Exponent to use for scientific notation. If omitted, a heuristic algorithm selects a suitable exponent. Returns ------- str Formatted string. """ fmt_ne, fmt_pe, fmt_se, fmt_lab, fmt_sc, strip, trans = format strings, nexp = _round([value, error, *errors], leader, exp) if strip: strings = _strip(strings) if trans: for i, x in enumerate(strings): c = x[-1] if c == "n": # nan, -nan x = trans[0] elif c == "f": # inf, -inf if x[0] == "-": x = "-" + trans[1] x = trans[1] strings[i] = x s = strings[0] asym = False liter = iter(labels) if labels is not None else None for si in strings[1:]: if si[0] == "-": asym = True s += fmt_ne % si elif asym: asym = False s += fmt_pe % si else: s += fmt_se % si if liter and not asym: y = next(liter) if y[0] in r"_\^<": s += y else: s += fmt_lab % y if nexp == 0: return s else: return fmt_sc % (s, nexp) def _strip(items: List[str]) -> List[str]: assert all("e" not in x for x in items) # ignore inf and nan mask = tuple(i for (i, s) in enumerate(items) if "." in s) if mask: # strip common trailing "0"s first = items[mask[0]] for i in range(len(first)): if all(items[k][-1 - i] == "0" for k in mask): i += 1 else: break # maybe strip common trailing "." after stripping "0"s if i > 0 and all(items[k][-1 - i] == "." for k in mask): i += 1 if i > 0: for k in mask: items[k] = items[k][:-i] # turn negative zero into positive zero if items[0] == "-0": items[0] = "0" return items def _find_smallest_nonzero_abs_value(seq): k = None xmin = float("infinity") for i, x in enumerate(seq): x = abs(x) if x > 0 and x < xmin: xmin = x k = i return k, xmin def _is_asym(value): if hasattr(value, "__len__") and hasattr(value, "__getitem__"): if len(value) != 2: raise ValueError("sequence must have two elements") return True return False def _unpack(values): assert len(values) > 0 assert not _is_asym(values[0]) result = [values[0]] for v in values[1:]: if _is_asym(v): result.append(-abs(v[0])) result.append(v[1]) else: result.append(v) return result def _unpacked_index(values, index): k = 0 for i in range(index): k += 2 if values[k] < 0 else 1 return k def _round(values, leader, n_exp_extern): assert len(values) >= 1 assert not _is_asym(values[0]) values = _unpack(values) if leader is None: # select leading error that determines precision leader, lerror = _find_smallest_nonzero_abs_value(values[1:]) if leader is not None: leader += 1 else: leader = _unpacked_index(values[1:], leader) + 1 asym = math.copysign(1, values[leader]) < 0 # also works for NaN and -0.0 if asym: offset, lerror = _find_smallest_nonzero_abs_value( values[leader : leader + 2] ) if offset is None: leader = None else: leader += offset else: lerror = abs(values[leader]) def fmt(x, n_digits): return ("%%.%if" % max(n_digits, 0)) % x n_exp = None if math.isfinite(lerror) and lerror > 0: n_exp = int(math.floor(math.log10(lerror))) + 1 if n_exp is None: leader = None if math.isfinite(values[0]) and values[0] != 0: n_exp = int(math.floor(math.log10(abs(values[0])))) else: # n_exp cannot be determined return [str(x) for x in values], 0 if leader is None: # invalid leading error, cannot determine digits scale = 10**-n_exp return ([fmt(v * scale, 4) for v in values], n_exp) scale = 10**-n_exp digits = round(lerror * scale, 3) if digits < 0.355: n_digits = 2 digits = round(digits, 2) else: n_digits = 1 if digits < 0.95: digits = round(digits, 1) else: digits = 1.0 if n_exp_extern is None: if abs(n_exp) > 2: n_exp_extern = int(round(n_exp / 3) * 3) else: n_exp_extern = 0 if math.isfinite(values[0]) and values[0] != 0: n = math.floor(math.log10(abs(values[0])) / 3) * 3 if n > n_exp_extern: n_exp_extern = n shift = n_exp - n_exp_extern values = [ fmt( ( round(x * scale, n_digits) if i != leader else math.copysign(digits, values[leader]) ) * 10**shift, n_digits - shift, ) for (i, x) in enumerate(values) ] return values, n_exp - shift iminuit-2.30.1/src/iminuit/testing.py0000644000000000000000000000273314332717401014504 0ustar00""" Common test functions for optimizers. Also see: https://en.wikipedia.org/wiki/Test_functions_for_optimization """ def rosenbrock(x, y): """ Rosenbrock function. Minimum: f(1, 1) = 0. https://en.wikipedia.org/wiki/Rosenbrock_function """ return (1 - x) ** 2 + 100 * (y - x**2) ** 2 def rosenbrock_grad(x, y): """Gradient of Rosenbrock function.""" return (-400 * x * (-(x**2) + y) + 2 * x - 2, -200 * x**2 + 200 * y) def ackley(x, y): """ Ackley function. Minimum: f(0, 0) = 0. https://en.wikipedia.org/wiki/Ackley_function """ from math import sqrt, exp, cos, pi, e term1 = -20 * exp(-0.2 * sqrt(0.5 * (x**2 + y**2))) term2 = -exp(0.5 * (cos(2 * pi * x) + cos(2 * pi * y))) return term1 + term2 + 20 + e def beale(x, y): """ Beale function. Minimum: f(3, 0.5) = 0. https://en.wikipedia.org/wiki/Test_functions_for_optimization """ term1 = 1.5 - x + x * y term2 = 2.25 - x + x * y**2 term3 = 2.625 - x + x * y**3 return term1 * term1 + term2 * term2 + term3 * term3 def matyas(x, y): """ Matyas function. Minimum: f(0, 0) = 0. https://en.wikipedia.org/wiki/Test_functions_for_optimization """ return 0.26 * (x**2 + y**2) - 0.48 * x * y def sphere_np(x): """ Sphere function for variable number of arguments. Minimum: f(0, ..., 0) = 0. https://en.wikipedia.org/wiki/Test_functions_for_optimization """ import numpy as np return np.sum(x**2) iminuit-2.30.1/src/iminuit/typing.py0000644000000000000000000000473014332717401014340 0ustar00""" Types for iminuit. These are used by mypy and similar tools. """ from typing import ( Protocol, Optional, List, Union, runtime_checkable, NamedTuple, Annotated, ) from numpy.typing import NDArray import numpy as np import dataclasses # Key for ValueView, ErrorView, etc. Key = Union[int, str, slice, List[Union[int, str]]] @runtime_checkable class Model(Protocol): """Type for user-defined model.""" def __call__(self, x: np.ndarray, *args: float) -> np.ndarray: """Evaluate model at locations x and return results as an array.""" ... # pragma: no cover @runtime_checkable class ModelGradient(Protocol): """Type for user-defined model gradient.""" def __call__(self, x: np.ndarray, *args: float) -> np.ndarray: """Evaluate model gradient at locations x and return results as an array.""" ... # pragma: no cover @runtime_checkable class Cost(Protocol): """Type for user-defined cost function.""" def __call__(self, *args: float) -> float: """Evaluate cost and return results as a float.""" ... # pragma: no cover @runtime_checkable class CostGradient(Protocol): """Type for user-defined gradient of a cost function.""" def __call__(self, *args: float) -> np.ndarray: """Evaluate gradient and return results as an array.""" ... # pragma: no cover @runtime_checkable class LossFunction(Protocol): """Type for user-defined loss function for LeastSquares clas.""" def __call__(self, z: NDArray) -> NDArray: """Evaluate loss function on values.""" ... # pragma: no cover class UserBound(NamedTuple): """Type for user-defined limit.""" min: Optional[float] max: Optional[float] @dataclasses.dataclass class Gt: """Annotation compatible with annotated-types.""" gt: float @dataclasses.dataclass class Ge: """Annotation compatible with annotated-types.""" ge: float @dataclasses.dataclass class Lt: """Annotation compatible with annotated-types.""" lt: float @dataclasses.dataclass class Le: """Annotation compatible with annotated-types.""" le: float @dataclasses.dataclass class Interval: """Annotation compatible with annotated-types.""" gt: Optional[float] = None ge: Optional[float] = None lt: Optional[float] = None le: Optional[float] = None # common convenience types PositiveFloat = Annotated[float, Gt(0)] Probability = Annotated[float, Interval(ge=0, le=1)] iminuit-2.30.1/src/iminuit/util.py0000644000000000000000000014520314332717401014004 0ustar00""" Data classes and utilities used by :class:`iminuit.Minuit`. You can look up the interface of data classes that iminuit uses here. """ from __future__ import annotations import inspect from collections import OrderedDict from argparse import Namespace from iminuit import _repr_html, _repr_text, _deprecated from iminuit.typing import Key, UserBound, Cost, CostGradient from iminuit.warnings import IMinuitWarning, HesseFailedWarning, PerformanceWarning import numpy as np from numpy.typing import NDArray, ArrayLike from typing import ( overload, Any, List, Union, Dict, Iterable, Generator, Tuple, Optional, Callable, Collection, Sequence, TypeVar, Annotated, get_args, get_origin, ) import abc from time import monotonic import warnings import sys T = TypeVar("T") __all__ = ( "IMinuitWarning", "HesseFailedWarning", "PerformanceWarning", "ValueView", "FixedView", "LimitView", "Matrix", "FMin", "Param", "Params", "MError", "MErrors", "make_func_code", "make_with_signature", "merge_signatures", "describe", "gradient", "is_positive_definite", ) class BasicView(abc.ABC): """ Array-like view of parameter state. Derived classes need to implement methods _set and _get to access specific properties of the parameter state. :meta private: """ __slots__ = ("_minuit", "_ndim") def __init__(self, minuit: Any, ndim: int = 0): # Users should not call this __init__, instances are created by the library self._minuit = minuit self._ndim = ndim def __iter__(self) -> Generator: """Get iterator over values.""" for i in range(len(self)): yield self._get(i) def __len__(self) -> int: """Get number of paramters.""" return self._minuit.npar # type: ignore @abc.abstractmethod def _get(self, idx: int) -> Any: return NotImplemented # pragma: no cover @abc.abstractmethod def _set(self, idx: int, value: Any) -> None: NotImplemented # pragma: no cover def __getitem__(self, key: Key) -> Any: """ Get values of the view. Parameters ---------- key: int, str, slice, list of int or str If the key is an int or str, return corresponding value. If it is a slice, list of int or str, return the corresponding subset. """ index = _key2index(self._minuit._var2pos, key) if isinstance(index, list): return [self._get(i) for i in index] return self._get(index) def __setitem__(self, key: Key, value: Any) -> None: """Assign new value at key, which can be index, parameter name, or slice.""" self._minuit._copy_state_if_needed() index = _key2index(self._minuit._var2pos, key) if isinstance(index, list): if _ndim(value) == self._ndim: # support basic broadcasting for i in index: self._set(i, value) else: if len(value) != len(index): raise ValueError("length of argument does not match slice") for i, v in zip(index, value): self._set(i, v) else: self._set(index, value) def __eq__(self, other: object) -> bool: """Return true if all values are equal.""" a, b = np.broadcast_arrays(self, other) # type:ignore return bool(np.all(a == b)) def __repr__(self) -> str: """Get detailed text representation.""" s = f"<{self.__class__.__name__}" for k, v in zip(self._minuit._pos2var, self): s += f" {k}={v}" s += ">" return s def to_dict(self) -> Dict[str, float]: """Obtain dict representation.""" return {k: self._get(i) for i, k in enumerate(self._minuit._pos2var)} def _ndim(obj: Any) -> int: nd = 0 while isinstance(obj, Iterable): nd += 1 for x in obj: if x is not None: obj = x break else: break return nd class ValueView(BasicView): """Array-like view of parameter values.""" def _get(self, i: int) -> float: return self._minuit._last_state[i].value # type:ignore def _set(self, i: int, value: float) -> None: self._minuit._last_state.set_value(i, value) class ErrorView(BasicView): """Array-like view of parameter errors.""" def _get(self, i: int) -> float: return self._minuit._last_state[i].error # type:ignore def _set(self, i: int, value: float) -> None: if value <= 0: warnings.warn( "Assigned errors must be positive. " "Non-positive values are replaced by a heuristic.", IMinuitWarning, ) value = _guess_initial_step(value) self._minuit._last_state.set_error(i, value) class FixedView(BasicView): """Array-like view of whether parameters are fixed.""" def _get(self, i: int) -> bool: return self._minuit._last_state[i].is_fixed # type:ignore def _set(self, i: int, fix: bool) -> None: if fix: self._minuit._last_state.fix(i) else: self._minuit._last_state.release(i) def __invert__(self) -> list: """Return list with inverted elements.""" return [not self._get(i) for i in range(len(self))] class LimitView(BasicView): """Array-like view of parameter limits.""" def __init__(self, minuit: Any): # Users should not call this __init__, instances are created by the library super(LimitView, self).__init__(minuit, 1) def _get(self, i: int) -> Tuple[float, float]: p = self._minuit._last_state[i] return ( p.lower_limit if p.has_lower_limit else -np.inf, p.upper_limit if p.has_upper_limit else np.inf, ) def _set(self, i: int, arg: UserBound) -> None: state = self._minuit._last_state val = state[i].value err = state[i].error # changing limits is a cheap operation, start from clean state state.remove_limits(i) low, high = _normalize_limit(arg) if low != -np.inf and high != np.inf: # both must be set if low == high: state.fix(i) else: state.set_limits(i, low, high) elif low != -np.inf: # lower limit must be set state.set_lower_limit(i, low) elif high != np.inf: # lower limit must be set state.set_upper_limit(i, high) # bug in Minuit2: must set parameter value and error again after changing limits if val < low: val = low elif val > high: val = high state.set_value(i, val) state.set_error(i, err) def _normalize_limit(lim: Optional[Iterable]) -> Tuple[float, float]: if lim is None: return (-np.inf, np.inf) a, b = lim if a is None: a = -np.inf if b is None: b = np.inf if a > b: raise ValueError(f"limit {lim!r} is invalid") return a, b class Matrix(np.ndarray): """ Enhanced Numpy ndarray. Works like a normal ndarray in computations, but also supports pretty printing in ipython and Jupyter notebooks. Elements can be accessed via indices or parameter names. """ __slots__ = ("_var2pos",) def __new__(cls, parameters: Union[Dict, Tuple]) -> Any: # noqa D102 # Users should not call __new__, instances are created by the library if isinstance(parameters, dict): var2pos = parameters elif isinstance(parameters, tuple): var2pos = {x: i for i, x in enumerate(parameters)} else: raise TypeError("parameters must be tuple or dict") n = len(parameters) obj = super().__new__(cls, (n, n)) obj._var2pos = var2pos return obj def __array_finalize__(self, obj: Any) -> None: """For internal use.""" if obj is None: self._var2pos: Dict[str, int] = {} else: self._var2pos = getattr(obj, "_var2pos", {}) def __getitem__( # type:ignore self, key: Union[Key, Tuple[Key, Key], Iterable[Key], NDArray], ) -> NDArray: """Get matrix element at key.""" var2pos = self._var2pos def trafo(key): if isinstance(key, str): return var2pos[key] if isinstance(key, slice): return slice(trafo(key.start), trafo(key.stop), key.step) if isinstance(key, tuple): return tuple(trafo(k) for k in key) return key if isinstance(key, slice): # slice returns square matrix sl = trafo(key) return super().__getitem__((sl, sl)) if isinstance(key, (str, tuple)): return super().__getitem__(trafo(key)) if isinstance(key, Iterable) and not isinstance(key, np.ndarray): # iterable returns square matrix index2 = [trafo(k) for k in key] # type:ignore t = super().__getitem__(index2).T return np.ndarray.__getitem__(t, index2).T return super().__getitem__(key) def to_dict(self) -> Dict[Tuple[str, str], float]: """ Convert matrix to dict. Since the matrix is symmetric, the dict only contains the upper triangular matrix. """ names = tuple(self._var2pos) d = {} for i, pi in enumerate(names): for j in range(i, len(names)): pj = names[j] d[pi, pj] = float(self[i, j]) return d def to_table(self) -> Tuple[List[List[str]], Tuple[str, ...]]: """ Convert matrix to tabular format. The output is consumable by the external `tabulate `_ module. Examples -------- >>> import tabulate as tab >>> from iminuit import Minuit >>> m = Minuit(lambda x, y: x ** 2 + y ** 2, x=1, y=2).migrad() >>> tab.tabulate(*m.covariance.to_table()) x y -- --- --- x 1 -0 y -0 4 """ names = tuple(self._var2pos) # type:ignore nums = _repr_text.matrix_format(self) tab = [] n = len(self) for i, name in enumerate(names): tab.append([name] + [nums[n * i + j] for j in range(n)]) return tab, names def correlation(self): """ Compute and return correlation matrix. If the matrix is already a correlation matrix, this effectively returns a copy of the original matrix. """ a = self.copy() d = np.diag(a) ** 0.5 a /= np.outer(d, d) + 1e-100 return a def __repr__(self): """Get detailed text representation.""" return super(Matrix, self).__str__() def __str__(self): """Get user-friendly text representation.""" if self.ndim != 2: return repr(self) return _repr_text.matrix(self) def _repr_html_(self): return _repr_html.matrix(self) def _repr_pretty_(self, p, cycle): if cycle: p.text("") else: p.text(str(self)) # ndarray uses __reduce__ for pickling instead of __getstate__ def __reduce__(self): """Get representation for pickling and copying.""" restore, args, state = super().__reduce__() return restore, args, (state, self._var2pos) def __setstate__(self, state): """Restore from pickled state.""" state, self._var2pos = state super().__setstate__(state) class FMin: """ Function minimum view. This object provides detailed metadata about the function minimum. Inspect this to check what exactly happened if the fit did not converge. Use the attribute :attr:`iminuit.Minuit.fmin` to get the best fit values, their uncertainties, or the function value at the minimum. For convenience, you can also get a basic OK from :class:`iminuit.Minuit` with the methods :attr:`iminuit.Minuit.valid` and :attr:`iminuit.Minuit.accurate`. See Also -------- :attr:`iminuit.Minuit.values` :attr:`iminuit.Minuit.errors` :attr:`iminuit.Minuit.merrors` :attr:`iminuit.Minuit.covariance` :attr:`iminuit.Minuit.fval` :attr:`iminuit.Minuit.valid` :attr:`iminuit.Minuit.accurate` """ __slots__ = ( "_src", "_algorithm", "_has_parameters_at_limit", "_nfcn", "_ngrad", "_ndof", "_edm_goal", "_time", ) def __init__( self, fmin: Any, algorithm: str, nfcn: int, ngrad: int, ndof: int, edm_goal: float, time: float, ): # Users should not call this __init__, instances are created by the library self._src = fmin self._algorithm = algorithm self._has_parameters_at_limit = False for mp in fmin.state: if mp.is_fixed or not mp.has_limits: continue v = mp.value e = mp.error lb = mp.lower_limit if mp.has_lower_limit else -np.inf ub = mp.upper_limit if mp.has_upper_limit else np.inf # the 0.5 error threshold is somewhat arbitrary self._has_parameters_at_limit |= min(v - lb, ub - v) < 0.5 * e self._nfcn = nfcn self._ngrad = ngrad self._ndof = ndof self._edm_goal = edm_goal self._time = time @property def algorithm(self) -> str: """Get algorithm that was used to compute the function minimum.""" return self._algorithm @property def edm(self) -> float: """ Get Estimated Distance to Minimum. Minuit uses this criterion to determine whether the fit converged. It depends on the gradient and the Hessian matrix. It measures how well the current second order expansion around the function minimum describes the function, by taking the difference between the predicted (based on gradient and Hessian) function value at the minimum and the actual value. """ return self._src.edm # type:ignore @property def edm_goal(self) -> float: """ Get EDM threshold value for stopping the minimization. The threshold is allowed to be violated by a factor of 10 in some situations. """ return self._edm_goal @property def fval(self) -> float: """Get cost function value at the minimum.""" return self._src.fval # type:ignore @property def reduced_chi2(self) -> float: """ Get χ²/ndof of the fit. This returns NaN if the cost function is unbinned, errordef is not 1, or if the cost function does not report the degrees of freedom. """ if np.isfinite(self._ndof) and self._ndof > 0 and self.errordef == 1: return self.fval / self._ndof return np.nan @property def has_parameters_at_limit(self) -> bool: """ Return whether any bounded parameter was fitted close to a bound. The estimated error for the affected parameters is usually off. May be an indication to remove or loosen the limits on the affected parameter. """ return self._has_parameters_at_limit @property def nfcn(self) -> int: """Get number of function calls so far.""" return self._nfcn @property def ngrad(self) -> int: """Get number of function gradient calls so far.""" return self._ngrad @property def is_valid(self) -> bool: """ Return whether Migrad converged successfully. For it to return True, the following conditions need to be fulfilled: - :attr:`has_reached_call_limit` is False - :attr:`is_above_max_edm` is False Note: The actual verdict is computed inside the Minuit2 C++ code, so we cannot guarantee that is_valid is exactly equivalent to these conditions. """ valid = self._src.is_valid if valid and self.edm < 0: return False return valid @property def has_valid_parameters(self) -> bool: """ Return whether parameters are valid. This is the same as :attr:`is_valid` and only kept for backward compatibility. """ return self.is_valid @property def has_accurate_covar(self) -> bool: """ Return whether the covariance matrix is accurate. While Migrad runs, it computes an approximation to the current Hessian matrix. If the strategy is set to 0 or if the fit did not converge, the inverse of this approximation is returned instead of the inverse of the accurately computed Hessian matrix. This property returns False if the approximation has been returned instead of an accurate matrix computed by the Hesse method. """ return self._src.has_accurate_covar # type:ignore @property def has_posdef_covar(self) -> bool: """ Return whether the Hessian matrix is positive definite. This must be the case if the extremum is a minimum, otherwise it is a saddle point. If it returns False, the fitted result may be correct, but the reported uncertainties are false. This may affect some parameters or all of them. Possible causes: * Model contains redundanted parameters that are 100% correlated. Fix: remove the parameters that are 100% correlated. * Cost function is not computed in double precision. Fix: try adjusting :attr:`iminuit.Minuit.precision` or change the cost function to compute in double precision. * Cost function is not analytical near the minimum. Fix: change the cost function to something analytical. Functions are not analytical if: * It does computations based on (pseudo)random numbers. * It contains vertical steps, for example from code like this:: if cond: return value1 else: return value2 """ return self._src.has_posdef_covar # type:ignore @property def has_made_posdef_covar(self) -> bool: """ Return whether the matrix was forced to be positive definite. While Migrad runs, it computes an approximation to the current Hessian matrix. It can happen that this approximation is not positive definite, but that is required to compute the next Newton step. Migrad then adds an appropriate diagonal matrix to enforce positive definiteness. If the fit has converged successfully, this should always return False. If Minuit forced the matrix to be positive definite, the parameter uncertainties are false, see :attr:`has_posdef_covar` for more details. """ return self._src.has_made_posdef_covar # type:ignore @property def hesse_failed(self) -> bool: """Return whether the last call to Hesse failed.""" return self._src.hesse_failed # type:ignore @property def has_covariance(self) -> bool: """ Return whether a covariance matrix was computed at all. This is false if the Simplex minimization algorithm was used instead of Migrad, in which no approximation to the Hessian is computed. """ return self._src.has_covariance # type:ignore @property def is_above_max_edm(self) -> bool: """ Return whether the EDM value is below the convergence threshold. Returns True, if the fit did not converge; otherwise returns False. """ return self._src.is_above_max_edm # type:ignore @property def has_reached_call_limit(self) -> bool: """ Return whether Migrad exceeded the allowed number of function calls. Returns True true, the fit was stopped before convergence was reached; otherwise returns False. """ return self._src.has_reached_call_limit # type:ignore @property def errordef(self) -> float: """Equal to the value of :attr:`iminuit.Minuit.errordef` when Migrad ran.""" return self._src.errordef # type:ignore @property def time(self) -> float: """Runtime of the last algorithm.""" return self._time def __eq__(self, other: object) -> bool: """Return True if all attributes are equal.""" def relaxed_equal(k: str, a: object, b: object) -> bool: a = getattr(a, k) b = getattr(b, k) if isinstance(a, float) and np.isnan(a): return np.isnan(b) # type:ignore return a == b # type:ignore return all(relaxed_equal(k, self, other) for k in self.__slots__) def __repr__(self) -> str: """Get detailed text representation.""" s = " str: """Get user-friendly text representation.""" return _repr_text.fmin(self) # type:ignore def _repr_html_(self) -> str: return _repr_html.fmin(self) # type:ignore def _repr_pretty_(self, p: Any, cycle: bool) -> None: if cycle: p.text("") else: p.text(str(self)) class Param: """Data object for a single Parameter.""" __slots__ = ( "number", "name", "value", "error", "merror", "is_const", "is_fixed", "lower_limit", "upper_limit", ) def __init__( self, *args: Union[int, str, float, Optional[Tuple[float, float]], bool], ): # Users should not call this __init__, instances are created by the library assert len(args) == len(self.__slots__) for k, arg in zip(self.__slots__, args): setattr(self, k, arg) def __eq__(self, other: object) -> bool: """Return True if all values are equal.""" return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) def __repr__(self) -> str: """Get detailed text representation.""" pairs = [] for k in self.__slots__: v = getattr(self, k) pairs.append(f"{k}={v!r}") return "Param(" + ", ".join(pairs) + ")" @property def has_limits(self): """Query whether the parameter has an lower or upper limit.""" return self.has_lower_limit or self.has_upper_limit @property def has_lower_limit(self): """Query whether parameter has a lower limit.""" return self.lower_limit is not None @property def has_upper_limit(self): """Query whether parameter has an upper limit.""" return self.upper_limit is not None def __str__(self) -> str: """Get user-friendly text representation.""" return _repr_text.params([self]) # type:ignore def _repr_pretty_(self, p: Any, cycle: bool) -> None: if cycle: p.text("Param(...)") else: p.text(str(self)) class Params(tuple): """Tuple-like holder of parameter data objects.""" __slots__ = () def _repr_html_(self): return _repr_html.params(self) def to_table(self): """ Convert parameter data to a tabular format. The output is consumable by the external `tabulate `_ module. Examples -------- >>> import tabulate as tab >>> from iminuit import Minuit >>> m = Minuit(lambda x, y: x ** 2 + (y / 2) ** 2 + 1, x=0, y=0) >>> m.fixed["x"] = True >>> m.migrad().minos() >>> tab.tabulate(*m.params.to_table()) pos name value error error- error+ limit- limit+ fixed ----- ------ ------- ------- -------- -------- -------- -------- ------- 0 x 0 0.1 yes 1 y 0 1.4 -1.0 1.0 """ header = [ "pos", "name", "value", "error", "error-", "error+", "limit-", "limit+", "fixed", ] tab = [] for i, mp in enumerate(self): name = mp.name row = [i, name] me = mp.merror if me: val, err, mel, meu = _repr_text.pdg_format(mp.value, mp.error, *me) else: val, err = _repr_text.pdg_format(mp.value, mp.error) mel = "" meu = "" row += [ val, err, mel, meu, f"{mp.lower_limit}" if mp.lower_limit is not None else "", f"{mp.upper_limit}" if mp.upper_limit is not None else "", "yes" if mp.is_fixed else "", ] tab.append(row) return tab, header def __getitem__(self, key): """Get item at key, which can be an index or a parameter name.""" if isinstance(key, str): for i, p in enumerate(self): if p.name == key: break key = i return super(Params, self).__getitem__(key) def __str__(self): """Get user-friendly text representation.""" return _repr_text.params(self) def _repr_pretty_(self, p, cycle): if cycle: p.text("Params(...)") else: p.text(str(self)) class MError: """ Minos data object. Attributes ---------- number : int Parameter index. name : str Parameter name. lower : float Lower error. upper : float Upper error. is_valid : bool Whether Minos computation was successful. lower_valid : bool Whether downward scan was successful. upper_valid : bool Whether upward scan was successful. at_lower_limit : bool Whether scan reached lower limit. at_upper_limit : bool Whether scan reached upper limit. at_lower_max_fcn : bool Whether allowed number of function evaluations was exhausted. at_upper_max_fcn : bool Whether allowed number of function evaluations was exhausted. lower_new_min : float Parameter value for new minimum, if one was found in downward scan. upper_new_min : float Parameter value for new minimum, if one was found in upward scan. nfcn : int Number of function calls. min : float Function value at the new minimum. """ __slots__ = ( "number", "name", "lower", "upper", "is_valid", "lower_valid", "upper_valid", "at_lower_limit", "at_upper_limit", "at_lower_max_fcn", "at_upper_max_fcn", "lower_new_min", "upper_new_min", "nfcn", "min", ) def __init__(self, *args: Union[int, str, float, bool]): # Users should not call this __init__, instances are created by the library assert len(args) == len(self.__slots__) for k, arg in zip(self.__slots__, args): setattr(self, k, arg) def __eq__(self, other: object) -> bool: """Return True if all values are equal.""" return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) def __repr__(self) -> str: """Get detailed text representation.""" s = " str: """Get user-friendly text representation.""" return _repr_text.merrors({None: self}) # type:ignore def _repr_html_(self) -> str: return _repr_html.merrors({None: self}) # type:ignore def _repr_pretty_(self, p: Any, cycle: bool) -> None: if cycle: p.text("") else: p.text(str(self)) class MErrors(OrderedDict): """Dict-like map from parameter name to Minos result object.""" __slots__ = () def _repr_html_(self): return _repr_html.merrors(self) def __repr__(self): """Get detailed text representation.""" return "" def __str__(self): """Get user-friendly text representation.""" return _repr_text.merrors(self) def _repr_pretty_(self, p, cycle): if cycle: p.text("") else: p.text(str(self)) def __getitem__(self, key): """Get item at key, which can be an index or a parameter name.""" if isinstance(key, int): if key < 0: key += len(self) if key < 0 or key >= len(self): raise IndexError("index out of range") for i, k in enumerate(self): if i == key: break key = k return OrderedDict.__getitem__(self, key) @_deprecated.deprecated("use jacobi.propagate instead from jacobi library") def propagate( fn: Callable, x: Collection[float], cov: Collection[Collection[float]], ) -> Tuple[NDArray, NDArray]: """ Numerically propagates the covariance into a new space. This function is deprecated and will be removed. Please use jacobi.propagate from the jacobi library, which is more accurate. The signatures of the two functions are compatible, so it is a drop-in replacement. Parameters ---------- fn: callable Vectorized function that computes y = fn(x). x: array-like with shape (N,) Input vector. cov: array-like with shape (N, N) Covariance matrix of input vector. Returns ------- y, ycov y is the result of fn(x) ycov is the propagated covariance matrix. """ from scipy.optimize import approx_fprime vx = np.atleast_1d(x) # type:ignore if np.ndim(cov) != 2: # type:ignore raise ValueError("cov must be 2D array-like") vcov = np.atleast_2d(cov) # type:ignore if vcov.shape[0] != vcov.shape[1]: raise ValueError("cov must have shape (N, N)") tol = 1e-10 dx = (np.diag(vcov) * tol) ** 0.5 if not np.all(dx >= 0): raise ValueError("diagonal elements of covariance matrix must be non-negative") y = fn(vx) jac = np.atleast_2d(approx_fprime(vx, fn, dx)) ycov = np.einsum("ij,kl,jl", jac, jac, vcov) return y, np.squeeze(ycov) if np.ndim(y) == 0 else ycov class _Timer: def __init__(self, fmin): self.value = fmin.time if fmin else 0.0 def __enter__(self): self.value += monotonic() def __exit__(self, *args): self.value = monotonic() - self.value @_deprecated.deprecated( "Use of ``func_code`` attribute to declare parameters is deprecated. " "Use ``_parameters`` instead, which is a dict of parameter names to limits." ) def make_func_code(params: Collection[str]) -> Namespace: """ Make a func_code object to fake a function signature. Example:: def f(a, b): ... f.func_code = make_func_code(["x", "y"]) """ return Namespace(co_varnames=tuple(params), co_argcount=len(params)) def make_with_signature( callable: Callable, *varnames: str, **replacements: str ) -> Callable: """ Return new callable with altered signature. Parameters ---------- callable: Original callable with positional arguments, whose names shall be changed. *varnames: sequence of str Replace the first N argument names with these. **replacements: mapping of str to str, optional Replace old argument name (key) with new argument name (value). Returns ------- Callable with positional-only arguments. """ pars = describe(callable, annotations=True) if pars: args = list(pars) n = len(varnames) if n > len(args): raise ValueError("varnames longer than original signature") args[:n] = varnames for old, new in replacements.items(): i = args.index(old) args[i] = new pars = {new: pars[old] for (new, old) in zip(args, pars)} class Caller: def __init__(self, parameters): self._parameters = parameters def __call__(self, *args: Any) -> Any: return callable(*args) return Caller(pars) def merge_signatures( callables: Iterable[Callable], annotations: bool = False ) -> Tuple[Any, List[List[int]]]: """ Merge signatures of callables with positional arguments. This is best explained by an example:: def f(x, y, z): ... def g(x, p): ... parameters, mapping = merge_signatures(f, g) # parameters is ('x', 'y', 'z', 'p') # mapping is ([0, 1, 2], [0, 3]) Parameters ---------- callables : Callables whose parameters can be extracted with :func:`describe`. annotations : bool, optional Whether to return the annotions. Default is False, for backward compatibility. Returns ------- tuple(parameters, mapping) parameters is the tuple of the merged parameter names. mapping contains the mapping of parameters indices from the merged signature to the original signatures. """ args: List[str] = [] anns: List[Optional[Tuple[float, float]]] = [] mapping = [] for f in callables: amap = [] for i, (k, ann) in enumerate(describe(f, annotations=True).items()): if k in args: amap.append(args.index(k)) else: amap.append(len(args)) args.append(k) anns.append(ann) mapping.append(amap) if annotations: return {k: a for (k, a) in zip(args, anns)}, mapping return args, mapping @overload def describe(callable: Callable) -> List[str]: ... # pragma: no cover @overload def describe( callable: Callable, annotations: bool ) -> Dict[str, Optional[Tuple[float, float]]]: ... # pragma: no cover def describe(callable, *, annotations=False): """ Attempt to extract the function argument names and annotations. Parameters ---------- callable : callable Callable whose parameter names should be extracted. annotations : bool, optional Whether to also extract annotations. Default is false. Returns ------- list or dict If annotate is False, return list of strings with the parameters names if successful and an empty list otherwise. If annotations is True, return a dict, which maps parameter names to annotations. For parameters without annotations, the dict maps to None. Notes ----- Parameter names are extracted with the following three methods, which are attempted in order. The first to succeed determines the result. 1. Using ``obj._parameters``, which is a dict that maps parameter names to parameter limits or None if the parameter has to limits. Users are encouraged to use this mechanism to provide signatures for objects that otherwise would not have a detectable signature. Example:: def f(*args): # no signature x, y = args return (x - 2) ** 2 + (y - 3) ** 2 f._parameters = {"x": None, "y": (1, 4)} Here, the first parameter is declared to have no limits (values from minus to plus infinity are allowed), while the second parameter is declared to have limits, it cannot be smaller than 1 or larger than 4. Note: In the past, the ``func_code`` attribute was used for a similar purpose as ``_parameters``. It is still supported for legacy code, but should not be used anymore in new code, since it does not support declaring parameter limits. If an objects has a ``func_code`` attribute, it is used to detect the parameters. Example:: from iminuit.util import make_func_code def f(*args): # no signature x, y = args return (x - 2) ** 2 + (y - 3) ** 2 # deprecated, make_func_code will raise a warning f.func_code = make_func_code(("x", "y")) 2. Using :func:`inspect.signature`. The :mod:`inspect` module provides a general function to extract the signature of a Python callable. It works on most callables, including Functors like this:: class MyLeastSquares: def __call__(self, a, b): ... Limits are supported via annotations, using the Annotated type that was introduced in Python-3.9 and can be obtained from the external package typing_extensions in Python-3.8. In the following example, the second parameter has a lower limit at 0, because it must be positive:: from typing import Annotated def my_cost_function(a: float, b: Annotated[float, 0:]): ... There are no standard annotations yet at the time of this writing. iminuit supports the annotations Gt, Ge, Lt, Le from the external package annotated-types, and interprets slice notation as limits. 3. Using the docstring. The docstring is textually parsed to detect the parameter names. This requires that a docstring is present which follows the Python standard formatting for function signatures. Here is a contrived example which is parsed correctly: fn(a, b: float, int c, d=1, e: float=2.2, double e=3). Ambiguous cases with positional and keyword argument are handled in the following way:: def fcn(a, b, *args, **kwargs): ... # describe returns [a, b]; # *args and **kwargs are ignored def fcn(a, b, c=1): ... # describe returns [a, b, c]; # positional arguments with default values are detected """ if _address_of_cfunc(callable) != 0: return {} if annotations else [] args = ( getattr(callable, "_parameters", {}) or _describe_impl_func_code(callable) or _describe_impl_inspect(callable) or _describe_impl_docstring(callable) ) if annotations: return args # for backward-compatibility return list(args) def _describe_impl_func_code(callable): # Check (faked) f.func_code; for backward-compatibility with iminuit-1.x if hasattr(callable, "func_code"): # cannot warn about deprecation here, since numba.njit also uses .func_code fc = callable.func_code return {x: None for x in fc.co_varnames[: fc.co_argcount]} return {} def _describe_impl_inspect(callable): try: signature = inspect.signature(callable) except ValueError: # raised when used on built-in function return {} r = {} for name, par in signature.parameters.items(): # stop when variable number of arguments is encountered if par.kind is inspect.Parameter.VAR_POSITIONAL: break # stop when keyword argument is encountered if par.kind is inspect.Parameter.VAR_KEYWORD: break r[name] = _get_limit(par.annotation) return r def _describe_impl_docstring(callable): doc = inspect.getdoc(callable) if doc is None: return {} # Examples of strings we want to parse: # min(iterable, *[, default=obj, key=func]) -> value # min(arg1, arg2, *args, *[, key=func]) -> value # Foo.bar(self, int ncall_me =10000, [resume=True, int nsplit=1]) # Foo.baz(self: Foo, ncall_me: int =10000) try: # function wrapper functools.partial does not offer __name__, # we cannot extract the signature in this case name = callable.__name__ except AttributeError: return {} token = name + "(" start = doc.find(token) if start < 0: return {} start += len(token) nbrace = 1 for ich, ch in enumerate(doc[start:]): if ch == "(": nbrace += 1 elif ch == ")": nbrace -= 1 if nbrace == 0: break items = [x.strip(" []") for x in doc[start : start + ich].split(",")] # strip self if callable is a class method if inspect.ismethod(callable): items = items[1:] # "iterable", "*", "default=obj", "key=func" # "arg1", "arg2", "*args", "*", "key=func" # "int ncall_me =10000", "resume=True", "int nsplit=1" # "ncall_me: int =10000" try: i = items.index("*args") items = items[:i] except ValueError: pass # "iterable", "*", "default=obj", "key=func" # "arg1", "arg2", "*", "key=func" # "int ncall_me =10000", "resume=True", "int nsplit=1" # "ncall_me: int =10000" def extract(s: str) -> str: i = s.find("=") if i >= 0: s = s[:i] i = s.find(":") if i >= 0: return s[:i].strip() s = s.strip() i = s.find(" ") if i >= 0: return s[i:].strip() return s # "iterable", "*", "default", "key" # "arg1", "arg2", "key" # "ncall_me", "resume", "nsplit" # "ncall_me" return {extract(x): None for x in items if x != "*"} def _get_limit( annotation: Union[type, Annotated[float, Any], str], ) -> Optional[Tuple[float, float]]: from iminuit import typing if isinstance(annotation, str): # This provides limited support for string annotations, which # have a lot of problems, see https://peps.python.org/pep-0649. try: annotation = eval(annotation, None, typing.__dict__) except NameError: # We ignore unknown annotations to fix issue #846. # I cannot replicate here what inspect.signature(..., eval_str=True) does. # I need a dict with the global objects at the call site of describe, but # it is not globals(). Anyway, when using strings, only the annotations # from the package annotated-types are supported. pass if annotation == inspect.Parameter.empty: return None if get_origin(annotation) is not Annotated: return None tp, *constraints = get_args(annotation) assert tp is float lower = -np.inf upper = np.inf for c in constraints: if isinstance(c, slice): if c.start is not None: lower = c.start if c.stop is not None: upper = c.stop continue if isinstance(c, Sequence): lower, upper = c continue # Minuit does not distinguish between closed and open intervals. # We use a chain of ifs so that the code also works with the # `Interval` class, which contains several of those attributes # and which can be None. gt = getattr(c, "gt", None) ge = getattr(c, "ge", None) lt = getattr(c, "lt", None) le = getattr(c, "le", None) if gt is not None: lower = gt if ge is not None: lower = ge if lt is not None: upper = lt if le is not None: upper = le return lower, upper def _guess_initial_step(val: float) -> float: return 1e-2 * abs(val) if val != 0 else 1e-1 # heuristic def _key2index_from_slice(var2pos: Dict[str, int], key: slice) -> List[int]: start = var2pos[key.start] if isinstance(key.start, str) else key.start stop = var2pos[key.stop] if isinstance(key.stop, str) else key.stop start, stop, step = slice(start, stop, key.step).indices(len(var2pos)) return list(range(start, stop, step)) def _key2index_item(var2pos: Dict[str, int], key: Union[str, int]) -> int: if isinstance(key, str): return var2pos[key] i = key if i < 0: i += len(var2pos) if i < 0 or i >= len(var2pos): raise IndexError return i def _key2index( var2pos: Dict[str, int], key: Key, ) -> Union[int, List[int]]: if key is ...: return list(range(len(var2pos))) if isinstance(key, slice): return _key2index_from_slice(var2pos, key) if not isinstance(key, str) and isinstance(key, Iterable): # convert boolean masks into list of indices if isinstance(key[0], bool): key = [k for k in range(len(var2pos)) if key[k]] return [_key2index_item(var2pos, k) for k in key] return _key2index_item(var2pos, key) def _address_of_cfunc(fcn: Any) -> int: from ctypes import ( c_void_p, c_double, c_uint32, POINTER, CFUNCTYPE, cast as ctypes_cast, ) c_sig = CFUNCTYPE(c_double, c_uint32, POINTER(c_double)) fcn = getattr(fcn, "ctypes", None) if isinstance(fcn, c_sig): return ctypes_cast(fcn, c_void_p).value # type: ignore return 0 def _iterate(x): if not isinstance(x, Iterable): yield x else: for xi in x: yield xi def _replace_none(x: Optional[T], v: T) -> T: if x is None: return v return x # poor-mans progressbar class ProgressBar: """ Simple progress bar. Renders as nice HTML progressbar in Jupyter notebooks. """ value: int = 0 max_value: int def _update(self, fraction): self._out.write(f"\r{100 * fraction:.0f} %") self._out.flush() def _finish(self): self._out.write("\r ") self._out.flush() def __init__(self, max_value): """ Initialize bar. Parameters ---------- max_value: int Total number of entries. """ self.max_value = max_value self._out = sys.stdout try: with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) # DeprecationWarning: Jupyter is migrating its paths ... from ipykernel.iostream import OutStream if isinstance(self._out, OutStream): from IPython.display import display, HTML self._update = lambda v: display( HTML( f" " f"{100 * v:.0f} %" ), clear=True, ) self._finish = lambda: display(HTML(""), clear=True) except ModuleNotFoundError: pass self._update(self.value) def __enter__(self, *args): """Noop.""" return self def __exit__(self, *args): """Clean up the bar.""" self._finish() def __add__(self, v): """Increment progress.""" self.value += v self._update(self.value / self.max_value) return self def _histogram_segments(mask, xe, masked): assert masked.ndim == 1 if mask is None: return [(masked, xe)] segments = [] a = 0 b = 0 am = 0 n = len(mask) while a < n: if not mask[a]: a += 1 continue b = a + 1 while b < n and mask[b]: b += 1 segments.append((masked[am : am + b - a], xe[a : b + 1])) am += b - a a = b + 1 return segments def _smart_sampling(f, xmin, xmax, start=20, tol=5e-3, maxiter=20, maxtime=10): t0 = monotonic() x = np.linspace(xmin, xmax, start) ynew = f(x) ymin = np.min(ynew) ymax = np.max(ynew) y = {xi: yi for (xi, yi) in zip(x, ynew)} a = x[:-1] b = x[1:] niter = 0 while len(a): niter += 1 if niter > maxiter: msg = ( f"Iteration limit {maxiter} in smart sampling reached, " f"produced {len(y)} points" ) warnings.warn(msg, RuntimeWarning) break if monotonic() - t0 > maxtime: msg = ( f"Time limit {maxtime} in smart sampling reached, " f"produced {len(y)} points" ) warnings.warn(msg, RuntimeWarning) break xnew = 0.5 * (a + b) ynew = f(xnew) ymin = min(ymin, np.min(ynew)) ymax = max(ymax, np.max(ynew)) for xi, yi in zip(xnew, ynew): y[xi] = yi yint = 0.5 * ( np.fromiter((y[ai] for ai in a), float) + np.fromiter((y[bi] for bi in b), float) ) dy = np.abs(ynew - yint) dx = np.abs(b - a) # in next iteration, handle intervals which do not # pass interpolation test and are not too narrow mask = (dy > tol * (ymax - ymin)) & (dx > tol * abs(xmax - xmin)) a = a[mask] b = b[mask] xnew = xnew[mask] a = np.append(a, xnew) b = np.append(xnew, b) xy = list(y.items()) xy.sort() return np.transpose(xy) def _detect_log_spacing(x: NDArray) -> bool: # x should never contain NaN x = np.sort(x) if x[0] <= 0: return False d_lin = np.diff(x) d_log = np.diff(np.log(x)) lin_rel_std = np.std(d_lin) / np.mean(d_lin) log_rel_std = np.std(d_log) / np.mean(d_log) return log_rel_std < lin_rel_std def gradient(fcn: Cost) -> Optional[CostGradient]: """ Return a callable which computes the gradient of fcn or None. Parameters ---------- fcn: Cost Cost function which may provide a callable gradient. How the gradient is detected is specified below in the Notes. Notes ----- This function checks whether the following attributes exist: `fcn.grad` and `fcn.has_grad`. If `fcn.grad` exists and is a CostGradient, it is returned unless `fcn.has_grad` exists and is False. If no useable gradient is detected, None is returned. Returns ------- callable or None The gradient function or None """ grad = getattr(fcn, "grad", None) has_grad = getattr(fcn, "has_grad", True) if grad and isinstance(grad, CostGradient) and has_grad: return grad return None def is_positive_definite(m: ArrayLike) -> bool: """ Return True if argument is a positive definite matrix. This test is somewhat expensive, because we attempt a cholesky decomposition. Parameters ---------- m : array-like Matrix to be tested. Returns ------- bool True if matrix is positive definite and False otherwise. """ m = np.atleast_2d(m) if np.all(m.T == m): # maybe check this first https://en.wikipedia.org/wiki/Diagonally_dominant_matrix # and only try cholesky if that fails try: np.linalg.cholesky(m) except np.linalg.LinAlgError: return False return True return False iminuit-2.30.1/src/iminuit/warnings.py0000644000000000000000000000076514332717401014662 0ustar00"""Warnings used by iminuit.""" class IMinuitWarning(RuntimeWarning): """Generic iminuit warning.""" class OptionalDependencyWarning(IMinuitWarning): """Feature requires an optional external package.""" class HesseFailedWarning(IMinuitWarning): """HESSE failed warning.""" class ErrordefAlreadySetWarning(IMinuitWarning): """The errordef attribute is already defined by the cost function.""" class PerformanceWarning(UserWarning): """Warning about performance issues.""" iminuit-2.30.1/src/lasymmatrix.cpp0000644000000000000000000000074114332717401014052 0ustar00#include "lasymmatrix.hpp" namespace py = pybind11; using namespace ROOT::Minuit2; py::tuple lasymmatrix2py(const LASymMatrix& self) { py::list ls; for (unsigned i = 0; i < self.size(); ++i) ls.append(self.Data()[i]); return py::make_tuple(self.Nrow(), ls); } LASymMatrix py2lasymmatrix(py::tuple tp) { LASymMatrix v(tp[0].cast()); auto ls = tp[1].cast(); for (unsigned i = 0; i < v.size(); ++i) v.Data()[i] = ls[i].cast(); return v; } iminuit-2.30.1/src/lasymmatrix.hpp0000644000000000000000000000042214332717401014053 0ustar00#ifndef IMINUIT_LASYMMATRIX #define IMINUIT_LASYMMATRIX #include "pybind11.hpp" #include namespace py = pybind11; using namespace ROOT::Minuit2; py::tuple lasymmatrix2py(const LASymMatrix& self); LASymMatrix py2lasymmatrix(py::tuple tp); #endif iminuit-2.30.1/src/lavector.cpp0000644000000000000000000000057714332717401013326 0ustar00#include "lavector.hpp" namespace py = pybind11; using namespace ROOT::Minuit2; py::list lavector2py(const LAVector& self) { py::list ls; for (unsigned i = 0; i < self.size(); ++i) ls.append(self.Data()[i]); return ls; } LAVector py2lavector(py::list ls) { LAVector v(ls.size()); for (unsigned i = 0; i < v.size(); ++i) v.Data()[i] = ls[i].cast(); return v; } iminuit-2.30.1/src/lavector.hpp0000644000000000000000000000036714332717401013330 0ustar00#ifndef IMINUIT_LAVECTOR #define IMINUIT_LAVECTOR #include "pybind11.hpp" #include namespace py = pybind11; using namespace ROOT::Minuit2; py::list lavector2py(const LAVector& v); LAVector py2lavector(py::list ls); #endif iminuit-2.30.1/src/machineprecision.cpp0000644000000000000000000000162714332717401015024 0ustar00#include "pybind11.hpp" #include namespace ROOT { namespace Minuit2 { bool operator==(const MnMachinePrecision& a, const MnMachinePrecision& b) { return a.Eps() == b.Eps() && a.Eps2() == b.Eps2(); } } // namespace Minuit2 } // namespace ROOT namespace py = pybind11; using namespace ROOT::Minuit2; void bind_machineprecision(py::module m) { py::class_(m, "MnMachinePrecision") .def(py::init<>()) .def_property("eps", &MnMachinePrecision::Eps, &MnMachinePrecision::SetPrecision) .def_property_readonly("eps2", &MnMachinePrecision::Eps2) .def(py::self == py::self) .def(py::pickle( [](const MnMachinePrecision& self) { return py::make_tuple(self.Eps()); }, [](py::tuple tp) { MnMachinePrecision p; p.SetPrecision(tp[0].cast()); return p; })) ; } iminuit-2.30.1/src/main.cpp0000644000000000000000000000204214332717401012420 0ustar00#include "pybind11.hpp" namespace py = pybind11; void bind_application(py::module); void bind_contours(py::module); void bind_fcn(py::module); void bind_functionminimum(py::module); void bind_hesse(py::module); void bind_machineprecision(py::module); void bind_migrad(py::module); void bind_minimumstate(py::module); void bind_minos(py::module); void bind_minuitparameter(py::module); void bind_print(py::module); void bind_scan(py::module); void bind_simplex(py::module); void bind_strategy(py::module); void bind_usercovariance(py::module); void bind_userparameterstate(py::module); void bind_usertransformation(py::module); PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { bind_application(m); bind_contours(m); bind_fcn(m); bind_functionminimum(m); bind_hesse(m); bind_machineprecision(m); bind_migrad(m); bind_minimumstate(m); bind_minos(m); bind_minuitparameter(m); bind_print(m); bind_scan(m); bind_simplex(m); bind_strategy(m); bind_usercovariance(m); bind_userparameterstate(m); bind_usertransformation(m); } iminuit-2.30.1/src/migrad.cpp0000644000000000000000000000134614332717401012745 0ustar00#include "fcn.hpp" #include "pybind11.hpp" #include #include namespace py = pybind11; using namespace ROOT::Minuit2; MnMigrad init(const FCN& fcn, const MnUserParameterState& state, const MnStrategy& str) { if (fcn.grad_.is_none()) { return MnMigrad(static_cast(fcn), state, str); } return MnMigrad(static_cast(fcn), state, str); } void bind_migrad(py::module m) { py::class_(m, "MnMigrad") .def(py::init(&init), py::keep_alive<1, 2>()) .def("set_print_level", [](MnMigrad& self, int lvl) { return self.Minimizer().Builder().SetPrintLevel(lvl); }) ; } iminuit-2.30.1/src/minimumstate.cpp0000644000000000000000000000720314332717401014214 0ustar00#include "lasymmatrix.hpp" #include "lavector.hpp" #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; py::tuple par2py(const MinimumParameters& pars) { return py::make_tuple(lavector2py(pars.Vec()), lavector2py(pars.Dirin()), pars.Fval(), pars.IsValid(), pars.HasStepSize()); } MinimumParameters py2par(py::tuple tp) { static_assert(std::is_standard_layout(), ""); struct Layout { MnAlgebraicVector fParameters; MnAlgebraicVector fStepSize; double fFVal; bool fValid; bool fHasStep; }; MinimumParameters pars(py2lavector(tp[0]), py2lavector(tp[1]), tp[2].cast()); // evil workaround, will segfault or cause UB if source layout changes auto& ptr = reinterpret_cast&>(pars); auto d = ptr.get(); d->fValid = tp[3].cast(); d->fHasStep = tp[4].cast(); return pars; } py::tuple err2py(const MinimumError& err) { return py::make_tuple(lasymmatrix2py(err.InvHessian()), err.Dcovar(), static_cast(err.GetStatus())); } MinimumError py2err(py::tuple tp) { auto status = static_cast(tp[2].cast()); if (status == MinimumError::MnPosDef) return MinimumError(py2lasymmatrix(tp[0]), tp[1].cast()); return MinimumError(py2lasymmatrix(tp[0]), status); } py::tuple grad2py(const FunctionGradient& g) { return py::make_tuple(lavector2py(g.Grad()), lavector2py(g.G2()), lavector2py(g.Gstep()), g.IsValid(), g.IsAnalytical()); } FunctionGradient py2grad(py::tuple tp) { const auto& gr = py2lavector(tp[0]); const auto& g2 = py2lavector(tp[1]); const auto& st = py2lavector(tp[2]); const auto& valid = tp[3].cast(); const auto& analytical = tp[4].cast(); if (valid) { if (analytical) return FunctionGradient{gr}; else return FunctionGradient{gr, g2, st}; } return FunctionGradient{gr.size()}; } void bind_minimumstate(py::module m) { py::class_(m, "MinimumState") .def(py::init()) .def_property_readonly( "vec", [](const MinimumState& self) { return lavector2py(self.Vec()); }) .def_property_readonly("fval", &MinimumState::Fval) .def_property_readonly("edm", &MinimumState::Edm) .def_property_readonly("nfcn", &MinimumState::NFcn) .def_property_readonly("is_valid", &MinimumState::IsValid) .def_property_readonly("has_parameters", &MinimumState::HasParameters) .def_property_readonly("has_covariance", &MinimumState::HasCovariance) .def(py::pickle( [](const MinimumState& self) { return py::make_tuple(par2py(self.Parameters()), err2py(self.Error()), grad2py(self.Gradient()), self.Edm(), self.NFcn()); }, [](py::tuple tp) { static_assert(std::is_standard_layout(), ""); struct Layout { MinimumParameters fParameters; MinimumError fError; FunctionGradient fGradient; double fEDM; int fNFcn; }; MinimumState st{0}; // evil workaround, will segfault or cause UB if source layout changes auto& ptr = reinterpret_cast&>(st); auto d = ptr.get(); d->fParameters = py2par(tp[0]); d->fError = py2err(tp[1]); d->fGradient = py2grad(tp[2]); d->fEDM = tp[3].cast(); d->fNFcn = tp[4].cast(); return st; })) ; } iminuit-2.30.1/src/minos.cpp0000644000000000000000000000271314332717401012626 0ustar00#include "pybind11.hpp" #include #include #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void bind_minos(py::module m) { py::class_(m, "MinosError") .def_property_readonly("number", &MinosError::Parameter) .def_property_readonly("lower", &MinosError::Lower) .def_property_readonly("upper", &MinosError::Upper) .def_property_readonly("is_valid", &MinosError::IsValid) .def_property_readonly("lower_valid", &MinosError::LowerValid) .def_property_readonly("upper_valid", &MinosError::UpperValid) .def_property_readonly("at_lower_limit", &MinosError::AtLowerLimit) .def_property_readonly("at_upper_limit", &MinosError::AtUpperLimit) .def_property_readonly("at_lower_max_fcn", &MinosError::AtLowerMaxFcn) .def_property_readonly("at_upper_max_fcn", &MinosError::AtUpperMaxFcn) .def_property_readonly("lower_new_min", &MinosError::LowerNewMin) .def_property_readonly("upper_new_min", &MinosError::UpperNewMin) .def_property_readonly("nfcn", &MinosError::NFcn) .def_property_readonly("min", &MinosError::Min) ; py::class_(m, "MnMinos") .def(py::init()) // int ipar, unsigned maxcalls, double toler .def("__call__", &MnMinos::Minos) ; } iminuit-2.30.1/src/minuitparameter.cpp0000644000000000000000000000602514332717401014707 0ustar00#include "equal.hpp" #include "pybind11.hpp" #include namespace ROOT { namespace Minuit2 { bool operator==(const MinuitParameter& a, const MinuitParameter& b) { return a.Number() == b.Number() && a.GetName() == b.GetName() && a.Value() == b.Value() && a.Error() == b.Error() && a.IsConst() == b.IsConst() && a.IsFixed() == b.IsFixed() && a.HasLimits() == b.HasLimits() && a.HasLowerLimit() == b.HasLowerLimit() && a.HasUpperLimit() == b.HasUpperLimit() && nan_equal(a.LowerLimit(), b.LowerLimit()) && nan_equal(a.UpperLimit(), b.UpperLimit()); } } // namespace Minuit2 } // namespace ROOT namespace py = pybind11; using namespace ROOT::Minuit2; void bind_minuitparameter(py::module m) { py::class_(m, "MinuitParameter") .def_property_readonly("number", &MinuitParameter::Number) .def_property_readonly("name", &MinuitParameter::GetName) .def_property_readonly("value", &MinuitParameter::Value) .def_property_readonly("error", &MinuitParameter::Error) .def_property_readonly("is_const", &MinuitParameter::IsConst) .def_property_readonly("is_fixed", &MinuitParameter::IsFixed) .def_property_readonly("has_limits", &MinuitParameter::HasLimits) .def_property_readonly("has_lower_limit", &MinuitParameter::HasLowerLimit) .def_property_readonly("has_upper_limit", &MinuitParameter::HasUpperLimit) .def_property_readonly("lower_limit", &MinuitParameter::LowerLimit) .def_property_readonly("upper_limit", &MinuitParameter::UpperLimit) .def(py::self == py::self) .def(py::pickle( [](const MinuitParameter& self) { return py::make_tuple(self.Number(), self.GetName(), self.Value(), self.Error(), self.IsConst(), self.IsFixed(), self.LowerLimit(), self.UpperLimit(), self.HasLowerLimit(), self.HasUpperLimit()); }, [](py::tuple tp) { static_assert(std::is_standard_layout(), ""); if (tp.size() != 10) throw std::runtime_error("invalid state"); MinuitParameter p{tp[0].cast(), tp[1].cast(), tp[2].cast(), tp[3].cast()}; struct Layout { unsigned int fNum; double fValue; double fError; bool fConst; bool fFix; double fLoLimit; double fUpLimit; bool fLoLimValid; bool fUpLimValid; std::string fName; }; auto d = reinterpret_cast(&p); d->fConst = tp[4].cast(); d->fFix = tp[5].cast(); d->fLoLimit = tp[6].cast(); d->fUpLimit = tp[7].cast(); d->fLoLimValid = tp[8].cast(); d->fUpLimValid = tp[9].cast(); return p; })) ; } iminuit-2.30.1/src/print.cpp0000644000000000000000000000144414332717401012635 0ustar00#include "pybind11.hpp" #include namespace py = pybind11; using namespace ROOT::Minuit2; using cstr = const char*; using namespace pybind11::literals; void bind_print(py::module m) { py::class_(m, "MnPrint") .def(py::init(), "prefix"_a, "level"_a) .def("error", &MnPrint::Error) .def("warn", &MnPrint::Warn) .def("info", &MnPrint::Info) .def("debug", &MnPrint::Debug) .def_property_static( "global_level", [](py::object) { return MnPrint::GlobalLevel(); }, [](py::object, int x) { MnPrint::SetGlobalLevel(x); }) .def("show_prefix_stack", &MnPrint::ShowPrefixStack) .def("add_filter", &MnPrint::AddFilter) .def("clear_filter", &MnPrint::ClearFilter) ; } iminuit-2.30.1/src/printimpl.cpp0000644000000000000000000000043614332717401013517 0ustar00#include "Minuit2/MnPrint.h" #include "pybind11.hpp" using ROOT::Minuit2::MnPrint; void MnPrint::Impl(MnPrint::Verbosity level, const std::string& s) { const char* label[4] = {"E", "W", "I", "D"}; const int ilevel = static_cast(level); pybind11::print(label[ilevel], s); } iminuit-2.30.1/src/pybind11.hpp0000644000000000000000000000325114332717401013133 0ustar00#ifndef PYBIND11_HPP #define PYBIND11_HPP // We must load pybind11 consistently through this header to ensure that our type_caster // specialization is used in every translation unit. Otherwise we get ODR violations. #include #include #include #include #include #include namespace pybind11 { namespace detail { // This specialization for vector acts as an override from the more generic // template in pybind11/stl.h. We use it to cast the C++ vector into a numpy array // instead of a Python list. template <> struct type_caster> { using vec_t = std::vector; using value_conv = make_caster; using size_conv = make_caster; bool load(handle src, bool convert) { value.clear(); // TODO optimize for python objects that support buffer protocol if (isinstance(src)) { auto seq = reinterpret_borrow(src); if (hasattr(seq, "__len__")) value.reserve(static_cast(len(seq))); for (auto it : seq) { value_conv conv; if (!conv.load(it, convert)) return false; value.push_back(cast_op(std::move(conv))); } return true; } return false; } template static handle cast(T&& src, return_value_policy, handle) { array_t arr(static_cast(src.size())); std::copy(src.begin(), src.end(), arr.mutable_data()); return arr.release(); } PYBIND11_TYPE_CASTER(vec_t, _("List[") + value_conv::name + _("]")); }; } // namespace detail } // namespace pybind11 #endif // PYBIND11_HPP iminuit-2.30.1/src/scan.cpp0000644000000000000000000000055014332717401012422 0ustar00#include "pybind11.hpp" #include #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void bind_scan(py::module m) { py::class_(m, "MnScan") .def(py::init()) ; } iminuit-2.30.1/src/simplex.cpp0000644000000000000000000000103114332717401013152 0ustar00#include "fcn.hpp" #include "pybind11.hpp" #include #include namespace py = pybind11; using namespace ROOT::Minuit2; void bind_simplex(py::module m) { py::class_(m, "MnSimplex") .def(py::init(), py::keep_alive<1, 2>()) .def("set_print_level", [](MnSimplex& self, int lvl) { return self.Minimizer().Builder().SetPrintLevel(lvl); }) ; } iminuit-2.30.1/src/strategy.cpp0000644000000000000000000000652714332717401013352 0ustar00#include "equal.hpp" #include "pybind11.hpp" #include namespace ROOT { namespace Minuit2 { bool operator==(const MnStrategy& a, const MnStrategy& b) { return a.Strategy() == b.Strategy() && a.GradientNCycles() == b.GradientNCycles() && a.GradientStepTolerance() == b.GradientStepTolerance() && a.GradientTolerance() == b.GradientTolerance() && a.HessianNCycles() == b.HessianNCycles() && a.HessianStepTolerance() == b.HessianStepTolerance() && a.HessianG2Tolerance() == b.HessianG2Tolerance() && a.HessianGradientNCycles() == b.HessianGradientNCycles() && a.StorageLevel() == b.StorageLevel(); } } // namespace Minuit2 } // namespace ROOT namespace py = pybind11; using namespace ROOT::Minuit2; void set_strategy(MnStrategy& self, unsigned s) { switch (s) { case 0: self.SetLowStrategy(); break; case 1: self.SetMediumStrategy(); break; case 2: self.SetHighStrategy(); break; default: throw std::invalid_argument("invalid strategy"); } } void bind_strategy(py::module m) { py::class_(m, "MnStrategy") .def(py::init<>()) .def(py::init()) .def_property("strategy", &MnStrategy::Strategy, set_strategy) .def_property("gradient_ncycles", &MnStrategy::GradientNCycles, &MnStrategy::SetGradientNCycles) .def_property("gradient_step_tolerance", &MnStrategy::GradientStepTolerance, &MnStrategy::SetGradientStepTolerance) .def_property("gradient_tolerance", &MnStrategy::GradientTolerance, &MnStrategy::SetGradientTolerance) .def_property("hessian_ncycles", &MnStrategy::HessianNCycles, &MnStrategy::SetHessianNCycles) .def_property("hessian_step_tolerance", &MnStrategy::HessianStepTolerance, &MnStrategy::SetHessianStepTolerance) .def_property("hessian_g2_tolerance", &MnStrategy::HessianG2Tolerance, &MnStrategy::SetHessianG2Tolerance) .def_property("hessian_gradient_ncycles", &MnStrategy::HessianGradientNCycles, &MnStrategy::SetHessianGradientNCycles) .def_property("storage_level", &MnStrategy::StorageLevel, &MnStrategy::SetStorageLevel) .def(py::self == py::self) .def(py::pickle( [](const MnStrategy& self) { return py::make_tuple( self.Strategy(), self.GradientNCycles(), self.GradientStepTolerance(), self.GradientTolerance(), self.HessianNCycles(), self.HessianStepTolerance(), self.HessianG2Tolerance(), self.HessianGradientNCycles(), self.StorageLevel()); }, [](py::tuple tp) { MnStrategy str(tp[0].cast()); str.SetGradientNCycles(tp[1].cast()); str.SetGradientStepTolerance(tp[2].cast()); str.SetGradientTolerance(tp[3].cast()); str.SetHessianNCycles(tp[4].cast()); str.SetHessianStepTolerance(tp[5].cast()); str.SetHessianG2Tolerance(tp[6].cast()); str.SetHessianGradientNCycles(tp[7].cast()); str.SetStorageLevel(tp[8].cast()); return str; })) ; py::implicitly_convertible(); } iminuit-2.30.1/src/usercovariance.cpp0000644000000000000000000000235614332717401014515 0ustar00#include "equal.hpp" #include "pybind11.hpp" #include #include namespace ROOT { namespace Minuit2 { bool operator==(const MnUserCovariance& a, const MnUserCovariance& b) { return a.Nrow() == b.Nrow() && a.Data() == b.Data(); } } // namespace Minuit2 } // namespace ROOT namespace py = pybind11; using namespace ROOT::Minuit2; MnUserCovariance init(py::sequence seq, unsigned n) { return MnUserCovariance{py::cast>(seq), n}; } void bind_usercovariance(py::module m) { py::class_(m, "MnUserCovariance") .def(py::init(&init)) .def("__getitem__", [](const MnUserCovariance& self, py::object args) { const auto tup = py::cast>(args); return self(tup.first, tup.second); }) .def_property_readonly("nrow", &MnUserCovariance::Nrow) .def(py::self == py::self) .def(py::pickle( [](const MnUserCovariance& self) { return py::make_tuple(self.Data(), self.Nrow()); }, [](py::tuple tp) { return MnUserCovariance(tp[0].cast>(), tp[1].cast()); })) ; } iminuit-2.30.1/src/userparameterstate.cpp0000644000000000000000000001403714332717401015423 0ustar00#include "equal.hpp" #include "pybind11.hpp" #include #include namespace ROOT { namespace Minuit2 { bool operator==(const MnUserParameterState& a, const MnUserParameterState& b) { return a.MinuitParameters() == b.MinuitParameters() && a.Fval() == b.Fval() && a.Covariance() == b.Covariance() && a.GlobalCC().GlobalCC() == b.GlobalCC().GlobalCC() && a.IntParameters() == b.IntParameters() && a.IntCovariance().Data() == b.IntCovariance().Data() && a.CovarianceStatus() == b.CovarianceStatus() && a.IsValid() == b.IsValid() && a.HasCovariance() == b.HasCovariance() && a.HasGlobalCC() == b.HasGlobalCC() && a.Fval() == b.Fval() && a.Edm() == b.Edm() && a.NFcn() == b.NFcn(); } } // namespace Minuit2 } // namespace ROOT namespace py = pybind11; using namespace ROOT::Minuit2; int size(const MnUserParameterState& self) { return static_cast(self.MinuitParameters().size()); } const MinuitParameter& getitem(const MnUserParameterState& self, int i) { const int n = size(self); if (i < 0) i += n; if (i >= n) throw py::index_error(); return self.Parameter(i); } auto iter(const MnUserParameterState& self) { return py::make_iterator(self.MinuitParameters().begin(), self.MinuitParameters().end()); } py::object globalcc2py(const MnGlobalCorrelationCoeff& gcc) { if (gcc.IsValid()) return py::cast(gcc.GlobalCC()); return py::cast(nullptr); } MnGlobalCorrelationCoeff py2globalcc(py::object o) { static_assert(std::is_standard_layout(), ""); struct Layout { std::vector fGlobalCC; bool fValid; }; MnGlobalCorrelationCoeff c; auto d = reinterpret_cast(&c); if (!o.is_none()) { d->fGlobalCC = o.cast>(); d->fValid = true; } return c; } void bind_userparameterstate(py::module m) { py::class_(m, "MnUserParameterState") .def(py::init<>()) .def(py::init()) .def("add", py::overload_cast(&MnUserParameterState::Add)) .def("add", py::overload_cast( &MnUserParameterState::Add)) .def("add", py::overload_cast( &MnUserParameterState::Add)) .def("fix", py::overload_cast(&MnUserParameterState::Fix)) .def("release", py::overload_cast(&MnUserParameterState::Release)) .def("set_value", py::overload_cast(&MnUserParameterState::SetValue)) .def("set_error", py::overload_cast(&MnUserParameterState::SetError)) .def("set_limits", py::overload_cast( &MnUserParameterState::SetLimits)) .def("set_upper_limit", py::overload_cast(&MnUserParameterState::SetUpperLimit)) .def("set_lower_limit", py::overload_cast(&MnUserParameterState::SetLowerLimit)) .def("remove_limits", py::overload_cast(&MnUserParameterState::RemoveLimits)) .def_property_readonly("fval", &MnUserParameterState::Fval) .def_property_readonly("edm", &MnUserParameterState::Edm) .def_property_readonly("covariance", &MnUserParameterState::Covariance) .def_property_readonly( "globalcc", [](const MnUserParameterState& self) { return globalcc2py(self.GlobalCC()); }) .def_property_readonly("is_valid", &MnUserParameterState::IsValid) .def_property_readonly("has_covariance", &MnUserParameterState::HasCovariance) .def_property_readonly("trafo", &MnUserParameterState::Trafo) .def("__len__", size) .def("__getitem__", getitem) .def("__iter__", iter) .def(py::self == py::self) .def(py::pickle( [](const MnUserParameterState& self) { return py::make_tuple(self.IsValid(), self.HasCovariance(), self.HasGlobalCC(), self.CovarianceStatus(), self.Fval(), self.Edm(), self.NFcn(), self.Trafo(), self.Covariance(), globalcc2py(self.GlobalCC()), self.IntParameters(), self.IntCovariance()); }, [](py::tuple tp) { static_assert(std::is_standard_layout(), ""); static_assert(std::is_standard_layout(), ""); if (tp.size() != 12) throw std::runtime_error("invalid state"); struct Layout { bool fValid; bool fCovarianceValid; bool fGCCValid; int fCovStatus; // covariance matrix status double fFVal; double fEDM; unsigned int fNFcn; MnUserParameters fParameters; MnUserCovariance fCovariance; MnGlobalCorrelationCoeff fGlobalCC; std::vector fIntParameters; MnUserCovariance fIntCovariance; }; MnUserParameterState st; // evil workaround, will segfault or cause UB if source layout changes auto d = reinterpret_cast(&st); d->fValid = tp[0].cast(); d->fCovarianceValid = tp[1].cast(); d->fGCCValid = tp[2].cast(); d->fCovStatus = tp[3].cast(); d->fFVal = tp[4].cast(); d->fEDM = tp[5].cast(); d->fNFcn = tp[6].cast(); reinterpret_cast(d->fParameters) = tp[7].cast(); d->fCovariance = tp[8].cast(); d->fGlobalCC = py2globalcc(tp[9]); d->fIntParameters = tp[10].cast>(); d->fIntCovariance = tp[11].cast(); return st; })) ; } iminuit-2.30.1/src/usertransformation.cpp0000644000000000000000000000500114332717401015437 0ustar00#include "pybind11.hpp" #include #include namespace py = pybind11; using namespace ROOT::Minuit2; static_assert(std::is_standard_layout(), ""); struct Layout { MnMachinePrecision fPrecision; std::vector fParameters; std::vector fExtOfInt; SinParameterTransformation fDoubleLimTrafo; SqrtUpParameterTransformation fUpperLimTrafo; SqrtLowParameterTransformation fLowerLimTrafo; mutable std::vector fCache; }; int size(const MnUserTransformation& self) { return static_cast(self.Parameters().size()); } auto iter(const MnUserTransformation& self) { return py::make_iterator(self.Parameters().begin(), self.Parameters().end()); } const auto& getitem(const MnUserTransformation& self, int i) { if (i < 0) i += size(self); if (i < 0 || i >= size(self)) throw py::index_error(); return self.Parameter(i); } void bind_usertransformation(py::module m) { py::class_(m, "MnUserTransformation") .def(py::init<>()) .def("name", &MnUserTransformation::GetName) .def("index", &MnUserTransformation::FindIndex) .def("ext2int", &MnUserTransformation::Ext2int) .def("int2ext", &MnUserTransformation::Int2ext) .def("dint2ext", &MnUserTransformation::DInt2Ext) .def("ext_of_int", &MnUserTransformation::ExtOfInt) .def("int_of_ext", &MnUserTransformation::IntOfExt) .def_property_readonly("variable_parameters", &MnUserTransformation::VariableParameters) .def("__len__", size) .def("__iter__", iter) .def("__getitem__", getitem) .def(py::pickle( [](const MnUserTransformation& self) { const auto d = reinterpret_cast(&self); return py::make_tuple(self.Precision().Eps(), self.Parameters(), d->fExtOfInt, self.InitialParValues()); }, [](py::tuple tp) { if (tp.size() != 4) throw std::runtime_error("invalid state"); MnUserTransformation tr; tr.SetPrecision(tp[0].cast()); // evil workaround, will segfault or cause UB if source layout changes auto d = reinterpret_cast(&tr); d->fParameters = tp[1].cast>(); d->fExtOfInt = tp[2].cast>(); d->fCache = tp[3].cast>(); return tr; })) ; } iminuit-2.30.1/tests/fmin_approximate.txt0000644000000000000000000000347014332717401015454 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ Migrad │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = 11.46 (χ²/ndof = 1.1) │ Nfcn = 10, Ngrad = 3 │ │ EDM = 1.23e-10 (Goal: 0.0001) │ │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Valid Minimum │ Below EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ No parameters at limit │ Below call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse ok │ Covariance APPROXIMATE │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/fmin_bad.html0000644000000000000000000000211014332717401013764 0ustar00
SciPy[L-BFGS-B]
FCN = nan Nfcn = 100000, Ngrad = 200000
EDM = 1.23e-10 (Goal: 1e-05) time = 1.2 sec
INVALID Minimum ABOVE EDM threshold (goal x 10)
SOME parameters at limit ABOVE call limit
Hesse FAILED ABOVE call limit
iminuit-2.30.1/tests/fmin_bad.txt0000644000000000000000000000346614332717401013656 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ SciPy[L-BFGS-B] │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = nan │ Nfcn = 100000, Ngrad = 200000 │ │ EDM = 1.23e-10 (Goal: 1e-05) │ time = 1.2 sec │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ INVALID Minimum │ ABOVE EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ SOME parameters at limit │ ABOVE call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse FAILED │ ABOVE call limit │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/fmin_good.html0000644000000000000000000000207514332717401014200 0ustar00
Migrad
FCN = 11.46 (χ²/ndof = 1.1) Nfcn = 10, Ngrad = 3
EDM = 1.23e-10 (Goal: 0.0001)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
iminuit-2.30.1/tests/fmin_good.txt0000644000000000000000000000347014332717401014053 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ Migrad │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = 11.46 (χ²/ndof = 1.1) │ Nfcn = 10, Ngrad = 3 │ │ EDM = 1.23e-10 (Goal: 0.0001) │ │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Valid Minimum │ Below EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ No parameters at limit │ Below call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse ok │ Covariance accurate │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/fmin_made_posdef.txt0000644000000000000000000000347014332717401015371 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ Migrad │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = 11.46 (χ²/ndof = 1.1) │ Nfcn = 10, Ngrad = 3 │ │ EDM = 1.23e-10 (Goal: 0.0001) │ │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Valid Minimum │ Below EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ No parameters at limit │ Below call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse ok │ Covariance FORCED pos. def. │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/fmin_no_cov.html0000644000000000000000000000207414332717401014532 0ustar00
Migrad
FCN = 11.46 (χ²/ndof = 1.1) Nfcn = 10, Ngrad = 3
EDM = 1.23e-10 (Goal: 0.0001)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse not run NO covariance
iminuit-2.30.1/tests/fmin_no_cov.txt0000644000000000000000000000347014332717401014406 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ Migrad │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = 11.46 (χ²/ndof = 1.1) │ Nfcn = 10, Ngrad = 3 │ │ EDM = 1.23e-10 (Goal: 0.0001) │ │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Valid Minimum │ Below EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ No parameters at limit │ Below call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse not run │ NO covariance │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/fmin_not_posdef.txt0000644000000000000000000000347014332717401015263 0ustar00┌─────────────────────────────────────────────────────────────────────────┠│ Migrad │ ├──────────────────────────────────┬──────────────────────────────────────┤ │ FCN = 11.46 (χ²/ndof = 1.1) │ Nfcn = 10, Ngrad = 3 │ │ EDM = 1.23e-10 (Goal: 0.0001) │ │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Valid Minimum │ Below EDM threshold (goal x 10) │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ No parameters at limit │ Below call limit │ ├──────────────────────────────────┼──────────────────────────────────────┤ │ Hesse FAILED │ Covariance NOT pos. def. │ └──────────────────────────────────┴──────────────────────────────────────┘ iminuit-2.30.1/tests/matrix.html0000644000000000000000000000057114332717401013542 0ustar00
x y
x 1 0.00
y 0.00 0.25
iminuit-2.30.1/tests/matrix.txt0000644000000000000000000000037414332717401013416 0ustar00┌───┬─────────────┠│ │ x y │ ├───┼─────────────┤ │ x │ 1 -0.00 │ │ y │ -0.00 0.25 │ └───┴─────────────┘ iminuit-2.30.1/tests/matrix_2.html0000644000000000000000000000056414332717401013765 0ustar00
x y
x 1 0.7
y 0.7 1
iminuit-2.30.1/tests/matrix_difficult_values.txt0000644000000000000000000000037414332717401017026 0ustar00┌───┬─────────────┠│ │ x y │ ├───┼─────────────┤ │ x │ -1.23 0.0 │ │ y │ 0.0 0 │ └───┴─────────────┘ iminuit-2.30.1/tests/matrix_large.txt0000644000000000000000000000031014332717401014556 0ustar00┌───┬───────┠│ │ x y z │ ├───┼───────┤ │ x │ 1 2 3 │ │ y │ 4 5 6 │ │ z │ 7 8 9 │ └───┴───────┘ iminuit-2.30.1/tests/matrix_long_names.txt0000644000000000000000000000122414332717401015613 0ustar00┌─────────────────┬─────────────────────────────────┠│ │ super-long-name x │ ├─────────────────┼─────────────────────────────────┤ │ super-long-name │ 1 0.1 │ │ x │ 0.1 1 │ └─────────────────┴─────────────────────────────────┘ iminuit-2.30.1/tests/matrix_mini.txt0000644000000000000000000000016414332717401014427 0ustar00┌───┬───┠│ │ x │ ├───┼───┤ │ x │ 1 │ └───┴───┘ iminuit-2.30.1/tests/merror.html0000644000000000000000000000166714332717401013553 0ustar00
x
Error -1 1
Valid True True
At Limit False False
Max FCN False False
New Min False False
iminuit-2.30.1/tests/merror.txt0000644000000000000000000000112314332717401013411 0ustar00┌──────────┬───────────────────────┠│ │ x │ ├──────────┼───────────┬───────────┤ │ Error │ -1 │ 1 │ │ Valid │ True │ True │ │ At Limit │ False │ False │ │ Max FCN │ False │ False │ │ New Min │ False │ False │ └──────────┴───────────┴───────────┘ iminuit-2.30.1/tests/merrors.html0000644000000000000000000000256614332717401013735 0ustar00
x y
Error -1 1 -0.5 0.5
Valid True True True True
At Limit False False False False
Max FCN False False False False
New Min False False False False
iminuit-2.30.1/tests/merrors.txt0000644000000000000000000000172114332717401013600 0ustar00┌──────────┬───────────────────────┬───────────────────────┠│ │ x │ y │ ├──────────┼───────────┬───────────┼───────────┬───────────┤ │ Error │ -1 │ 1 │ -0.5 │ 0.5 │ │ Valid │ True │ True │ True │ True │ │ At Limit │ False │ False │ False │ False │ │ Max FCN │ False │ False │ False │ False │ │ New Min │ False │ False │ False │ False │ └──────────┴───────────┴───────────┴───────────┴───────────┘ iminuit-2.30.1/tests/params.html0000644000000000000000000000164414332717401013523 0ustar00
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x 2 1 -1 1
1 y 1.0 0.5 -0.5 0.5
iminuit-2.30.1/tests/params.txt0000644000000000000000000000217214332717401013373 0ustar00┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ x │ 2 │ 1 │ -1 │ 1 │ │ │ │ │ 1 │ y │ 1.0 │ 0.5 │ -0.5 │ 0.5 │ │ │ │ └───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/params_difficult_values.txt0000644000000000000000000000201314332717401016775 0ustar00┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ x │ -0 │ 0.012e-9 │ │ │ │ │ CONST │ └───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/params_init.html0000644000000000000000000000163614332717401014547 0ustar00
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x 0.0 0.1
1 y 0.0 0.1
iminuit-2.30.1/tests/params_latex_1.txt0000644000000000000000000000201614332717401015005 0ustar00┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ 𛼠│ 1.00 │ 0.01 │ │ │ │ │ │ └───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/params_latex_2.txt0000644000000000000000000000206714332717401015014 0ustar00┌───┬──────────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼──────────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ $\alpha$ │ 1.00 │ 0.01 │ │ │ │ │ │ └───┴──────────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/params_long_names.txt0000644000000000000000000000220414332717401015571 0ustar00┌───┬─────────────────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼─────────────────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ super-long-name │ 0 │ 0 │ │ │ │ │ │ └───┴─────────────────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/params_with_limits.html0000644000000000000000000000164514332717401016140 0ustar00
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 x 3.0 0.2 0 yes
1 y 5.0 0.1 0 10
iminuit-2.30.1/tests/params_with_limits.txt0000644000000000000000000000217214332717401016007 0ustar00┌───┬──────┬───────────┬───────────┬────────────┬────────────┬─────────┬─────────┬───────┠│ │ Name │ Value │ Hesse Err │ Minos Err- │ Minos Err+ │ Limit- │ Limit+ │ Fixed │ ├───┼──────┼───────────┼───────────┼────────────┼────────────┼─────────┼─────────┼───────┤ │ 0 │ x │ 3.0 │ 0.2 │ │ │ 0 │ │ yes │ │ 1 │ y │ 5.0 │ 0.1 │ │ │ 0 │ 10 │ │ └───┴──────┴───────────┴───────────┴────────────┴────────────┴─────────┴─────────┴───────┘ iminuit-2.30.1/tests/test_core.py0000644000000000000000000001504114332717401013707 0ustar00from iminuit._core import ( FCN, MnUserParameterState, MnUserTransformation, MnMigrad, MnStrategy, MnScan, FunctionMinimum, MnSimplex, MnPrint, MnUserCovariance, MinimumState, ) from pytest import approx import pytest import pickle import numpy as np @pytest.fixture def debug(): prev = MnPrint.global_level MnPrint.global_level = 3 MnPrint.show_prefix_stack(True) yield MnPrint.global_level = prev MnPrint.show_prefix_stack(False) def test_MnStrategy(): assert MnStrategy() == 1 assert MnStrategy(0) == 0 assert MnStrategy(2) == 2 s = MnStrategy() s.strategy = 2 assert s.strategy == 2 assert s != 1 assert not (s != 2) def test_MnUserCovariance(): c = MnUserCovariance((1, 2, 3), 2) assert c.nrow == 2 assert c[(0, 0)] == 1 assert c[(1, 0)] == 2 assert c[(0, 1)] == 2 assert c[(1, 1)] == 3 pkl = pickle.dumps(c) c2 = pickle.loads(pkl) assert c2.nrow == 2 assert c2[(0, 0)] == 1 assert c2[(1, 1)] == 3 assert c2 == c def fn(x, y): return 10 + x**2 + ((y - 1) / 2) ** 2 def fn_grad(x, y): return (2 * x, y - 1) def test_MnUserParameterState(): st = MnUserParameterState() st.add("x", 1, 0.2) st.add("ðŸ˜", 3, 0.3, 1, 4) assert len(st) == 2 assert st[0].number == 0 assert st[0].name == "x" assert st[0].value == 1 assert st[0].error == 0.2 assert st[1].number == 1 assert st[1].name == "ðŸ˜" assert st[1].value == 3 assert st[1].error == 0.3 assert st[1].lower_limit == 1 assert st[1].upper_limit == 4 st2 = MnUserParameterState(st) assert st2 == st st2.set_value(0, 1.1) assert st2 != st def test_MnMigrad(): fcn = FCN(fn, None, False, 1) state = MnUserParameterState() state.add("x", 5, 0.1) state.add("y", 3, 0.2, -5, 5) migrad = MnMigrad(fcn, state, 1) fmin = migrad(0, 0.1) assert fmin.is_valid state = fmin.state assert state[0].value == approx(0, abs=5e-3) assert state[0].error == approx(1, abs=5e-3) assert state[1].value == approx(1, abs=5e-3) assert state[1].error == approx(2, abs=6e-2) assert fcn._nfcn > 0 assert fcn._ngrad == 0 def test_MnMigrad_grad(): fcn = FCN(lambda x: 10 + x**2, lambda x: [2 * x], False, 1) state = MnUserParameterState() state.add("x", 5, 0.1) migrad = MnMigrad(fcn, state, 1) fmin = migrad(0, 0.1) state = fmin.state assert len(state) == 1 assert state[0].number == 0 assert state[0].name == "x" assert state[0].value == approx(0, abs=1e-3) assert state[0].error == approx(1, abs=1e-3) assert fcn._nfcn > 0 assert fcn._ngrad > 0 def test_MnMigrad_cfunc(): nb = pytest.importorskip("numba") c_sig = nb.types.double(nb.types.uintc, nb.types.CPointer(nb.types.double)) y = np.arange(5) @nb.cfunc(c_sig) def fcn(n, x): x = nb.carray(x, (n,)) r = 0.0 for i in range(n): r += (y[i] - x[i]) ** 2 return r fcn = FCN(fcn, None, True, 1) state = MnUserParameterState() for i in range(len(y)): state.add(f"x{i}", 5, 0.1) migrad = MnMigrad(fcn, state, 1) fmin = migrad(0, 0.1) state = fmin.state assert len(state) == len(y) for i, p in enumerate(state): assert p.number == i assert p.value == approx(i, abs=1e-3) assert p.error == approx(1, abs=1e-3) def test_MnMigrad_np(): fcn = FCN( lambda xy: 10 + xy[0] ** 2 + ((xy[1] - 1) / 2) ** 2, lambda xy: [2 * xy[0], (xy[1] - 1)], True, 1, ) state = MnUserParameterState() state.add("x", 5, 0.1) state.add("ðŸ˜", 3, 0.2, -5, 5) assert len(state) == 2 str = MnStrategy(2) migrad = MnMigrad(fcn, state, str) fmin = migrad(0, 0.1) state = fmin.state assert len(state) == 2 assert state[0].number == 0 assert state[0].name == "x" assert state[0].value == approx(0, abs=1e-2) assert state[0].error == approx(1, abs=1e-2) assert state[1].number == 1 assert state[1].name == "ðŸ˜" assert state[1].value == approx(1, abs=1e-2) assert state[1].error == approx(2, abs=6e-2) assert fcn._nfcn > 0 assert fcn._ngrad > 0 def test_MnScan(): fcn = FCN(lambda x: 10 + x**2, None, False, 1) state = MnUserParameterState() state.add("x", 2, 5) scan = MnScan(fcn, state, 1) fmin = scan(0, 0.1) assert fmin.is_valid state = fmin.state assert len(state) == 1 assert state[0].value == approx(0, abs=1e-2) def test_MnSimplex(): fcn = FCN(lambda x: 10 + x**2, None, False, 1) state = MnUserParameterState() state.add("x", 2, 5) simplex = MnSimplex(fcn, state, 1) fmin = simplex(0, 0.1) assert fmin.is_valid state = fmin.state assert len(state) == 1 assert state[0].value == approx(0, abs=5e-2) def test_FunctionMinimum(): fcn = FCN(lambda x: 10 + x**2, None, False, 1) st = MnUserParameterState() st.add("x", 0.01, 5) str = MnStrategy(1) fm1 = FunctionMinimum(fcn, st, str, 0.2) assert fm1.is_valid assert len(fm1.state) == 1 assert fm1.fval == 10.0001 fm2 = FunctionMinimum(fcn, st, str, 0) assert not fm2.is_valid def test_FunctionMinimum_pickle(): st = MnUserParameterState() st.add("x", 1, 0.1) st.add("y", 2, 0.1, 1, 3) fm = FunctionMinimum(FCN(fn, None, False, 1), st, 1, 0.1) pkl = pickle.dumps(fm) fm2 = pickle.loads(pkl) assert len(fm.state) == len(fm2.state) assert fm.state == fm2.state assert fm.edm == fm2.edm assert fm.fval == fm2.fval assert fm.is_valid == fm2.is_valid assert fm.has_accurate_covar == fm2.has_accurate_covar assert fm.has_posdef_covar == fm2.has_posdef_covar assert fm.has_made_posdef_covar == fm2.has_made_posdef_covar assert fm.hesse_failed == fm2.hesse_failed assert fm.has_covariance == fm2.has_covariance assert fm.is_above_max_edm == fm2.is_above_max_edm assert fm.has_reached_call_limit == fm2.has_reached_call_limit assert fm.errordef == fm2.errordef def test_MnUserTransformation_pickle(): tr = MnUserTransformation() pkl = pickle.dumps(tr) tr2 = pickle.loads(pkl) assert len(tr2) == len(tr) def test_MinimumState_pickle(): st = MinimumState(3) pkl = pickle.dumps(st) st2 = pickle.loads(pkl) assert st.vec == st2.vec assert st.fval == st2.fval assert st.edm == st2.edm assert st.nfcn == st2.nfcn assert st.is_valid == st2.is_valid assert st.has_parameters == st2.has_parameters assert st.has_covariance == st2.has_covariance iminuit-2.30.1/tests/test_cost.py0000644000000000000000000016473414332717401013745 0ustar00from __future__ import annotations import pytest import numpy as np from numpy.testing import assert_allclose, assert_equal from iminuit import Minuit from iminuit.cost import ( CostSum, UnbinnedNLL, BinnedNLL, ExtendedUnbinnedNLL, ExtendedBinnedNLL, LeastSquares, Constant, NormalConstraint, Template, multinomial_chi2, PerformanceWarning, ) from iminuit.util import describe from iminuit.typing import Annotated, Gt, Lt from typing import Sequence import pickle def norm_logpdf(x, mu, sigma): z = (x - mu) / sigma return -0.5 * (np.log(2 * np.pi) + z**2) - np.log(sigma) def norm_pdf(x, mu, sigma): return np.exp(norm_logpdf(x, mu, sigma)) def norm_cdf(x, mu, sigma): from math import erf z = (x - mu) / (np.sqrt(2) * sigma) return (1 + np.vectorize(erf)(z)) * 0.5 def mvnorm(mux, muy, sx, sy, rho): stats = pytest.importorskip("scipy.stats") C = np.empty((2, 2)) C[0, 0] = sx**2 C[0, 1] = C[1, 0] = sx * sy * rho C[1, 1] = sy**2 m = [mux, muy] return stats.multivariate_normal(m, C) def expon_cdf(x, a): with np.errstate(over="ignore"): return -np.expm1(-x / a) def scaled_expon_cdf(x, n, a): with np.errstate(over="ignore"): return n * -np.expm1(-x / a) def numerical_cost_gradient(fcn): jacobi = pytest.importorskip("jacobi").jacobi return lambda *args: jacobi(lambda p: fcn(*p), args)[0] def numerical_model_gradient(fcn): jacobi = pytest.importorskip("jacobi").jacobi return lambda x, *args: jacobi(lambda p: fcn(x, *p), args)[0].T def numerical_extended_model_gradient(fcn): jacobi = pytest.importorskip("jacobi").jacobi def fn(x, *args): fint = jacobi(lambda p: fcn(x, *p)[0], args)[0] f = jacobi(lambda p: fcn(x, *p)[1], args)[0].T return fint, f return fn @pytest.fixture def unbinned(): rng = np.random.default_rng(1) x = rng.normal(size=1000) mle = (len(x), np.mean(x), np.std(x, ddof=1)) return mle, x @pytest.fixture def binned(unbinned): mle, x = unbinned nx, xe = np.histogram(x, bins=50, range=(-3, 3)) assert np.sum(nx == 0) > 0 return mle, nx, xe def logpdf(x, mu, sigma): return norm_logpdf(x, mu, sigma) def pdf(x, mu, sigma): return norm_pdf(x, mu, sigma) def pdf_nosig(x, *par): return norm_pdf(x, *par) def annotated_pdf(x, mu, sigma: Annotated[float, 0 : np.inf]): return norm_pdf(x, mu, sigma) def cdf(x, mu, sigma): return norm_cdf(x, mu, sigma) def cdf_nosig(x, *par): return norm_cdf(x, *par) def scaled_cdf(x, n, mu, sigma): return n * norm_cdf(x, mu, sigma) def scaled_cdf_nosig(x, *par): return par[0] * norm_cdf(x, *par[1:]) def line(x, a, b): return a + b * x def line_nosig(x, *par): return par[0] + par[1] * x def test_norm_logpdf(): norm = pytest.importorskip("scipy.stats").norm x = np.linspace(-3, 3) assert_allclose(norm_logpdf(x, 3, 2), norm.logpdf(x, 3, 2)) def test_norm_pdf(): norm = pytest.importorskip("scipy.stats").norm x = np.linspace(-3, 3) assert_allclose(norm_pdf(x, 3, 2), norm.pdf(x, 3, 2)) def test_norm_cdf(): norm = pytest.importorskip("scipy.stats").norm x = np.linspace(-3, 3) assert_allclose(norm_cdf(x, 3, 2), norm.cdf(x, 3, 2)) def test_describe(): c = Constant(2.5) assert describe(c, annotations=True) == {} c = NormalConstraint("foo", 1.5, 0.1) assert describe(c, annotations=True) == {"foo": None} def model( x, foo: Annotated[float, Gt(1), Lt(2)], bar: float, baz: Annotated[float, 0:] ): return x assert describe(model, annotations=True) == { "x": None, "foo": (1, 2), "bar": None, "baz": (0, np.inf), } c = UnbinnedNLL([], model) assert describe(c, annotations=True) == { "foo": (1, 2), "bar": None, "baz": (0, np.inf), } c = BinnedNLL([], [1], model) assert describe(c, annotations=True) == { "foo": (1, 2), "bar": None, "baz": (0, np.inf), } def test_Constant_1(): c = Constant(2.5) assert c.value == 2.5 assert c.ndata == 0 assert c.has_grad assert_equal(c.grad(), []) def test_Constant_2(): c = NormalConstraint(("a", "b"), (1, 2), (3, 4)) + Constant(10.2) assert_allclose(c(1, 2), 10.2) assert_allclose(c(4, 2), 10.2 + 1) def test_Constant_3(): c = NormalConstraint(("a", "b"), (1, 2), (3, 4)) + Constant(10.2) ref = numerical_cost_gradient(c) assert c.has_grad assert_allclose(c.grad(1, 2), ref(1, 2)) assert_allclose(c.grad(2, 3), ref(2, 3)) assert_allclose(c.grad(-1, -2), ref(-1, -2)) @pytest.mark.parametrize("verbose", (0, 1)) @pytest.mark.parametrize("model", (logpdf, pdf)) @pytest.mark.parametrize("use_grad", (False, True)) def test_UnbinnedNLL(unbinned, verbose, model, use_grad): mle, x = unbinned cost = UnbinnedNLL( x, model, verbose=verbose, log=model is logpdf, grad=numerical_model_gradient(model), ) assert cost.ndata == np.inf if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(1, 2), ref(1, 2), rtol=1e-3) assert_allclose(cost.grad(-1, 3), ref(-1, 3), rtol=1e-3) m = Minuit(cost, mu=0, sigma=1, grad=use_grad) m.limits["sigma"] = (0, None) m.migrad() assert m.valid assert_allclose(m.values, mle[1:], atol=1e-3) assert m.errors["mu"] == pytest.approx(1000**-0.5, rel=0.05) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 assert_equal(m.fmin.reduced_chi2, np.nan) if use_grad and verbose == 0: fi = cost.fisher_information(*m.values) cov = cost.covariance(*m.values) assert_allclose(cov, np.linalg.inv(fi)) assert_allclose(np.diag(cov) ** 0.5, m.errors, rtol=5e-2) rho1 = m.covariance.correlation()[0, 1] rho2 = cov[0, 1] / (cov[0, 0] * cov[1, 1]) ** 0.5 assert_allclose(rho1, rho2, atol=0.01) def test_UnbinnedNLL_name(unbinned): mle, x = unbinned cost = UnbinnedNLL(x, pdf_nosig, name=("mu", "sigma")) assert cost.ndata == np.inf m = Minuit(cost, mu=0, sigma=1) assert m.parameters == ("mu", "sigma") m.limits["sigma"] = (0, None) m.migrad() assert m.valid def test_UnbinnedNLL_rename(unbinned): mle, x = unbinned cost = UnbinnedNLL(x, annotated_pdf, name=("m", "s")) m = Minuit(cost, m=0, s=1) assert m.limits["m"] == (-np.inf, np.inf) assert m.limits["s"] == (0, np.inf) assert m.parameters == ("m", "s") m.migrad() assert m.valid def test_UnbinnedNLL_name_bad(): with pytest.raises( ValueError, match="length of name does not match number of model parameters" ): UnbinnedNLL([1, 2, 3], pdf, name=("mu", "sigma", "foo")) @pytest.mark.parametrize("use_grad", (False, True)) def test_UnbinnedNLL_2D(use_grad): def model(x_y, mux, muy, sx, sy, rho): return mvnorm(mux, muy, sx, sy, rho).pdf(x_y.T) truth = 0.1, 0.2, 0.3, 0.4, 0.5 x, y = mvnorm(*truth).rvs(size=100, random_state=1).T cost = UnbinnedNLL((x, y), model, grad=numerical_model_gradient(model)) m = Minuit(cost, *truth, grad=use_grad) m.limits["sx", "sy"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid if use_grad: assert m.ngrad > 0 ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*m.values), ref(*m.values), rtol=0.01) else: assert m.ngrad == 0 assert_allclose(m.values, truth, atol=0.2) @pytest.mark.parametrize("use_grad", (False, True)) def test_UnbinnedNLL_mask(use_grad): c = UnbinnedNLL( [1, np.nan, 2], lambda x, a: x + a**2, grad=lambda x, a: np.ones_like(x) * 2 * a, ) assert c.mask is None assert np.isnan(c(0)) c.mask = np.arange(3) != 1 assert_equal(c.mask, (True, False, True)) assert not np.isnan(c(0)) assert_allclose(c.grad(0), [0]) ref = numerical_cost_gradient(c) assert_allclose(c.grad(1), ref(1), atol=1e-3) @pytest.mark.parametrize("log", (False, True)) def test_UnbinnedNLL_properties(log): c = UnbinnedNLL([1, 2], norm_logpdf if log else norm_pdf, log=log) x = np.linspace(0, 1) expected = norm_pdf(x, 1, 2) assert_allclose(c.pdf(x, 1, 2), expected) expected *= len(c.data) assert_allclose(c.scaled_pdf(x, 1, 2), expected) with pytest.raises(AttributeError): c.pdf = None with pytest.raises(AttributeError): c.scaled_pdf = None assert_equal(c.data, [1, 2]) c.data = [2, 3] assert_equal(c.data, [2, 3]) with pytest.raises(ValueError): c.data = [1, 2, 3] assert c.verbose == 0 c.verbose = 1 assert c.verbose == 1 @pytest.mark.parametrize("log", (False, True)) def test_UnbinnedNLL_visualize(log): pytest.importorskip("matplotlib") c = UnbinnedNLL([1, 2], norm_logpdf if log else norm_pdf, log=log) # auto-sampling c.visualize((1, 2)) # linear spacing c.visualize((1, 2), model_points=10) # linear spacing and different binning c.visualize((1, 2), model_points=10, bins=20) # trigger log-spacing c = UnbinnedNLL([1, 100, 1000], norm_logpdf if log else norm_pdf, log=log) c.visualize((1, 2), model_points=10) c.visualize((1, 2), model_points=10, bins=20) # manual spacing c.visualize((1, 2), model_points=np.linspace(1, 1000)) with pytest.warns(FutureWarning, match="keyword 'nbins' is deprecated"): c.visualize((1, 2), nbins=20) def test_UnbinnedNLL_visualize_2D(): pytest.importorskip("matplotlib") def model(x_y, mux, muy, sx, sy, rho): return mvnorm(mux, muy, sx, sy, rho).pdf(x_y.T) truth = 0.1, 0.2, 0.3, 0.4, 0.5 x, y = mvnorm(*truth).rvs(size=10, random_state=1).T c = UnbinnedNLL((x, y), model) with pytest.raises(ValueError, match="not implemented for multi-dimensional"): c.visualize(truth) def test_UnbinnedNLL_pickle(): c = UnbinnedNLL([1, 2], norm_pdf) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) def test_UnbinnedNLL_annotated(): c = UnbinnedNLL([], annotated_pdf) m = Minuit(c, mu=1, sigma=1.5) assert m.limits[0] == (-np.inf, np.inf) assert m.limits[1] == (0, np.inf) @pytest.mark.parametrize("verbose", (0, 1)) @pytest.mark.parametrize("model", (logpdf, pdf)) @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedUnbinnedNLL(unbinned, verbose, model, use_grad): mle, x = unbinned log = model is logpdf def density(x, n, mu, sigma): if log: return n, np.log(n) + logpdf(x, mu, sigma) return n, n * pdf(x, mu, sigma) cost = ExtendedUnbinnedNLL( x, density, verbose=verbose, log=log, grad=numerical_extended_model_gradient(density), ) assert cost.ndata == np.inf m = Minuit(cost, n=len(x), mu=0, sigma=1, grad=use_grad) m.limits["n"] = (0, None) m.limits["sigma"] = (0, None) m.migrad() assert m.valid assert_allclose(m.values, mle, atol=1e-3) assert m.errors["mu"] == pytest.approx(1000**-0.5, rel=0.05) assert_equal(m.fmin.reduced_chi2, np.nan) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_ExtendedUnbinnedNLL_name(unbinned): mle, x = unbinned cost = ExtendedUnbinnedNLL( x, lambda x, *par: (par[0], pdf(x, *par[1:])), name=("n", "mu", "sigma") ) assert cost.ndata == np.inf m = Minuit(cost, n=len(x), mu=0, sigma=1) assert m.parameters == ("n", "mu", "sigma") m.limits["n"] = (0, None) m.limits["sigma"] = (0, None) m.migrad() assert m.valid @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedUnbinnedNLL_2D(use_grad): def model(x_y, n, mux, muy, sx, sy, rho): return n, n * mvnorm(mux, muy, sx, sy, rho).pdf(x_y.T) truth = 100.0, 0.1, 0.2, 0.3, 0.4, 0.5 x, y = mvnorm(*truth[1:]).rvs(size=int(truth[0]), random_state=1).T cost = ExtendedUnbinnedNLL( (x, y), model, grad=numerical_extended_model_gradient(model) ) m = Minuit(cost, *truth, grad=use_grad) m.limits["n", "sx", "sy"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth, atol=0.5) if use_grad: assert m.ngrad > 0 ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*m.values), ref(*m.values), rtol=0.01) else: assert m.ngrad == 0 def test_ExtendedUnbinnedNLL_mask(): def model(x, a): return 1, x + a c = ExtendedUnbinnedNLL( [1, np.nan, 2], model, grad=numerical_extended_model_gradient(model) ) assert c.ndata == np.inf assert np.isnan(c(0)) c.mask = np.arange(3) != 1 assert not np.isnan(c(0)) assert c.ndata == np.inf ref = numerical_cost_gradient(c) assert_allclose(c.grad(0), ref(0)) assert_allclose(c.grad(1.5), ref(1.5)) @pytest.mark.parametrize("log", (False, True)) def test_ExtendedUnbinnedNLL_properties(log): def log_model(x, s, mu, sigma): return s, np.log(s) + norm_logpdf(x, mu, sigma) def model(x, s, mu, sigma): n, y = log_model(x, s, mu, sigma) return n, np.exp(y) c = ExtendedUnbinnedNLL([1, 2, 3], log_model if log else model, log=log) x = np.linspace(0, 1) scale, expected = model(x, 1, 2, 3) assert_allclose(c.scaled_pdf(x, 1, 2, 3), expected) expected /= scale assert_allclose(c.pdf(x, 1, 2, 3), expected) with pytest.raises(AttributeError): c.scaled_pdf = None with pytest.raises(AttributeError): c.pdf = None @pytest.mark.parametrize("log", (False, True)) def test_ExtendedUnbinnedNLL_visualize(log): pytest.importorskip("matplotlib") def log_model(x, s, mu, sigma): return s, np.log(s) + norm_logpdf(x, mu, sigma) def model(x, s, mu, sigma): return s, s * norm_pdf(x, mu, sigma) c = ExtendedUnbinnedNLL( [1, 2, 3], log_model if log else model, log=log, ) c.visualize((1, 2, 3)) def test_ExtendedUnbinnedNLL_visualize_2D(): pytest.importorskip("matplotlib") def model(x_y, n, mux, muy, sx, sy, rho): return n * 100, n * 100 * mvnorm(mux, muy, sx, sy, rho).pdf(x_y.T) truth = 1.0, 0.1, 0.2, 0.3, 0.4, 0.5 x, y = mvnorm(*truth[1:]).rvs(size=int(truth[0] * 100)).T c = ExtendedUnbinnedNLL((x, y), model) with pytest.raises(ValueError, match="not implemented for multi-dimensional"): c.visualize(truth) def test_ExtendedUnbinnedNLL_pickle(): c = ExtendedUnbinnedNLL([1, 2], norm_pdf) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) @pytest.mark.parametrize("verbose", (0, 1)) @pytest.mark.parametrize("use_grad", (False, True)) def test_BinnedNLL(binned, verbose, use_grad): mle, nx, xe = binned cost = BinnedNLL(nx, xe, cdf, verbose=verbose, grad=numerical_model_gradient(cdf)) assert cost.ndata == len(nx) if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*mle[1:]), ref(*mle[1:])) assert_allclose(cost.grad(-1, 2), ref(-1, 2)) m = Minuit(cost, mu=0, sigma=1, grad=use_grad) m.limits["sigma"] = (0, None) m.migrad() assert m.valid # binning loses information compared to unbinned case assert_allclose(m.values, mle[1:], rtol=0.15) assert m.errors["mu"] == pytest.approx(1000**-0.5, rel=0.05) assert m.ndof == len(nx) - 2 assert_allclose(m.fmin.reduced_chi2, 1, atol=0.15) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_BinnedNLL_pulls(binned): mle, nx, xe = binned cost = BinnedNLL(nx, xe, cdf) m = Minuit(cost, mu=0, sigma=1) m.limits["sigma"] = (0, None) m.migrad() pulls = cost.pulls(m.values) assert np.nanmean(pulls) == pytest.approx(0, abs=0.05) assert np.nanvar(pulls) == pytest.approx(1, abs=0.2) @pytest.mark.parametrize("use_grad", (False, True)) def test_BinnedNLL_weighted(use_grad): xe = np.array([0, 0.2, 0.4, 0.8, 1.5, 10]) p = np.diff(expon_cdf(xe, 1)) n = p * 1000 c = BinnedNLL(n, xe, expon_cdf) assert_equal(c.data, n) m1 = Minuit(c, 1) m1.migrad() assert m1.values[0] == pytest.approx(1, rel=1e-2) # variance * 4 = (sigma * 2)^2, constructed so that # fitted parameter has twice the uncertainty w = np.transpose((n, 4 * n)) c = BinnedNLL(w, xe, expon_cdf, grad=numerical_model_gradient(expon_cdf)) assert_equal(c.data, w) if use_grad: ref = numerical_cost_gradient(c) assert_allclose(c.grad(*m1.values), ref(*m1.values)) assert_allclose(c.grad(12), ref(12)) m2 = Minuit(c, 1, grad=use_grad) m2.migrad() assert m2.valid assert m2.values[0] == pytest.approx(1, rel=1e-2) assert m2.errors[0] == pytest.approx(2 * m1.errors[0], rel=1e-2) if use_grad: assert m2.ngrad > 0 else: assert m2.ngrad == 0 @pytest.mark.parametrize("use_grad", (False, True)) def test_BinnedNLL_negative_weights(use_grad): n = [48.57881659, 7.39393075, -1.6026582, 2.56719152, 1.03007896] vn = [242.13921373, 46.13228182, 15.26273872, 6.26334277, 1.52360132] xe = [0.0, 1.41453733, 2.82907465, 4.24361198, 5.6581493, 7.07268663] w = np.transpose((n, vn)) c = BinnedNLL(w, xe, expon_cdf, grad=numerical_model_gradient(expon_cdf)) if use_grad: ref = numerical_cost_gradient(c) assert_allclose(c.grad(1), ref(1)) assert_allclose(c.grad(12), ref(12)) m2 = Minuit(c, 1, grad=use_grad) m2.limits = (0, None) m2.migrad() assert m2.valid assert m2.values[0] == pytest.approx(1.3, abs=0.05) if use_grad: assert m2.ngrad > 0 else: assert m2.ngrad == 0 def test_BinnedNLL_name(binned): mle, nx, xe = binned cost = BinnedNLL(nx, xe, cdf_nosig, name=("mu", "sigma")) assert cost.ndata == len(nx) m = Minuit(cost, mu=0, sigma=1) m.limits["sigma"] = (0, None) m.migrad() assert m.valid assert m.parameters == ("mu", "sigma") def test_BinnedNLL_bad_input_1(): with pytest.raises(ValueError): BinnedNLL([1], [1], lambda x, a: 0) def test_BinnedNLL_bad_input_2(): with pytest.raises(ValueError): BinnedNLL([[[1]]], [1], lambda x, a: 0) def test_BinnedNLL_bad_input_3(): with pytest.raises(ValueError): BinnedNLL([[1, 2, 3]], [1], lambda x, a: 0) def test_BinnedNLL_bad_input_4(): with pytest.raises(ValueError, match="n must either have same dimension as xe"): BinnedNLL([[1, 2, 3]], [1, 2], lambda x, a: 0) def test_BinnedNLL_bad_input_5(): with pytest.raises(ValueError, match="n must either have same dimension as xe"): BinnedNLL([[1, 2, 3]], [1, 2], lambda x, a: 0) def test_BinnedNLL_bad_input_6(): with pytest.raises( ValueError, match="not supported for multidimensional histograms" ): BinnedNLL([[1]], [[1, 2], [3, 4]], lambda x, a: 0, use_pdf="numerical") def test_BinnedNLL_bad_input_7(): with pytest.raises(ValueError, match="xe must be iterable"): BinnedNLL([0, 1], 0, lambda x, a: 0) def test_BinnedNLL_bad_input_8(): with pytest.raises(ValueError, match="use_pdf and grad cannot be used together"): BinnedNLL( [0, 1], [1, 2, 3], lambda x, a: 0, grad=lambda x, a: [1], use_pdf="numeric" ) def test_BinnedNLL_ndof_zero(): c = BinnedNLL([1], [0, 1], lambda x, scale: expon_cdf(x, scale)) m = Minuit(c, scale=1) m.migrad() assert c.ndata == m.nfit assert np.isnan(m.fmin.reduced_chi2) @pytest.mark.parametrize("use_grad", (False, True)) def test_BinnedNLL_2D(use_grad): truth = (0.1, 0.2, 0.3, 0.4, 0.5) x, y = mvnorm(*truth).rvs(size=1000, random_state=1).T w, xe, ye = np.histogram2d(x, y, bins=(20, 50)) def model(xy, mux, muy, sx, sy, rho): return mvnorm(mux, muy, sx, sy, rho).cdf(xy.T) cost = BinnedNLL(w, (xe, ye), model, grad=numerical_model_gradient(model)) assert cost.ndata == np.prod(w.shape) if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*truth), ref(*truth)) m = Minuit(cost, *truth, grad=use_grad) m.limits["sx", "sy"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth, atol=0.05) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 assert cost.ndata == np.prod(w.shape) w2 = w.copy() w2[1, 1] += 1 cost.n = w2 assert cost(*m.values) > m.fval def test_BinnedNLL_2D_with_zero_bins(): truth = (0.1, 0.2, 0.3, 0.4, 0.5) x, y = mvnorm(*truth).rvs(size=1000, random_state=1).T w, xe, ye = np.histogram2d(x, y, bins=(50, 100), range=((-5, 5), (-5, 5))) assert np.mean(w == 0) > 0.25 def model(xy, mux, muy, sx, sy, rho): return mvnorm(mux, muy, sx, sy, rho).cdf(xy.T) cost = BinnedNLL(w, (xe, ye), model) m = Minuit(cost, *truth) m.limits["sx", "sy"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth, atol=0.05) def test_BinnedNLL_mask(): c = BinnedNLL( [5, 1000, 1], [0, 1, 2, 3], expon_cdf, grad=numerical_model_gradient(expon_cdf) ) assert c.ndata == 3 ref = numerical_cost_gradient(c) assert_allclose(c.grad(2), ref(2)) c_unmasked = c(1) c.mask = np.arange(3) != 1 assert c(1) < c_unmasked assert c.ndata == 2 ref = numerical_cost_gradient(c) assert_allclose(c.grad(2), ref(2)) def test_BinnedNLL_properties(): def cdf(x, a, b): return 0 c = BinnedNLL([1], [1, 2], cdf) assert c.cdf is cdf with pytest.raises(AttributeError): c.cdf = None assert_equal(c.n, [1]) assert_equal(c.xe, [1, 2]) c.n = [2] assert_equal(c.n, [2]) with pytest.raises(ValueError): c.n = [1, 2] def test_BinnedNLL_visualize(): pytest.importorskip("matplotlib") c = BinnedNLL([1, 2], [1, 2, 3], expon_cdf) c.visualize((1,)) c.mask = np.array([False, True]) c.visualize((1,)) def test_BinnedNLL_visualize_2D(): pytest.importorskip("matplotlib") truth = (0.1, 0.2, 0.3, 0.4, 0.5) x, y = mvnorm(*truth).rvs(size=10, random_state=1).T w, xe, ye = np.histogram2d(x, y, bins=(50, 100), range=((-5, 5), (-5, 5))) def model(xy, mux, muy, sx, sy, rho): return mvnorm(mux, muy, sx, sy, rho).cdf(xy.T) c = BinnedNLL(w, (xe, ye), model) c.visualize(truth) def test_BinnedNLL_pickle(): c = BinnedNLL([1], [1, 2], expon_cdf) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) @pytest.mark.parametrize("use_pdf", ["approximate", "numerical"]) def test_BinnedNLL_with_pdf(use_pdf): if use_pdf == "numerical": pytest.importorskip("scipy") xe = np.array([0, 0.1, 0.2, 0.3]) n = [1, 2, 3] c = BinnedNLL(n, xe, norm_pdf, use_pdf=use_pdf) par = [0.05, 1] ref = np.diff(norm_cdf(xe, *par)) * np.sum(n) assert_allclose(c.prediction(par), ref, rtol=1e-3) def test_BinnedNLL_use_pdf_bad_value(): with pytest.raises(ValueError): BinnedNLL([1, 2], [1, 2, 3], norm_pdf, use_pdf="foo") @pytest.mark.parametrize("use_pdf", ["approximate", "numerical"]) def test_BinnedNLL_with_pdf_3D(use_pdf): xe = (np.array([0, 0.1]), np.array([0.1, 0.3, 0.4]), np.array([0, 0.1, 0.2, 0.3])) n = [[[1, 2, 3], [3, 4, 5]]] def pdf(r, mx, my, mz, sx, sy, sz): x, y, z = r return norm_pdf(x, mx, sx) * norm_pdf(y, my, sy) * norm_pdf(z, mz, sz) def cdf(r, mx, my, mz, sx, sy, sz): x, y, z = r return norm_cdf(x, mx, sx) * norm_cdf(y, my, sy) * norm_cdf(z, mz, sz) if use_pdf == "numerical": with pytest.raises( ValueError, match=( 'use_pdf="numerical" is not supported ' "for multidimensional histograms" ), ): BinnedNLL(n, xe, pdf, use_pdf=use_pdf) else: c1 = BinnedNLL(n, xe, pdf, use_pdf=use_pdf) c2 = BinnedNLL(n, xe, cdf) par = [0, 1, 2, 3, 4, 5] assert_allclose(c1.prediction(par), c2.prediction(par), rtol=1e-3) @pytest.mark.parametrize("verbose", (0, 1)) @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedBinnedNLL(binned, verbose, use_grad): mle, nx, xe = binned cost = ExtendedBinnedNLL( nx, xe, scaled_cdf, verbose=verbose, grad=numerical_model_gradient(scaled_cdf) ) assert cost.ndata == len(nx) if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*mle), ref(*mle)) m = Minuit(cost, n=mle[0], mu=0, sigma=1, grad=use_grad) m.limits["n"] = (0, None) m.limits["sigma"] = (0, None) m.migrad() assert m.valid # binning loses information compared to unbinned case assert_allclose(m.values, mle, rtol=0.15) assert m.errors["mu"] == pytest.approx(1000**-0.5, rel=0.05) assert m.ndof == len(nx) - 3 assert_allclose(m.fmin.reduced_chi2, 1, 0.1) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_ExtendedBinnedNLL_name(binned): mle, nx, xe = binned cost = ExtendedBinnedNLL(nx, xe, scaled_cdf_nosig, name=("n", "mu", "sigma")) assert cost.ndata == len(nx) m = Minuit(cost, n=mle[0], mu=0, sigma=1) m.limits["sigma"] = (0, None) m.migrad() assert m.valid assert m.parameters == ("n", "mu", "sigma") @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedBinnedNLL_weighted(use_grad): xe = np.array([0, 1, 10]) n = np.diff(expon_cdf(xe, 1)) m1 = Minuit(ExtendedBinnedNLL(n, xe, expon_cdf), 1) m1.migrad() assert_allclose(m1.values, (1,), rtol=1e-2) w = np.transpose((n, 4 * n)) c = ExtendedBinnedNLL(w, xe, expon_cdf, grad=numerical_model_gradient(expon_cdf)) if use_grad: ref = numerical_cost_gradient(c) assert_allclose(c.grad(1), ref(1), atol=1e-14) assert_allclose(c.grad(12), ref(12)) m2 = Minuit(c, 1.1, grad=use_grad) m2.migrad() assert m2.valid assert_allclose(m2.values, (1,), rtol=1e-2) assert m2.errors[0] == pytest.approx(2 * m1.errors[0], rel=1e-2) if use_grad: assert m2.ngrad > 0 else: assert m2.ngrad == 0 @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedBinnedNLL_negative_weights(use_grad): n = [48.57881659, 7.39393075, -1.6026582, 2.56719152, 1.03007896] vn = [242.13921373, 46.13228182, 15.26273872, 6.26334277, 1.52360132] xe = [0.0, 1.41453733, 2.82907465, 4.24361198, 5.6581493, 7.07268663] w = np.transpose((n, vn)) c = ExtendedBinnedNLL( w, xe, scaled_expon_cdf, grad=numerical_model_gradient(scaled_expon_cdf) ) # if use_grad: # ref = numerical_cost_gradient(c) # assert_allclose(c.grad(1, 0.1), ref(1, 0.1)) # assert_allclose(c.grad(1, 1), ref(1, 1)) # assert_allclose(c.grad(2, 12), ref(2, 12)) m2 = Minuit(c, 50, 1, grad=use_grad) m2.limits = (0, None) m2.migrad() assert m2.valid assert m2.values[0] == pytest.approx(65, abs=1) assert m2.values[1] == pytest.approx(1.3, abs=0.05) if use_grad: assert m2.ngrad > 0 else: assert m2.ngrad == 0 def test_ExtendedBinnedNLL_bad_input(): with pytest.raises(ValueError): ExtendedBinnedNLL([1], [1], lambda x, a: 0) @pytest.mark.parametrize("use_grad", (False, True)) def test_ExtendedBinnedNLL_2D(use_grad): truth = (1.0, 0.1, 0.2, 0.3, 0.4, 0.5) x, y = mvnorm(*truth[1:]).rvs(size=int(truth[0] * 100), random_state=1).T w, xe, ye = np.histogram2d(x, y, bins=(10, 20)) def model(xy, n, mux, muy, sx, sy, rho): return n * 100 * mvnorm(mux, muy, sx, sy, rho).cdf(np.transpose(xy)) cost = ExtendedBinnedNLL(w, (xe, ye), model, grad=numerical_model_gradient(model)) assert cost.ndata == np.prod(w.shape) if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(*truth), ref(*truth)) m = Minuit(cost, *truth, grad=use_grad) m.limits["n", "sx", "sy"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth, atol=0.1) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_ExtendedBinnedNLL_3D(): norm = pytest.importorskip("scipy.stats").norm truth = (1.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7) n = int(truth[0] * 10000) x, y = mvnorm(*truth[1:-2]).rvs(size=n).T z = norm(truth[-2], truth[-1]).rvs(size=n) w, edges = np.histogramdd((x, y, z), bins=(5, 10, 20)) def model(xyz, n, mux, muy, sx, sy, rho, muz, sz): *xy, z = xyz return ( n * 10000 * mvnorm(mux, muy, sx, sy, rho).cdf(np.transpose(xy)) * norm(muz, sz).cdf(z) ) cost = ExtendedBinnedNLL(w, edges, model) assert cost.ndata == np.prod(w.shape) m = Minuit(cost, *truth) m.limits["n", "sx", "sy", "sz"] = (0, None) m.limits["rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth, atol=0.05) def test_ExtendedBinnedNLL_mask(): c = ExtendedBinnedNLL( [1, 1000, 2], [0, 1, 2, 3], expon_cdf, grad=numerical_model_gradient(expon_cdf) ) assert c.ndata == 3 c_unmasked = c(2) c.mask = np.arange(3) != 1 assert c(2) < c_unmasked assert c.ndata == 2 ref = numerical_cost_gradient(c) assert_allclose(c.grad(2), ref(2)) def test_ExtendedBinnedNLL_properties(): def cdf(x, a): return 0 c = ExtendedBinnedNLL([1], [1, 2], cdf) assert c.scaled_cdf is cdf def test_ExtendedBinnedNLL_visualize(): pytest.importorskip("matplotlib") def model(x, s, slope): return s * expon_cdf(x, slope) c = ExtendedBinnedNLL([1], [1, 2], model) c.visualize((1, 2)) def test_ExtendedBinnedNLL_visualize_2D(): pytest.importorskip("matplotlib") truth = (1.0, 0.1, 0.2, 0.3, 0.4, 0.5) x, y = mvnorm(*truth[1:]).rvs(size=int(truth[0] * 1000), random_state=1).T w, xe, ye = np.histogram2d(x, y, bins=(10, 20)) def model(xy, n, mux, muy, sx, sy, rho): return n * 1000 * mvnorm(mux, muy, sx, sy, rho).cdf(np.transpose(xy)) c = ExtendedBinnedNLL(w, (xe, ye), model) c.visualize(truth) def test_ExtendedBinnedNLL_pickle(): c = BinnedNLL([1], [1, 2], expon_cdf) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) def test_ExtendedBinnedNLL_weighted_pulls(): rng = np.random.default_rng(1) xe = np.linspace(0, 5, 500) p = np.diff(expon_cdf(xe, 2)) m = p * 100000 n = rng.poisson(m * 4) / 4 nvar = m * 4 / 4**2 w = np.transpose((n, nvar)) c = ExtendedBinnedNLL(w, xe, lambda x, n, s: n * expon_cdf(x, s)) m = Minuit(c, np.sum(n), 2) m.limits["n"] = (0.1, None) m.limits["s"] = (0.1, None) m.migrad() assert m.valid pulls = c.pulls(m.values) assert np.nanmean(pulls) == pytest.approx(0, abs=0.1) assert np.nanvar(pulls) == pytest.approx(1, abs=0.2) @pytest.mark.parametrize( "loss,use_grad", [ ("linear", False), ("linear", True), ("soft_l1", False), ("soft_l1", True), (np.arctan, False), ], ) @pytest.mark.parametrize("verbose", (0, 1)) def test_LeastSquares(loss, verbose, use_grad): rng = np.random.default_rng(1) x = np.linspace(0, 1, 1000) ye = 0.1 y = rng.normal(2 * x + 1, ye) cost = LeastSquares( x, y, ye, line, loss=loss, verbose=verbose, grad=numerical_model_gradient(line), ) assert cost.ndata == len(x) if use_grad: ref = numerical_cost_gradient(cost) assert_allclose(cost.grad(1, 2), ref(1, 2)) m = Minuit(cost, a=0, b=0, grad=use_grad) m.migrad() assert_allclose(m.values, (1, 2), rtol=0.05) assert cost.loss == loss if loss != "linear": cost.loss = "linear" assert cost.loss != loss m.migrad() assert_allclose(m.values, (1, 2), rtol=0.05) assert m.ndof == len(x) - 2 assert_allclose(m.fmin.reduced_chi2, 1, atol=5e-2) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_LeastSquares_name(): rng = np.random.default_rng(1) x = np.linspace(0, 1, 1000) ye = 0.1 y = rng.normal(2 * x + 1, ye) cost = LeastSquares(x, y, ye, line_nosig, name=("a", "b")) assert cost.ndata == len(x) m = Minuit(cost, a=0, b=0) assert m.parameters == ("a", "b") m.migrad() assert_allclose(m.values, (1, 2), rtol=0.05) def test_LeastSquares_2D(): def model(xy, a, b): x, y = xy return a * x + b * y x = np.array([1.0, 2.0, 3.0]) y = np.array([4.0, 5.0, 6.0]) f = model((x, y), 1.5, 0.2) fe = 1.5 c = LeastSquares((x, y), f, fe, model, grad=numerical_model_gradient(model)) assert c.ndata == 3 ref = numerical_cost_gradient(c) assert_allclose(c.grad(1, 2), ref(1, 2)) assert_equal(c.x, (x, y)) assert_equal(c.y, f) assert_equal(c.yerror, fe) assert_allclose(c(1.5, 0.2), 0.0) assert_allclose(c(2.5, 0.2), np.sum(((f - 2.5 * x - 0.2 * y) / fe) ** 2)) assert_allclose(c(1.5, 1.2), np.sum(((f - 1.5 * x - 1.2 * y) / fe) ** 2)) c.y = 2 * f assert_equal(c.y, 2 * f) c.x = (y, x) assert_equal(c.x, (y, x)) def test_LeastSquares_3D(): def model(xyz, a, b): x, y, z = xyz return a * x + b * y + a * b * z x = np.array([1.0, 2.0, 3.0, 4.0]) y = np.array([4.0, 5.0, 6.0, 7.0]) z = np.array([7.0, 8.0, 9.0, 10.0]) f = model((x, y, z), 1.5, 0.2) fe = 1.5 c = LeastSquares((x, y, z), f, fe, model, grad=numerical_model_gradient(model)) assert c.ndata == 4 ref = numerical_cost_gradient(c) assert_allclose(c.grad(1, 2), ref(1, 2)) assert_equal(c.x, (x, y, z)) assert_equal(c.y, f) assert_equal(c.yerror, fe) assert_allclose(c(1.5, 0.2), 0.0) assert_allclose( c(2.5, 0.2), np.sum(((f - 2.5 * x - 0.2 * y - 2.5 * 0.2 * z) / fe) ** 2) ) assert_allclose( c(1.5, 1.2), np.sum(((f - 1.5 * x - 1.2 * y - 1.5 * 1.2 * z) / fe) ** 2) ) c.y = 2 * z assert_equal(c.y, 2 * z) c.x = (y, x, z) assert_equal(c.x, (y, x, z)) def test_LeastSquares_bad_input(): with pytest.raises(ValueError, match="shape mismatch"): LeastSquares([1, 2], [], [1], lambda x, a: 0) with pytest.raises(ValueError, match="shape mismatch"): LeastSquares([1, 2], [3, 4, 5], [1], lambda x, a: 0) with pytest.raises(ValueError, match="unknown loss"): LeastSquares([1], [1], [1], lambda x, a: 0, loss="foo") with pytest.raises(ValueError, match="loss must be str or LossFunction"): LeastSquares([1], [1], [1], lambda x, a: 0, loss=[1, 2, 3]) @pytest.mark.parametrize("use_grad", (False, True)) def test_LeastSquares_mask(use_grad): c = LeastSquares( [1, 2, 3], [3, np.nan, 4], [1, 1, 1], lambda x, a: x + a, grad=lambda x, a: np.ones_like(x), ) assert c.ndata == 3 assert np.isnan(c(0)) assert np.all(np.isnan(c.grad(1))) m = Minuit(c, 1, grad=use_grad) assert m.ndof == 2 m.migrad() assert not m.valid c.mask = np.arange(3) != 1 assert c.ndata == 2 assert not np.isnan(c(0)) assert not np.any(np.isnan(c.grad(0))) assert m.ndof == 1 m.migrad() assert m.valid assert_equal(m.values, [1.5]) def test_LeastSquares_mask_2(): c = LeastSquares([1, 2], [1, 5], 1, lambda x, a: a * x) assert c(2) == pytest.approx(2) c.mask = [False, True] assert c(2) == pytest.approx(1) c.x = [2, 2] c.y = [4, 4] c.yerror = [2, 2] assert c(2) == pytest.approx(0) assert c(1) == pytest.approx(1) def test_LeastSquares_properties(): def model(x, a): return x + 2 * a c = LeastSquares(1, 2, 3, model) assert_equal(c.x, [1]) assert_equal(c.y, [2]) assert_equal(c.yerror, [3]) assert c.model(1, 1) == model(1, 1) assert c.model(2, 3) == model(2, 3) with pytest.raises(AttributeError): c.model = model with pytest.raises(ValueError): c.x = [1, 2] with pytest.raises(ValueError): c.y = [1, 2] with pytest.raises(ValueError): c.yerror = [1, 2] def test_LeastSquares_visualize(): pytest.importorskip("matplotlib") c = LeastSquares([1, 2], [2, 3], 0.1, line) # auto-sampling (x, y, ye), (xm, ym) = c.visualize((1, 2)) assert_equal(x, (1, 2)) assert_equal(y, (2, 3)) assert_equal(ye, 0.1) assert len(xm) == 39 # linear spacing (x, y, ye), (xm, ym) = c.visualize((1, 2), model_points=10) assert len(xm) == 10 assert_allclose(xm[1:] - xm[:-1], xm[1] - xm[0]) # trigger use of log-spacing c = LeastSquares([1, 10, 100], [2, 3, 4], 0.1, line) (x, y, ye), (xm, ym) = c.visualize((1, 2), model_points=10) assert len(xm) == 10 assert_allclose(xm[1:] / xm[:-1], xm[1] / xm[0]) # manual spacing (x, y, ye), (xm, ym) = c.visualize((1, 2), model_points=np.linspace(1, 100)) assert_equal(xm, np.linspace(1, 100)) def test_LeastSquares_visualize_par_array(): pytest.importorskip("matplotlib") def line(x, par): return par[0] + par[1] * x c = LeastSquares([1, 2], [2, 3], 0.1, line) c.visualize((1, 2)) def test_LeastSquares_visualize_2D(): pytest.importorskip("matplotlib") c = LeastSquares([[1, 2], [2, 3]], [1, 2], 0.1, line) with pytest.raises(ValueError, match="not implemented for multi-dimensional"): c.visualize((1, 2)) def test_LeastSquares_pickle(): c = LeastSquares([1, 2], [2, 3], 0.1, line) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) assert c.model is c2.model def test_LeastSquares_pulls(): c = LeastSquares([1, 2], [2, 3], 0.1, line) # pulls are zero for parameters 1, 1 assert_equal(c.pulls((1, 1)), [0, 0]) # correct slope but line offset by 1 with error 0.1 produces pulls [10, 10] assert_equal(c.pulls((0, 1)), [10, 10]) c.mask = [True, False] assert_equal(c.pulls((0, 1)), [10, np.nan]) @pytest.mark.parametrize("use_grad", (False, True)) def test_CostSum_1(use_grad): def model1(x, a): return a + x def grad1(x, a): return np.ones((1, len(x))) def model2(x, b, a): return a + b * x def grad2(x, b, a): g = np.empty((2, len(x))) g[0] = x g[1] = 1 return g def model3(x, c): return c * np.ones_like(x) def grad3(x, c): return np.ones((1, len(x))) lsq1 = LeastSquares(1, 2, 3, model1, grad=grad1) assert describe(lsq1) == ["a"] if use_grad: assert_allclose(lsq1.grad(2), numerical_cost_gradient(lsq1)(2)) lsq2 = LeastSquares(1, 3, 4, model2, grad=grad2) assert describe(lsq2) == ["b", "a"] if use_grad: assert_allclose(lsq2.grad(2, 3), numerical_cost_gradient(lsq2)(2, 3)) lsq3 = LeastSquares(1, 1, 1, model3, grad=grad3) assert describe(lsq3) == ["c"] if use_grad: assert_allclose(lsq3.grad(4), numerical_cost_gradient(lsq3)(4)) lsq12 = lsq1 + lsq2 assert lsq12._items == [lsq1, lsq2] assert isinstance(lsq12, CostSum) assert isinstance(lsq1, LeastSquares) assert isinstance(lsq2, LeastSquares) assert describe(lsq12) == ["a", "b"] assert lsq12.ndata == 2 assert lsq12(1, 2) == lsq1(1) + lsq2(2, 1) if use_grad: a = 2 b = 3 ref = np.zeros(2) ref[0] += lsq1.grad(a)[0] ref[[1, 0]] += lsq2.grad(b, a) assert_allclose(lsq12.grad(a, b), ref) lsq121 = lsq12 + lsq1 assert lsq121._items == [lsq1, lsq2, lsq1] assert describe(lsq121) == ["a", "b"] assert lsq121.ndata == 3 if use_grad: a = 2 b = 3 ref = np.zeros(2) ref[0] += lsq1.grad(a)[0] ref[[1, 0]] += lsq2.grad(b, a) ref[0] += lsq1.grad(a)[0] assert_allclose(lsq121.grad(a, b), ref) lsq312 = lsq3 + lsq12 assert lsq312._items == [lsq3, lsq1, lsq2] assert describe(lsq312) == ["c", "a", "b"] assert lsq312.ndata == 3 if use_grad: a = 2 b = 3 c = 4 ref = np.zeros(3) ref[0] += lsq3.grad(c)[0] ref[1] += lsq1.grad(a)[0] ref[[2, 1]] += lsq2.grad(b, a) assert_allclose(lsq312.grad(c, a, b), ref) lsq31212 = lsq312 + lsq12 assert lsq31212._items == [lsq3, lsq1, lsq2, lsq1, lsq2] assert describe(lsq31212) == ["c", "a", "b"] assert lsq31212.ndata == 5 if use_grad: a = 2 b = 3 c = 4 ref = np.zeros(3) ref[:] += lsq312.grad(c, a, b) ref[1:] += lsq12.grad(a, b) assert_allclose(lsq31212.grad(c, a, b), ref) lsq31212 += lsq1 assert lsq31212._items == [lsq3, lsq1, lsq2, lsq1, lsq2, lsq1] assert describe(lsq31212) == ["c", "a", "b"] assert lsq31212.ndata == 6 m = Minuit(lsq12, a=0, b=0, grad=use_grad) m.migrad() assert m.parameters == ("a", "b") assert_allclose(m.values, (1, 2)) assert_allclose(m.errors, (3, 5)) assert_allclose(m.covariance, ((9, -9), (-9, 25)), atol=1e-10) if use_grad: assert m.ngrad > 0 else: assert m.ngrad == 0 def test_CostSum_2(): ref = NormalConstraint("a", 1, 2), NormalConstraint(("b", "a"), (1, 1), (2, 2)) cs = ref[0] + ref[1] assert cs.ndata == 3 assert isinstance(cs, Sequence) assert len(cs) == 2 assert cs[0] is ref[0] assert cs[1] is ref[1] for c, r in zip(cs, ref): assert c is r assert cs.index(ref[0]) == 0 assert cs.index(ref[1]) == 1 assert cs.count(ref[0]) == 1 def test_CostSum_3(): def line_np(x, par): return par[0] + par[1] * x lsq = LeastSquares([1, 2, 3], [3, 4, 5], 1, line_np) con = NormalConstraint("par", (1, 1), (1, 1)) cs = sum([lsq, con]) assert cs((1, 1)) == lsq((1, 1)) + con((1, 1)) cs = 1.5 + lsq + con assert cs((1, 1)) == lsq((1, 1)) + con((1, 1)) + 1.5 def test_CostSum_4(): pytest.importorskip("scipy.special") t = Template([1, 2], [1, 2, 3], [[1, 1], [0, 1]], method="asy") assert t.errordef == Minuit.LIKELIHOOD m1 = Minuit(t, 1, 1) m1.migrad() cs = CostSum(t) assert cs.errordef == Minuit.LEAST_SQUARES m2 = Minuit(cs, 1, 1) m2.migrad() assert_allclose(m1.errors, m2.errors) def test_CostSum_visualize(): pytest.importorskip("matplotlib") lsq = LeastSquares([1, 2, 3], [3, 4, 5], 1, line) con = NormalConstraint(("a", "b"), (1, 1), (1, 1)) c = lsq + con + 1 c.visualize((1, 2)) def test_NormalConstraint_1(): c1 = NormalConstraint("a", 1, 1.5) c2 = NormalConstraint(("a", "b"), (1, 2), (3, 4)) c3 = NormalConstraint(("a", "b"), (1, 2), ((1, 0.5), (0.5, 4))) assert describe(c1) == ["a"] assert describe(c2) == ["a", "b"] assert describe(c3) == ["a", "b"] assert c1.ndata == 1 assert c2.ndata == 2 assert c3.ndata == 2 assert c1.has_grad assert c2.has_grad assert c3.has_grad assert c1.value == 1 assert_equal(c1.covariance, [1.5**2]) assert_equal(c2.value, (1, 2)) assert_equal(c2.covariance, (9, 16)) assert_equal(c3.value, (1, 2)) assert_equal(c3.covariance, ((1, 0.5), (0.5, 4))) assert_allclose(c1(1), 0) assert_allclose(c1(1 + 1.5), 1) assert_allclose(c1(1 - 1.5), 1) assert_allclose(c2(1, 2), 0) assert_allclose(c2(1 + 3, 2), 1) assert_allclose(c2(1 - 3, 2), 1) assert_allclose(c2(1, 2 + 4), 1) assert_allclose(c2(1, 2 - 4), 1) def ref(x, y): d = np.subtract((x, y), (1, 2)) c = ((1, 0.5), (0.5, 4)) cinv = np.linalg.inv(c) return d.T @ cinv @ d assert_allclose(c3(1, 2), 0) assert_allclose(c3(2, 2), ref(2, 2)) assert_allclose(c3(3, 4), ref(3, 4)) assert_allclose(c3(-1, -2), ref(-1, -2)) ref = numerical_cost_gradient(c1) assert_allclose(c1.grad(1), [0]) assert_allclose(c1.grad(2), ref(2)) assert_allclose(c1.grad(-2), ref(-2)) ref = numerical_cost_gradient(c2) assert_allclose(c2.grad(1, 2), [0, 0]) assert_allclose(c2.grad(2, 3), ref(2, 3)) assert_allclose(c2.grad(-2, -4), ref(-2, -4)) ref = numerical_cost_gradient(c3) assert_allclose(c3.grad(1, 2), [0, 0]) assert_allclose(c3.grad(2, 3), ref(2, 3)) assert_allclose(c3.grad(-2, -4), ref(-2, -4)) c1.value = 2 c1.covariance = 4 assert_equal(c1.value, 2) assert_equal(c1.covariance, 4) assert_allclose(c1(2), 0) assert_allclose(c1(4), 1) assert_allclose(c1(0), 1) c2.value = (2, 3) c2.covariance = (1, 4) assert_equal(c2.value, (2, 3)) assert_equal(c2.covariance, (1, 4)) assert_allclose(c2(2, 3), 0) assert_allclose(c2(1, 3), 1) assert_allclose(c2(2, 5), 1) c3.value = (2, 3) c3.covariance = [(4, 1), (1, 5)] assert_equal(c3.value, (2, 3)) assert_equal(c3.covariance, [(4, 1), (1, 5)]) def ref(x, y): d = np.subtract((x, y), (2, 3)) c = ((4, 1), (1, 5)) cinv = np.linalg.inv(c) return d.T @ cinv @ d assert_allclose(c3(2, 3), 0) assert_allclose(c3(1, 3), ref(1, 3)) assert_allclose(c3(2, 5), ref(2, 5)) @pytest.mark.parametrize("use_grad", (False, True)) def test_NormalConstraint_2(use_grad): c1 = NormalConstraint("a", 1, 1) c2 = c1 + NormalConstraint("a", 1, 0.1) m = Minuit(c1, 0, grad=use_grad) m.migrad() if use_grad: assert m.ngrad > 0 assert_allclose(m.values, (1,), atol=1e-2) assert_allclose(m.errors, (1,), rtol=1e-2) m = Minuit(c2, 0, grad=use_grad) m.migrad() if use_grad: assert m.ngrad > 0 assert_allclose(m.values, (1,), atol=1e-2) assert_allclose(m.errors, (0.1,), rtol=1e-2) def test_NormalConstraint_3(): lsq1 = NormalConstraint(("a", "b"), (1, 2), (2, 2)) lsq2 = lsq1 + NormalConstraint("b", 2, 0.1) + NormalConstraint("a", 1, 0.01) sa = 0.1 sb = 0.02 rho = 0.5 cov = ((sa**2, rho * sa * sb), (rho * sa * sb, sb**2)) lsq3 = lsq1 + NormalConstraint(("a", "b"), (1, 2), cov) assert describe(lsq1) == ["a", "b"] assert describe(lsq2) == ["a", "b"] assert describe(lsq3) == ["a", "b"] assert lsq1.ndata == 2 assert lsq2.ndata == 4 m = Minuit(lsq1, 0, 0) m.migrad() assert_allclose(m.values, (1, 2), atol=1e-3) assert_allclose(m.errors, (2, 2), rtol=1e-3) m = Minuit(lsq2, 0, 0) m.migrad() assert_allclose(m.values, (1, 2), atol=1e-3) assert_allclose(m.errors, (0.01, 0.1), rtol=1e-2) m = Minuit(lsq3, 0, 0) m.migrad() assert_allclose(m.values, (1, 2), atol=1e-3) assert_allclose(m.errors, (sa, sb), rtol=1e-2) assert_allclose(m.covariance, cov, rtol=1e-2) def test_NormalConstraint_visualize(): pytest.importorskip("matplotlib") c = NormalConstraint(("a", "b"), (1, 2), (3, 4)) c.visualize((1, 2)) c = NormalConstraint(("a", "b"), (1, 2), np.eye(2)) c.visualize((1, 2)) def test_NormalConstraint_pickle(): c = NormalConstraint(("a", "b"), (1, 2), (3, 4)) b = pickle.dumps(c) c2 = pickle.loads(b) assert describe(c) == describe(c2) and describe(c) == ["a", "b"] assert_equal(c.value, c2.value) assert_equal(c.covariance, c2.covariance) def test_NormalConstraint_bad_input_1(): with pytest.raises(ValueError, match="scalar or one-dimensional"): NormalConstraint("par", [[[1, 2]]], np.eye(2)) def test_NormalConstraint_bad_input_2(): with pytest.raises(ValueError, match="not match size of args"): NormalConstraint(["a", "b", "c"], [1, 2], np.eye(2)) def test_NormalConstraint_bad_input_3(): with pytest.raises(ValueError, match="size of error does not match size of value"): NormalConstraint(["a", "b"], [1, 2], np.eye(3)) def test_NormalConstraint_bad_input_4(): with pytest.raises(ValueError, match="positive definite"): NormalConstraint(["a", "b"], [1, 2], [[1, 1], [1, 1]]) def test_NormalConstraint_bad_input_5(): n = NormalConstraint(["a", "b"], [1, 2], [[1, 0], [0, 1]]) with pytest.raises(ValueError, match="positive definite"): n.covariance = [[1, 1], [1, 1]] def test_NormalConstraint_bad_input_6(): with pytest.raises(ValueError, match="cannot have more than two dimensions"): NormalConstraint(["a", "b"], [1, 2], np.ones((2, 2, 2))) dtypes_to_test = [np.float32] if hasattr(np, "float128"): # not available on all platforms dtypes_to_test.append(np.float128) def test_multinomial_chi2(): zero = np.array(0) one = np.array(1) assert multinomial_chi2(zero, zero) == 0 assert multinomial_chi2(zero, one) == 0 assert multinomial_chi2(one, zero) == 0 n = np.array([(0.0, 0.0)]) assert_allclose(multinomial_chi2(n, zero), 0) assert_allclose(multinomial_chi2(n, one), 0) @pytest.mark.skipif( not hasattr(np, "float128"), reason="float128 not available on all platforms" ) def test_model_float128(): def model(x, a): x = x.astype(np.float128) return a + x for cost in ( UnbinnedNLL([1], model), ExtendedUnbinnedNLL([1], lambda x, a: (1, model(x, a))), BinnedNLL([1], [1, 2], model), BinnedNLL([[1, 1]], [1, 2], model), ExtendedBinnedNLL([1], [1, 2], model), ExtendedBinnedNLL([[1, 1]], [1, 2], model), LeastSquares([1.0], [2.0], [3.0], model), LeastSquares([1.0], [2.0], [3.0], model, loss="soft_l1"), ): assert cost(1).dtype == np.float128 Minuit(cost, a=0).migrad() # should not raise def test_model_performance_warning(): def model(x, a): return [0 for xi in x] with pytest.warns(PerformanceWarning): BinnedNLL([1], [1.0, 2.0], model)(1) with pytest.warns(PerformanceWarning): ExtendedBinnedNLL([1], [1.0, 2.0], model)(1) with pytest.warns(PerformanceWarning): UnbinnedNLL([1], model)(1) with pytest.warns(PerformanceWarning): ExtendedUnbinnedNLL([1], lambda x, a: (1, model(x, a)))(1) @pytest.mark.parametrize("cls", (BinnedNLL, ExtendedBinnedNLL)) def test_update_data_with_mask(cls): xe = np.arange(0, 4) nx = np.diff(expon_cdf(xe, 1)) nx[0] += 1 c = cls(nx.copy(), xe, expon_cdf) c.mask = [False, True, True] assert c(1) == 0 nx[0] += 1 c.n = nx assert c(1) == 0 nx[1] += 1 c.n = nx assert c(1) != 0 nx[0] -= 2 c.mask = (True, False, True) c.n = nx assert c(1) == 0 @pytest.mark.parametrize("method", ("jsc", "asy", "da")) def test_Template(method): if method == "asy": pytest.importorskip("scipy.special") xe = np.array([0, 1, 2, 3]) t = np.array([[1, 1, 0], [0, 1, 3]]) n = t[0] + t[1] c = Template(n, xe, t, method=method) m = Minuit(c, 1, 1) assert m.limits[0] == (0, np.inf) assert m.limits[1] == (0, np.inf) m.migrad() assert m.valid assert m.ndof == 1 if method == "asy": assert c.errordef == 0.5 assert_equal(m.fmin.reduced_chi2, np.nan) # asy produces values far away from truth in this case assert_allclose(m.values, [1, 3], atol=0.2) else: assert c.errordef == 1.0 assert_allclose(m.fval, 0, atol=1e-4) assert_allclose(m.fmin.reduced_chi2, 0, atol=1e-5) assert_allclose(m.values, [2, 4], atol=1e-2) @pytest.mark.parametrize( "template", ( (np.array([1.0, 1.0, 0.0]), np.array([0.0, 1.0, 3.0])), ( np.array([[1.0, 1.0], [1.0, 1.0], [0.0, 0.0]]), np.array([[0.0, 0.0], [1.0, 1.0], [3.0, 3.0]]), ), ), ) def test_Template_does_not_modify_inputs(template): from copy import deepcopy xe = np.array([0, 1, 2, 3]) template_copy = deepcopy(template) n = template[0] + template[1] Template(n, xe, template, method="da") assert_equal(template, template_copy) def generate(rng, nmc, truth, bins, tf=1, df=1): stats = pytest.importorskip("scipy.stats") xe = np.linspace(0, 2, bins + 1) b = np.diff(stats.truncexpon(1, 0, 2).cdf(xe)) s = np.diff(stats.norm(1, 0.1).cdf(xe)) n = b * truth[0] + s * truth[1] t = b * nmc, s * nmc if rng is not None: n = rng.poisson(n / df) * df if df != 1: n = np.transpose((n, n * df)) t = [rng.poisson(ti / tf) * tf for ti in t] if tf != 1: t = [np.transpose((tj, tj * tf)) for tj in t] return n, xe, np.array(t) @pytest.mark.parametrize("method", ("jsc", "asy", "da")) @pytest.mark.parametrize("with_mask", (False, True)) @pytest.mark.parametrize("weighted_data", (False, True)) def test_Template_weighted(method, with_mask, weighted_data): rng = np.random.default_rng(1) truth = 750, 250 z = [] rng = np.random.default_rng(1) for itoy in range(100): ni, xe, ti = generate(rng, 400, truth, 15, 1.5, 1.5 if weighted_data else 1) c = Template(ni, xe, ti, method=method) if with_mask: cx = 0.5 * (xe[1:] + xe[:-1]) c.mask = cx != 1.5 m = Minuit(c, *truth) m.limits = (0, None) m.strategy = 0 for iter in range(10): m.migrad(iterate=1) m.hesse() if m.valid and m.accurate: break assert m.valid z.append((m.values[1] - truth[1]) / m.errors[1]) assert_allclose(np.mean(z), 0, atol=0.3) assert_allclose(np.std(z), 1, rtol=0.1) def test_Template_bad_input(): with pytest.raises(ValueError): Template([1, 2], [1, 2, 3], []) with pytest.raises(ValueError, match="do not match"): Template([1, 2], [1, 2, 3], [[1, 2, 3], [1, 2, 3]]) with pytest.raises(ValueError, match="do not match"): Template( [1, 2], [1, 2, 3], [[[1, 2], [3, 4]], [[1, 2], [3, 4], [5, 6]]], ) with pytest.raises(ValueError, match="not understood"): Template([1], [1, 2], [[1]], method="foo") with pytest.raises(ValueError, match="number of names"): Template([1], [1, 2], [[1]], name=("b", "s")) with pytest.raises(ValueError, match="model_or_template"): Template([1], [1, 2], [[1], None]) def test_Template_visualize(): pytest.importorskip("matplotlib") xe = [0, 1, 2] n = [1, 2] t = [[1, 2], [5, 4]] c = Template(n, xe, t) c.visualize((1, 2)) c.mask = np.array([False, True]) c.visualize((1, 2)) def test_Template_visualize_2D(): pytest.importorskip("matplotlib") xe = ([0, 1, 2], [0, 1, 2]) n = [[1, 2], [3, 4]] t = [[[1, 2], [1, 2]], [[5, 4], [5, 4]]] c = Template(n, xe, t) c.visualize((1, 2)) def test_Template_pickle(): n = np.array([1, 2, 3]) xe = np.array([0, 1, 2, 3]) t = np.array([[1, 1, 0], [0, 1, 3]]) c = Template(n, xe, t) b = pickle.dumps(c) c2 = pickle.loads(b) assert_equal(c.data, c2.data) def test_Template_with_model(): n = np.array([3, 2, 3]) xe = np.array([0, 1, 2, 3]) t = np.array([0.1, 0, 1]) c = Template(n, xe, (t, scaled_cdf)) assert describe(c) == ["x0", "x1_n", "x1_mu", "x1_sigma"] m = Minuit(c, 1, 1, 0.5, 1) m.limits["x0", "x1_n"] = (0, None) m.limits["x1_sigma"] = (0.1, None) m.limits["x1_mu"] = (xe[0], xe[-1]) m.migrad() assert m.valid c2 = Template(n, xe, (t, scaled_cdf), name=("a", "b", "c", "d")) assert describe(c2) == ["a", "b", "c", "d"] m = Minuit(c2, 1, 1, 0.5, 1) m.limits["d"] = (0.1, None) m.migrad() assert m.valid def test_Template_with_model_2D(): truth1 = (1.0, 0.1, 0.2, 0.3, 0.4, 0.5) x1, y1 = mvnorm(*truth1[1:]).rvs(size=int(truth1[0] * 1000), random_state=1).T truth2 = (1.0, 0.2, 0.1, 0.4, 0.3, 0.0) x2, y2 = mvnorm(*truth2[1:]).rvs(size=int(truth2[0] * 1000), random_state=1).T x = np.append(x1, x2) y = np.append(y1, y2) w, xe, ye = np.histogram2d(x, y, bins=(3, 5)) def model(xy, n, mux, muy, sx, sy, rho): return n * 1000 * mvnorm(mux, muy, sx, sy, rho).cdf(np.transpose(xy)) x3, y3 = mvnorm(*truth2[1:]).rvs(size=int(truth2[0] * 10000), random_state=2).T template = np.histogram2d(x3, y3, bins=(xe, ye))[0] cost = Template(w, (xe, ye), (model, template)) assert cost.ndata == np.prod(w.shape) m = Minuit(cost, *truth1, 1) m.limits["x0_n", "x0_sx", "x0_sy"] = (0, None) m.limits["x0_rho"] = (-1, 1) m.migrad() assert m.valid assert_allclose(m.values, truth1 + (1e3,), rtol=0.1) def test_Template_with_only_models(): n = np.array([3, 2, 3]) xe = np.array([0, 1, 2, 3]) c = Template(n, xe, (lambda x, n, mu: n * expon_cdf(x, mu), scaled_cdf)) assert describe(c) == ["x0_n", "x0_mu", "x1_n", "x1_mu", "x1_sigma"] m = Minuit(c, 1, 0.5, 1, 0.5, 1) m.limits["x0_n", "x1_n", "x1_sigma"] = (0, None) m.limits["x0_mu", "x1_mu"] = (xe[0], xe[-1]) m.migrad() assert m.valid def test_Template_pulls(): rng = np.random.default_rng(1) xe = np.linspace(0, 1, 200) tmu = np.array( [ np.diff(norm_cdf(xe, 0.5, 0.1)) * 1000, np.diff(expon_cdf(xe, 1)) * 10000, ] ) truth = (1000, 2000) mu = sum(truth[i] * (tmu[i] / np.sum(tmu[i])) for i in range(2)) n = rng.poisson(mu) t = rng.poisson(tmu) c = Template(n, xe, t) m = Minuit(c, *truth) m.migrad() assert m.valid pulls = c.pulls(m.values) assert np.nanmean(pulls) == pytest.approx(0, abs=0.1) assert np.nanvar(pulls) == pytest.approx(1, abs=0.1) def test_deprecated(): from iminuit import cost with pytest.warns(FutureWarning): from iminuit.cost import BarlowBeestonLite assert BarlowBeestonLite is cost.Template with pytest.warns(FutureWarning): from iminuit.cost import barlow_beeston_lite_chi2_jsc assert barlow_beeston_lite_chi2_jsc is cost.template_chi2_jsc with pytest.warns(FutureWarning): from iminuit.cost import barlow_beeston_lite_chi2_hpd assert barlow_beeston_lite_chi2_hpd is cost.template_chi2_da def test_deprecated_Template_method(): from iminuit import cost with pytest.warns(FutureWarning): t = Template([1], [2, 3], [[1], [2]], method="hpd") t._impl is cost.template_chi2_da @pytest.mark.parametrize("cost", (BinnedNLL, ExtendedBinnedNLL)) def test_binned_cost_with_model_shape_error_message_1D(cost): n = [1, 2] edges = [0.1, 0.2, 0.3] # cdf should return same length as xe, not same length as n def cdf(xe, a): return xe[:-1] c = cost(n, edges, cdf) with pytest.raises( ValueError, match=(r"output of model has shape \(2,\), but \(3,\) is required"), ): c(1) @pytest.mark.parametrize("cost", (BinnedNLL, ExtendedBinnedNLL)) def test_binned_cost_with_model_shape_error_message_2D(cost): n = [[1, 2, 3], [4, 5, 6]] edges = [0.5, 0.6, 0.7], [0.1, 0.2, 0.3, 0.4] def cdf(xye, a): # xye has shape (2, N), returned array should be (N,) return np.ones(xye.shape[1] - 1) c = cost(n, edges, cdf) with pytest.raises( ValueError, match=(r"output of model has shape \(11,\), but \(12,\) is required"), ): c(1) iminuit-2.30.1/tests/test_deprecated.py0000644000000000000000000000220414332717401015054 0ustar00from iminuit._deprecated import deprecated, deprecated_parameter import pytest def test_deprecated_func_1(): @deprecated("bla") def func(x): pass with pytest.warns( FutureWarning, match="func is deprecated: bla", ): func(1) def test_deprecated_func_2(): @deprecated("bla", removal="1.0") def func(x): pass with pytest.warns( DeprecationWarning, match="func is deprecated and will be removed in version 1.0: bla", ): func(1) def test_deprecated_func_3(): @deprecated("bla", removal="1000.0") def func(x): pass with pytest.warns( FutureWarning, match="func is deprecated and will be removed in version 1000.0: bla", ): func(1) def test_deprecated_parameter(): @deprecated_parameter(foo="bar") def some_function(x, y, foo): pass some_function(1, 2, foo=3) with pytest.warns( FutureWarning, match="keyword 'bar' is deprecated, please use 'foo'", ): some_function(1, 2, bar=3) with pytest.raises(TypeError): some_function(x=1, baz=3, y=2) iminuit-2.30.1/tests/test_describe.py0000644000000000000000000001340714332717401014543 0ustar00from iminuit.util import describe, make_func_code from iminuit.typing import Annotated, Gt, Lt, Ge, Le, Interval from math import ldexp import platform from functools import wraps import pytest import numpy as np from numpy.typing import NDArray is_pypy = platform.python_implementation() == "PyPy" def test_function(): def f(x, y): pass assert describe(f) == ["x", "y"] def test_class_method(): class A: def f(self, x, y): pass assert describe(A().f) == ["x", "y"] def test_class_unbound_method(): class A: def f(self, x, y): pass assert describe(A.f) == ["self", "x", "y"] def test_functor(): class A: def __call__(self, x, y): pass assert describe(A()) == ["x", "y"] def test_builtin_by_parsing_doc(): assert describe(ldexp) == ["x", "i"] def test_lambda(): assert describe(lambda a, b: 0) == ["a", "b"] def test_generic_function(): def f(*args): pass assert describe(f) == [] def test_generic_partial(): from functools import partial def f(*args): pass partial_f = partial(f, 42, 12, 4) assert describe(partial_f) == [] def test_generic_lambda(): assert describe(lambda *args: 0) == [] def test_generic_class_method(): class A: def f(self, *args): pass assert describe(A().f) == [] def test_generic_functor(): class A: def __call__(self, *args): pass assert describe(A()) == [] def test_generic_functor_with_fake_func(): class A: def __init__(self): self.func_code = make_func_code(["x", "y"]) def __call__(self, *args): pass with pytest.warns(FutureWarning): assert describe(A()) == ["x", "y"] def test_decorated_function(): def dummy_decorator(f): @wraps(f) def decorated(*args, **kwargs): return f(*args, **kwargs) return decorated @dummy_decorator def one_arg(x): pass @dummy_decorator def many_arg(x, y, z, t): pass @dummy_decorator def kw_only(x, *, y, z): pass assert describe(one_arg) == list("x") assert describe(many_arg) == list("xyzt") assert describe(kw_only) == list("xyz") def test_ambiguous_1(): def f(x, *args): pass assert describe(f) == ["x"] def test_ambiguous_2(): def f(x, kw=None): pass assert describe(f) == ["x", "kw"] def test_ambiguous_3(): def f(x, **kw): pass assert describe(f) == ["x"] def test_ambiguous_4(): class A: def __call__(self, x, **kw): pass assert describe(A()) == ["x"] def test_from_docstring_1(): def f(*args): """f(x, y, z)""" assert describe(f) == ["x", "y", "z"] def test_from_docstring_2(): class Foo: def bar(self, *args): """Foo.bar(self, int ncall_me =10000, [resume=True, int nsplit=1])""" pass def baz(self, *args): """Foo.baz(self: Foo, ncall_me: int =10000, arg: np.ndarray = [])""" assert describe(Foo().bar) == ["ncall_me", "resume", "nsplit"] assert describe(Foo().baz) == ["ncall_me", "arg"] def test_from_docstring_3(): assert describe(min) == ["iterable", "default", "key"] def test_from_docstring_4(): def f(*args): """f(a=(), b=[], *args, *[, foo=1])""" assert describe(f) == ["a", "b"] def test_from_bad_docstring_2(): def foo(*args): """foo is some function""" pass assert describe(foo) == [] def test_with_type_hints(): def foo( x: NDArray, a: Annotated[float, Gt(0), Lt(1)], b: float, c: Annotated[float, 0:], d: Annotated[float, Ge(1)], e: Annotated[float, Le(2)], f: Annotated[float, Interval(gt=2, lt=3)], g: Annotated[float, (4, 5)], ): ... r = describe(foo, annotations=True) assert r == { "x": None, "a": (0, 1), "b": None, "c": (0, np.inf), "d": (1, np.inf), "e": (-np.inf, 2), "f": (2, 3), "g": (4, 5), } class Foo: def __call__(self, x: NDArray, a: Annotated[float, Gt(0), Lt(1)], b: float): ... r = describe(Foo.__call__, annotations=True) assert r == {"self": None, "x": None, "a": (0, 1), "b": None} r = describe(Foo(), annotations=True) assert r == {"x": None, "a": (0, 1), "b": None} def test_with_pydantic_types(): tp = pytest.importorskip("pydantic.types") def foo( x: NDArray, a: tp.PositiveFloat, b: tp.NonNegativeFloat, c: float, d: Annotated[float, tp.annotated_types.Gt(1)], e: Annotated[float, tp.annotated_types.Interval(gt=0, lt=1)], ): ... r = describe(foo, annotations=True) assert r == { "x": None, "a": (0, np.inf), "b": (0, np.inf), "c": None, "d": (1, np.inf), "e": (0, 1), } def test_with_annotated_types(): tp = pytest.importorskip("annotated_types") def foo( x: NDArray, a: float, b: Annotated[float, tp.Gt(1)], c: Annotated[float, tp.Interval(gt=0, lt=1)], ): ... r = describe(foo, annotations=True) assert r == { "x": None, "a": None, "b": (1, np.inf), "c": (0, 1), } class Foo(float): pass def test_string_annotation_1(): def f(x, mu: "Foo"): pass assert describe(f, annotations=True) == {"x": None, "mu": None} def test_string_annotation_2(): def f(x, mu: "Annotated[float, Gt(1)]"): pass assert describe(f, annotations=True) == {"x": None, "mu": (1, np.inf)} def test_string_annotation_3(): def f(x, mu: "Bar"): # noqa pass assert describe(f, annotations=True) == {"x": None, "mu": None} iminuit-2.30.1/tests/test_draw.py0000644000000000000000000001434014332717401013715 0ustar00import pytest from iminuit import Minuit from pathlib import Path import numpy as np from numpy.testing import assert_allclose import contextlib mpl = pytest.importorskip("matplotlib") plt = pytest.importorskip("matplotlib.pyplot") mpl.use("Agg") def f1(x, y): return (1 - x) ** 2 + np.exp((y - 1) ** 2) @pytest.fixture def minuit(): m = Minuit(f1, x=0, y=0) m.migrad() return m @pytest.fixture def fig(request): fig = plt.figure() yield fig p = Path(__file__).parent / "fig" if not p.exists(): p.mkdir() fig.savefig(p / (request.node.name + ".svg")) plt.close() @pytest.mark.parametrize("arg", ("x", 1)) def test_profile_1(fig, minuit, arg): minuit.draw_profile(arg) plt.ylim(0, 5) def test_profile_2(fig, minuit): minuit.draw_profile("x", grid=np.linspace(0, 5)) @pytest.mark.parametrize("arg", ("x", 1)) def test_mnprofile_1(fig, minuit, arg): # plots with hesse errors minuit.draw_mnprofile(arg) plt.ylim(0, 5) def test_mnprofile_2(fig, minuit): minuit.minos() minuit.draw_mnprofile("x", grid=np.linspace(0, 5)) def test_mncontour_1(fig, minuit): minuit.draw_mncontour("x", "y") def test_mncontour_2(fig, minuit): # use 0, 1 instead of "x", "y" minuit.draw_mncontour(0, 1, cl=0.68) def test_mncontour_3(fig, minuit): minuit.draw_mncontour("x", "y", cl=[0.68, 0.9]) def test_mncontour_4(fig, minuit): minuit.draw_mncontour("x", "y", size=20, interpolated=200) def test_mncontour_5(fig, minuit): minuit.draw_mncontour("x", "y", size=20, interpolated=10) def test_contour_1(fig, minuit): minuit.draw_contour("x", "y") def test_contour_2(fig, minuit): # use 0, 1 instead of "x", "y" minuit.draw_contour(0, 1, size=20, bound=2) def test_contour_3(fig, minuit): minuit.draw_contour("x", "y", size=100, bound=((-0.5, 2.5), (-1, 3))) def test_contour_4(fig, minuit): minuit.draw_contour("x", "y", size=(10, 50), bound=((-0.5, 2.5), (-1, 3))) def test_contour_5(fig, minuit): minuit.draw_contour("x", "y", grid=(np.linspace(-0.5, 2.5), np.linspace(-1, 3))) def test_mnmatrix_1(fig, minuit): minuit.draw_mnmatrix() def test_mnmatrix_2(fig, minuit): minuit.draw_mnmatrix(cl=[0.68, 0.9]) def test_mnmatrix_3(fig): m = Minuit(lambda x: x**2, x=0) m.migrad() m.draw_mnmatrix() def test_mnmatrix_4(fig, minuit): with pytest.raises(ValueError): minuit.draw_mnmatrix(cl=[]) def test_mnmatrix_5(): m = Minuit(lambda x: x**2, x=10) with pytest.raises(RuntimeError, match="minimum is not valid"): m.draw_mnmatrix() def test_mnmatrix_6(fig, minuit): minuit.fixed = True with pytest.raises(RuntimeError, match="all parameters are fixed"): minuit.draw_mnmatrix() def test_mnmatrix_7(fig): # provoke an mnprofile iteration on asymmetric profile m = Minuit(lambda x: abs(x) ** 2 + x**4 + 10 * x, x=0) m.migrad() m.draw_mnmatrix(cl=[1, 3]) @pytest.mark.filterwarnings("ignore::DeprecationWarning") def test_interactive(): ipywidgets = pytest.importorskip("ipywidgets") def cost(a, b): return a**2 + b**2 class Plot: def __init__(self): self.called = False self.raises = False def __call__(self, args): self.called = True if self.raises: raise ValueError("foo") @contextlib.contextmanager def assert_call(self): self.called = False yield assert self.called plot = Plot() m = Minuit(cost, 1, 1) with pytest.raises(AttributeError, match="no visualize method"): m.interactive(raise_on_exception=True) with plot.assert_call(): out1 = m.interactive(plot) assert isinstance(out1, ipywidgets.HBox) # manipulate state to also check this code ui = out1.children[1] header, parameters = ui.children fit_button, update_button, reset_button, algo_select = header.children with plot.assert_call(): fit_button.click() assert_allclose(m.values, (0, 0), atol=1e-5) with plot.assert_call(): reset_button.click() assert_allclose(m.values, (1, 1), atol=1e-5) algo_select.value = "Scipy" with plot.assert_call(): fit_button.click() algo_select.value = "Simplex" with plot.assert_call(): fit_button.click() update_button.value = False with plot.assert_call(): # because of implementation details, we have to trigger the slider several times for i in range(5): parameters.children[0].slider.value = i # change first slider parameters.children[0].fix.value = True with plot.assert_call(): parameters.children[0].fit.value = True class Cost: def visualize(self, args): return plot(args) def __call__(self, a, b): return (a - 100) ** 2 + (b + 100) ** 2 c = Cost() m = Minuit(c, 0, 0) with plot.assert_call(): out = m.interactive(raise_on_exception=True) # this should modify slider range ui = out.children[1] header, parameters = ui.children fit_button, update_button, reset_button, algo_select = header.children assert parameters.children[0].slider.max == 1 assert parameters.children[1].slider.min == -1 with plot.assert_call(): fit_button.click() assert_allclose(m.values, (100, -100), atol=1e-5) # this should trigger an exception plot.raises = True with plot.assert_call(): fit_button.click() @pytest.mark.filterwarnings("ignore::DeprecationWarning") def test_interactive_raises(): pytest.importorskip("ipywidgets") def raiser(args): raise ValueError m = Minuit(lambda x, y: 0, 0, 1) # by default do not raise m.interactive(raiser) with pytest.raises(ValueError): m.interactive(raiser, raise_on_exception=True) @pytest.mark.filterwarnings("ignore::DeprecationWarning") def test_interactive_with_array_func(): pytest.importorskip("ipywidgets") def cost(par): return par[0] ** 2 + (par[1] / 2) ** 2 class TraceArgs: nargs = 0 def __call__(self, par): self.nargs = len(par) trace_args = TraceArgs() m = Minuit(cost, (1, 2)) m.interactive(trace_args) assert trace_args.nargs > 0 iminuit-2.30.1/tests/test_experimental.py0000644000000000000000000000060414332717401015453 0ustar00from iminuit import util, experimental def test_expanded(): def f(x, y, z): return x + y + z def g(x, a, b): return x + a + b f2, g2 = experimental.expanded(f, g) assert f(1, 2, 3) + g(1, 4, 5) == f2(1, 2, 3, 4, 5) + g2(1, 2, 3, 4, 5) assert util.describe(f2) == ["x", "y", "z", "a", "b"] assert util.describe(g2) == ["x", "y", "z", "a", "b"] iminuit-2.30.1/tests/test_fmin_bad.txt0000644000000000000000000000301414332717401014702 0ustar00┌──────────────────────────────────┬──────────────────────────────────────┠│ FCN = nan │ Nfcn = 100000 │ │ EDM = 1.23e-10 (Goal: 1e-05) │ Ngrad = 200000 │ ├───────────────┬──────────────────┼──────────────────────────────────────┤ │INVALID Minimum│INVALID Parameters│ SOME Parameters at limit │ ├───────────────┴──────────────────┼──────────────────────────────────────┤ │ ABOVE EDM threshold (goal x 10) │ ABOVE call limit │ ├───────────────┬──────────────────┼───────────┬─────────────┬────────────┤ │ Hesse FAILED │ NO Covariance │APPROXIMATE│NOT pos. def.│ FORCED │ └───────────────┴──────────────────┴───────────┴─────────────┴────────────┘ iminuit-2.30.1/tests/test_functions.py0000644000000000000000000000306614332717401014773 0ustar00from iminuit import Minuit from iminuit.testing import ( rosenbrock, rosenbrock_grad, ackley, beale, matyas, sphere_np, ) import numpy as np from numpy.testing import assert_allclose import pytest @pytest.mark.parametrize("grad", (None, rosenbrock_grad)) def test_rosenbrock(grad): m = Minuit(rosenbrock, x=0, y=0, grad=grad) m.tol = 1e-4 m.migrad() assert_allclose(m.fval, 0, atol=1e-6) assert_allclose(m.values["x"], 1.0, atol=1e-3) assert_allclose(m.values["y"], 1.0, atol=1e-3) def test_ackley(): m = Minuit(ackley, x=0.3, y=-0.2) # m.errors = 1.7 m.tol = 1e-4 m.migrad() assert_allclose(m.fval, 0, atol=1e-6) assert_allclose(m.values, [0, 0], atol=1e-6) def test_beale(): m = Minuit(beale, x=0.5, y=0.25) m.tol = 1e-4 m.migrad() assert_allclose(m.fval, 0, atol=1e-6) assert_allclose(m.values, [3, 0.5], atol=1e-3) def test_matyas(): m = Minuit(matyas, x=0.5, y=0.5) m.tol = 1e-4 m.migrad() assert_allclose(m.fval, 0, atol=1e-14) assert_allclose(m.values, [0, 0], atol=1e-14) def test_matyas_oneside(): """One-sided limit when the minimum is in the forbidden region.""" m = Minuit(matyas, x=2.5, y=0.5) m.tol = 1e-4 m.limits["x"] = (1, None) m.migrad() assert_allclose(m.values, [1, 0.923], atol=1e-3) @pytest.mark.parametrize("start", (2, (2, 2, 2))) def test_sphere_np(start): m = Minuit(sphere_np, start) m.migrad() assert_allclose(m.fval, 0, atol=1e-6) assert_allclose(m.values, np.zeros_like(start), atol=1e-3) iminuit-2.30.1/tests/test_issue.py0000644000000000000000000001057614332717401014117 0ustar00import numpy as np import warnings def test_issue_424(): from iminuit import Minuit def fcn(x, y, z): return (x - 1) ** 2 + (y - 4) ** 2 / 2 + (z - 9) ** 2 / 3 m = Minuit(fcn, x=0.0, y=0.0, z=0.0) m.migrad() m.fixed["x"] = True m.errors["x"] = 2 m.hesse() # this used to release x assert m.fixed["x"] assert m.errors["x"] == 2 def test_issue_544(): import pytest from iminuit import Minuit from iminuit.util import IMinuitWarning def fcn(x, y): return x**2 + y**2 m = Minuit(fcn, x=0, y=0) m.fixed = True with pytest.warns(IMinuitWarning): m.hesse() # this used to cause a segfault def test_issue_648(): from iminuit import Minuit class F: first = True def __call__(self, a, b): if self.first: assert a == 1.0 and b == 2.0 self.first = False return a**2 + b**2 m = Minuit(F(), a=1, b=2) m.fixed["a"] = False # this used to change a to b m.migrad() def test_issue_643(): from iminuit import Minuit def fcn(x, y, z): return (x - 2) ** 2 + (y - 3) ** 2 + (z - 4) ** 2 m = Minuit(fcn, x=2, y=3, z=4) m.migrad() m2 = Minuit(fcn, x=m.values["x"], y=m.values["y"], z=m.values["z"]) # used to call MnHesse when it was not needed and quickly exhaust call limit for i in range(10): m2.minos() m2.reset() # used to exhaust call limit, because calls to MnHesse did not reset call count for i in range(10): m2.values = m.values m2.minos() def test_issue_669(): from iminuit import Minuit def fcn(x, y): return x**2 + (y / 2) ** 2 m = Minuit(fcn, x=0, y=0) m.migrad() xy1 = m.mncontour(x="x", y="y", size=10) xy2 = m.mncontour(x="y", y="x", size=10) # used to fail # needs better way to compare polygons for x, y in xy1: match = False for y2, x2 in xy2: if abs(x - x2) < 1e-3 and abs(y - y2) < 1e-3: match = True break assert match # cannot define this inside function, pickle will not allow it def fcn(par): return np.sum(par**2) # cannot define this inside function, pickle will not allow it def grad(par): return 2 * par def test_issue_687(): import pickle import numpy as np from iminuit import Minuit start = np.zeros(3) m = Minuit(fcn, start) m.migrad() s_m = str(m) s = pickle.dumps(m) m2 = pickle.loads(s) s_m2 = str(m2) # this used to fail assert s_m == s_m2 def test_issue_694(): import pytest import numpy as np from iminuit import Minuit from iminuit.cost import ExtendedUnbinnedNLL stats = pytest.importorskip("scipy.stats") xmus = 1.0 xmub = 5.0 xsigma = 1.0 ymu = 0.5 ysigma = 0.2 ytau = 0.1 for seed in range(100): rng = np.random.default_rng(seed) xs = rng.normal(xmus, xsigma, size=33) xb = rng.normal(xmub, xsigma, size=66) x = np.append(xs, xb) def model(x, sig_n, sig_mu, sig_sigma, bkg_n, bkg_tau): return sig_n + bkg_n, ( sig_n * stats.norm.pdf(x, sig_mu, sig_sigma) + bkg_n * stats.expon.pdf(x, 0, bkg_tau) ) nll = ExtendedUnbinnedNLL(x, model) m = Minuit(nll, sig_n=33, sig_mu=ymu, sig_sigma=ysigma, bkg_n=66, bkg_tau=ytau) # with Simplex the fit never yields NaN, which is good but not what we want here with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) m.migrad(use_simplex=False) if np.isnan(m.fmin.edm): assert not m.valid assert m.fmin.is_above_max_edm break else: assert False def test_issue_923(): from iminuit import Minuit from iminuit.cost import LeastSquares import numpy as np import pytest # implicitly needed by visualize pytest.importorskip("matplotlib") def model(x, c1): c2 = 100 res = np.zeros(len(x)) mask = x < 47 res[mask] = c1 res[~mask] = c2 return res xtest = np.linspace(0, 74) ytest = xtest * 0 + 1 ytesterr = ytest least_squares = LeastSquares(xtest, ytest, ytesterr, model) m = Minuit(least_squares, c1=1) m.migrad() # this used to trigger an endless (?) loop m.visualize() iminuit-2.30.1/tests/test_minimize.py0000644000000000000000000001002214332717401014572 0ustar00import pytest from iminuit import minimize import numpy as np from numpy.testing import assert_allclose, assert_equal opt = pytest.importorskip("scipy.optimize") def func(x, *args): c = args[0] if args else 1 return c + x[0] ** 2 + (x[1] - 1) ** 2 + (x[2] - 2) ** 2 def grad(x, *args): return 2 * (x - (0, 1, 2)) def test_simple(): result = minimize(func, (1, 1, 1)) assert_allclose(result.x, (0, 1, 2), atol=1e-8) assert_allclose(result.fun, 1) assert result.nfev > 0 assert result.njev == 0 def test_gradient(): result = minimize(func, (1, 1, 1), jac=grad) assert_allclose(result.x, (0, 1, 2), atol=1e-8) assert_allclose(result.fun, 1) assert result.nfev > 0 assert result.njev > 0 def test_args(): result = minimize(func, np.ones(3), args=(5,)) assert_allclose(result.x, (0, 1, 2), atol=1e-8) assert_allclose(result.fun, 5) assert result.nfev > 0 assert result.njev == 0 def test_callback(): trace = [] result = minimize(func, np.ones(3), callback=lambda x: trace.append(x.copy())) assert_allclose(result.x, (0, 1, 2), atol=1e-8) assert_allclose(result.fun, 1) assert result.nfev == len(trace) assert_allclose(trace[0], np.ones(3), atol=1e-2) assert_allclose(trace[-1], result.x, atol=1e-2) def test_tol(): ref = np.ones(2) def rosen(par): x, y = par return (1 - x) ** 2 + 100 * (y - x**2) ** 2 r1 = minimize(rosen, (0, 0), tol=1) r2 = minimize(rosen, (0, 0), tol=1e-6) assert max(np.abs(r2.x - ref)) < max(np.abs(r1.x - ref)) def test_disp(capsys): minimize(lambda x: np.sum(x**2), 0) assert capsys.readouterr()[0] == "" minimize(lambda x: np.sum(x**2), 0, options={"disp": True}) assert capsys.readouterr()[0] != "" def test_hessinv(): r = minimize(func, (1, 1, 1)) href = np.zeros((3, 3)) for i in range(3): href[i, i] = 0.5 assert_allclose(r.hess_inv, href, atol=1e-8) def test_unsupported(): with pytest.raises(ValueError): minimize(func, (1, 1, 1), constraints=[]) with pytest.raises(ValueError): minimize(func, (1, 1, 1), jac=True) def test_call_limit(): ref = minimize(func, (1, 1, 1)) with pytest.warns(UserWarning): r1 = minimize(func, (1, 1, 1), options={"maxiter": 1}) assert r1.nfev < ref.nfev assert not r1.success assert "Call limit" in r1.message with pytest.warns(DeprecationWarning): r2 = minimize(func, (1, 1, 1), options={"maxfev": 1}) assert not r2.success assert r2.nfev == r1.nfev r3 = minimize(func, (1, 1, 1), options={"maxfun": 1}) assert not r3.success assert r3.nfev == r1.nfev def test_eps(): ref = minimize(func, (1, 1, 1)) r = minimize(func, (1, 1, 1), options={"eps": 1e-10}) assert np.any(ref.x != r.x) assert_allclose(r.x, ref.x, atol=1e-9) def test_bad_function(): class Fcn: n = 0 def __call__(self, x): self.n += 1 return np.sum(x**2 + 1e-2 * (self.n % 3)) r = minimize(Fcn(), [1], options={"maxfun": 100000000}) assert not r.success assert "Estimated distance to minimum too large" in r.message def test_bounds(): r1 = minimize(func, (1.5, 1.7, 1.5), bounds=opt.Bounds((1, 1.5, 1), (2, 2, 2))) assert r1.success assert_allclose(r1.x, (1, 1.5, 2), atol=1e-2) r2 = minimize(func, (1.5, 1.7, 1.5), bounds=((1, 2), (1.5, 2), (1, 2))) assert r2.success assert_equal(r1.x, r2.x) def test_method_warn(): with pytest.raises(ValueError): minimize(func, (1.5, 1.7, 1.5), method="foo") def test_hess_warn(): with pytest.warns(UserWarning): minimize(func, (1.5, 1.7, 1.5), hess=True) def test_unreliable_uncertainties(): r = minimize(func, (1.5, 1.7, 1.5), options={"stra": 0}) assert ( r.message == "Optimization terminated successfully, but uncertainties are unrealiable." ) def test_simplex(): r = minimize(func, (1.5, 1.7, 1.5), method="simplex", tol=1e-4) assert r.success assert_allclose(r.x, (0, 1, 2), atol=2e-3) iminuit-2.30.1/tests/test_minuit.py0000644000000000000000000012647314332717401014300 0ustar00import platform import pytest import numpy as np from numpy.testing import assert_allclose, assert_equal from iminuit import Minuit from iminuit.util import Param, make_func_code from iminuit.warnings import IMinuitWarning, ErrordefAlreadySetWarning from iminuit.typing import Annotated from pytest import approx from argparse import Namespace @pytest.fixture def debug(): from iminuit._core import MnPrint prev = MnPrint.global_level MnPrint.global_level = 3 MnPrint.show_prefix_stack(True) yield MnPrint.global_level = prev MnPrint.show_prefix_stack(False) is_pypy = platform.python_implementation() == "PyPy" def test_version(): import iminuit assert iminuit.__version__ def func0(x, y): # values = (2.0, 5.0), errors = (2.0, 1.0) return (x - 2.0) ** 2 / 4.0 + np.exp((y - 5.0) ** 2) + 10 def func0_grad(x, y): dfdx = (x - 2.0) / 2.0 dfdy = 2.0 * (y - 5.0) * np.exp((y - 5.0) ** 2) return [dfdx, dfdy] class Func1: errordef = 4 def __call__(self, x, y): return func0(x, y) * 4 class Func2: errordef = 4 def __init__(self): self.func_code = make_func_code(["x", "y"]) def __call__(self, *arg): return func0(arg[0], arg[1]) * 4 def func4(x, y, z): return 0.2 * (x - 2.0) ** 2 + 0.1 * (y - 5.0) ** 2 + 0.25 * (z - 7.0) ** 2 + 10 def func4_grad(x, y, z): dfdx = 0.4 * (x - 2.0) dfdy = 0.2 * (y - 5.0) dfdz = 0.5 * (z - 7.0) return dfdx, dfdy, dfdz def func5(x, long_variable_name_really_long_why_does_it_has_to_be_this_long, z): return ( (x - 1) ** 2 + long_variable_name_really_long_why_does_it_has_to_be_this_long**2 + (z + 1) ** 2 ) def func5_grad(x, long_variable_name_really_long_why_does_it_has_to_be_this_long, z): dfdx = 2 * (x - 1) dfdy = 2 * long_variable_name_really_long_why_does_it_has_to_be_this_long dfdz = 2 * (z + 1) return dfdx, dfdy, dfdz def func6(x, m, s, a): return a / ((x - m) ** 2 + s**2) class Correlated: def __init__(self): sx = 2 sy = 1 corr = 0.5 cov = (sx**2, corr * sx * sy), (corr * sx * sy, sy**2) self.cinv = np.linalg.inv(cov) def __call__(self, x): return np.dot(x.T, np.dot(self.cinv, x)) def func_np(x): # test numpy support return np.sum((x - 1) ** 2) def func_np_grad(x): # test numpy support return 2 * (x - 1) data_y = [ 0.552, 0.735, 0.846, 0.875, 1.059, 1.675, 1.622, 2.928, 3.372, 2.377, 4.307, 2.784, 3.328, 2.143, 1.402, 1.44, 1.313, 1.682, 0.886, 0.0, 0.266, 0.3, ] data_x = list(range(len(data_y))) def func_test_helper(f, grad=None, errordef=None): m = Minuit(f, x=0, y=0, grad=grad) if errordef: m.errordef = errordef m.migrad() val = m.values assert_allclose(val["x"], 2.0, rtol=2e-3) assert_allclose(val["y"], 5.0, rtol=2e-3) assert_allclose(m.fval, 11.0 * m.errordef, rtol=1e-3) assert m.valid assert m.accurate m.hesse() err = m.errors assert_allclose(err["x"], 2.0, rtol=1e-3) assert_allclose(err["y"], 1.0, rtol=1e-3) m.errors = (1, 2) assert_allclose(err["x"], 1.0, rtol=1e-3) assert_allclose(err["y"], 2.0, rtol=1e-3) return m def test_mncontour_interpolated_1(): m = Minuit(func0, 1, 1) m.migrad() # interpolated < size is ignored pts = m.mncontour("x", "y", size=20, interpolated=10) assert len(pts) == 21 def test_mncontour_interpolated_2(): pytest.importorskip("scipy.interpolate") m = Minuit(func0, 1, 1) m.migrad() pts = m.mncontour("x", "y", size=20, interpolated=200) assert len(pts) == 200 def test_func0(): m1 = func_test_helper(func0) m2 = func_test_helper(func0, grad=func0_grad) assert m1.ngrad == 0 assert m2.ngrad > 0 # check that providing gradient improves convergence assert m2.nfcn < m1.nfcn def test_lambda(): func_test_helper(lambda x, y: func0(x, y)) def test_Func1(): func_test_helper(Func1()) def test_Func2(): with pytest.warns(FutureWarning): func_test_helper(Func2()) def test_no_signature(): def no_signature(*args): x, y = args return (x - 1) ** 2 + (y - 2) ** 2 m = Minuit(no_signature, 3, 4) assert m.values == (3, 4) assert m.parameters == ("x0", "x1") m = Minuit(no_signature, x=1, y=2, name=("x", "y")) assert m.values == (1, 2) m.migrad() val = m.values assert_allclose((val["x"], val["y"], m.fval), (1, 2, 0), atol=1e-8) assert m.valid with pytest.raises(RuntimeError): Minuit(no_signature, x=1) with pytest.raises(RuntimeError): Minuit(no_signature, x=1, y=2) def test_use_array_call(): inf = float("infinity") m = Minuit( func_np, (1, 1), name=("a", "b"), ) m.fixed = False m.errors = 1 m.limits = (0, inf) m.migrad() assert m.parameters == ("a", "b") assert_allclose(m.values, (1, 1)) m.hesse() c = m.covariance assert_allclose((c[("a", "a")], c[("b", "b")]), (1, 1)) with pytest.raises(RuntimeError): Minuit(lambda *args: 0, [1, 2], name=["a", "b", "c"]) def test_release_with_none(): m = Minuit(func0, x=0, y=0) m.fixed = (True, False) assert m.fixed == (True, False) m.fixed = None assert m.fixed == (False, False) def test_parameters(): m = Minuit(lambda a, b: 0, a=1, b=1) assert m.parameters == ("a", "b") assert m.pos2var == ("a", "b") assert m.var2pos["a"] == 0 assert m.var2pos["b"] == 1 def test_covariance(): m = Minuit(func0, x=0, y=0) assert m.covariance is None m.migrad() c = m.covariance assert_allclose((c["x", "x"], c["y", "y"]), (4, 1), rtol=1e-4) assert_allclose((c[0, 0], c[1, 1]), (4, 1), rtol=1e-4) expected = [[4.0, 0.0], [0.0, 1.0]] assert_allclose(c, expected, atol=1e-4) assert isinstance(c, np.ndarray) assert c.shape == (2, 2) c = c.correlation() expected = [[1.0, 0.0], [0.0, 1.0]] assert_allclose(c, expected, atol=1e-4) assert c["x", "x"] == approx(1.0) def test_array_func_1(): m = Minuit(func_np, (2, 1)) m.errors = (1, 1) assert m.parameters == ("x0", "x1") assert m.values == (2, 1) assert m.errors == (1, 1) m.migrad() assert_allclose(m.values, (1, 1), rtol=1e-2) c = m.covariance assert_allclose(np.diag(c), (1, 1), rtol=1e-2) def test_array_func_2(): m = Minuit(func_np, (2, 1), grad=func_np_grad, name=("a", "b")) m.fixed = (False, True) m.errors = (0.5, 0.5) m.limits = ((0, 2), (-np.inf, np.inf)) assert m.values == (2, 1) assert m.errors == (0.5, 0.5) assert m.fixed == (False, True) assert m.limits["a"] == (0, 2) m.migrad() assert m.fmin.ngrad > 0 assert_allclose(m.values, (1, 1), rtol=1e-2) c = m.covariance assert_allclose(c, ((1, 0), (0, 0)), rtol=1e-2) m.minos() assert len(m.merrors) == 1 assert m.merrors[0].lower == approx(-1, abs=1e-2) assert m.merrors[0].name == "a" def test_wrong_use_of_array_init(): m = Minuit(lambda a, b: a**2 + b**2, (1, 2)) with pytest.raises(TypeError): m.migrad() def test_reset(): m = Minuit(func0, x=0, y=0) m.migrad() n = m.nfcn m.migrad() assert m.nfcn > n m.reset() m.migrad() assert m.nfcn == n m = Minuit(func0, grad=func0_grad, x=0, y=0) m.migrad() n = m.nfcn k = m.ngrad m.migrad() assert m.nfcn > n assert m.ngrad > k m.reset() m.migrad() assert m.nfcn == n assert m.ngrad == k def test_typo(): with pytest.raises(RuntimeError): Minuit(lambda x: 0, y=1) m = Minuit(lambda x: 0, x=0) with pytest.raises(KeyError): m.errors["y"] = 1 with pytest.raises(KeyError): m.limits["y"] = (0, 1) def test_initial_guesses(): m = Minuit(lambda x: 0, x=0) assert m.values["x"] == 0 assert m.errors["x"] == 0.1 m = Minuit(lambda x: 0, x=1) assert m.values["x"] == 1 assert m.errors["x"] == 1e-2 @pytest.mark.parametrize("grad", (None, func0_grad)) def test_fixed(grad): m = Minuit(func0, grad=grad, x=0, y=0) assert m.npar == 2 assert m.nfit == 2 m.migrad() m.minos() assert_allclose(m.values, (2, 5), rtol=2e-3) assert_allclose(m.errors, (2, 1), rtol=1e-4) assert_allclose(m.covariance, ((4, 0), (0, 1)), atol=1e-4) m = Minuit(func0, grad=grad, x=0, y=10) assert not m.fixed["y"] m.fixed["y"] = True assert m.fixed["y"] assert m.npar == 2 assert m.nfit == 1 m.migrad() assert_allclose(m.values, (2, 10), rtol=1e-2) assert_allclose(m.fval, func0(2, 10)) assert m.fixed == [False, True] assert_allclose(m.covariance, [[4, 0], [0, 0]], atol=3e-4 if grad is None else 3e-2) assert not m.fixed["x"] assert m.fixed["y"] m.fixed["x"] = True m.fixed["y"] = False assert m.npar == 2 assert m.nfit == 1 m.migrad() m.hesse() assert_allclose(m.values, (2, 5), rtol=1e-2) assert_allclose(m.covariance, [[0, 0], [0, 1]], atol=1e-4) with pytest.raises(KeyError): m.fixed["a"] # fix by setting limits m = Minuit(func0, x=0, y=10.0) m.limits["y"] = (10, 10) assert m.fixed["y"] assert m.npar == 2 assert m.nfit == 1 # initial value out of range is forced in range m = Minuit(func0, x=0, y=20.0) m.limits["y"] = (10, 10) assert m.fixed["y"] assert m.values["y"] == 10 assert m.npar == 2 assert m.nfit == 1 m.fixed = True assert m.fixed == [True, True] m.fixed[1:] = False assert m.fixed == [True, False] assert m.fixed[:1] == [True] def test_fixto(): m = Minuit(func0, x=0, y=0) assert np.all(~m.fixed) m.fixto(0, 1) assert m.fixed[0] assert m.values[0] == 1 m.fixto([0, 1], 0) assert np.all(m.fixed) assert m.values == [0, 0] m.fixed = False assert np.all(~m.fixed) m.fixto(slice(0, 2), [1, 2]) assert np.all(m.fixed) assert_equal(m.values, [1, 2]) m.fixed = False assert np.all(~m.fixed) m.fixto(..., [2, 3]) assert np.all(m.fixed) assert_equal(m.values, [2, 3]) with pytest.raises(ValueError, match="length of argument"): m.fixto([1], [1, 2]) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_minos(grad): m = Minuit(func0, grad=grad, x=0, y=0) m.migrad() m.minos() assert len(m.merrors) == 2 assert m.merrors["x"].lower == approx(-m.errors["x"], abs=4e-3) assert m.merrors["x"].upper == approx(m.errors["x"], abs=4e-3) assert m.merrors[1].lower == m.merrors["y"].lower assert m.merrors[-1].upper == m.merrors["y"].upper @pytest.mark.parametrize("cl", (0.68, 0.90, 1, 1.5, 2)) @pytest.mark.parametrize("k", (10, 1000)) @pytest.mark.parametrize("limit", (False, True)) def test_minos_cl(cl, k, limit): opt = pytest.importorskip("scipy.optimize") stats = pytest.importorskip("scipy.stats") def nll(lambd): return lambd - k * np.log(lambd) # find location of min + up by hand def crossing(x): return nll(k + x) - (nll(k) + up) if cl >= 1: bound = cl * k**0.5 up = 0.5 * cl**2 else: bound = (stats.chi2(1).ppf(cl) * k) ** 0.5 up = 0.5 * stats.chi2(1).ppf(cl) bound *= 1.5 upper = opt.root_scalar(crossing, bracket=(0, bound)).root lower = opt.root_scalar(crossing, bracket=(-bound, 0)).root m = Minuit(nll, lambd=k) m.limits["lambd"] = (0, None) if limit else None m.errordef = Minuit.LIKELIHOOD m.migrad() assert m.valid assert m.accurate m.minos(cl=cl) assert m.values["lambd"] == approx(k) assert m.errors["lambd"] == approx(k**0.5, abs=2e-3 if limit else None) assert m.merrors["lambd"].lower == approx(lower, rel=1e-3) assert m.merrors["lambd"].upper == approx(upper, rel=1e-3) assert m.merrors[0].lower == m.merrors["lambd"].lower assert m.merrors[-1].upper == m.merrors["lambd"].upper with pytest.raises(KeyError): m.merrors["xy"] with pytest.raises(KeyError): m.merrors["z"] with pytest.raises(IndexError): m.merrors[1] with pytest.raises(IndexError): m.merrors[-2] def test_minos_some_fix(): m = Minuit(func0, x=0, y=0) m.fixed["x"] = True m.migrad() m.minos() assert "x" not in m.merrors me = m.merrors["y"] assert me.name == "y" assert me.lower == approx(-0.83, abs=1e-2) assert me.upper == approx(0.83, abs=1e-2) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_minos_single(grad): m = Minuit(func0, grad=func0_grad, x=0, y=0) m.strategy = 0 m.migrad() m.minos("x") assert len(m.merrors) == 1 me = m.merrors["x"] assert me.name == "x" assert me.lower == approx(-2, rel=2e-3) assert me.upper == approx(2, rel=2e-3) def test_minos_single_fixed(): m = Minuit(func0, x=0, y=0) m.fixed["x"] = True m.migrad() m.minos(1) assert len(m.merrors) == 1 me = m.merrors["y"] assert me.name == "y" assert me.lower == approx(-0.83, abs=1e-2) def test_minos_single_fixed_raising(): m = Minuit(func0, x=0, y=0) m.fixed["x"] = True m.migrad() with pytest.warns(RuntimeWarning): m.minos("x") assert len(m.merrors) == 0 assert m.fixed["x"] m.minos() assert len(m.merrors) == 1 assert "y" in m.merrors def test_minos_single_no_migrad(): m = Minuit(func0, x=0, y=0) with pytest.raises(RuntimeError): m.minos("x") def test_minos_single_nonsense_variable(): m = Minuit(func0, x=0, y=0) m.migrad() with pytest.raises(ValueError): m.minos("nonsense") def test_minos_with_bad_fmin(): m = Minuit(lambda x: 0, x=0) m.migrad() with pytest.raises(RuntimeError): m.minos() def test_minos_bad_index(): m = Minuit(func0, 1, 1) m.migrad() with pytest.raises(ValueError): m.minos(2) @pytest.mark.parametrize("grad", (None, func5_grad)) def test_fixing_long_variable_name(grad): m = Minuit( func5, grad=grad, long_variable_name_really_long_why_does_it_has_to_be_this_long=2, x=0, z=0, ) m.fixed["long_variable_name_really_long_why_does_it_has_to_be_this_long"] = True m.migrad() assert_allclose(m.values, [1, 2, -1], atol=1e-3) def test_initial_value(): m = Minuit(func0, x=1.0, y=2.0) assert_allclose(m.values[0], 1.0) assert_allclose(m.values[1], 2.0) assert_allclose(m.values["x"], 1.0) assert_allclose(m.values["y"], 2.0) m = Minuit(func0, 1.0, 2.0) assert_allclose(m.values[0], 1.0) assert_allclose(m.values[1], 2.0) assert_allclose(m.values["x"], 1.0) assert_allclose(m.values["y"], 2.0) m = Minuit(func0, (1.0, 2.0)) assert_allclose(m.values[0], 1.0) assert_allclose(m.values[1], 2.0) assert_allclose(m.values["x"], 1.0) assert_allclose(m.values["y"], 2.0) with pytest.raises(RuntimeError): Minuit(func0, 1, y=2) with pytest.raises(RuntimeError): Minuit(func0) @pytest.mark.parametrize("grad", (None, func0_grad)) @pytest.mark.parametrize("cl", (None, 0.5, 0.9, 1, 1.5, 2)) @pytest.mark.parametrize("experimental", (False, True)) def test_mncontour(grad, cl, experimental): stats = pytest.importorskip("scipy.stats") m = Minuit(func0, grad=grad, x=1.0, y=2.0) m.migrad() ctr = m.mncontour("x", "y", size=30, cl=cl, experimental=experimental) if cl is None: cl = 0.68 elif cl >= 1: cl = stats.chi2(1).cdf(cl**2) factor = stats.chi2(2).ppf(cl) cl2 = stats.chi2(1).cdf(factor) assert len(ctr) == 31 assert len(ctr[0]) == 2 m.minos("x", "y", cl=cl2) xm = m.merrors["x"] ym = m.merrors["y"] cmin = np.min(ctr, axis=0) cmax = np.max(ctr, axis=0) x, y = m.values assert_allclose((x + xm.lower, y + ym.lower), cmin, atol=1e-2) assert_allclose((x + xm.upper, y + ym.upper), cmax, atol=1e-2) @pytest.mark.parametrize("experimental", (False, True)) def test_mncontour_limits(experimental): pytest.importorskip("scipy.optimize") def cost(x, y): return x**2 + y**2 m = Minuit(cost, x=0.5, y=0.5) m.limits = (0, 2) m.migrad() cont = m.mncontour(0, 1, size=30, experimental=experimental) assert np.all(cont[:, 0] >= 0) assert np.all(cont[:, 1] >= 0) def test_mncontour_no_fmin(): m = Minuit(func0, x=0, y=0) with pytest.raises(RuntimeError): # fails, because this is not a minimum m.mncontour("x", "y") # succeeds m.values = (2, 5) # use 0, 1 instead of "x", "y" c = m.mncontour(0, 1, size=10) # compute reference to compare with m2 = Minuit(func0, x=0, y=0) m2.migrad() c2 = m.mncontour("x", "y", size=10) assert_allclose(c, c2) def test_mncontour_with_fixed_var(): m = Minuit(func0, x=0, y=0) m.fixed["x"] = True m.migrad() with pytest.raises(ValueError): m.mncontour("x", "y") @pytest.mark.parametrize("experimental", (False, True)) def test_mncontour_array_func(experimental): stats = pytest.importorskip("scipy.stats") m = Minuit(Correlated(), (0, 0), name=("x", "y")) m.migrad() cl = stats.chi2(2).cdf(1) ctr = m.mncontour("x", "y", size=30, cl=cl, experimental=experimental) assert len(ctr) == 31 assert len(ctr[0]) == 2 m.minos("x", "y") x, y = m.values xm = m.merrors["x"] ym = m.merrors["y"] cmin = np.min(ctr, axis=0) cmax = np.max(ctr, axis=0) assert_allclose((x + xm.lower, y + ym.lower), cmin, atol=1e-2) assert_allclose((x + xm.upper, y + ym.upper), cmax, atol=1e-2) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_contour(grad): m = Minuit(func0, grad=grad, x=1.0, y=2.0) m.migrad() x, y, v = m.contour("x", "y") X, Y = np.meshgrid(x, y) assert_allclose(func0(X, Y), v.T) def test_contour_separate_size(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() x, y, v = m.contour("x", "y", size=(10, 20)) assert len(x) == 10 assert len(y) == 20 X, Y = np.meshgrid(x, y) assert_allclose(func0(X, Y), v.T) def test_contour_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() x, y, v = m.contour("x", "y", grid=(np.linspace(0, 2, 10), np.linspace(0, 4, 20))) assert len(x) == 10 assert len(y) == 20 X, Y = np.meshgrid(x, y) assert_allclose(func0(X, Y), v.T) def test_contour_bad_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() with pytest.raises(ValueError): m.contour("x", "y", grid=([1, 2, 3], [[1, 2, 3]])) with pytest.raises(ValueError): m.contour("x", "y", grid=([1, 2, 3],)) with pytest.raises(ValueError): m.contour("x", "y", grid=([1, 2, 3], [1, 2], [3, 4])) with pytest.raises(ValueError): m.contour("x", "y", grid=(10, [1, 2, 3])) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_profile(grad): m = Minuit(func0, grad=grad, x=1.0, y=2.0) m.migrad() y, v = m.profile("y", subtract_min=False) assert_allclose(func0(m.values[0], y), v) v2 = m.profile("y", subtract_min=True)[1] assert np.min(v2) == 0 assert_allclose(v - np.min(v), v2) def test_profile_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() y, v = m.profile("y", grid=np.linspace(0, 4, 15)) assert len(y) == 15 assert y[0] == 0 assert y[-1] == 4 assert_allclose(func0(m.values[0], y), v) def test_profile_bad_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() with pytest.raises(ValueError): m.profile("y", grid=[[1, 2, 3]]) with pytest.raises(ValueError): m.profile("y", grid=10) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_mnprofile(grad): m = Minuit(func0, grad=grad, x=1.0, y=2.0) m.migrad() with pytest.raises(ValueError): m.mnprofile("foo") y, v, _ = m.mnprofile("y", size=10, subtract_min=False) m2 = Minuit(func0, grad=grad, x=1.0, y=2.0) m2.fixed[1] = True v2 = [] for yi in y: m2.values = (m.values[0], yi) m2.migrad() v2.append(m2.fval) assert_allclose(v, v2) # use 1 instead of "y" y, v3, _ = m.mnprofile(1, size=10, subtract_min=True) assert np.min(v3) == 0 assert_allclose(v - np.min(v), v3) def test_mnprofile_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() y, v, _ = m.mnprofile("y", grid=np.linspace(0, 4, 15)) assert len(y) == 15 assert y[0] == 0 assert y[-1] == 4 m2 = Minuit(func0, x=1.0, y=2.0) m2.fixed[1] = True v2 = [] for yi in y: m2.values = (m.values[0], yi) m2.migrad() v2.append(m2.fval) assert_allclose(v, v2) def test_mnprofile_bad_grid(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() with pytest.raises(ValueError): m.mnprofile("y", grid=10) with pytest.raises(ValueError): m.mnprofile("y", grid=[[10, 20]]) def test_contour_subtract(): m = Minuit(func0, x=1.0, y=2.0) m.migrad() v = m.contour("x", "y", subtract_min=False)[2] # use 0 and 1 instead "x", "y" v2 = m.contour(0, 1, subtract_min=True)[2] assert np.min(v2) == 0 assert_allclose(v - np.min(v), v2) def test_profile_array_func(): m = Minuit(Correlated(), (0, 0), name=("x", "y")) m.migrad() a = m.profile("y") b = m.profile(1) assert_equal(a, b) def test_mnprofile_array_func(): m = Minuit(Correlated(), (0, 0), name=("x", "y")) m.migrad() a = m.mnprofile("y") b = m.mnprofile(1) assert_equal(a, b) def test_mnprofile_bad_func(): m = Minuit(lambda x, y: 0, 0, 0) with pytest.warns(IMinuitWarning): m.mnprofile("x") def test_fmin_uninitialized(capsys): m = Minuit(func0, x=0, y=0) assert m.fmin is None assert m.fval is None def test_reverse_limit(): # issue 94 def f(x, y, z): return (x - 2) ** 2 + (y - 3) ** 2 + (z - 4) ** 2 with pytest.raises(ValueError): m = Minuit(f, x=0, y=0, z=0) m.limits["x"] = (3.0, 2.0) @pytest.fixture def minuit(): m = Minuit(func0, x=0, y=0) m.migrad() m.hesse() m.minos() return m def test_fcn(): m = Minuit(func0, x=0, y=0) v = m.fcn([2.0, 5.0]) assert v == func0(2.0, 5.0) def test_grad(): m = Minuit(func0, grad=func0_grad, x=0, y=0) v = m.fcn([2.0, 5.0]) g = m.grad([2.0, 5.0]) assert v == func0(2.0, 5.0) assert_equal(g, func0_grad(2.0, 5.0)) def test_values(minuit): expected = [2.0, 5.0] assert len(minuit.values) == 2 assert_allclose(minuit.values, expected, atol=4e-3) minuit.values = expected assert minuit.values == expected assert minuit.values[-1] == 5 assert minuit.values[0] == 2 assert minuit.values[1] == 5 assert minuit.values["x"] == 2 assert minuit.values["y"] == 5 assert minuit.values[:1] == [2] minuit.values[1:] = [3] assert minuit.values[:] == [2, 3] assert minuit.values[-1] == 3 minuit.values = 7 assert minuit.values[:] == [7, 7] with pytest.raises(KeyError): minuit.values["z"] with pytest.raises(IndexError): minuit.values[3] with pytest.raises(IndexError): minuit.values[-10] = 1 with pytest.raises(ValueError): minuit.values[:] = [2] def test_fmin(): m = Minuit(lambda x, s: (x * s) ** 2, x=1, s=1) m.fixed["s"] = True m.migrad() fm1 = m.fmin assert fm1.is_valid m.values["s"] = 0 m.migrad() fm2 = m.fmin assert fm1.is_valid assert not fm2.is_valid def test_chi2_fit(): def chi2(x, y): return (x - 1) ** 2 + ((y - 2) / 3) ** 2 m = Minuit(chi2, x=0, y=0) m.migrad() assert_allclose(m.values, (1, 2)) assert_allclose(m.errors, (1, 3)) def test_likelihood(): # normal distributed # fmt: off z = np.array([-0.44712856, 1.2245077 , 0.40349164, 0.59357852, -1.09491185, 0.16938243, 0.74055645, -0.9537006 , -0.26621851, 0.03261455, -1.37311732, 0.31515939, 0.84616065, -0.85951594, 0.35054598, -1.31228341, -0.03869551, -1.61577235, 1.12141771, 0.40890054, -0.02461696, -0.77516162, 1.27375593, 1.96710175, -1.85798186, 1.23616403, 1.62765075, 0.3380117 , -1.19926803, 0.86334532, -0.1809203 , -0.60392063, -1.23005814, 0.5505375 , 0.79280687, -0.62353073, 0.52057634, -1.14434139, 0.80186103, 0.0465673 , -0.18656977, -0.10174587, 0.86888616, 0.75041164, 0.52946532, 0.13770121, 0.07782113, 0.61838026, 0.23249456, 0.68255141, -0.31011677, -2.43483776, 1.0388246 , 2.18697965, 0.44136444, -0.10015523, -0.13644474, -0.11905419, 0.01740941, -1.12201873, -0.51709446, -0.99702683, 0.24879916, -0.29664115, 0.49521132, -0.17470316, 0.98633519, 0.2135339 , 2.19069973, -1.89636092, -0.64691669, 0.90148689, 2.52832571, -0.24863478, 0.04366899, -0.22631424, 1.33145711, -0.28730786, 0.68006984, -0.3198016 , -1.27255876, 0.31354772, 0.50318481, 1.29322588, -0.11044703, -0.61736206, 0.5627611 , 0.24073709, 0.28066508, -0.0731127 , 1.16033857, 0.36949272, 1.90465871, 1.1110567 , 0.6590498 , -1.62743834, 0.60231928, 0.4202822 , 0.81095167, 1.04444209]) # fmt: on data = 2 * z + 1 def nll(mu, sigma): z = (data - mu) / sigma logp = -0.5 * z**2 - np.log(sigma) return -np.sum(logp) m = Minuit(nll, mu=0, sigma=1) m.errordef = Minuit.LIKELIHOOD m.limits["sigma"] = (0, None) m.migrad() mu = np.mean(data) sigma = np.std(data) assert_allclose(m.values, (mu, sigma), rtol=5e-3) s_mu = sigma / len(data) ** 0.5 assert_allclose(m.errors, (s_mu, 0.12047), rtol=1e-1) def test_oneside(): # Solution: x=2., y=5. m = Minuit(func0, x=0, y=0) m.limits["x"] = (None, 9) m.migrad() assert_allclose(m.values, (2, 5), atol=2e-2) m.values["x"] = 0 m.limits["x"] = (None, 1) m.migrad() assert_allclose(m.values, (1, 5), atol=1e-3) m.values = (5, 0) m.limits["x"] = (3, None) m.migrad() assert_allclose(m.values, (3, 5), atol=4e-3) def test_oneside_outside(): m = Minuit(func0, x=5, y=0) m.limits["x"] = (None, 1) assert m.values["x"] == 1 m.limits["x"] = (2, None) assert m.values["x"] == 2 def test_migrad_ncall(): class Func: nfcn = 0 def __call__(self, x): self.nfcn += 1 return np.exp(x**2) # check that counting is accurate fcn = Func() m = Minuit(fcn, x=3) m.migrad() assert m.nfcn == fcn.nfcn fcn.nfcn = 0 m.reset() m.migrad() assert m.nfcn == fcn.nfcn ncalls_without_limit = m.nfcn # check that ncall argument limits function calls in migrad # note1: Minuit only checks the ncall counter in units of one iteration # step, therefore the call counter is in general not equal to ncall. # note2: If you pass ncall=0, Minuit uses a heuristic value that depends # on the number of parameters. m.reset() m.migrad(ncall=1) assert m.nfcn < ncalls_without_limit @pytest.mark.parametrize("arg", (1, np.array([1.0, 2.0]))) def test_ngrad(arg): class Func: ngrad = 0 def __call__(self, x): return np.sum(x**2) def grad(self, x): self.ngrad += 1 if np.ndim(x) == 1: return 2 * x return [2 * x] # check that counting is accurate fcn = Func() m = Minuit(fcn, arg) m.migrad() assert m.ngrad > 0 assert m.ngrad == fcn.ngrad fcn.ngrad = 0 m.reset() m.migrad() assert m.ngrad == fcn.ngrad # HESSE ignores analytical gradient before = m.ngrad m.hesse() assert m.ngrad == before m.reset() m.migrad() m2 = Minuit(lambda x: fcn(x), arg) m2.migrad() assert m.ngrad > 0 assert m2.ngrad == 0 # apparently this is not always the case: # assert m2.nfcn > m.nfcn def test_errordef(): m = Minuit(lambda x: x**2, 0) m.errordef = 4 assert m.errordef == 4 m.migrad() m.hesse() assert_allclose(m.errors["x"], 2) m.errordef = 1 m.hesse() assert_allclose(m.errors["x"], 1) with pytest.raises(ValueError): m.errordef = 0 def test_print_level(): from iminuit._core import MnPrint m = Minuit(lambda x: 0, x=0) m.print_level = 0 assert m.print_level == 0 assert MnPrint.global_level == 0 m.print_level = 1 assert MnPrint.global_level == 1 MnPrint.global_level = 0 def test_params(): m = Minuit(func0, x=1, y=2) m.errors = (3, 4) m.fixed["x"] = True m.limits["y"] = (None, 10) # these are the initial param states expected = ( Param(0, "x", 1.0, 3.0, None, False, True, None, None), Param(1, "y", 2.0, 4.0, None, False, False, None, 10), ) assert m.params == expected m.migrad() m.minos() assert m.init_params == expected expected = [ Namespace(number=0, name="x", value=1.0, error=3.0, merror=(-3.0, 3.0)), Namespace(number=1, name="y", value=5.0, error=1.0, merror=(-1.0, 1.0)), ] params = m.params for i, exp in enumerate(expected): p = params[i] assert p.number == exp.number assert p.name == exp.name assert p.value == approx(exp.value, rel=1e-2) assert p.error == approx(exp.error, rel=1e-2) assert p.error == approx(exp.error, rel=1e-2) def test_non_analytical_function(): class Func: i = 0 def __call__(self, a): self.i += 1 return self.i % 3 m = Minuit(Func(), 0) m.migrad() assert not m.fmin.is_valid assert m.fmin.is_above_max_edm def test_non_invertible(): m = Minuit(lambda x, y: 0, 1, 2) m.strategy = 0 m.migrad() assert m.fmin.is_valid m.hesse() assert not m.fmin.is_valid assert m.covariance is None def test_function_without_local_minimum(): m = Minuit(lambda a: -a, 0) m.migrad() assert not m.fmin.is_valid assert m.fmin.is_above_max_edm def test_function_with_maximum(): def func(a): return -(a**2) m = Minuit(func, a=0) m.migrad() assert not m.fmin.is_valid def test_perfect_correlation(): def func(a, b): return (a - b) ** 2 m = Minuit(func, a=1, b=2) m.migrad() assert m.fmin.is_valid assert not m.fmin.has_accurate_covar assert not m.fmin.has_posdef_covar assert m.fmin.has_made_posdef_covar def test_modify_param_state(): m = Minuit(func0, x=1, y=2) m.errors["y"] = 1 m.fixed["y"] = True m.migrad() assert_allclose(m.values, [2, 2], atol=1e-4) assert_allclose(m.errors, [2, 1], atol=1e-4) m.fixed["y"] = False m.values["x"] = 1 m.errors["x"] = 1 assert_allclose(m.values, [1, 2], atol=1e-4) assert_allclose(m.errors, [1, 1], atol=1e-4) m.migrad() assert_allclose(m.values, [2, 5], atol=1e-3) assert_allclose(m.errors, [2, 1], atol=1e-3) m.values["y"] = 6 m.hesse() assert_allclose(m.values, [2, 6], atol=1e-3) assert_allclose(m.errors, [2, 0.35], atol=1e-3) def test_view_lifetime(): m = Minuit(func0, x=1, y=2) val = m.values del m val["x"] = 3 # should not segfault assert val["x"] == 3 def test_hesse_without_migrad(): m = Minuit(lambda x: x**2 + x**4, x=0) m.errordef = 0.5 # second derivative: 12 x^2 + 2 m.hesse() assert m.errors["x"] == approx(0.5**0.5, abs=1e-4) m.values["x"] = 1 m.hesse() assert m.errors["x"] == approx((1.0 / 14.0) ** 0.5, abs=1e-4) assert m.fmin m = Minuit(lambda x: 0, 0) m.hesse() assert not m.accurate assert m.fmin.hesse_failed def test_edm_goal(): m = Minuit(func0, x=0, y=0) m.migrad() assert m.fmin.edm_goal == approx(0.0002) m.hesse() assert m.fmin.edm_goal == approx(0.0002) def throwing(x): raise RuntimeError("user message") def divide_by_zero(x): return 1 / 0 def returning_nan(x): return np.nan def returning_garbage(x): return "foo" @pytest.mark.parametrize( "func,expected", [ (throwing, RuntimeError("user message")), (divide_by_zero, ZeroDivisionError("division by zero")), (returning_nan, RuntimeError("result is NaN")), (returning_garbage, RuntimeError("Unable to cast Python instance")), ], ) def test_bad_functions(func, expected): m = Minuit(func, x=1) m.throw_nan = True with pytest.raises(type(expected)) as excinfo: m.migrad() assert str(expected) in str(excinfo.value) def test_throw_nan(): m = Minuit(returning_nan, x=1) assert not m.throw_nan m.migrad() m.throw_nan = True with pytest.raises(RuntimeError): m.migrad() assert m.throw_nan def returning_nan_array(x): return np.array([1, np.nan]) def returning_garbage_array(x): return np.array([1, "foo"]) def returning_noniterable(x): return 0 @pytest.mark.parametrize( "func,expected", [ (throwing, RuntimeError("user message")), (divide_by_zero, ZeroDivisionError("division by zero")), (returning_nan_array, RuntimeError("result is NaN")), (returning_garbage_array, RuntimeError("Unable to cast Python instance")), (returning_noniterable, RuntimeError()), ], ) def test_bad_functions_np(func, expected): m = Minuit(lambda x: np.dot(x, x), (1, 1), grad=func) m.throw_nan = True with pytest.raises(type(expected)) as excinfo: m.migrad() assert str(expected) in str(excinfo.value) @pytest.mark.parametrize("sign", (-1, 1)) def test_parameter_at_limit(sign): m = Minuit(lambda x: (x - sign * 1.2) ** 2, x=0) m.limits["x"] = (-1, 1) m.migrad() assert m.values["x"] == approx(sign * 1.0, abs=1e-3) assert m.fmin.has_parameters_at_limit m = Minuit(lambda x: (x - sign * 1.2) ** 2, x=0) m.migrad() assert m.values["x"] == approx(sign * 1.2, abs=1e-3) assert not m.fmin.has_parameters_at_limit @pytest.mark.parametrize("iterate,valid", ((1, False), (5, True))) def test_inaccurate_fcn(iterate, valid): def f(x): return abs(x) ** 10 + 1e6 m = Minuit(f, x=2) m.migrad(iterate=iterate) assert m.valid == valid def test_migrad_iterate(): m = Minuit(lambda x: 0, x=2) with pytest.raises(ValueError): m.migrad(iterate=0) def test_precision(): def fcn(x): return np.exp(x * x + 1) m = Minuit(fcn, x=-1) assert m.precision is None m.precision = 0.1 assert m.precision == 0.1 m.migrad() fm1 = m.fmin m.reset() m.precision = 1e-9 m.migrad() fm2 = m.fmin assert fm2.edm < fm1.edm with pytest.raises(ValueError): m.precision = -1.0 fcn.precision = 0.1 fm3 = Minuit(fcn, x=-1).migrad().fmin assert fm3.edm == fm1.edm @pytest.mark.parametrize("grad", (None, func0_grad)) def test_scan(grad): m = Minuit(func0, x=0, y=0, grad=grad) m.errors[0] = 10 m.limits[1] = (-10, 10) m.scan(ncall=99) assert m.fmin.nfcn == approx(99, rel=0.2) if grad is None: assert m.valid assert_allclose(m.values, (2, 5), atol=0.6) def test_scan_with_fixed_par(): m = Minuit(func0, x=3, y=0) m.fixed["x"] = True m.limits[1] = (-10, 10) m.scan() assert m.valid assert_allclose(m.values, (3, 5), atol=0.1) assert m.errors[1] == approx(1, abs=8e-3) m = Minuit(func0, x=5, y=4) m.fixed["y"] = True m.limits[0] = (0, 10) m.scan() assert m.valid assert_allclose(m.values, (2, 4), atol=0.1) assert m.errors[0] == approx(2, abs=1e-1) @pytest.mark.parametrize("grad", (None, func0_grad)) def test_simplex(grad): m = Minuit(func0, x=0, y=0, grad=grad) m.tol = 2e-4 # must decrease tolerance to get same accuracy as Migrad m.simplex() assert m.valid assert_allclose(m.values, (2, 5), atol=5e-3) m2 = Minuit(func0, x=0, y=0, grad=grad) m2.precision = 0.001 m2.simplex() assert m2.fval != m.fval m3 = Minuit(func0, x=0, y=0, grad=grad) m3.simplex(ncall=10) assert 10 <= m3.fmin.nfcn < 15 assert m3.fval > m.fval def test_simplex_with_fixed_par_and_limits(): m = Minuit(func0, x=3, y=0) m.tol = 2e-4 # must decrease tolerance to get same accuracy as Migrad m.fixed["x"] = True m.limits[1] = (-10, 10) m.simplex() assert m.valid assert_allclose(m.values, (3, 5), atol=2e-3) m = Minuit(func0, x=5, y=4) m.tol = 2e-4 # must decrease tolerance to get same accuracy as Migrad m.fixed["y"] = True m.limits[0] = (0, 10) m.simplex() assert m.valid assert_allclose(m.values, (2, 4), atol=3e-3) def test_tolerance(): m = Minuit(func0, x=0, y=0) assert m.tol == 0.1 m.migrad() assert m.valid edm = m.fmin.edm m.tol = 0 m.reset() m.migrad() assert m.fmin.edm < edm m.reset() m.tol = None assert m.tol == 0.1 m.reset() m.migrad() assert m.fmin.edm == edm def test_bad_tolerance(): m = Minuit(func0, x=0, y=0) with pytest.raises(ValueError): m.tol = -1 def test_cfunc(): nb = pytest.importorskip("numba") c_sig = nb.types.double(nb.types.uintc, nb.types.CPointer(nb.types.double)) @nb.cfunc(c_sig) def fcn(n, x): x = nb.carray(x, (n,)) r = 0.0 for i in range(n): r += (x[i] - i) ** 2 return r m = Minuit(fcn, (1, 2, 3)) m.migrad() assert_allclose(m.values, (0, 1, 2), atol=1e-8) @pytest.mark.parametrize("cl", (0.5, None, 0.9)) @pytest.mark.parametrize("experimental", (False, True)) def test_confidence_level(cl, experimental): stats = pytest.importorskip("scipy.stats") mpath = pytest.importorskip("matplotlib.path") cov = ((1.0, 0.5), (0.5, 4.0)) truth = (1.0, 2.0) d = stats.multivariate_normal(truth, cov) def nll(par): return -np.log(d.pdf(par)) nll.errordef = 0.5 cl_ref = 0.68 if cl is None else cl m = Minuit(nll, (0.0, 0.0)) m.migrad() n = 10000 r = d.rvs(n, random_state=1) # check that mncontour indeed contains fraction of random points equal to CL pts = m.mncontour("x0", "x1", cl=cl, experimental=experimental) p = mpath.Path(pts) cl2 = np.sum(p.contains_points(r)) / n assert cl2 == approx(cl_ref, abs=0.01) # check that minos interval indeed contains fraction of random points equal to CL m.minos(cl=cl) for ipar, (v, me) in enumerate(zip(m.values, m.merrors.values())): a = v + me.lower b = v + me.upper cl2 = np.sum((a < r[:, ipar]) & (r[:, ipar] < b)) / n assert cl2 == approx(cl_ref, abs=0.01) def test_repr(): m = Minuit(func0, 0, 0) assert repr(m) == f"{m.params!r}" m.migrad() assert repr(m) == f"{m.fmin!r}\n{m.params!r}\n{m.covariance!r}" m.minos() assert repr(m) == f"{m.fmin!r}\n{m.params!r}\n{m.merrors!r}\n{m.covariance!r}" @pytest.mark.parametrize("grad", (None, func0_grad)) def test_pickle(grad): import pickle m = Minuit(func0, x=1, y=1, grad=grad) m.fixed[1] = True m.limits[0] = 0, 10 m.migrad() pkl = pickle.dumps(m) m2 = pickle.loads(pkl) assert id(m2) != id(m) # check correct linking of views assert id(m2.values._minuit) == id(m2) assert id(m2.errors._minuit) == id(m2) assert id(m2.limits._minuit) == id(m2) assert id(m2.fixed._minuit) == id(m2) assert m2.init_params == m.init_params assert m2.params == m.params assert m2.fmin == m.fmin assert_equal(m2.covariance, m.covariance) m.fixed = False m2.fixed = False m.migrad() m.minos() m2.migrad() m2.minos() assert m2.merrors == m.merrors assert m2.fmin.fval == m.fmin.fval assert m2.fmin.edm == m.fmin.edm assert m2.fmin.nfcn == m.fmin.nfcn assert m2.fmin.ngrad == m.fmin.ngrad def test_minos_new_min(): xref = [1.0] m = Minuit(lambda x: (x - xref[0]) ** 2, x=0) m.migrad() assert m.values[0] == approx(xref[0], abs=1e-3) m.minos() assert m.merrors["x"].lower == approx(-1, abs=1e-2) assert m.merrors["x"].upper == approx(1, abs=1e-2) xref[0] = 1.1 m.minos() # values are not updated... assert m.values[0] == approx(1.0, abs=1e-3) # should be 1.1 # ...but interval is correct assert m.merrors["x"].lower == approx(-0.9, abs=1e-2) assert m.merrors["x"].upper == approx(1.1, abs=1e-2) def test_minos_without_migrad(): m = Minuit(lambda x, y: (x - 1) ** 2 + (y / 2) ** 2, 1.001, 0.001) m.minos() me = m.merrors["x"] assert me.is_valid assert me.lower == approx(-1, abs=5e-3) assert me.upper == approx(1, abs=5e-3) me = m.merrors["y"] assert me.is_valid assert me.lower == approx(-2, abs=5e-3) assert me.upper == approx(2, abs=5e-3) def test_missing_ndata(): m = Minuit(lambda a: a, 1) assert_equal(m.ndof, np.nan) def test_call_limit_reached_in_hesse(): m = Minuit(lambda x: ((x - 1.2) ** 4).sum(), np.ones(10) * 10) m.migrad(ncall=200) assert m.fmin.has_reached_call_limit assert m.fmin.nfcn < 205 def test_bad_cl(): m = Minuit(func0, 1, 1) m.migrad() for cl in (0, -1): with pytest.raises(ValueError): m.minos(cl=cl) with pytest.raises(ValueError): m.mncontour("x", "y", cl=cl) def test_negative_errors(): m = Minuit(func0, -1, -1) assert np.all(np.array(m.errors) > 0) with pytest.warns(): m.errors[0] = -1 assert m.errors[0] > 0 with pytest.warns(): m.errors = -2 assert np.all(np.array(m.errors) > 0) m.errors = 10 assert_allclose(m.errors, 10) m.errors = (1, 2) assert_allclose(m.errors, (1, 2)) def test_visualize(): m = Minuit(func0, 1, 1) m.migrad() with pytest.raises(AttributeError): m.visualize() kwargs = {} func0.visualize = lambda args, **kw: kwargs.update(kw) m.visualize(foo="bar") assert kwargs == {"foo": "bar"} del func0.visualize def test_annotated_cost_function(): def cost(a, b: Annotated[float, 0.1:1]): return a**2 + b**2 m = Minuit(cost, 0.5, 0.5) assert m.limits[0] == (-np.inf, np.inf) assert m.limits[1] == (0.1, 1.0) m.migrad() assert_allclose(m.values, (0, 0.1), atol=1e-2) m2 = Minuit(cost, 0.5, 0.5, name=("x", "y")) assert m2.limits["x"] == (-np.inf, np.inf) assert m2.limits["y"] == (0.1, 1.0) m.migrad() assert_allclose(m.values, (0, 0.1), atol=1e-2) def test_enforced_grad(): def cost(a, b): return a**2 + b**2 with pytest.raises(ValueError): Minuit(cost, 0, 0, grad=True) def test_bad_grad(): def cost(a, b): return a**2 + b**2 with pytest.raises(ValueError, match="provided gradient is not a CostGradient"): Minuit(cost, 0, 0, grad="foo") def test_errordef_already_set_warning(): def cost(a, b): return a**2 + b**2 cost.errordef = 1 m = Minuit(cost, 0, 0) m.hesse() assert_allclose(m.errors, [1, 1]) with pytest.warns(ErrordefAlreadySetWarning): m.errordef = 4 # check that cost.errordef value is still overridden m.hesse() assert_allclose(m.errors, [2, 2]) def test_mnprofile_bad_cost(): def fn(a, b): if b > 0: return a**2 return (a - 0.1) ** 2 m = Minuit(fn, 1, 2) # test iterative fitting with custom precision # m.precision = 1e-18 m.migrad() with pytest.warns(IMinuitWarning, match="MIGRAD fails to converge"): m.mnprofile("a") def test_migrad_iterative_with_precision(): def fn(a, b): return 0 m1 = Minuit(fn, 1, 2) m1.precision = 1e-7 m1.migrad(iterate=5) m2 = Minuit(fn, 1, 2) m2.precision = 1e-7 m2.migrad(iterate=1) assert m2.fmin.nfcn < m1.fmin.nfcn iminuit-2.30.1/tests/test_parse_version.py0000644000000000000000000000102714332717401015635 0ustar00from iminuit._parse_version import parse_version import pytest @pytest.mark.parametrize( "s,ref", [ ("1.2", (1, 2)), ("1.2.3", (1, 2, 3)), ("1.2a1", (1, 2)), ("1.2.3a1", (1, 2, 3)), ("1.2.post1", (1, 2)), ("1.2.3.post1", (1, 2, 3)), ("1.2a1.dev1", (1, 2)), ("1.2.3a1.dev1", (1, 2, 3)), ], ) def test_parse_version(s, ref): assert parse_version(s) == ref def test_parse_version_bad(): with pytest.raises(ValueError): parse_version("a.b.c") iminuit-2.30.1/tests/test_pdg_format.py0000644000000000000000000002356714332717401015115 0ustar00# Copyright 2020 Hans Dembinski # 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. # 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 HOLDER 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. # test: pytest --doctest-modules coverage report: pytest --cov --cov-report html import pytest from iminuit.pdg_format import ( _find_smallest_nonzero_abs_value, _is_asym, _unpack, _strip, _unpacked_index, pdg_format, term, latex, ) import math def test_find_smallest_nonzero_abs_value(): assert _find_smallest_nonzero_abs_value((-1.1, 3)) == (0, 1.1) assert _find_smallest_nonzero_abs_value((-10, 3, 1.2, 0, 4)) == (2, 1.2) assert _find_smallest_nonzero_abs_value(()) == (None, math.inf) assert _find_smallest_nonzero_abs_value((0, math.inf, -math.inf)) == ( None, math.inf, ) def test_is_asym(): assert _is_asym((1, 2)) assert not _is_asym(1) assert _is_asym([1, 2]) with pytest.raises(ValueError): _is_asym([]) with pytest.raises(ValueError): _is_asym([1, 2, 3]) def test_unpack(): assert _unpack([1, (2, 3), 4]) == [1, -2, 3, 4] with pytest.raises(ValueError): _unpack([1, [2, 3, 4]]) def test_unpacked_index(): assert _unpacked_index([1, 1], 0) == 0 assert _unpacked_index([1, 1], 1) == 1 assert _unpacked_index([1, 1], 2) == 2 assert _unpacked_index([1, -1, 1], 0) == 0 assert _unpacked_index([1, -1, 1], 1) == 1 assert _unpacked_index([1, -1, 1], 2) == 3 assert _unpacked_index([1, -1, 1, 1], 3) == 4 assert _unpacked_index([1, -1, 1, -1, 1], 3) == 5 def test_strip(): assert _strip(["123", "20"]) == ["123", "20"] assert _strip(["10", "20"]) == ["10", "20"] assert _strip(["0.10", "0.20", "0.30"]) == ["0.1", "0.2", "0.3"] assert _strip(["0.11", "0.20"]) == ["0.11", "0.20"] assert _strip(["10.0", "20.0"]) == ["10", "20"] assert _strip(["1.200", "3.40"]) == ["1.20", "3.4"] assert _strip(["0.000", "0.000"]) == ["0", "0"] assert _strip(["-0.00", "0.00"]) == ["0", "0"] def test_term_format(): def ft(*args, **kwargs): return pdg_format(*args, format=term, **kwargs) assert ft(2.345e-09, 0.1e-09) == "(2.35 ± 0.10)E-09" assert ft(2.345e-09, 0.354e-09) == "(2.35 ± 0.35)E-09" assert ft(2.345e-09, 0.355e-09) == "(2.3 ± 0.4)E-09" assert ft(2.345e-09, 0.949e-09) == "(2.3 ± 0.9)E-09" assert ft(2.345e-09, 0.95e-09) == "(2.3 ± 1.0)E-09" assert ft(2.345e-09, 0.999e-09) == "(2.3 ± 1.0)E-09" assert ft(2.3456, 0.001) == "2.3456 ± 0.0010" assert ft(2.3456, 0.00354) == "2.3456 ± 0.0035" assert ft(2.3456, 0.00355) == "2.346 ± 0.004" assert ft(2.3456, 0.00949) == "2.346 ± 0.009" assert ft(2.3456, 0.0095) == "2.346 ± 0.010" assert ft(2.3456, 0.00999) == "2.346 ± 0.010" assert ft(2.3456, 0.01) == "2.346 ± 0.010" assert ft(2.3456, 0.0354) == "2.346 ± 0.035" assert ft(2.3456, 0.0355) == "2.35 ± 0.04" assert ft(2.3456, 0.0949) == "2.35 ± 0.09" assert ft(2.3456, 0.095) == "2.35 ± 0.10" assert ft(2.3456, 0.0999) == "2.35 ± 0.10" assert ft(2.3456, 0.1) == "2.35 ± 0.10" assert ft(2.3456, 0.354) == "2.35 ± 0.35" assert ft(2.3456, 0.355) == "2.3 ± 0.4" assert ft(2.3456, 0.949) == "2.3 ± 0.9" assert ft(2.3456, 0.95) == "2.3 ± 1.0" assert ft(2.3456, 0.999) == "2.3 ± 1.0" assert ft(2.3456, 1) == "2.3 ± 1.0" assert ft(2.3456, 3.54) == "2.3 ± 3.5" assert ft(2.3456, 3.55) == "2 ± 4" assert ft(2.3456, 9.49) == "2 ± 9" assert ft(2.3456, 9.5) == "2 ± 10" assert ft(2.3456, 9.99) == "2 ± 10" assert ft(23.456, 10) == "23 ± 10" assert ft(23.456, 35.4) == "23 ± 35" assert ft(23.456, 35.5) == "20 ± 40" assert ft(23.456, 94.9) == "20 ± 90" assert ft(23.456, 95.0) == "20 ± 100" assert ft(23.456, 99.9) == "20 ± 100" assert ft(234.56, 100) == "(0.23 ± 0.10)E+03" assert ft(234.56, 354) == "(0.23 ± 0.35)E+03" assert ft(234.56, 355) == "(0.2 ± 0.4)E+03" assert ft(234.56, 949) == "(0.2 ± 0.9)E+03" assert ft(234.56, 950) == "(0.2 ± 1.0)E+03" assert ft(234.56, 999) == "(0.2 ± 1.0)E+03" assert ft(2345.6, 1000) == "(2.3 ± 1.0)E+03" assert ft(2345.6, 3540) == "(2.3 ± 3.5)E+03" assert ft(2345.6, 3550) == "(2 ± 4)E+03" assert ft(2345.6, 9490) == "(2 ± 9)E+03" assert ft(2345.6, 9500) == "(2 ± 10)E+03" assert ft(2345.6, 9990) == "(2 ± 10)E+03" assert ft(2.3456e12, 1e11) == "(2.35 ± 0.10)E+12" assert ft(2.3456e12, 3.54e11) == "(2.35 ± 0.35)E+12" assert ft(2.3456e12, 3.55e11) == "(2.3 ± 0.4)E+12" assert ft(2.3456e12, 9.49e11) == "(2.3 ± 0.9)E+12" assert ft(2.3456e12, 9.5e11) == "(2.3 ± 1.0)E+12" assert ft(2.3456e12, 9.99e11) == "(2.3 ± 1.0)E+12" assert ft(-2.3456e13, 1e11) == "(-23.46 ± 0.10)E+12" assert ft(-2.3456e13, 3.54e11) == "(-23.46 ± 0.35)E+12" assert ft(-2.3456e13, 3.55e11) == "(-23.5 ± 0.4)E+12" assert ft(-2.3456e13, 9.49e11) == "(-23.5 ± 0.9)E+12" assert ft(-2.3456e13, 9.5e11) == "(-23.5 ± 1.0)E+12" assert ft(-2.3456e13, 9.99e11) == "(-23.5 ± 1.0)E+12" assert ft(math.nan, 1.0) == "nan ± 1" assert ft(math.nan, 3.54) == "nan ± 3.5" assert ft(math.nan, 3.55) == "nan ± 4" assert ft(math.nan, 9.49) == "nan ± 9" assert ft(math.nan, 9.99) == "nan ± 10" assert ft(math.inf, 1.0) == "inf ± 1" assert ft(math.inf, 3.54) == "inf ± 3.5" assert ft(-math.inf, 3.55) == "-inf ± 4" assert ft(math.inf, 9.49) == "inf ± 9" assert ft(-math.inf, 9.99) == "-inf ± 10" assert ft(math.nan, 1.0e3) == "(nan ± 1)E+03" assert ft(math.nan, 3.54e3) == "(nan ± 3.5)E+03" assert ft(math.nan, 3.55e3) == "(nan ± 4)E+03" assert ft(math.nan, 9.49e3) == "(nan ± 9)E+03" assert ft(math.nan, 9.99e3) == "(nan ± 10)E+03" assert ft(2.3456, math.nan) == "2.3456 ± nan" assert ft(1.2345e9, math.nan) == "(1.2345 ± nan)E+09" assert ft(2.3456e4, math.inf) == "(2.3456 ± inf)E+04" # implementation is robust against input errors assert ft(2.3456e-3, -1) == "0 -1" assert ft(0, 0) == "0 ± 0" assert ft(2.3456e10, 0) == "(2.3456 ± 0.0000)E+10" assert ft(2.3456e10, 0) == "(2.3456 ± 0.0000)E+10" assert ft(1.2345e100, 1.2345e100) == "(0.012 ± 0.012)E+102" assert ft(1.2345, 0.123, 0.0123) == "1.234 ± 0.123 ± 0.012" assert ft(1.2345, 0.1, 0.4) == "1.23 ± 0.10 ± 0.40" assert ft(1.234, (0.11, 0.22), 0.45) == "1.23 -0.11 +0.22 ± 0.45" assert ( ft(1.234, -0.11, 0.22, 0.45, labels=("a", "b")) == "1.23 -0.11 +0.22 (a) ± 0.45 (b)" ) assert ( ft(1.234, -0.11, 0.22, 0.45, labels=("a", "b"), leader=1) == "1.2 -0.1 +0.2 (a) ± 0.5 (b)" ) data_as_list = [1.234, -0.11, 0.22, 0.45] assert ft(*data_as_list, leader=1) == "1.2 -0.1 +0.2 ± 0.5" assert ft(1.2, -0.0, 0.0, 0.0, leader=0) == "1.2 -0.0 +0.0 ± 0.0" assert ft(-1.234567e-22, 1.234567e-11) == "(-0.000 ± 0.012)E-09" def test_latex_format(): def ft(*args, **kwargs): return pdg_format(*args, format=latex, **kwargs) nan = math.nan inf = math.inf assert ft(234.56, 12.3) == r"235 \pm 12" assert ft(2345.6, 123) == r"(2.35 \pm 0.12) \times 10^{3}" assert ft(2345.6, 355) == r"(2.3 \pm 0.4) \times 10^{3}" assert ft(234.5, 123.4) == r"(0.23 \pm 0.12) \times 10^{3}" assert ft(23.45, 12.34) == r"23 \pm 12" assert ft(2.345, 1.234) == r"2.3 \pm 1.2" assert ft(0.2345, 0.1234) == r"0.23 \pm 0.12" assert ft(0.02345, 0.01234) == r"0.023 \pm 0.012" assert ft(0.02345, 0.09123) == r"0.02 \pm 0.09" assert ft(nan, 2.34e3) == r"(\mathrm{NaN} \pm 2.3) \times 10^{3}" assert ft(1e9, nan) == r"(1 \pm \mathrm{NaN}) \times 10^{9}" assert ft(inf, 2.345e3) == r"(\infty \pm 2.3) \times 10^{3}" assert ft(1.2345e9, inf) == r"(1.2345 \pm \infty) \times 10^{9}" assert ft(inf, -inf) == r"\infty \pm \infty" # tolerance against input errors assert ft(0, 0) == r"0 \pm 0" assert ft(1.234, 0.123, 2.345) == r"1.23 \pm 0.12 \pm 2.35" assert ft(1.234, 0.96, 0.45) == r"1.2 \pm 1.0 \pm 0.5" assert ( ft(1.234, (0.12, 0.78), (0.045, 0.067)) == r"1.23 {}_{-0.12}^{+0.78} {}_{-0.05}^{+0.07}" ) assert ( ft(1.234, (0.12, 0.78), (0.045, 0.067)) == r"1.23 {}_{-0.12}^{+0.78} {}_{-0.05}^{+0.07}" ) assert ( ft(1.234, (0.12, 0.78), (0.45, 0.67), leader=1) == r"1.2 {}_{-0.1}^{+0.8} {}_{-0.5}^{+0.7}" ) assert ( ft(1.234, -0.12, 0.78, -0.45, 0.67, leader=1) == r"1.2 {}_{-0.1}^{+0.8} {}_{-0.5}^{+0.7}" ) assert ( ft(1.234, 0.123, 2.345, labels=(r"_\mathrm{a}", "b")) == r"1.23 \pm 0.12_\mathrm{a} \pm 2.35 (\mathrm{b})" ) assert ( ft(1.234, (0.123, 2.345), 4.56, labels=("a", "b")) == r"1.23 {}_{-0.12}^{+2.35} (\mathrm{a}) \pm 4.56 (\mathrm{b})" ) iminuit-2.30.1/tests/test_repr.py0000644000000000000000000003104014332717401013724 0ustar00# flake8: noqa: E501 from iminuit import Minuit from iminuit.util import Param, Matrix, FMin, MError from iminuit import _repr_html, _repr_text import pytest from argparse import Namespace from pathlib import Path import numpy as np from iminuit._hide_modules import hide_modules nan = float("nan") inf = float("infinity") def f1(x, y): return (x - 2) ** 2 + (y - 1) ** 2 / 0.25 + 1 def test_color_1(): g = _repr_html.ColorGradient((-1, 10, 10, 20), (2, 20, 20, 10)) assert g.rgb(-1) == "rgb(10,10,20)" assert g.rgb(2) == "rgb(20,20,10)" assert g.rgb(-1.00001) == "rgb(10,10,20)" assert g.rgb(1.99999) == "rgb(20,20,10)" assert g.rgb(0.5) == "rgb(15,15,15)" def test_color_2(): g = _repr_html.ColorGradient( (-1, 50, 50, 250), (0, 100, 100, 100), (1, 250, 50, 50) ) assert g.rgb(-1) == "rgb(50,50,250)" assert g.rgb(-0.5) == "rgb(75,75,175)" assert g.rgb(0) == "rgb(100,100,100)" assert g.rgb(0.5) == "rgb(175,75,75)" assert g.rgb(1) == "rgb(250,50,50)" def test_html_tag(): tag = _repr_html.tag def stag(*args, **kwargs): return _repr_html.to_str(tag(*args, **kwargs)) # fmt: off assert stag('foo', 'bar', baz='hi', xyzzy='2') == ' bar ' assert stag('foo') == """""" assert tag('foo', tag('bar', 'baz')) == ['', [' baz '], ''] assert stag('foo', tag('bar', 'baz')) == """ baz """ # fmt: on def ref(fn): with open(Path(__file__).parent / fn, encoding="utf-8") as f: return f.read().strip() def test_pdg_format(): assert _repr_text.pdg_format(1.2567, 0.1234) == ["1.26", "0.12"] assert _repr_text.pdg_format(1.2567e3, 0.1234e3) == ["1.26e3", "0.12e3"] assert _repr_text.pdg_format(1.2567e4, 0.1234e4) == ["12.6e3", "1.2e3"] assert _repr_text.pdg_format(1.2567e-1, 0.1234e-1) == ["0.126", "0.012"] assert _repr_text.pdg_format(1.2567e-2, 0.1234e-2) == ["0.0126", "0.0012"] assert _repr_text.pdg_format(1.0, 0.0, 0.25) == ["1.00", "0.00", "0.25"] assert _repr_text.pdg_format(0, 1, -1) == ["0", "1", "-1"] assert _repr_text.pdg_format(2, -1, 1) == ["2", "-1", "1"] assert _repr_text.pdg_format(2.01, -1.01, 1.01) == ["2", "-1", "1"] assert _repr_text.pdg_format(1.999, -0.999, 0.999) == ["2", "-1", "1"] assert _repr_text.pdg_format(1, 0.5, -0.5) == ["1.0", "0.5", "-0.5"] assert _repr_text.pdg_format(1.0, 1e-3) == ["1.000", "0.001"] assert _repr_text.pdg_format(1.0, 1e-4) == ["1.0000", "0.0001"] assert _repr_text.pdg_format(1.0, 1e-5) == ["1.00000", "0.00001"] assert _repr_text.pdg_format(-1.234567e-22, 1.234567e-11) == ["-0", "0.012e-9"] assert _repr_text.pdg_format(nan, 1.23e-2) == ["nan", "0.012"] assert _repr_text.pdg_format(nan, 1.23e10) == ["nan", "0.012e12"] assert _repr_text.pdg_format(nan, -nan) == ["nan", "nan"] assert _repr_text.pdg_format(inf, 1.23e10) == ["inf", "0.012e12"] def test_matrix_format(): def a(*args): return np.reshape(args, (2, 2)) assert _repr_text.matrix_format(a(1e1, 2e2, -3e3, -4e4)) == [ "10", "200", "-3.00e3", "-4e+04", ] assert _repr_text.matrix_format(a(2e2, nan, -nan, -4e4)) == [ "200", "nan", "nan", "-4e+04", ] assert _repr_text.matrix_format(a(2e2, inf, -nan, -4e4)) == [ "200", "inf", "nan", "-4e+04", ] @pytest.fixture def minuit(): m = Minuit(f1, x=0, y=0) m.tol = 1e-4 m.migrad() m.hesse() m.minos() return m @pytest.fixture def fmin_good(): fm = Namespace( fval=11.456, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=True, has_posdef_covar=True, has_made_posdef_covar=False, hesse_failed=False, has_covariance=True, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) return FMin(fm, "Migrad", 10, 3, 10, 1e-4, 0.01) @pytest.fixture def fmin_bad(): fm = Namespace( fval=nan, edm=1.23456e-10, up=0.5, is_valid=False, has_valid_parameters=False, has_accurate_covar=False, has_posdef_covar=False, has_made_posdef_covar=True, hesse_failed=True, has_covariance=False, is_above_max_edm=True, has_reached_call_limit=True, has_parameters_at_limit=True, errordef=1, state=[ Namespace( has_limits=True, is_fixed=False, value=0, error=0.5, lower_limit=0, upper_limit=1, has_lower_limit=True, has_upper_limit=True, ) ], ) return FMin(fm, "SciPy[L-BFGS-B]", 100000, 200000, 1, 1e-5, 1.2) @pytest.fixture def fmin_no_cov(): fm = Namespace( fval=11.456, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=False, has_posdef_covar=False, has_made_posdef_covar=False, hesse_failed=False, has_covariance=False, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) return FMin(fm, "Migrad", 10, 3, 10, 1e-4, 0.01) def test_html_fmin_good(fmin_good): assert fmin_good._repr_html_() == ref("fmin_good.html").format( good=_repr_html.good_style ) def test_html_fmin_bad(fmin_bad): assert fmin_bad._repr_html_() == ref("fmin_bad.html").format( bad=_repr_html.bad_style, warn=_repr_html.warn_style ) def test_html_fmin_no_cov(fmin_no_cov): assert fmin_no_cov._repr_html_() == ref("fmin_no_cov.html").format( good=_repr_html.good_style, bad=_repr_html.bad_style, warn=_repr_html.warn_style ) def test_html_params(minuit): assert minuit.init_params._repr_html_() == ref("params_init.html") assert minuit.params._repr_html_() == ref("params.html") def test_html_params_with_limits(): m = Minuit(f1, x=3, y=5) m.fixed["x"] = True m.errors = (0.2, 0.1) m.limits = ((0, None), (0, 10)) assert m.init_params._repr_html_() == ref("params_with_limits.html") def test_html_merror(minuit): me = minuit.merrors[0] assert me._repr_html_() == ref("merror.html").format(good=_repr_html.good_style) def test_html_merrors(minuit): mes = minuit.merrors assert mes._repr_html_() == ref("merrors.html").format(good=_repr_html.good_style) def test_html_matrix(): matrix = Matrix(("x", "y")) matrix[:] = ((1.0, 0.0), (0.0, 0.25)) assert matrix._repr_html_() == ref("matrix.html") def test_html_correlation_matrix(): matrix = Matrix(("x", "y")) matrix[:] = ((1.0, 0.707), (0.707, 1.0)) assert matrix._repr_html_() == ref("matrix_2.html") def test_html_minuit(): m = Minuit(lambda x, y: x**2 + 4 * y**2, x=0, y=0) assert m._repr_html_() == m.params._repr_html_() m.migrad() assert ( m._repr_html_() == m.fmin._repr_html_() + m.params._repr_html_() + m.covariance._repr_html_() ) m.minos() assert ( m._repr_html_() == m.fmin._repr_html_() + m.params._repr_html_() + m.merrors._repr_html_() + m.covariance._repr_html_() ) def test_text_fmin_good(fmin_good): assert _repr_text.fmin(fmin_good) == ref("fmin_good.txt") def test_text_fmin_bad(fmin_bad): assert _repr_text.fmin(fmin_bad) == ref("fmin_bad.txt") def test_text_fmin_no_cov(fmin_no_cov): assert _repr_text.fmin(fmin_no_cov) == ref("fmin_no_cov.txt") def test_text_fmin_not_posdef(): fm = Namespace( fval=11.456, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=False, has_posdef_covar=False, has_made_posdef_covar=False, hesse_failed=True, has_covariance=False, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) fmin = FMin(fm, "Migrad", 10, 3, 10, 1e-4, 0.01) assert _repr_text.fmin(fmin) == ref("fmin_not_posdef.txt") def test_text_fmin_made_posdef(): fm = Namespace( fval=11.456, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=False, has_posdef_covar=True, has_made_posdef_covar=True, hesse_failed=False, has_covariance=True, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) fmin = FMin(fm, "Migrad", 10, 3, 10, 1e-4, 0.01) assert _repr_text.fmin(fmin) == ref("fmin_made_posdef.txt") def test_text_fmin_approximate(): fm = Namespace( fval=11.456, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=False, has_posdef_covar=True, has_made_posdef_covar=False, hesse_failed=False, has_covariance=True, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) fmin = FMin(fm, "Migrad", 10, 3, 10, 1e-4, 0.01) assert _repr_text.fmin(fmin) == ref("fmin_approximate.txt") def test_text_params(minuit): assert _repr_text.params(minuit.params) == ref("params.txt") def test_text_params_with_latex_names(): pytest.importorskip("unicodeitplus") m = Minuit(lambda x: x**2, 1, name=[r"$\alpha$"]) assert _repr_text.params(m.params) == ref("params_latex_1.txt") with hide_modules("unicodeitplus"): from iminuit.warnings import OptionalDependencyWarning with pytest.warns( OptionalDependencyWarning, match="rendering simple LaTeX requires optional package 'unicodeitplus'", ): assert _repr_text.params(m.params) == ref("params_latex_2.txt") def test_text_params_with_long_names(): mps = [ Param( 0, "super-long-name", 0, 0, None, False, False, None, None, ) ] assert _repr_text.params(mps) == ref("params_long_names.txt") def test_text_params_difficult_values(): mps = [ Param( 0, "x", -1.234567e-22, 1.234567e-11, None, True, False, None, None, ) ] assert _repr_text.params(mps) == ref("params_difficult_values.txt") def test_text_params_with_limits(): m = Minuit( f1, x=3, y=5, ) m.fixed["x"] = True m.errors = (0.2, 0.1) m.limits = ((0, None), (0, 10)) assert _repr_text.params(m.params) == ref("params_with_limits.txt") def test_text_merror(): me = MError( 0, "x", -1.0, 1.0, True, True, True, False, False, False, False, False, False, 42, 0.123, ) assert _repr_text.merrors({None: me}) == ref("merror.txt") def test_text_merrors(minuit): assert _repr_text.merrors(minuit.merrors) == ref("merrors.txt") def test_text_matrix(): m = Matrix({"x": 0, "y": 1}) m[:] = ((1.0, -0.0), (-0.0, 0.25)) assert _repr_text.matrix(m) == ref("matrix.txt") def test_text_matrix_mini(): m = Matrix({"x": 0}) m[:] = [1.0] assert _repr_text.matrix(m) == ref("matrix_mini.txt") def test_text_matrix_large(): m = Matrix({"x": 0, "y": 1, "z": 2}) m[:] = ((1, 2, 3), (4, 5, 6), (7, 8, 9)) assert _repr_text.matrix(m) == ref("matrix_large.txt") def test_text_matrix_with_long_names(): m = Matrix({"super-long-name": 0, "x": 1}) m[:] = ((1.0, 0.1), (0.1, 1.0)) assert _repr_text.matrix(m) == ref("matrix_long_names.txt") def test_text_matrix_difficult_values(): m = Matrix({"x": 0, "y": 1}) m[:] = ((-1.23456, 0), (0, 0)) assert _repr_text.matrix(m) == ref("matrix_difficult_values.txt") def test_text_minuit(): m = Minuit(lambda x, y: x**2 + 4 * y**2, x=0, y=0) assert str(m) == str(m.params) m.migrad() assert str(m) == str(m.fmin) + "\n" + str(m.params) + "\n" + str(m.covariance) m.minos() assert str(m) == str(m.fmin) + "\n" + str(m.params) + "\n" + str( m.merrors ) + "\n" + str(m.covariance) iminuit-2.30.1/tests/test_repr_pretty.py0000644000000000000000000000742514332717401015345 0ustar00from contextlib import contextmanager from iminuit.testing import sphere_np from iminuit import util, _repr_text as tx, Minuit from argparse import Namespace class PrintAssert: data = "" def __init__(self, expected): self.expected = expected def __enter__(self): return self def __exit__(self, *args): assert self.data == self.expected def text(self, arg): self.data += arg def pretty(self, arg): if hasattr(arg, "_repr_pretty_"): arg._repr_pretty_(self, False) else: self.data += repr(arg) def breakable(self): self.data += "\n" @contextmanager def group(self, n, start, stop): self.data += start yield self.data += stop def test_Minuit(): m = Minuit(sphere_np, (0, 0)) with PrintAssert("") as pr: m._repr_pretty_(pr, True) with PrintAssert(tx.params(m.params)) as pr: m._repr_pretty_(pr, False) m.migrad() expected = ( tx.fmin(m.fmin) + "\n" + tx.params(m.params) + "\n" + tx.matrix(m.covariance) ) with PrintAssert(expected) as pr: m._repr_pretty_(pr, False) m.minos() expected = ( tx.fmin(m.fmin) + "\n" + tx.params(m.params) + "\n" + tx.merrors(m.merrors) + "\n" + tx.matrix(m.covariance) ) with PrintAssert(expected) as pr: m._repr_pretty_(pr, False) def test_Matrix(): m = util.Matrix(("a", "b")) m[:] = [[1, 2], [3, 4]] with PrintAssert("") as pr: m._repr_pretty_(pr, True) with PrintAssert(tx.matrix(m)) as pr: m._repr_pretty_(pr, False) def test_Param(): values = 3, "foo", 1.2, 3.4, None, False, False, 42, None p = util.Param(*values) with PrintAssert("Param(...)") as pr: p._repr_pretty_(pr, True) with PrintAssert(tx.params([p])) as pr: p._repr_pretty_(pr, False) def test_Params(): p = util.Params([util.Param(3, "foo", 1.2, 3.4, None, False, False, 42, None)]) with PrintAssert("Params(...)") as pr: p._repr_pretty_(pr, True) with PrintAssert(tx.params(p)) as pr: p._repr_pretty_(pr, False) def test_MError(): me = util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.7, ) with PrintAssert("") as pr: me._repr_pretty_(pr, True) with PrintAssert(tx.merrors({None: me})) as pr: me._repr_pretty_(pr, False) def test_MErrors(): mes = util.MErrors( x=util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.7, ) ) with PrintAssert("") as pr: mes._repr_pretty_(pr, True) with PrintAssert(tx.merrors(mes)) as pr: mes._repr_pretty_(pr, False) def test_FMin(): fm = Namespace( fval=1.23456e-10, edm=1.23456e-10, up=0.5, is_valid=True, has_valid_parameters=True, has_accurate_covar=True, has_posdef_covar=True, has_made_posdef_covar=False, hesse_failed=False, has_covariance=True, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, errordef=1, state=[], ) fmin = util.FMin(fm, "foo", 1, 2, 1, 0.1, 1.2) with PrintAssert("") as pr: fmin._repr_pretty_(pr, True) with PrintAssert(tx.fmin(fmin)) as pr: fmin._repr_pretty_(pr, False) iminuit-2.30.1/tests/test_scipy.py0000644000000000000000000001511114332717401014104 0ustar00import pytest from numpy.testing import assert_allclose from iminuit import Minuit from iminuit.testing import rosenbrock, rosenbrock_grad import numpy as np scopt = pytest.importorskip("scipy.optimize") def fcn(a, b): return a**2 + ((b - 1) / 2.0) ** 2 + 3 def grad(a, b): return 2 * a, b - 1 def hess(a, b): return [[2, 0], [0, 0.5]] def hessp(a, b, v): return np.dot(hess(a, b), v) @pytest.mark.parametrize("array_call", (False, True)) @pytest.mark.parametrize("fixed", (False, True)) @pytest.mark.parametrize( "method", ( "Nelder-Mead", "Powell", "CG", "BFGS", "Newton-CG", "L-BFGS-B", "TNC", "COBYLA", "SLSQP", "trust-constr", "dogleg", "trust-ncg", "trust-exact", "trust-krylov", ), ) def test_scipy_method(array_call, fixed, method): fn = (lambda par: fcn(*par)) if array_call else fcn gr = None he = None hep = None if method in ( "Newton-CG", "trust-constr", "dogleg", "trust-ncg", "trust-exact", "trust-krylov", ): gr = (lambda par: grad(*par)) if array_call else grad if method in ("Newton-CG", "dogleg", "trust-ncg", "trust-exact", "trust-krylov"): he = (lambda par: hess(*par)) if array_call else hess if method in ("Newton-CG", "trust-ncg", "trust-krylov", "trust-constr"): hep = (lambda par, v: hessp(*par, v)) if array_call else hessp if array_call: m = Minuit(fn, (1, 2), grad=gr) else: m = Minuit(fn, a=1, b=2, grad=gr) m.fixed[0] = fixed m.scipy(method=method, hess=he) assert m.valid if fixed: assert_allclose(m.values, [1, 1], atol=1e-3) assert_allclose(m.errors[1], 2, rtol=1e-2) else: assert_allclose(m.values, [0, 1], atol=1e-3) assert_allclose(m.errors, [1, 2], rtol=1e-2) if hep: m.scipy(method=method, hessp=hep) assert m.valid if fixed: assert_allclose(m.values, [1, 1], atol=1e-3) assert_allclose(m.errors[1], 2, rtol=1e-2) else: assert_allclose(m.values, [0, 1], atol=1e-3) assert_allclose(m.errors, [1, 2], rtol=1e-2) @pytest.mark.parametrize("stra", (0, 1)) @pytest.mark.parametrize("grad", (None, grad)) def test_scipy_unbounded(stra, grad): m = Minuit(fcn, a=1, b=2, grad=grad) m.strategy = stra m.scipy() assert m.valid assert m.accurate == (stra == 1) assert_allclose(m.values, [0, 1], atol=1e-3) if stra == 1: assert_allclose(m.errors, [1, 2], atol=3e-2) if grad: assert m.fmin.ngrad > 0 else: assert m.fmin.ngrad == 0 @pytest.mark.parametrize("stra", (0, 1)) @pytest.mark.parametrize("grad", (None, grad)) @pytest.mark.parametrize( "lower,upper", ( (-0.1, None), (0, None), (0.1, None), (None, -0.1), (None, 0), (None, 0.1), (-0.1, 0.1), ), ) def test_scipy_bounded(stra, grad, lower, upper): m = Minuit(fcn, a=1, b=2, grad=grad) m.limits["a"] = (lower, upper) m.strategy = stra m.scipy() if stra == 1: assert m.valid assert m.accurate lower = -np.inf if lower is None else lower upper = np.inf if upper is None else upper assert_allclose(m.values, [np.clip(0, lower, upper), 1], atol=1e-3) if stra == 1: assert_allclose(m.errors[1], 2, atol=3e-2) if grad: assert m.fmin.ngrad > 0 else: assert m.fmin.ngrad == 0 @pytest.mark.parametrize("grad", (None, grad)) def test_scipy_fixed(grad): m = Minuit(fcn, a=1, b=2, grad=grad) m.fixed["a"] = True m.scipy() assert m.valid assert_allclose(m.values, [1, 1], atol=1e-3) assert_allclose(m.errors, [0.01, 2], atol=3e-2) if grad: assert m.fmin.ngrad > 0 else: assert m.fmin.ngrad == 0 @pytest.mark.parametrize("stra", (0, 1)) @pytest.mark.parametrize("grad", (None, grad)) def test_scipy_errordef(stra, grad): m = Minuit(fcn, a=1, b=2, grad=grad) m.errordef = 4 m.strategy = stra m.scipy() assert m.valid assert_allclose(m.values, [0, 1], atol=1e-3) assert_allclose(m.errors, [2, 4], rtol=0.3) if grad: assert m.fmin.ngrad > 0 else: assert m.fmin.ngrad == 0 @pytest.mark.parametrize("stra", (0, 1)) @pytest.mark.parametrize("grad", (None, rosenbrock_grad)) def test_scipy_ncall(stra, grad): m = Minuit(rosenbrock, x=2, y=2, grad=grad) m.strategy = stra m.scipy() assert m.valid nfcn = m.fmin.nfcn m.reset() m.scipy(ncall=1) assert m.fmin.nfcn < nfcn assert not m.valid @pytest.mark.parametrize("lb", (0, 0.1)) @pytest.mark.parametrize("fixed", (False, True)) def test_scipy_constraints_1(lb, fixed): def fcn(a, x, y): return a + x**2 + y**2 m = Minuit(fcn, a=3, x=1, y=2) m.fixed["a"] = fixed con_a = scopt.NonlinearConstraint(lambda a, x, y: a, lb, np.inf) con_x = scopt.NonlinearConstraint(lambda a, x, y: x, lb, np.inf) con_y = scopt.NonlinearConstraint(lambda a, x, y: y, lb, np.inf) m.scipy(constraints=[con_a, con_x, con_y]) assert m.valid == (lb == 0 and fixed) if fixed: assert_allclose(m.values, [3, lb, lb], atol=1e-3) else: assert_allclose(m.values, [lb, lb, lb], atol=1e-3) assert m.accurate @pytest.mark.parametrize("fixed", (False, True)) def test_scipy_constraints_2(fixed): def fcn(x, y): return x**2 + y**2 m = Minuit(fcn, x=1, y=2) m.fixed["x"] = fixed con = scopt.LinearConstraint([1, 1], 0.1, np.inf) m.scipy(method="COBYLA", constraints=con) assert m.valid == fixed if fixed: assert_allclose(m.values, [1, 0.0], atol=1e-3) assert_allclose(m.errors[1], 1, atol=1e-3) else: assert_allclose(m.values, [0.05, 0.05], atol=1e-3) assert_allclose(m.errors, [1, 1], atol=1e-3) def test_bad_constraint(): m = Minuit(fcn, a=1, b=2) with pytest.raises(ValueError): m.scipy(constraints={}) with pytest.raises(ValueError): m.scipy(constraints=[{}]) def test_high_print_level(capsys): m = Minuit(fcn, a=1, b=2) m.scipy() assert capsys.readouterr()[0] == "" m.reset() m.print_level = 1 m.scipy() m.print_level = 0 assert capsys.readouterr()[0] != "" def test_on_modified_state(): m = Minuit(fcn, a=1, b=2) m.scipy() assert m.valid assert_allclose(m.values, [0, 1], atol=1e-3) m.fixed[1] = True # modify latest state m.values = 1, 2 m.scipy() # used to fail assert m.valid assert_allclose(m.values, [0, 2], atol=1e-3) iminuit-2.30.1/tests/test_tabulate.py0000644000000000000000000000164314332717401014563 0ustar00from iminuit import Minuit import pytest tab = pytest.importorskip("tabulate") def framed(s): return "\n" + str(s) + "\n" def test_params(): m = Minuit(lambda x, y: x**2 + (y / 2) ** 2 + 1, x=0, y=0) m.limits["y"] = (-1, 1) m.fixed["x"] = True m.migrad() m.minos() assert ( framed(tab.tabulate(*m.params.to_table())) == """ pos name value error error- error+ limit- limit+ fixed ----- ------ ------- ------- -------- -------- -------- -------- ------- 0 x 0 0.1 yes 1 y 0 1.5 -1.0 1.0 -1.0 1.0 """ ) def test_matrix(): m = Minuit(lambda x, y: x**2 + (y / 2) ** 2 + 1, x=0, y=0) m.migrad() assert ( framed(tab.tabulate(*m.covariance.to_table())) == """ x y -- --- --- x 1 0 y 0 4 """ ) iminuit-2.30.1/tests/test_util.py0000644000000000000000000004661514332717401013747 0ustar00from iminuit import util import pytest from argparse import Namespace from numpy.testing import assert_equal, assert_allclose import numpy as np from iminuit._core import MnUserParameterState from iminuit._optional_dependencies import optional_module_for import pickle from iminuit._hide_modules import hide_modules try: import scipy # noqa scipy_available = True except ModuleNotFoundError: scipy_available = False def test_ndim(): ndim = util._ndim assert ndim(1) == 0 assert ndim([]) == 1 assert ndim([[]]) == 2 assert ndim(None) == 0 assert ndim((None, None)) == 1 assert ndim(((1, 2), None)) == 2 assert ndim((None, (1, 2))) == 2 def test_BasicView(): with pytest.raises(TypeError): util.BasicView(None, 2) def test_ValueView(): state = MnUserParameterState() state.add("x", 1.0, 0.1) state.add("y", 2.2, 0.1) state.add("z", 3.3, 0.1) v = util.ValueView( Namespace( _var2pos={"x": 0, "y": 1, "z": 2}, _pos2var=("x", "y", "z"), npar=3, _last_state=state, _copy_state_if_needed=lambda: None, ) ) assert v == v assert v == (1.0, 2.2, 3.3) assert v != (1.0, 2.1, 3.3) assert v != 0 assert repr(v) == "" assert str(v) == repr(v) v[:] = (1, 2, 3) assert_equal(v[:3], (1, 2, 3)) assert_equal(v[0:3], (1, 2, 3)) assert_equal(v[0:10], (1, 2, 3)) assert_equal(v, (1, 2, 3)) v[1:] = 4 assert_equal(v, (1, 4, 4)) v["y"] = 2 assert_equal(v, (1, 2, 4)) v["y":] = 3 assert_equal(v, (1, 3, 3)) v[:"z"] = 2 assert_equal(v, (2, 2, 3)) v_dict = v.to_dict() assert isinstance(v_dict, dict) assert v_dict["x"] == v["x"] assert v_dict["y"] == v["y"] assert v_dict["z"] == v["z"] v[:] = (1, 2, 3) assert_equal(v[["x", "z"]], (1, 3)) assert_equal(v[[2, 0]], (3, 1)) v[["x", "z"]] = (3, 1) assert_equal(v, (3, 2, 1)) def test_FixedView_as_mask_for_other_views(): state = MnUserParameterState() state.add("x", 1, 0.1) state.add("y", 2, 0.1) state.add("z", 3, 0.1) fake_minuit = Namespace( _var2pos={"x": 0, "y": 1, "z": 2}, _pos2var=("x", "y", "z"), npar=3, _last_state=state, _copy_state_if_needed=lambda: None, ) v = util.ValueView(fake_minuit) f = util.FixedView(fake_minuit) f[1] = True assert_equal(f, [False, True, False]) assert_equal(v[f], [2]) assert_equal(v[~f], [1, 3]) v[f] = 5 assert_equal(v, [1, 5, 3]) v[~f] = [2, 4] assert_equal(v, [2, 5, 4]) def test_FixedView_comparison_with_broadcasting(): state = MnUserParameterState() state.add("x", 1, 0.1) state.add("y", 2, 0.1) state.add("z", 3, 0.1) fake_minuit = Namespace( _var2pos={"x": 0, "y": 1, "z": 2}, _pos2var=("x", "y", "z"), npar=3, _last_state=state, _copy_state_if_needed=lambda: None, ) f = util.FixedView(fake_minuit) assert_equal(f, [False, False, False]) # broadcasting assert f == False # noqa f[0] = True assert_equal(f, [True, False, False]) assert f != False # noqa def test_Matrix(): m = util.Matrix(("a", "b")) m[:] = [[1, 2], [2, 8]] assert_equal(m, ((1, 2), (2, 8))) assert repr(m) == "[[1. 2.]\n [2. 8.]]" c = m.correlation() assert_allclose(c, ((1.0, 0.5**0.5), (0.5**0.5, 1.0))) assert m["a", "b"] == 2.0 assert m["a", 1] == 2.0 assert m[1, "a"] == 2.0 assert m[1, 1] == 8.0 assert_equal(m[0], [1, 2]) assert_equal(m["b"], (2, 8)) assert_equal(m[:], [[1, 2], [2, 8]]) assert_equal(m[:, 0], [1, 2]) assert_equal(m[:, 1], [2, 8]) # this swaps rows and cols assert_equal(m[[1, 0]], [[8, 2], [2, 1]]) m *= 2 assert_equal(m, ((2, 4), (4, 16))) m2 = np.dot(m, (1, 1)) assert repr(m2) == "[ 6. 20.]" assert str(m2) == "[ 6. 20.]" assert_allclose(m2, (6, 20)) # matrix is always square m = util.Matrix(("a", "b", "c")) m[:] = np.arange(9).reshape((3, 3)) # [0 1 2 # 3 4 5 # 6 7 8] # m1 = m[:2] # assert_equal(m1, [[0, 1], [3, 4]]) m2 = m[[0, 2]] assert_equal(m2, [[0, 2], [6, 8]]) m3 = m[["a", "c"]] assert_equal(m3, [[0, 2], [6, 8]]) d = m.to_dict() assert list(d.keys()) == [ ("a", "a"), ("a", "b"), ("a", "c"), ("b", "b"), ("b", "c"), ("c", "c"), ] for k, v in d.items(): assert v == m[k] with pytest.raises(TypeError): util.Matrix("ab") with pytest.raises(TypeError): util.Matrix(1) m2 = pickle.loads(pickle.dumps(m)) assert type(m2) is util.Matrix assert_equal(m2, m) assert m2._var2pos == m._var2pos def test_Param(): values = 3, "foo", 1.2, 3.4, None, False, False, 42, None p = util.Param(*values) assert p.number == 3 assert p.name == "foo" assert p.value == 1.2 assert p.error == 3.4 assert p.merror is None assert not p.is_const assert not p.is_fixed assert p.has_limits assert p.has_lower_limit assert not p.has_upper_limit assert p.lower_limit == 42 assert p.upper_limit is None assert repr(p) == ( "Param(number=3, name='foo', value=1.2, error=3.4, merror=None, " "is_const=False, is_fixed=False, lower_limit=42, upper_limit=None)" ) def test_Params(): p = util.Params( [ util.Param(0, "foo", 1.2, 3.4, None, False, False, 42, None), util.Param(1, "bar", 3.4, 4.5, None, False, False, 42, None), ] ) assert repr(p) == repr((p[0], p[1])) assert p[0].number == 0 assert p[1].number == 1 assert p["foo"].number == 0 assert p["bar"].number == 1 def test_MError(): me = util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.7, ) assert repr(me) == ( "" ) assert me == util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.7, ) assert me != util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.8, ) def test_MErrors(): mes = util.MErrors( x=util.MError( 1, "x", 0.1, 0.2, True, True, True, False, False, False, False, False, False, 11, 0.7, ) ) assert repr(mes) == f"" @pytest.mark.parametrize("errordef", (0.5, 1.0)) def test_FMin(errordef): fm = Namespace( fval=1.23456e-10, edm=1.23456e-10, errordef=errordef, is_valid=True, has_valid_parameters=True, has_accurate_covar=True, has_posdef_covar=True, has_made_posdef_covar=False, hesse_failed=False, has_covariance=True, is_above_max_edm=False, has_reached_call_limit=False, has_parameters_at_limit=False, state=[], ) fmin = util.FMin(fm, "foo", 1, 2, 1, 0.1, 1.2) assert {x for x in dir(fmin) if not x.startswith("_")} == { "algorithm", "edm", "edm_goal", "errordef", "fval", "reduced_chi2", "nfcn", "ngrad", "is_valid", "has_accurate_covar", "has_valid_parameters", "has_posdef_covar", "has_made_posdef_covar", "hesse_failed", "has_covariance", "is_above_max_edm", "has_reached_call_limit", "has_parameters_at_limit", "time", } assert fmin.algorithm == "foo" assert fmin.edm == 1.23456e-10 assert fmin.edm_goal == 0.1 assert not fmin.has_parameters_at_limit assert fmin.time == 1.2 assert fmin == util.FMin(fm, "foo", 1, 2, 1, 0.1, 1.2) assert fmin != util.FMin(fm, "foo", 1, 2, 1, 0.3, 1.2) assert fmin != util.FMin(fm, "bar", 1, 2, 1, 0.1, 1.2) assert fmin != util.FMin(fm, "foo", 1, 2, 1, 0.1, 1.5) if errordef == 1: reduced_chi2 = fmin.fval else: reduced_chi2 = np.nan assert repr(fmin) == ( f"" ) def test_normalize_limit(): assert util._normalize_limit(None) == (-np.inf, np.inf) assert util._normalize_limit((None, 2)) == (-np.inf, 2) assert util._normalize_limit((2, None)) == (2, np.inf) assert util._normalize_limit((None, None)) == (-np.inf, np.inf) with pytest.raises(ValueError): util._normalize_limit((3, 2)) def test_guess_initial_step(): assert util._guess_initial_step(0) == 0.1 assert util._guess_initial_step(1) == 0.01 def test_address_of_cfunc(): nb = pytest.importorskip("numba") nb_sig = nb.types.double(nb.types.uintc, nb.types.CPointer(nb.types.double)) @nb.cfunc(nb_sig) def fcn(n, x): x = nb.carray(x, (n,)) r = 0.0 for i in range(n): r += (x[i] - i) ** 2 return r from ctypes import cast, c_void_p, CFUNCTYPE, POINTER, c_double, c_uint32 address = cast(fcn.ctypes, c_void_p).value assert util._address_of_cfunc(fcn) == address # let's see if we can call the function pointer, going full circle c_sig = CFUNCTYPE(c_double, c_uint32, POINTER(c_double)) c_fcn = cast(address, c_sig) v = np.array((1.0, 2.0)) assert c_fcn(2, v.ctypes.data_as(POINTER(c_double))) == 2.0 def test_address_of_cfunc_bad_signature(): nb = pytest.importorskip("numba") nb_sig = nb.types.double(nb.types.double, nb.types.CPointer(nb.types.double)) @nb.cfunc(nb_sig) def fcn(y, x): return 0 assert util._address_of_cfunc(fcn) == 0 def test_make_func_code(): with pytest.warns(FutureWarning): fc = util.make_func_code(["a", "b"]) assert fc.co_varnames == ("a", "b") assert fc.co_argcount == 2 with pytest.warns(FutureWarning): fc = util.make_func_code(("x",)) assert fc.co_varnames == ("x",) assert fc.co_argcount == 1 def test_make_with_signature(): def f(a, b): return a + b f1 = util.make_with_signature(f, "x", "y") assert util.describe(f1) == ["x", "y"] assert f1(1, 2) == f(1, 2) f2 = util.make_with_signature(f, b="z") assert util.describe(f2) == ["a", "z"] assert f2(1, 2) == f(1, 2) assert f1 is not f2 f3 = util.make_with_signature(f, "x", b="z") assert util.describe(f3) == ["x", "z"] assert f3(1, 2) == f(1, 2) # check that arguments are not overridden assert util.describe(f1) == ["x", "y"] assert util.describe(f) == ["a", "b"] with pytest.raises(ValueError): util.make_with_signature(f, "a", "b", "c") with pytest.raises(ValueError): util.make_with_signature(f, "a", "b", "c", b="z") def test_make_with_signature_on_func_without_code_object(): class Fcn: def __call__(self, x, y): return x + y f = Fcn() assert not hasattr(f, "__code__") f1 = util.make_with_signature(f, "x", "y") assert util.describe(f1) == ["x", "y"] assert f1(1, 2) == f(1, 2) assert f1 is not f f2 = util.make_with_signature(f1, x="a") assert util.describe(f2) == ["a", "y"] assert f2(1, 2) == f(1, 2) def test_merge_signatures(): def f(x, y, z): return x + y + z def g(x, a, b): return x + a + b args, (pf, pg) = util.merge_signatures([f, g]) assert args == ["x", "y", "z", "a", "b"] assert pf == [0, 1, 2] assert pg == [0, 3, 4] @pytest.mark.skipif(not scipy_available, reason="needs scipy") def test_propagate_1(): cov = [ [1.0, 0.1, 0.2], [0.1, 2.0, 0.3], [0.2, 0.3, 3.0], ] x = [1, 2, 3] def fn(x): return 2 * x + 1 with pytest.warns(FutureWarning): y, ycov = util.propagate(fn, x, cov) np.testing.assert_allclose(y, [3, 5, 7]) np.testing.assert_allclose( ycov, [[4, 0.4, 0.8], [0.4, 8, 1.2], [0.8, 1.2, 12]], rtol=1e-3 ) with pytest.warns(FutureWarning): y, ycov = util.propagate(fn, [1], [[2]]) np.testing.assert_allclose(y, 3) np.testing.assert_allclose(ycov, 8, rtol=1e-3) @pytest.mark.skipif(not scipy_available, reason="needs scipy") def test_propagate_2(): cov = [ [1.0, 0.1, 0.2], [0.1, 2.0, 0.3], [0.2, 0.3, 3.0], ] x = [1.0, 2.0, 3.0] a = 0.5 * np.arange(30).reshape((10, 3)) def fn(x): return np.dot(a, x) with pytest.warns(FutureWarning): y, ycov = util.propagate(fn, x, cov) np.testing.assert_equal(y, fn(x)) np.testing.assert_allclose(ycov, np.einsum("ij,kl,jl", a, a, cov), rtol=1e-3) def fn(x): return np.linalg.multi_dot([x.T, cov, x]) with pytest.warns(FutureWarning): y, ycov = util.propagate(fn, x, cov) np.testing.assert_equal(y, fn(np.array(x))) jac = 2 * np.dot(cov, x) np.testing.assert_allclose(ycov, np.einsum("i,k,ik", jac, jac, cov), rtol=1e-3) @pytest.mark.skipif(not scipy_available, reason="needs scipy") def test_propagate_3(): # matrices with full zero rows and columns are supported cov = [ [1.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.2, 0.0, 3.0], ] x = [1.0, 2.0, 3.0] def fn(x): return 2 * x + 1 with pytest.warns(FutureWarning): y, ycov = util.propagate(fn, x, cov) np.testing.assert_allclose(y, [3, 5, 7]) np.testing.assert_allclose(ycov, [[4, 0.0, 0.8], [0.0, 0.0, 0.0], [0.8, 0.0, 12]]) @pytest.mark.skipif(not scipy_available, reason="needs scipy") def test_propagate_on_bad_input(): cov = [[np.nan, 0.0], [0.0, 1.0]] x = [1.0, 2.0] def fn(x): return 2 * x + 1 with pytest.warns(FutureWarning): with pytest.raises(ValueError): util.propagate(fn, x, cov) with pytest.warns(FutureWarning): with pytest.raises(ValueError): util.propagate(fn, x, 1) cov = [[1.0], [1.0]] with pytest.warns(FutureWarning): with pytest.raises(ValueError): util.propagate(fn, x, cov) def test_iterate(): assert list(util._iterate(1)) == [1] assert list(util._iterate([1, 2])) == [1, 2] def test_replace_none(): assert util._replace_none(None, 2) == 2 assert util._replace_none(3, 2) == 3 def test_progressbar(capsys): with util.ProgressBar(max_value=4) as bar: for i in range(4): bar += 1 stdout, stderr = capsys.readouterr() assert stdout == "\r0 %\r25 %\r50 %\r75 %\r100 %\r " def test_progressbar_no_ipykernel(capsys): with hide_modules("ipykernel"): with util.ProgressBar(max_value=4) as bar: for i in range(4): bar += 1 stdout, stderr = capsys.readouterr() assert stdout == "\r0 %\r25 %\r50 %\r75 %\r100 %\r " def test_progressbar_html(capsys): import sys m_iostream = pytest.importorskip("ipykernel.iostream") m_display = pytest.importorskip("IPython.display") class OutStream: def write(self, s): original_stdout.write(s) def flush(self): original_stdout.flush() def display(msg, **kwargs): sys.stdout.write(msg._repr_html_()) original_stdout = sys.stdout # make ProgressBar think it is running in Jupyter sys.stdout = OutStream() # monkey-patching our mockups m_iostream.OutStream = OutStream m_display.display = display with util.ProgressBar(max_value=4) as bar: for i in range(4): bar += 1 sys.stdout = original_stdout stdout, stderr = capsys.readouterr() assert stdout == ( " 0 %" " 25 %" " 50 %" " 75 %" " 100 %" ) @pytest.mark.parametrize( "mask_expected", ( (None, [[0, 1, 2]]), ([True, False], [[0]]), ([False, True], [[1]]), ([True, True, True, False, True, True, False, True], [[0, 1, 2], [4, 5], [7]]), ), ) def test_histogram_segments(mask_expected): mask, expected = mask_expected if mask is None: xe = np.linspace(0, 1, 4) masked = np.arange(3) else: xe = np.linspace(0, 1, len(mask)) masked = np.arange(len(mask))[np.array(mask)] segments = util._histogram_segments(mask, xe, masked) assert_equal([s[0] for s in segments], expected) @pytest.mark.parametrize( "fn_expected", ((lambda x: x, 40), (lambda x: x**11, 60), (np.log, 80)) ) def test_smart_sampling_1(fn_expected): fn, expected = fn_expected x, y = util._smart_sampling(fn, 1e-10, 5) assert len(y) < expected def test_smart_sampling_2(): # should not raise a warning x, y = util._smart_sampling(np.log, 1e-10, 1, tol=1e-5) assert 0 < len(x) < 1000 def test_smart_sampling_3(): def step(x): return np.where(x > 0.5, 0, 1) with pytest.warns(RuntimeWarning, match="Iteration limit"): x, y = util._smart_sampling(step, 0, 1, tol=0) assert 0 < len(x) < 80 def test_smart_sampling_4(): from time import sleep def step(x): sleep(0.1) return np.where(x > 0.5, 0, 1) with pytest.warns(RuntimeWarning, match="Time limit"): x, y = util._smart_sampling(step, 0, 1, maxtime=0) assert 0 < len(x) < 30 @pytest.mark.parametrize( "x,expected", [([1, 2, 3], False), ([-1, 1000, 100000], False), ([1, 10, 100], True)], ) def test_detect_log_spacing_1(x, expected): assert util._detect_log_spacing(x) == expected def test_optional_module_for_1(): with optional_module_for("foo"): import iminuit # noqa def test_optional_module_for_2(): from iminuit.warnings import OptionalDependencyWarning with pytest.warns( OptionalDependencyWarning, match="foo requires optional package 'foobarbaz'" ): with optional_module_for("foo"): import foobarbaz # noqa def test_optional_module_for_3(): from iminuit.warnings import OptionalDependencyWarning with pytest.warns( OptionalDependencyWarning, match="foo requires optional package 'foo'" ): with optional_module_for("foo", replace={"foobarbaz": "foo"}): import foobarbaz # noqa def test_positive_definite(): assert util.is_positive_definite([[1, 0], [0, 1]]) assert not util.is_positive_definite([[1, 1], [1, 1]]) assert not util.is_positive_definite([[1, 0], [1, 1]]) iminuit-2.30.1/tests/test_without_ipywidgets.py0000644000000000000000000000101114332717401016722 0ustar00from iminuit._hide_modules import hide_modules from iminuit.cost import LeastSquares import pytest pytest.importorskip("ipywidgets") def test_interactive(): pytest.importorskip("matplotlib") import iminuit cost = LeastSquares([1.1, 2.2], [3.3, 4.4], 1, lambda x, a: a * x) iminuit.Minuit(cost, 1).interactive() with hide_modules("ipywidgets", reload="iminuit.ipywidget"): with pytest.raises(ModuleNotFoundError, match="Please install"): iminuit.Minuit(cost, 1).interactive() iminuit-2.30.1/tests/test_without_matplotlib.py0000644000000000000000000000071014332717401016706 0ustar00from iminuit import cost from iminuit._hide_modules import hide_modules import pytest pytest.importorskip("matplotlib.pyplot") def test_visualize(): import iminuit c = cost.LeastSquares([1, 2], [3, 4], 1, lambda x, a: a * x) s = iminuit.Minuit(c, 1).migrad()._repr_html_() assert " License: Minuit is from SEAL Minuit It's LGPL v2 http://seal.web.cern.ch/seal/main/license.html. For iminuit, I'm releasing it as MIT license: Copyright (c) 2012 Piti Ongmongkolkul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Note: MIT license is GPL compatible, so it is an acceptable license for a wrapper, as can be seen here: http://www.gnu.org/licenses/old-licenses/gpl-2.0-faq.html#GPLWrapper http://www.gnu.org/licenses/old-licenses/gpl-2.0-faq.html#OrigBSD (L)GPL can be combined or included in code that does not impose more restrictive conditions. Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Science/Research Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Programming Language :: C++ Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development Classifier: Topic :: Scientific/Engineering :: Physics Classifier: Topic :: Scientific/Engineering :: Mathematics Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: Unix Classifier: Operating System :: MacOS Project-URL: Repository, http://github.com/scikit-hep/iminuit Project-URL: Documentation, https://scikit-hep.org/iminuit Requires-Python: >=3.9 Requires-Dist: numpy>=1.21 Requires-Dist: coverage; extra == "test" Requires-Dist: ipywidgets; extra == "test" Requires-Dist: ipykernel; extra == "test" Requires-Dist: joblib; extra == "test" Requires-Dist: jacobi; extra == "test" Requires-Dist: matplotlib; extra == "test" Requires-Dist: numpy; extra == "test" Requires-Dist: numba; platform_python_implementation == "CPython" and extra == "test" Requires-Dist: numba-stats; platform_python_implementation == "CPython" and extra == "test" Requires-Dist: pytest; extra == "test" Requires-Dist: pytest-xdist; extra == "test" Requires-Dist: scipy; extra == "test" Requires-Dist: tabulate; extra == "test" Requires-Dist: boost_histogram; extra == "test" Requires-Dist: resample; extra == "test" Requires-Dist: unicodeitplus; extra == "test" Requires-Dist: pydantic; extra == "test" Requires-Dist: annotated_types; extra == "test" Requires-Dist: sphinx-rtd-theme; extra == "doc" Requires-Dist: nbsphinx; extra == "doc" Requires-Dist: nbconvert; extra == "doc" Requires-Dist: nbformat; extra == "doc" Requires-Dist: jupyter_client; extra == "doc" Requires-Dist: ipykernel; extra == "doc" Requires-Dist: jax; extra == "doc" Requires-Dist: jaxlib; extra == "doc" Requires-Dist: pytest-xdist; extra == "doc" Provides-Extra: test Provides-Extra: doc Description-Content-Type: text/x-rst .. |iminuit| image:: doc/_static/iminuit_logo.svg :alt: iminuit |iminuit| ========= .. version-marker-do-not-remove .. image:: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg :target: https://scikit-hep.org .. image:: https://img.shields.io/pypi/v/iminuit.svg :target: https://pypi.org/project/iminuit .. image:: https://img.shields.io/conda/vn/conda-forge/iminuit.svg :target: https://github.com/conda-forge/iminuit-feedstock .. image:: https://coveralls.io/repos/github/scikit-hep/iminuit/badge.svg?branch=develop :target: https://coveralls.io/github/scikit-hep/iminuit?branch=develop .. image:: https://github.com/scikit-hep/iminuit/actions/workflows/docs.yml/badge.svg?branch=main :target: https://scikit-hep.org/iminuit .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3949207.svg :target: https://doi.org/10.5281/zenodo.3949207 .. image:: https://img.shields.io/badge/ascl-2108.024-blue.svg?colorB=262255 :target: https://ascl.net/2108.024 :alt: ascl:2108.024 .. image:: https://img.shields.io/gitter/room/Scikit-HEP/iminuit :target: https://gitter.im/Scikit-HEP/iminuit .. image:: https://mybinder.org/badge_logo.svg :target: https://mybinder.org/v2/gh/scikit-hep/iminuit/develop?filepath=doc%2Ftutorial ``iminuit`` is a Jupyter-friendly Python interface for the ``Minuit2`` C++ library maintained by CERN's `ROOT team `_. Minuit was designed to optimize statistical cost functions, for maximum-likelihood and least-squares fits. It provides the best-fit parameters and error estimates from likelihood profile analysis. The iminuit package brings additional features: - Builtin cost functions for statistical fits to N-dimensional data - Unbinned and binned maximum-likelihood + extended versions - `Template fits with error propagation `_ - Least-squares (optionally robust to outliers) - Gaussian penalty terms for parameters - Cost functions can be combined by adding them: ``total_cost = cost_1 + cost_2`` - Visualization of the fit in Jupyter notebooks - Support for SciPy minimizers as alternatives to Minuit's MIGRAD algorithm (optional) - Support for Numba accelerated functions (optional) Minimal dependencies -------------------- ``iminuit`` is promised to remain a lean package which only depends on ``numpy``, but additional features are enabled if the following optional packages are installed. - ``numba``: Cost functions are partially JIT-compiled if ``numba`` is installed. - ``matplotlib``: Visualization of fitted model for builtin cost functions - ``ipywidgets``: Interactive fitting, see example below (also requires ``matplotlib``) - ``scipy``: Compute Minos intervals for arbitrary confidence levels - ``unicodeitplus``: Render names of model parameters in simple LaTeX as Unicode Documentation ------------- Checkout our large and comprehensive list of `tutorials`_ that take you all the way from beginner to power user. For help and how-to questions, please use the `discussions`_ on GitHub or `gitter`_. **Lecture by Glen Cowan** `In the exercises to his lecture for the KMISchool 2022 `_, Glen Cowan shows how to solve statistical problems in Python with iminuit. You can find the lectures and exercises on the Github page, which covers both frequentist and Bayesian methods. `Glen Cowan `_ is a known for his papers and international lectures on statistics in particle physics, as a member of the Particle Data Group, and as author of the popular book `Statistical Data Analysis `_. In a nutshell ------------- ``iminuit`` can be used with a user-provided cost functions in form of a negative log-likelihood function or least-squares function. Standard functions are included in ``iminuit.cost``, so you don't have to write them yourself. The following example shows how to perform an unbinned maximum likelihood fit. .. code:: python import numpy as np from iminuit import Minuit from iminuit.cost import UnbinnedNLL from scipy.stats import norm x = norm.rvs(size=1000, random_state=1) def pdf(x, mu, sigma): return norm.pdf(x, mu, sigma) # Negative unbinned log-likelihood, you can write your own cost = UnbinnedNLL(x, pdf) m = Minuit(cost, mu=0, sigma=1) m.limits["sigma"] = (0, np.inf) m.migrad() # find minimum m.hesse() # compute uncertainties .. image:: doc/_static/demo_output.png :alt: Output of the demo in a Jupyter notebook Interactive fitting ------------------- ``iminuit`` optionally supports an interactive fitting mode in Jupyter notebooks. .. image:: doc/_static/interactive_demo.gif :alt: Animated demo of an interactive fit in a Jupyter notebook High performance when combined with numba ----------------------------------------- When ``iminuit`` is used with cost functions that are JIT-compiled with `numba`_ (JIT-compiled pdfs are provided by `numba_stats`_ ), the speed is comparable to `RooFit`_ with the fastest backend. `numba`_ with auto-parallelization is considerably faster than the parallel computation in `RooFit`_. .. image:: doc/_static/roofit_vs_iminuit+numba.svg More information about this benchmark is given `in the Benchmark section of the documentation `_. Citation -------- If you use iminuit in a scientific work, please cite us. A generic BibTeX entry is:: @article{iminuit, author={Hans Dembinski and Piti Ongmongkolkul et al.}, title={scikit-hep/iminuit}, DOI={10.5281/zenodo.3949207}, publisher={Zenodo}, year={2020}, month={Dec}, url={https://doi.org/10.5281/zenodo.3949207} } The DOI and URL in this entry point always to the latest release of iminuit. You can also cite the actual release that you used, please follow the `Zenodo link `_, which offers entries for common bibliography formats for all iminuit releases. The recommended scientific reference for the MINUIT algorithms is:: @article{James:1975dr, author = "James, F. and Roos, M.", title = "{Minuit: A System for Function Minimization and Analysis of the Parameter Errors and Correlations}", reportNumber = "CERN-DD-75-20", doi = "10.1016/0010-4655(75)90039-9", journal = "Comput. Phys. Commun.", volume = "10", pages = "343--367", year = "1975" } Partner projects ---------------- * `numba_stats`_ provides faster implementations of probability density functions than scipy, and a few specific ones used in particle physics that are not in scipy. * `boost-histogram`_ from Scikit-HEP provides fast generalized histograms that you can use with the builtin cost functions. * `jacobi`_ provides a robust, fast, and accurate calculation of the Jacobi matrix of any transformation function and building a function for generic error propagation. Versions -------- The 2.x series has introduced breaking interfaces changes with respect to the 1.x series. There are no plans to introduce further breaking changes. All interface changes from 1.x to 2.x are documented in the `changelog`_ with recommendations how to upgrade. To keep old scripts running, pin your major iminuit version to <2: the command ``pip install 'iminuit<2'`` installs the 1.x series. .. _changelog: https://scikit-hep.org/iminuit/changelog.html .. _tutorials: https://scikit-hep.org/iminuit/tutorials.html .. _discussions: https://github.com/scikit-hep/iminuit/discussions .. _gitter: https://gitter.im/Scikit-HEP/iminuit .. _jacobi: https://github.com/hdembinski/jacobi .. _numba_stats: https://github.com/HDembinski/numba-stats .. _boost-histogram: https://github.com/scikit-hep/boost-histogram .. _numba: https://numba.pydata.org .. _RooFit: https://root.cern/manual/roofit/