pax_global_header00006660000000000000000000000064134543541460014523gustar00rootroot0000000000000052 comment=5351d0fbc8ca2a7418a77200c4408ff80fd8eaa1 nlopt-2.6.1/000077500000000000000000000000001345435414600126655ustar00rootroot00000000000000nlopt-2.6.1/.gitignore000066400000000000000000000003101345435414600146470ustar00rootroot00000000000000# binaries *.exe *.dll *.lib *.exp *.obj *.so *.do *.o *.a *.dylib *.dSYM *.mex* *.oct *.py[cod] *.tar.gz *.zip # build output: prefer out-of-tree builds build/ # MacOS .DS_Store # VSCode .vscode/ nlopt-2.6.1/.travis.yml000066400000000000000000000025531345435414600150030ustar00rootroot00000000000000language: cpp sudo: false matrix: include: - os: linux addons: apt: packages: - swig - python-dev - python-numpy - guile-2.0-dev - liboctave-dev - cmake - gfortran - binutils-mingw-w64-x86-64 - g++-mingw-w64-x86-64 - gfortran-mingw-w64-x86-64 script: - pip install mkdocs python-markdown-math --user - PATH=$PATH:~/.local/bin mkdocs build - mkdir build && pushd build - cmake -DCMAKE_INSTALL_PREFIX=~/.local -DNLOPT_MATLAB=OFF -DNLOPT_FORTRAN=ON -DCMAKE_C_FLAGS='-std=c89 -pedantic -D_POSIX_C_SOURCE=200112L -Wall -Wextra -Werror' -DCMAKE_CXX_FLAGS='-Wall -Wextra' .. - make install -j2 && ctest -j2 --output-on-failure - rm -rf * ~/.local - cmake -DCMAKE_INSTALL_PREFIX=~/.local -DNLOPT_PYTHON=OFF -DNLOPT_OCTAVE=OFF -DNLOPT_GUILE=OFF -DNLOPT_MATLAB=OFF -DNLOPT_FORTRAN=ON -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/toolchain-x86_64-w64-mingw32.cmake .. - make install -j2 - os: osx install: - brew update - brew install swig octave guile || echo "nope" script: - mkdir build && pushd build - cmake -DCMAKE_INSTALL_PREFIX=~/.local -DPYTHON_EXECUTABLE=/usr/bin/python -DNLOPT_FORTRAN=ON .. - make install && ctest --output-on-failure nlopt-2.6.1/AUTHORS000066400000000000000000000005751345435414600137440ustar00rootroot00000000000000NLopt was originally written/packaged by: Steven G. Johnson with subsequent contributions by Julien Schueller and other contributors that can be found in the git history, summarized here: https://github.com/stevengj/nlopt/graphs/contributors See the subdirectories for the authors of the original nonlinear optimization libraries utilized by NLopt. nlopt-2.6.1/CMakeLists.txt000066400000000000000000000352221345435414600154310ustar00rootroot00000000000000#============================================================================== # NLOPT CMake file # # NLopt is a free/open-source library for nonlinear optimization, providing # a common interface for a number of different free optimization routines # available online as well as original implementations of various other # algorithms # WEBSITE: http://ab-initio.mit.edu/wiki/index.php/NLopt # AUTHOR: Steven G. Johnson # # This CMakeLists.txt file was created to compile NLOPT with the CMAKE utility. # Benoit Scherrer, 2010 CRL, Harvard Medical School # Copyright (c) 2008-2009 Children's Hospital Boston #============================================================================== cmake_minimum_required (VERSION 2.8.11) if (NOT DEFINED CMAKE_BUILD_TYPE) set (CMAKE_BUILD_TYPE Release CACHE STRING "Build type") endif () project (nlopt) #============================================================================== # version set (NLOPT_MAJOR_VERSION "2") set (NLOPT_MINOR_VERSION "6") set (NLOPT_BUGFIX_VERSION "1") set (NLOPT_VERSION_STRING ${NLOPT_MAJOR_VERSION}.${NLOPT_MINOR_VERSION}.${NLOPT_BUGFIX_VERSION}) message (STATUS "NLopt version ${NLOPT_VERSION_STRING}") # This is the ABI version number, which differes from the API version above # (it indicates ABI compatibility), but they are typically incremented together. set(SO_MAJOR 0) set(SO_MINOR 10) set(SO_PATCH 0) #============================================================================== list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) option (NLOPT_CXX "enable cxx routines" ON) option (NLOPT_FORTRAN "enable fortran tests" OFF) option (BUILD_SHARED_LIBS "Build NLopt as a shared library" ON) option (NLOPT_PYTHON "build python bindings" ON) option (NLOPT_OCTAVE "build octave bindings" ON) option (NLOPT_MATLAB "build matlab bindings" ON) option (NLOPT_GUILE "build guile bindings" ON) option (NLOPT_SWIG "use SWIG to build bindings" ON) if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) option (NLOPT_TESTS "build unit tests" ON) else () option (NLOPT_TESTS "build unit tests" OFF) endif () if (NLOPT_FORTRAN) enable_language (Fortran) endif () include (GNUInstallDirs) # Offer the user the choice of overriding the installation directories set (INSTALL_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries") set (INSTALL_BIN_DIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables") set (INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for header files") set (INSTALL_DATA_DIR ${CMAKE_INSTALL_DATADIR}/nlopt CACHE PATH "Installation directory for data files") set (INSTALL_MAN_DIR ${CMAKE_INSTALL_MANDIR} CACHE PATH "Installation directory for man documentation") set (INSTALL_CMAKE_DIR ${INSTALL_LIB_DIR}/cmake/nlopt CACHE PATH "Installation directory for cmake config files") # Make relative paths absolute (needed later on) foreach (p LIB BIN INCLUDE DATA CMAKE) set (var INSTALL_${p}_DIR) set (RELATIVE_INSTALL_${p}_DIR ${INSTALL_${p}_DIR}) if (NOT IS_ABSOLUTE "${${var}}") set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") endif () endforeach () set (CMAKE_INSTALL_RPATH ${INSTALL_LIB_DIR}) set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) if(POLICY CMP0042) # Set MACOSX_RPATH to ON cmake_policy(SET CMP0042 NEW) endif() if (POLICY CMP0086) # UseSWIG honors SWIG_MODULE_NAME via -module flag cmake_policy(SET CMP0086 NEW) endif () include (CheckIncludeFiles) include (CheckFunctionExists) include (CheckTypeSize) include (CheckCCompilerFlag) include (CheckCXXSymbolExists) include (CheckCXXCompilerFlag) include (CheckLibraryExists) #============================================================================== # COMPILATION CHECKINGS and CONFIGURATION GENERATION #============================================================================== check_include_file (dlfcn.h HAVE_DLFCN_H) check_include_file (getopt.h HAVE_GETOPT_H) check_include_file (unistd.h HAVE_UNISTD_H) check_include_file (string.h HAVE_STRING_H) check_include_file (strings.h HAVE_STRINGS_H) check_include_file (inttypes.h HAVE_INTTYPES_H) check_include_file (memory.h HAVE_MEMORY_H) check_include_file (stdlib.h HAVE_STDLIB_H) check_include_file (stdint.h HAVE_STDINT_H) check_include_file (time.h HAVE_TIME_H) check_include_file (sys/types.h HAVE_SYS_TYPES_H) check_include_file (sys/stat.h HAVE_SYS_STAT_H) check_include_file (sys/time.h HAVE_SYS_TIME_H) if (HAVE_TIME_H AND HAVE_SYS_TIME_H) set (TIME_WITH_SYS_TIME TRUE) endif () check_function_exists (getpid HAVE_GETPID) check_function_exists (syscall HAVE_GETTID_SYSCALL) check_function_exists (isinf HAVE_ISINF) check_function_exists (isnan HAVE_ISNAN) check_function_exists (gettimeofday HAVE_GETTIMEOFDAY) check_function_exists (qsort_r HAVE_QSORT_R) check_function_exists (time HAVE_TIME) check_function_exists (copysign HAVE_COPYSIGN) check_type_size ("uint32_t" SIZEOF_UINT32_T) set (HAVE_UINT32_T ${SIZEOF_UINT32_T}) check_type_size ("unsigned int" SIZEOF_UNSIGNED_INT) check_type_size ("unsigned long" SIZEOF_UNSIGNED_LONG) check_library_exists ("m" sqrt "" HAVE_LIBM) if (HAVE_LIBM) set (M_LIBRARY m) endif() if (NOT DEFINED HAVE_FPCLASSIFY) message(STATUS "Looking for fpclassify") file (WRITE ${PROJECT_BINARY_DIR}/fpclassify.c "#include \n") file (APPEND ${PROJECT_BINARY_DIR}/fpclassify.c "int main(void) {\n") file (APPEND ${PROJECT_BINARY_DIR}/fpclassify.c "if (!fpclassify(3.14159)) fpclassify(2.7183);\n") file (APPEND ${PROJECT_BINARY_DIR}/fpclassify.c " return 0; }\n") try_compile (HAVE_FPCLASSIFY ${PROJECT_BINARY_DIR}/build_fpclassify ${PROJECT_BINARY_DIR}/fpclassify.c CMAKE_FLAGS -DLINK_LIBRARIES=m) message(STATUS "Looking for fpclassify - ${HAVE_FPCLASSIFY}") endif () option (WITH_THREADLOCAL "check thread local keyword" ON) if (WITH_THREADLOCAL AND NOT DEFINED THREADLOCAL) foreach (_THREADLOCAL_KEY "__thread" "__declspec(thread)") unset (HAVE_THREAD_LOCAL_STORAGE CACHE) check_c_source_compiles(" ${_THREADLOCAL_KEY} int tls; int main(void) { return 0; }" HAVE_THREAD_LOCAL_STORAGE) if (HAVE_THREAD_LOCAL_STORAGE) set (THREADLOCAL ${_THREADLOCAL_KEY} CACHE STRING "Thread local keyword") endif () endforeach() endif () if (NLOPT_CXX OR NLOPT_PYTHON OR NLOPT_GUILE OR NLOPT_OCTAVE) check_cxx_symbol_exists (__cplusplus ciso646 SYSTEM_HAS_CXX) if (SYSTEM_HAS_CXX) check_cxx_compiler_flag ("-std=c++11" SUPPORTS_STDCXX11) if (SUPPORTS_STDCXX11) set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") if (NLOPT_CXX) set (NLOPT_CXX11 ON) endif () endif () else() message (FATAL_ERROR "The compiler doesn't support CXX.") endif () endif () #============================================================================== # CREATE nlopt_config.h #============================================================================== configure_file (${CMAKE_CURRENT_SOURCE_DIR}/nlopt_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/nlopt_config.h IMMEDIATE) # pkgconfig file if (UNIX OR MINGW) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/nlopt.pc.in ${CMAKE_CURRENT_BINARY_DIR}/nlopt.pc @ONLY) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/nlopt.pc DESTINATION ${RELATIVE_INSTALL_LIB_DIR}/pkgconfig) endif () #============================================================================== # nlopt LIBRARY TARGET (SHARED OR STATIC) #============================================================================== configure_file (src/api/nlopt.h ${PROJECT_BINARY_DIR}/src/api/nlopt.h COPYONLY) set (NLOPT_HEADERS ${PROJECT_BINARY_DIR}/src/api/nlopt.h ${PROJECT_BINARY_DIR}/src/api/nlopt.hpp ${PROJECT_BINARY_DIR}/src/api/nlopt.f ) set (NLOPT_SOURCES src/algs/direct/DIRect.c src/algs/direct/direct_wrap.c src/algs/direct/DIRserial.c src/algs/direct/DIRsubrout.c src/algs/direct/direct-internal.h src/algs/direct/direct.h src/algs/cdirect/cdirect.c src/algs/cdirect/hybrid.c src/algs/cdirect/cdirect.h src/algs/praxis/praxis.c src/algs/praxis/praxis.h src/algs/luksan/plis.c src/algs/luksan/plip.c src/algs/luksan/pnet.c src/algs/luksan/mssubs.c src/algs/luksan/pssubs.c src/algs/luksan/luksan.h src/algs/crs/crs.c src/algs/crs/crs.h src/algs/mlsl/mlsl.c src/algs/mlsl/mlsl.h src/algs/mma/mma.c src/algs/mma/mma.h src/algs/mma/ccsa_quadratic.c src/algs/cobyla/cobyla.c src/algs/cobyla/cobyla.h src/algs/newuoa/newuoa.c src/algs/newuoa/newuoa.h src/algs/neldermead/nldrmd.c src/algs/neldermead/neldermead.h src/algs/neldermead/sbplx.c src/algs/auglag/auglag.c src/algs/auglag/auglag.h src/algs/bobyqa/bobyqa.c src/algs/bobyqa/bobyqa.h src/algs/isres/isres.c src/algs/isres/isres.h src/algs/slsqp/slsqp.c src/algs/slsqp/slsqp.h src/algs/esch/esch.c src/algs/esch/esch.h src/api/general.c src/api/options.c src/api/optimize.c src/api/deprecated.c src/api/nlopt-internal.h src/api/nlopt.h src/api/f77api.c src/api/f77funcs.h src/api/f77funcs_.h src/api/nlopt.hpp src/api/nlopt-in.hpp src/util/mt19937ar.c src/util/sobolseq.c src/util/soboldata.h src/util/timer.c src/util/stop.c src/util/nlopt-util.h src/util/redblack.c src/util/redblack.h src/util/qsort_r.c src/util/rescale.c ) if (NLOPT_CXX) list (APPEND NLOPT_SOURCES src/algs/stogo/global.cc src/algs/stogo/linalg.cc src/algs/stogo/local.cc src/algs/stogo/stogo.cc src/algs/stogo/tools.cc src/algs/stogo/global.h src/algs/stogo/linalg.h src/algs/stogo/local.h src/algs/stogo/stogo_config.h src/algs/stogo/stogo.h src/algs/stogo/tools.h) endif () if (NLOPT_CXX11) list (APPEND NLOPT_SOURCES src/algs/ags/data_types.hpp src/algs/ags/evolvent.hpp src/algs/ags/evolvent.cc src/algs/ags/solver.hpp src/algs/ags/solver.cc src/algs/ags/local_optimizer.hpp src/algs/ags/local_optimizer.cc src/algs/ags/ags.h src/algs/ags/ags.cc) endif () install (FILES ${NLOPT_HEADERS} DESTINATION ${RELATIVE_INSTALL_INCLUDE_DIR}) set (nlopt_lib nlopt) add_library (${nlopt_lib} ${NLOPT_SOURCES}) target_link_libraries (${nlopt_lib} ${M_LIBRARY}) set_target_properties (${nlopt_lib} PROPERTIES SOVERSION ${SO_MAJOR}) set_target_properties (${nlopt_lib} PROPERTIES VERSION "${SO_MAJOR}.${SO_MINOR}.${SO_PATCH}") #============================================================================== # INCLUDE DIRECTORIES #============================================================================== target_include_directories (${nlopt_lib} PRIVATE ${PROJECT_BINARY_DIR}/src/api ${PROJECT_BINARY_DIR} src/algs/stogo src/algs/ags src/util src/algs/direct src/algs/cdirect src/algs/praxis src/algs/luksan src/algs/crs src/algs/mlsl src/algs/mma src/algs/cobyla src/algs/newuoa src/algs/neldermead src/algs/auglag src/algs/bobyqa src/algs/isres src/algs/slsqp src/algs/esch src/api) get_target_property (NLOPT_PRIVATE_INCLUDE_DIRS ${nlopt_lib} INCLUDE_DIRECTORIES) target_include_directories (${nlopt_lib} INTERFACE "$" "$/${CMAKE_INSTALL_INCLUDEDIR}>") if (BUILD_SHARED_LIBS) target_compile_definitions (${nlopt_lib} PUBLIC NLOPT_DLL) target_compile_definitions (${nlopt_lib} PRIVATE NLOPT_DLL_EXPORT) endif () # pass -fPIC in case swig module is built with static library if (NOT BUILD_SHARED_LIBS) check_c_compiler_flag (-fPIC HAS_FPIC) if (HAS_FPIC) set (CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") set (CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS}") endif () endif () install ( TARGETS ${nlopt_lib} EXPORT NLoptLibraryDepends RUNTIME DESTINATION ${RELATIVE_INSTALL_BIN_DIR} LIBRARY DESTINATION ${RELATIVE_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${RELATIVE_INSTALL_LIB_DIR} ) if (MSVC AND BUILD_SHARED_LIBS AND NOT CMAKE_VERSION VERSION_LESS 3.1) install (FILES $ DESTINATION ${RELATIVE_INSTALL_BIN_DIR} CONFIGURATIONS Debug RelWithDebInfo COMPONENT Debug) endif () add_subdirectory (src/api) if (NLOPT_PYTHON) find_package (PythonInterp) find_package (PythonLibs) find_package (NumPy) endif () if (NOT DEFINED INSTALL_PYTHON_DIR AND PYTHONINTERP_FOUND) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; print(sysconfig.get_python_lib(plat_specific=True, prefix='${CMAKE_INSTALL_PREFIX}'))" OUTPUT_VARIABLE _ABS_PYTHON_MODULE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE ) get_filename_component (_ABS_PYTHON_MODULE_PATH ${_ABS_PYTHON_MODULE_PATH} ABSOLUTE) file (RELATIVE_PATH _REL_PYTHON_MODULE_PATH ${CMAKE_INSTALL_PREFIX} ${_ABS_PYTHON_MODULE_PATH}) set (INSTALL_PYTHON_DIR ${_REL_PYTHON_MODULE_PATH}) endif () if (NLOPT_GUILE) find_package (Guile) endif () if (NLOPT_SWIG) find_package (SWIG) if (SWIG_FOUND) add_subdirectory (src/swig) endif () endif () if (NLOPT_OCTAVE) find_package (Octave) endif () if (NLOPT_MATLAB) find_package (Matlab COMPONENTS MX_LIBRARY) endif () if (OCTAVE_FOUND OR Matlab_FOUND) add_subdirectory (src/octave) endif () if (NLOPT_TESTS) enable_testing () add_subdirectory (test) endif () set (CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") set (CPACK_PACKAGE_VERSION_MAJOR "${NLOPT_MAJOR_VERSION}") set (CPACK_PACKAGE_VERSION_MINOR "${NLOPT_MINOR_VERSION}") set (CPACK_PACKAGE_VERSION_PATCH "${NLOPT_BUGFIX_VERSION}") set (CPACK_SOURCE_GENERATOR "TBZ2;TGZ" ) set (CPACK_BINARY_STGZ OFF CACHE BOOL "STGZ") set (CPACK_BINARY_TBZ2 ON CACHE BOOL "TBZ2") set (CPACK_BINARY_TGZ ON CACHE BOOL "TGZ") set (CPACK_BINARY_TZ OFF CACHE BOOL "TZ") set (CPACK_SOURCE_IGNORE_FILES ".git;/build;.*~;${CPACK_SOURCE_IGNORE_FILES}") set (CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${NLOPT_VERSION_STRING}) include (CPack) # configuration files export (TARGETS ${nlopt_lib} NAMESPACE NLopt:: FILE ${PROJECT_BINARY_DIR}/NLoptLibraryDepends.cmake) # Install the export set for use with the install-tree install(EXPORT NLoptLibraryDepends NAMESPACE NLopt:: DESTINATION ${RELATIVE_INSTALL_CMAKE_DIR} COMPONENT Development) # Create a NLOPTConfig.cmake file for the use from the install tree # and install it set (NLOPT_LIBRARIES "NLopt::${nlopt_lib}") set (NLOPT_CMAKE_DIR "${INSTALL_CMAKE_DIR}") file (RELATIVE_PATH rel_include_dir "${NLOPT_CMAKE_DIR}" "${INSTALL_INCLUDE_DIR}") list (APPEND RELATIVE_NLOPT_INCLUDE_DIRS ${rel_include_dir}) file (RELATIVE_PATH rel_lib_dir "${NLOPT_CMAKE_DIR}" "${INSTALL_LIB_DIR}") list (APPEND RELATIVE_NLOPT_LIB_DIR ${rel_lib_dir}) configure_file (cmake/NLoptConfig.cmake.in NLoptConfig.cmake @ONLY) configure_file (cmake/NLoptConfigVersion.cmake.in NLoptConfigVersion.cmake @ONLY) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/NLoptConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/NLoptConfigVersion.cmake DESTINATION ${RELATIVE_INSTALL_CMAKE_DIR} COMPONENT Development) nlopt-2.6.1/COPYING000066400000000000000000000036731345435414600137310ustar00rootroot00000000000000NLopt combines several free/open-source nonlinear optimization libraries by various authors. See the COPYING, COPYRIGHT, and README files in the subdirectories for the original copyright and licensing information of these packages. The compiled NLopt library, i.e. the combined work of all of the included optimization routines, is licensed under the conjunction of all of these licensing terms. Currently, the most restrictive terms are for the code in the "luksan" directory, which is licensed under the GNU Lesser General Public License (GNU LGPL), version 2.1 or later (see luksan/COPYRIGHT). That means that the compiled NLopt library is governed by the terms of the LGPL. --------------------------------------------------------------------------- Other portions of NLopt, including any modifications to the abovementioned packages, are licensed under the standard "MIT License:" Copyright (c) 2007-2011 Massachusetts Institute of Technology 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. nlopt-2.6.1/COPYRIGHT000066400000000000000000000022611345435414600141610ustar00rootroot00000000000000/* Copyright (c) 2007-2019 Massachusetts Institute of Technology * and other contributors * * 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. */ nlopt-2.6.1/ChangeLog000066400000000000000000000001061345435414600144340ustar00rootroot00000000000000See https://github.com/stevengj/nlopt for a detailed version history. nlopt-2.6.1/NEWS.md000066400000000000000000000350001345435414600137610ustar00rootroot00000000000000# NLopt Release Notes ## NLopt 2.6.1 13 April 2019 * Fix `nlopt_version` result for 2.6.x and update soname. ## NLopt 2.6 12 April 2019 * New `nlopt_set_upper_bound` and `nlopt_set_lower_bound` functions in the low-level C API to set one bound at a time ([#257]). * There is no longer a separate `libnlopt_cxx` library: C++ algorithms (STOGO and AGS) are compiled and included by default ([#198]). * Various build fixes ([#197], [#216], [#245], [#250], [#230], [#261], etc.), other fixes ([#242], [#258]). ## NLopt 2.5 26 July 2018 * New AGS global solver ([#194]), thanks to Vladislav Sovrasov. * New `nlopt_get_numevals` function providing a built-in evaluation counter ([#160]). * New `nlopt_get_errmsg` function for more descriptive error messages. * Build system is converted to `cmake` ([#49]), thanks to Julien Schueller * Plugins updated for recent Octave and Guile versions. * Various other build fixes and minor bug fixes. ## NLopt 2.4.2 20 May 2014 * Fix CRS for empty dimensions (where lower `==` upper bound) (issue [#13]). * Improvements to CMake (thanks to @xantares) and Windows builds (issue [#12]). * Fix guile2 compatibility (issue [#21]). ## NLopt 2.4.1 19 November 2013 * Use `cdecl` calling convention instead of stdcall on Win32, to simplify shared-library usage and for consistency with Win64. ## NLopt 2.4 2 November 2013 * New genetic algorithm ESCH, thanks to Carlos Henrique da Silva Santos. * Fix swig dir for `VPATH` builds, thanks to Sandro Vitenti for the bug report. * Use `python-config` program in the `configure` script to find the include directories for Python, if possible (may be overridden by `PYTHON_CONFIG` environment variable). * Bugfix in copy constructor for C++ and Python interfaces. * Bugfix in return value for setting min/max objective. * Handle negative rescalings in COBYLA and BOBYQA. * Plugin installation honors the `configure --prefix`, if any (thanks to xantares@github). * Various compilation fixes for compatibility with recent software. ## NLopt 2.3.1 16 September 2012 * Bug fix: COBLYA should return `ROUNDOFF_LIMITED` rather than `XTOL_REACHED` if the trust-region radius underflows to zero; thanks to David Liu. * Bug fix: incorrect return value from set min/max objective. * Handle case of negative rescalings (from negative dx) in COBYLA and BOBYQA; thanks to Alexander Law for the bug report ## NLopt 2.3 20 July 2012 * In Matlab/Octave interface, make returning NaN from the objective equivalent to `nlopt_force_stop`; thanks to Norman Violet for the suggestion. * Added CCSA-quadratic (`NLOPT_LD_CCSAQ`), similar to MMA. * Added interface for supplying a preconditioner (approximate Hessian); currently only supported in CCSAQ. * When adding mconstraints, allow `tol==NULL` as synonym for zero tolerances. * Added missing `NLOPT_LD_SLSQP` constant in Matlab/Octave. * Lower tolerance for dual optimization in MMA/CCSAQ; thanks to Christophe Leruste for the problem report * Fixed bug in timer, thanks to William Vaughn for the patch. * Bug fix to convergence test in sbplx; thanks to Douglas Bates. ## NLopt 2.2.4 9 June 2011 * Fixed linking problem for C++ and Python shared libraries on MacOS X; thanks to Volker Lorrmann for the bug report. ## NLopt 2.2.3 8 June 2011 * Fixed additional re-entrancy problem in Luksan algorithms missed in the previous version; thanks to Gert Wollny for the bug report. * Fixed set/get `vector_storage` in Fortran interface for Fortran compilers with all-uppercase linkage. ## NLopt 2.2.2 26 May 2011 * Added `set_vector_storage` API to modify the memory usage and the subspace dimension for low-storage quasi-Newton methods. * Fixed missing support for maxtime stopping criteria in Luksan and `ORIG_DIRECT` algorithms; thanks to Jurgen Werner for the bug report. * Fixed algorithms to support the case where the lower and upper bounds are equal for some variables (which effectively eliminates those variables from optimization). * Added missing xtol check to SLSQP, which caused erroneous `ROUNDOFF_LIMITED` error codes to be returned; thanks to Alexander Riess for the bug report. * Fixed slight overcounting of function evaluations for maxeval check in SLSQP. * Fixed deprecated API to support `xtol_abs == NULL` for backward compatibility (thanks to Francesco Biscani for the bug report). * Made Luksan algorithms (e.g. LBFGS and other quasi-Newton methods) re-entrant; thanks to Gert Wollny for the bug report. (Fixes Gentoo bug #368685.) * Fixed bug in DIRECT (not `ORIG_DIRECT`), where a typo caused suboptimal convergence in some cases; thanks to Sinisa Hristov for the bug report. ## NLopt 2.2.1 6 September 2010 * If you compile `nlopt.h` with the `NLOPT_DLL_EXPOR`T symbol `#defined`, it now uses the `dllexport` directive (under Windows), useful for compiling an NLopt DLL under Microsoft compilers; thanks to Benoit Scherrer for the suggestion. * Handle case where `copysign` function is missing, e.g. on Windows; thanks to Benoit Scherrer for the bug report. * Remove C99-style mixed declaration and code in a couple files, so that code compiles in C89; thanks to Benoit Scherrer for the bug report. * Removed a few compiler warnings under Microsoft compilers; thanks to Benoit Scherrer for the bug report. * Export `nlopt_get_algorithm_name` function on Windows; thanks to Ofek Shilon for the bug report. * Don't use `dllimport` directive with `lcc` on Windows (which doesn't support it); thanks to Laurent Vanbeylen for the bug report. * Update Nodedal README directory to indicate that Nocedal's LBFGS code is now available under the GPL, and therefore may be distributed with a future NLopt version (although Luksan's LBFGS code already works well). * Bug fix in `set`/`get_xtol_abs`; thanks to David Rivest-Henault for the report. ## NLopt 2.2 15 July 2010 * Added SLSQP algorithm for gradient-based local optimization with nonlinear constraints via sequential quadratic programming, based on the implementation by Dieter Kraft that was adapted for SciPy. * Modified BOBYQA and COBYLA algorithms to support unequal initial step sizes in different directions; thanks to Tom Fiddaman for pointing out the need for this in the case where different directions have very different scales. * Added Python module docstring; thanks to Sebastian Walter for the suggestion. * Added `GUILE_INSTALL_DIR` variable to allow the user to change the Guile installation directory. * Added Fortran interface for vector-valued constraints. * Throw correct exceptions in Python for the `add_*constraint` functions; thanks to Dmitrey Kroshko for the bug report. * Support forced stop and exceptions in `ORIG_DIRECT` algorithm. * Remove arbitrary `1e20` upper bound on function values from `ORIG_DIRECT` code. * Bugfix in C++ interface (and some other language front-ends) when deallocating the nlopt_opt object in cases like MLSL where local_optimizer is used; thanks to Jurgen Werner for the bug report. ## NLopt 2.1.2 8 July 2010 * The Python mconstraint (vector-valued constraint) functions now pass a 2-dimensional array for the gradient argument, rather than a flattened 1d array. * Improved handling of exceptions and forced stops for constrained optimization, making sure that no constraints are evaluated after the stop. * Return an `NLOPT_INVALID_ARGS` error if more than n equality constraints are added in an n-dimensional problem. * Fix bug that could cause spurious `NLOPT_INVALID_ARGS` errors when adding constraints under rare circumstances. * Eliminate a few small memory leaks that could occur under error conditions. ## NLopt 2.1.1 7 July 2010 * More robust configure check for Python include directories, via `distutils.sysconfig.get_python_inc()` and `numpy.get_include()`. Thanks to Nathaniel Smith for the tip. * Bug fix in Guile interface: added missing prefix to nlopt-version-major etcetera. ## NLopt 2.1 6 July 2010 * New vector-valued constraint feature; thanks to Dmitrey Kroshko of OpenOpt for the suggestion. * COBYLA now accepts equality constraints. * Guard against multiple inclusion in `nlopt.hpp`; thanks to Saul Thurrowgood for the suggestion. ## NLopt 2.0.2 17 June 2010 * Fixed compilation failure in Microsoft Visual Studio, due to incorrect usage of `__stdcall` keyword; thanks to Dave Katz for the bug report. ## NLopt 2.0.1 16 June 2010 * Bug fix in Fortran API (for `nlo_get_` functions returning arrays). * Fixed buggy compilation with MinGW. ## NLopt 2.0 15 June 2010 * New C API, that works by creating an `nlopt_opt` "object" and then calling functions to set the optimization parameters — much more extensible than the old API (which is preserved for backwards compatibility). (Updated Fortran, Matlab, and GNU Octave wrappers as well.) * C++ `nlopt.hpp` wrapper around C API, allowing namespaces, object constructors/destructors, `std::vector`, and exceptions to be exploited. * New nlopt wrappers callable from Python and GNU Guile, generated with the help of SWIG. * New `man nlopt` manual page documenting new API. * New AUGLAG algorithm(s) implementing an augmented-Lagrangian method proposed by Birgin and Martinez (2008), which supports nonlinear equality and inequality constraints "wrapped around" other local/global optimization methods. * Added API for nonlinear equality constraints (currently only supported by AUGLAG and ISRES algorithms). * Support inequality constraints directly in `ORIG_DIRECT` algorithms (no need to return NaN when constraint is violated). * Inequality/equality constraints now have optional tolerances that are used as conditions in stopping criteria. * Pseudo-randomize simplex steps in COBYLA algorithm, improving robustness by avoiding accidentally taking steps that don't improve conditioning (which seems to happen sometimes with active bound constraints). The algorithm remains deterministic (a deterministic seed is used), however. * Allow COBYLA to increase the trust-region radius if the predicted improvement was approximately right and the simplex is OK, following a suggestion in the SAS manual for PROC NLP that seems to improve convergence speed. * Added `nlopt_force_stop` function to force a (graceful) halt to the optimization, and corresponding `NLOPT_FORCED_STOP` return code. * Improved thread-safety in random-number generation: thread-local storage is used for random-number state, on compilers that support it (e.g. gcc, Intel, Microsoft), to make the generation thread-safe. In this case, the random-number seed must be set per-thread. * Return an error in global-search algorithms if the domain is not finite. * Use `stdcall` convention on Windows; thanks to Alan Young for the suggestion. * Added missing absolute-tolerance criteria in Luksan algorithms; thanks to Greg Nicholas for the bug report. * Fixed compilation under C++, and use C++ compiler for everything in `--with-cxx` mode; thanks to Greg Nicholas for the bug report. * In MMA, only stop at minf_max/stopval if the point is feasible. * Fix Matlab mex file to not include unnecessary `nlopt-util.h` file, simplifying Windows compilation. ## NLopt 1.2 18 November 2009 * Added Powell's BOBYQA algorithm for box-constrained optimization without derivatives, an improvement on NEWUOA. * Added ISRES genetic algorithm, supporting nonlinearly constrained global optimization. * New functions `nlopt_{set/get}_stochastic_population` to provide optional greater control over the random "population" sizes in stochastic algorithms (although it still has a sensible default). * Bug fix: remove extraneous text accidentally included in `nlopt.f` Fortran include file. * Bug fix: `configure` script now correctly handles Matlab installation when `MEX_INSTALL_DIR` is specified manually by the user. ## NLopt 1.1 12 November 2009 * `configure` script detects whether `--enable-shared` is required in order to compile Matlab and Octave plugins (as is the case on x86_64), and disables compilation of those plugins if `--enable-shared` is not used. * Added `--without-octave` and `--without-matlab` configure options to disable Octave and Matlab plugins, respectively. * Modified COBYLA algorithm to have better support for bound constraints. * Added new `NLOPT_ROUNDOFF_LIMITED` failure code to indicate cases in which optimization breaks down due to roundoff errors, in which case it is possible that useful results were obtained. * Experimental support for nonlinear equality constraints via augmented-Lagrangian method. * Support for compiling under Windows (ideally with MinGW) as a DLL, although you have to manually add `#define NLOPT_DLL` to nlopt.h *after* installing (after compiling NLopt). * Added several checks for roundoff-related breakdown to NEWUOA code. * When only a relative error tolerance is specified, no longer fails to halt when exact convergence to zero is obtained. * Workaround for incompatible `qsort_r` functions in BSD and GNU libc by always using my own version; thanks to Wendy Vandoolaeghe and Philippe Preux for the bug report and explanation. * Workaround for gcc 3.4.x conflict with `HUGE_VAL` definition in Solaris (gcc bug 19933). * Better identification of Matlab-plugin installation directory. * Fixed identification of Octave-plugin installation directory for recent Octave versions. ## NLopt 1.0.1 13 Nov. 2008 * Allow user to override Matlab-plugin installation directory with `MEX_INSTALL_DIR`. * Bug fix in my DIRECT code that prevented convergence (DIRECT-L unaffected). * MLSL needs a nonzero default `ftol_rel` and/or `xtol_rel` to ensure that its local searches terminate; use roughly machine precision as defaults. ## NLopt 1.0 11 Nov. 2008 * Initial public release. [#12]: https://github.com/stevengj/nlopt/issues/12 [#13]: https://github.com/stevengj/nlopt/issues/13 [#21]: https://github.com/stevengj/nlopt/issues/21 [#49]: https://github.com/stevengj/nlopt/issues/49 [#160]: https://github.com/stevengj/nlopt/issues/160 [#194]: https://github.com/stevengj/nlopt/issues/194 [#197]: https://github.com/stevengj/nlopt/issues/197 [#198]: https://github.com/stevengj/nlopt/issues/198 [#216]: https://github.com/stevengj/nlopt/issues/216 [#230]: https://github.com/stevengj/nlopt/issues/230 [#242]: https://github.com/stevengj/nlopt/issues/242 [#245]: https://github.com/stevengj/nlopt/issues/245 [#250]: https://github.com/stevengj/nlopt/issues/250 [#257]: https://github.com/stevengj/nlopt/issues/257 [#258]: https://github.com/stevengj/nlopt/issues/258 [#261]: https://github.com/stevengj/nlopt/issues/261 nlopt-2.6.1/README.md000066400000000000000000000044341345435414600141510ustar00rootroot00000000000000[![Latest Docs](https://readthedocs.org/projects/nlopt/badge/?version=latest)](http://nlopt.readthedocs.io/en/latest/) [![Build Status](https://travis-ci.org/stevengj/nlopt.svg?branch=master)](https://travis-ci.org/stevengj/nlopt) [![Build Status](https://ci.appveyor.com/api/projects/status/github/stevengj/nlopt?branch=master&svg=true)](https://ci.appveyor.com/project/StevenGJohnson/nlopt) NLopt is a library for nonlinear local and global optimization, for functions with and without gradient information. It is designed as a simple, unified interface and packaging of several free/open-source nonlinear optimization libraries. The latest release can be downloaded from the [NLopt releases](https://github.com/stevengj/nlopt/releases) page on Github, and the [NLopt manual]( https://nlopt.readthedocs.io/en/latest/) is hosted on readthedocs. NLopt is compiled and installed with the [CMake](https://cmake.org/) build system (see `CMakeLists.txt` file for available options): git clone git://github.com/stevengj/nlopt cd nlopt mkdir build cd build cmake .. make sudo make install (To build the latest development sources from git, you will need [SWIG](http://www.swig.org/) to generate the Python and Guile bindings.) Once it is installed, `#include ` in your C/C++ programs and link it with `-lnlopt -lm`. You may need to use a C++ compiler to link in order to include the C++ libraries (which are used internally by NLopt, even though it exports a C API). See the [C reference manual](https://nlopt.readthedocs.io/en/latest/NLopt_Reference/). There are also interfaces for [C++](https://nlopt.readthedocs.io/en/latest/NLopt_C-plus-plus_Reference/), [Fortran](https://nlopt.readthedocs.io/en/latest/NLopt_Fortran_Reference/), [Python](https://nlopt.readthedocs.io/en/latest/NLopt_Python_Reference/), [Matlab or GNU Octave](https://nlopt.readthedocs.io/en/latest/NLopt_Matlab_Reference/), [OCaml](https://bitbucket.org/mkur/nlopt-ocaml), [GNU Guile](https://nlopt.readthedocs.io/en/latest/NLopt_Guile_Reference/), [GNU R](https://www.ucl.ac.uk/~uctpjyy/nloptr.html), [Lua](https://github.com/rochus-keller/LuaNLopt), [Rust](https://github.com/jesskfullwood/rust-nlopt), and [Julia](https://github.com/JuliaOpt/NLopt.jl). Interfaces for other languages may be added in the future. nlopt-2.6.1/TODO000066400000000000000000000005351345435414600133600ustar00rootroot00000000000000Add nonlinearly constrained multistart algorithm. Add option to control subspace size (mf) in LBFGS etcetera. STOGO has bitrotted - doesn't return proper NLopt codes, doesn't support forced stop, etcetera. Needs to be fixed. If local_optimizer is set, STOGO should use it instead of its own BFGS. Wrappers for GNU R, Java, Perl, Ocaml, C#, ... nlopt-2.6.1/appveyor.yml000066400000000000000000000012001345435414600152460ustar00rootroot00000000000000version: 1.0.{build} os: Visual Studio 2015 clone_folder: C:\projects\nlopt test: off configuration: - Release branches: only: - master environment: matrix: - CMAKE_PLATFORM: "Visual Studio 10 2010" - CMAKE_PLATFORM: "Visual Studio 14 2015" - CMAKE_PLATFORM: "Visual Studio 14 2015 Win64" install: - cinstall: python #- choco install swig build_script: - echo Running cmake... - cd c:\projects\nlopt - cmake -G "%CMAKE_PLATFORM%" -DCMAKE_INSTALL_PREFIX="C:\projects\nlopt\install" . - cmake --build . --config %Configuration% --target install - ctest -C %Configuration% --output-on-failure --timeout 100 nlopt-2.6.1/cmake/000077500000000000000000000000001345435414600137455ustar00rootroot00000000000000nlopt-2.6.1/cmake/FindGuile.cmake000066400000000000000000000063641345435414600166260ustar00rootroot00000000000000# Copyright (c) 2008, 2014 OpenCog.org (http://opencog.org) # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # - Try to find Guile; Once done this will define # # GUILE_FOUND - system has the GUILE library # GUILE_INCLUDE_DIRS - the GUILE include directory # GUILE_LIBRARIES - The libraries needed to use GUILE # GUILE_VERSION_STRING - Version # GUILE_SITE_DIR - site dir # GUILE_EXTENSION_DIR - extension dir # GUILE_ROOT_DIR - prefix dir # Look for the header file # Look for guile-2.2 first, then 2.0, then 1.8 # Macports for OSX puts things in /opt/local find_path (GUILE_INCLUDE_DIR libguile.h PATH_SUFFIXES guile/2.2 guile/2.0 guile/1.8 libguile guile HINTS /opt/local/include ) # Look for the library find_library (GUILE_LIBRARY NAMES guile-2.2 guile-2.0 guile HINTS /opt/local/lib ) set (GUILE_LIBRARIES ${GUILE_LIBRARY}) set (GUILE_INCLUDE_DIRS ${GUILE_INCLUDE_DIR}) # check guile's version if we're using cmake >= 2.6 if (GUILE_INCLUDE_DIR) SET(GUILE_VERSION_MAJOR 0) SET(GUILE_VERSION_MINOR 0) SET(GUILE_VERSION_PATCH 0) IF(NOT EXISTS "${GUILE_INCLUDE_DIR}/libguile/version.h") MESSAGE(FATAL_ERROR "Found ${GUILE_INCLUDE_DIR}/libguile.h but not version.h; check your guile installation!") ENDIF(NOT EXISTS "${GUILE_INCLUDE_DIR}/libguile/version.h") # Extract the libguile version from the 'version.h' file SET(GUILE_MAJOR_VERSION 0) FILE(READ "${GUILE_INCLUDE_DIR}/libguile/version.h" _GUILE_VERSION_H_CONTENTS) STRING(REGEX MATCH "#define SCM_MAJOR_VERSION[ ]+([0-9])" _MATCH "${_GUILE_VERSION_H_CONTENTS}") SET(GUILE_VERSION_MAJOR ${CMAKE_MATCH_1}) STRING(REGEX MATCH "#define SCM_MINOR_VERSION[ ]+([0-9]+)" _MATCH "${_GUILE_VERSION_H_CONTENTS}") SET(GUILE_VERSION_MINOR ${CMAKE_MATCH_1}) STRING(REGEX MATCH "#define SCM_MICRO_VERSION[ ]+([0-9]+)" _MATCH "${_GUILE_VERSION_H_CONTENTS}") SET(GUILE_VERSION_PATCH ${CMAKE_MATCH_1}) SET(GUILE_VERSION_STRING "${GUILE_VERSION_MAJOR}.${GUILE_VERSION_MINOR}.${GUILE_VERSION_PATCH}") endif () find_program(GUILE_EXECUTABLE NAMES guile ) find_program(GUILE_CONFIG_EXECUTABLE NAMES guile-config ) if (GUILE_CONFIG_EXECUTABLE) execute_process (COMMAND ${GUILE_CONFIG_EXECUTABLE} info prefix OUTPUT_VARIABLE GUILE_ROOT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${GUILE_CONFIG_EXECUTABLE} info sitedir OUTPUT_VARIABLE GUILE_SITE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${GUILE_CONFIG_EXECUTABLE} info extensiondir OUTPUT_VARIABLE GUILE_EXTENSION_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) endif () # IF(GUILE_FOUND AND GUILE_VERSION_MAJOR EQUAL 2) # ADD_DEFINITIONS(-DHAVE_GUILE2) # ENDIF(GUILE_FOUND AND GUILE_VERSION_MAJOR EQUAL 2) # handle REQUIRED and QUIET options include (FindPackageHandleStandardArgs) find_package_handle_standard_args (Guile REQUIRED_VARS GUILE_EXECUTABLE GUILE_ROOT_DIR GUILE_INCLUDE_DIRS GUILE_LIBRARIES VERSION_VAR GUILE_VERSION_STRING) mark_as_advanced (GUILE_INCLUDE_DIR GUILE_LIBRARY) nlopt-2.6.1/cmake/FindNumPy.cmake000066400000000000000000000077561345435414600166370ustar00rootroot00000000000000# - Find the NumPy libraries # This module finds if NumPy is installed, and sets the following variables # indicating where it is. # # TODO: Update to provide the libraries and paths for linking npymath lib. # # NUMPY_FOUND - was NumPy found # NUMPY_VERSION - the version of NumPy found as a string # NUMPY_VERSION_MAJOR - the major version number of NumPy # NUMPY_VERSION_MINOR - the minor version number of NumPy # NUMPY_VERSION_PATCH - the patch version number of NumPy # NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 # NUMPY_INCLUDE_DIRS - path to the NumPy include files #============================================================================ # Copyright 2012 Continuum Analytics, Inc. # # MIT License # # 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. # #============================================================================ # Finding NumPy involves calling the Python interpreter if(NumPy_FIND_REQUIRED) find_package(PythonInterp REQUIRED) else() find_package(PythonInterp) endif() if(NOT PYTHONINTERP_FOUND) set(NUMPY_FOUND FALSE) return() endif() execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import numpy as n; print(n.__version__); print(n.get_include());" RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT ERROR_VARIABLE _NUMPY_ERROR_VALUE OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0) if(NumPy_FIND_REQUIRED) message(FATAL_ERROR "NumPy import failure:\n${_NUMPY_ERROR_VALUE}") endif() set(NUMPY_FOUND FALSE) return() endif() # Convert the process output into a list string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT}) string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES}) list(GET _NUMPY_VALUES 0 NUMPY_VERSION) list(GET _NUMPY_VALUES 1 NUMPY_INCLUDE_DIRS) string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}") if("${_VER_CHECK}" STREQUAL "") # The output from Python was unexpected. Raise an error always # here, because we found NumPy, but it appears to be corrupted somehow. message(FATAL_ERROR "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n") return() endif() # Make sure all directory separators are '/' string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS}) # Get the major and minor version numbers string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION}) list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR) list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR) list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH) string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH}) math(EXPR NUMPY_VERSION_DECIMAL "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") find_package_message(NUMPY "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}" "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}") set(NUMPY_FOUND TRUE) nlopt-2.6.1/cmake/FindOctave.cmake000066400000000000000000000171721345435414600170010ustar00rootroot00000000000000# - Find Octave # GNU Octave is a high-level interpreted language, primarily intended for numerical computations. # available at http://www.gnu.org/software/octave/ # # This module defines: # OCTAVE_EXECUTABLE - octave interpreter # OCTAVE_INCLUDE_DIRS - include path for mex.h, mexproto.h # OCTAVE_LIBRARIES - required libraries: octinterp, octave, cruft # OCTAVE_OCTINTERP_LIBRARY - path to the library octinterp # OCTAVE_OCTAVE_LIBRARY - path to the library octave # OCTAVE_CRUFT_LIBRARY - path to the library cruft # OCTAVE_VERSION_STRING - octave version string # OCTAVE_MAJOR_VERSION - major version # OCTAVE_MINOR_VERSION - minor version # OCTAVE_PATCH_VERSION - patch version # OCTAVE_OCT_FILE_DIR - object files that will be dynamically loaded # OCTAVE_OCT_LIB_DIR - oct libraries # OCTAVE_ROOT_DIR - octave prefix # OCTAVE_M_SITE_DIR - .m files site dir # OCTAVE_OCT_SITE_DIR - .oct files site dir # # The macro octave_add_oct allows to create compiled modules. # octave_add_oct (target_name # [SOURCES] source1 [source2 ...] # [LINK_LIBRARIES lib1 [lib2 ...]] # [EXTENSION ext] #) # # To install it, you can the use the variable OCTAVE_OCT_FILE_DIR as follow: # file (RELATIVE_PATH PKG_OCTAVE_OCT_SITE_DIR ${OCTAVE_ROOT_DIR} ${OCTAVE_OCT_SITE_DIR}) # install ( # TARGETS target_name # DESTINATION ${PKG_OCTAVE_OCT_SITE_DIR} #) #============================================================================= # Copyright 2013, Julien Schueller # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # The views and conclusions contained in the software and documentation are those # of the authors and should not be interpreted as representing official policies, # either expressed or implied, of the FreeBSD Project. #============================================================================= find_program(OCTAVE_CONFIG_EXECUTABLE NAMES octave-config ) if (OCTAVE_CONFIG_EXECUTABLE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTAVE_HOME OUTPUT_VARIABLE OCTAVE_ROOT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} --m-site-dir OUTPUT_VARIABLE OCTAVE_M_SITE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} --oct-site-dir OUTPUT_VARIABLE OCTAVE_OCT_SITE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p BINDIR OUTPUT_VARIABLE OCTAVE_BIN_PATHS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTINCLUDEDIR OUTPUT_VARIABLE OCTAVE_INCLUDE_PATHS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTLIBDIR OUTPUT_VARIABLE OCTAVE_LIBRARIES_PATHS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTFILEDIR OUTPUT_VARIABLE OCTAVE_OCT_FILE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTLIBDIR OUTPUT_VARIABLE OCTAVE_OCT_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -v OUTPUT_VARIABLE OCTAVE_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE) if (OCTAVE_VERSION_STRING) string (REGEX REPLACE "([0-9]+)\\..*" "\\1" OCTAVE_MAJOR_VERSION ${OCTAVE_VERSION_STRING}) string (REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" OCTAVE_MINOR_VERSION ${OCTAVE_VERSION_STRING}) string (REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OCTAVE_PATCH_VERSION ${OCTAVE_VERSION_STRING}) endif () endif () find_program(OCTAVE_EXECUTABLE HINTS ${OCTAVE_BIN_PATHS} NAMES octave ) find_program(OCTAVE_MKOCTFILE HINTS ${OCTAVE_BIN_PATHS} NAMES mkoctfile ) find_library(OCTAVE_OCTINTERP_LIBRARY NAMES octinterp liboctinterp HINTS ${OCTAVE_LIBRARIES_PATHS} ) find_library(OCTAVE_OCTAVE_LIBRARY NAMES octave liboctave HINTS ${OCTAVE_LIBRARIES_PATHS} ) find_library(OCTAVE_CRUFT_LIBRARY NAMES cruft libcruft HINTS ${OCTAVE_LIBRARIES_PATHS} ) set (OCTAVE_LIBRARIES ${OCTAVE_OCTINTERP_LIBRARY}) list (APPEND OCTAVE_LIBRARIES ${OCTAVE_OCTAVE_LIBRARY}) if (OCTAVE_CRUFT_LIBRARY) list (APPEND OCTAVE_LIBRARIES ${OCTAVE_CRUFT_LIBRARY}) endif () find_path (OCTAVE_INCLUDE_DIR NAMES octave/oct.h PATHS "${OCTAVE_INCLUDE_PATHS}/.." ) set (OCTAVE_INCLUDE_DIRS ${OCTAVE_INCLUDE_DIR} ${OCTAVE_INCLUDE_DIR}/octave) macro (octave_add_oct FUNCTIONNAME) set (_CMD SOURCES) set (_SOURCES) set (_LINK_LIBRARIES) set (_EXTENSION) set (_OCT_EXTENSION oct) foreach (_ARG ${ARGN}) if (${_ARG} MATCHES SOURCES) set (_CMD SOURCES) elseif (${_ARG} MATCHES LINK_LIBRARIES) set (_CMD LINK_LIBRARIES) elseif (${_ARG} MATCHES EXTENSION) set (_CMD EXTENSION) else () if (${_CMD} MATCHES SOURCES) list (APPEND _SOURCES "${_ARG}") elseif (${_CMD} MATCHES LINK_LIBRARIES) list (APPEND _LINK_LIBRARIES "${_ARG}") elseif (${_CMD} MATCHES EXTENSION) set (_OCT_EXTENSION ${_ARG}) endif () endif () endforeach () add_library (${FUNCTIONNAME} SHARED ${_SOURCES}) target_link_libraries (${FUNCTIONNAME} ${OCTAVE_LIBRARIES} ${_LINK_LIBRARIES}) set_target_properties (${FUNCTIONNAME} PROPERTIES PREFIX "" SUFFIX ".${_OCT_EXTENSION}" ) endmacro () # handle REQUIRED and QUIET options include (FindPackageHandleStandardArgs) find_package_handle_standard_args (Octave REQUIRED_VARS OCTAVE_EXECUTABLE OCTAVE_ROOT_DIR OCTAVE_INCLUDE_DIRS OCTAVE_LIBRARIES VERSION_VAR OCTAVE_VERSION_STRING) mark_as_advanced ( OCTAVE_OCT_FILE_DIR OCTAVE_OCT_LIB_DIR OCTAVE_OCTINTERP_LIBRARY OCTAVE_OCTAVE_LIBRARY OCTAVE_CRUFT_LIBRARY OCTAVE_LIBRARIES OCTAVE_INCLUDE_DIR OCTAVE_INCLUDE_DIRS OCTAVE_ROOT_DIR OCTAVE_VERSION_STRING OCTAVE_MAJOR_VERSION OCTAVE_MINOR_VERSION OCTAVE_PATCH_VERSION ) nlopt-2.6.1/cmake/NLoptConfig.cmake.in000066400000000000000000000016061345435414600175410ustar00rootroot00000000000000 # defined since 2.8.3 if (CMAKE_VERSION VERSION_LESS 2.8.3) get_filename_component (CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) endif () # Tell the user project where to find our headers and libraries set (NLOPT_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/@RELATIVE_NLOPT_INCLUDE_DIRS@") set (NLOPT_LIBRARY_DIRS "${CMAKE_CURRENT_LIST_DIR}/@RELATIVE_NLOPT_LIB_DIR@") # Allows loading NLOPT settings from another project set (NLOPT_CONFIG_FILE "${CMAKE_CURRENT_LIST_FILE}") # List of compilation flags -DTOTO to export set (NLOPT_DEFINITIONS "@NLOPT_DEFINITIONS@") # Our library dependencies (contains definitions for IMPORTED targets) include ("${CMAKE_CURRENT_LIST_DIR}/NLoptLibraryDepends.cmake") # These are IMPORTED targets created by NLOPTLibraryDepends.cmake set (NLOPT_LIBRARIES "@NLOPT_LIBRARIES@") if (CMAKE_VERSION VERSION_LESS 2.8.3) set (CMAKE_CURRENT_LIST_DIR) endif () nlopt-2.6.1/cmake/NLoptConfigVersion.cmake.in000066400000000000000000000006111345435414600211020ustar00rootroot00000000000000 set (PACKAGE_VERSION "@NLOPT_VERSION_STRING@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set (PACKAGE_VERSION_COMPATIBLE FALSE) else () set (PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set (PACKAGE_VERSION_EXACT TRUE) endif () endif () nlopt-2.6.1/cmake/TargetLinkLibrariesWithDynamicLookup.cmake000066400000000000000000000060021345435414600242010ustar00rootroot00000000000000# # - This module provides the function # target_link_libraries_with_dynamic_lookup which can be used to # "weakly" link loadable module. # # Link a library to a target such that the symbols are resolved at # run-time not link-time. This should be used when compiling a # loadable module when the symbols should be resolve from the run-time # environment where the module is loaded, and not a specific system # library. # # Specifically, for OSX it uses undefined dynamic_lookup. This is # similar to using "-shared" on Linux where undefined symbols are # ignored. # # Additionally, the linker is checked to see if it supports undefined # symbols when linking a shared library. If it does then the library # is not linked when specified with this function. # # http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/ # # Function: _CheckUndefinedSymbolsAllowed # # Check if the linker allows undefined symbols for shared libraries. # # UNDEFINED_SYMBOLS_ALLOWED - true if the linker will allow # undefined symbols for shared libraries # function(_CheckUndefinedSymbolsAllowed) set(VARIABLE "UNDEFINED_SYMBOLS_ALLOWED") set(cache_var "${VARIABLE}_hash") # hash the CMAKE_FLAGS passed and check cache to know if we need to rerun string(MD5 cmake_flags_hash "${CMAKE_SHARED_LINKER_FLAGS}") if(NOT DEFINED "${cache_var}" ) unset("${VARIABLE}" CACHE) elseif(NOT "${${cache_var}}" STREQUAL "${cmake_flags_hash}" ) unset("${VARIABLE}" CACHE) endif() if(NOT DEFINED "${VARIABLE}") set(test_project_dir "${PROJECT_BINARY_DIR}/CMakeTmp/${VARIABLE}") file(WRITE "${test_project_dir}/CMakeLists.txt" " project(undefined C) add_library(foo SHARED \"foo.c\") ") file(WRITE "${test_project_dir}/foo.c" " extern int bar(void); int foo(void) {return bar()+1;} ") if(APPLE AND ${CMAKE_VERSION} VERSION_GREATER 2.8.11) set( _rpath_arg "-DCMAKE_MACOSX_RPATH='${CMAKE_MACOSX_RPATH}'" ) else() set( _rpath_arg ) endif() try_compile(${VARIABLE} "${test_project_dir}" "${test_project_dir}" undefined CMAKE_FLAGS "-DCMAKE_SHARED_LINKER_FLAGS='${CMAKE_SHARED_LINKER_FLAGS}'" ${_rpath_arg} OUTPUT_VARIABLE output) set(${cache_var} "${cmake_flags_hash}" CACHE INTERNAL "hashed try_compile flags") if(${VARIABLE}) message(STATUS "Performing Test ${VARIABLE} - Success") else() message(STATUS "Performing Test ${VARIABLE} - Failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing Test ${VARIABLE} failed with the following output:\n" "${OUTPUT}\n") endif() endif() endfunction() _CheckUndefinedSymbolsAllowed() macro( target_link_libraries_with_dynamic_lookup target ) if ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) set_target_properties( ${target} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" ) elseif(UNDEFINED_SYMBOLS_ALLOWED) # linker allows undefined symbols, let's just not link else() target_link_libraries ( ${target} ${ARGN} ) endif() endmacro() nlopt-2.6.1/cmake/toolchain-i686-w64-mingw32.cmake000066400000000000000000000021461345435414600213260ustar00rootroot00000000000000set (CMAKE_SYSTEM_NAME Windows) # specify the cross compiler set (CMAKE_C_COMPILER i686-w64-mingw32-gcc) set (CMAKE_CXX_COMPILER i686-w64-mingw32-g++) # where is the target environment set (CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) # search for programs in the build host directories set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # Make sure Qt can be detected by CMake set (QT_BINARY_DIR /usr/i686-w64-mingw32/bin /usr/bin) set (QT_INCLUDE_DIRS_NO_SYSTEM ON) # set the resource compiler (RHBZ #652435) set (CMAKE_RC_COMPILER i686-w64-mingw32-windres) set (CMAKE_MC_COMPILER i686-w64-mingw32-windmc) # override boost thread component suffix as mingw-w64-boost is compiled with threadapi=win32 set (Boost_THREADAPI win32) # These are needed for compiling lapack (RHBZ #753906) set (CMAKE_Fortran_COMPILER i686-w64-mingw32-gfortran) set (CMAKE_AR:FILEPATH i686-w64-mingw32-ar) set (CMAKE_RANLIB:FILEPATH i686-w64-mingw32-ranlib) nlopt-2.6.1/cmake/toolchain-x86_64-w64-mingw32.cmake000066400000000000000000000021701345435414600215650ustar00rootroot00000000000000set (CMAKE_SYSTEM_NAME Windows) # specify the cross compiler set (CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set (CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) # where is the target environment set (CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) # search for programs in the build host directories set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # Make sure Qt can be detected by CMake set (QT_BINARY_DIR /usr/x86_64-w64-mingw32/bin /usr/bin) set (QT_INCLUDE_DIRS_NO_SYSTEM ON) # set the resource compiler (RHBZ #652435) set (CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) set (CMAKE_MC_COMPILER x86_64-w64-mingw32-windmc) # override boost thread component suffix as mingw-w64-boost is compiled with threadapi=win32 set (Boost_THREADAPI win32) # These are needed for compiling lapack (RHBZ #753906) set (CMAKE_Fortran_COMPILER x86_64-w64-mingw32-gfortran) set (CMAKE_AR:FILEPATH x86_64-w64-mingw32-ar) set (CMAKE_RANLIB:FILEPATH x86_64-w64-mingw32-ranlib) nlopt-2.6.1/doc/000077500000000000000000000000001345435414600134325ustar00rootroot00000000000000nlopt-2.6.1/doc/README000066400000000000000000000013341345435414600143130ustar00rootroot00000000000000This is the documentation tree for NLopt. Markdown (.md) files for NLopt documentation live in $(top_src_dir)/doc/docs. To build and visualize the HTML documentation locally using the mkdocs package (useful for verifying on your local machine before committing), install the `mkdocs` package, then run the following command from the top-level meep repository tree: % mkdocs serve and then open the following URL in a browser window: http://127.0.0.1:8000/NLopt This launches a little web server on your local machine plus a filesystem hook for rebuilding the documentation tree automatically whenever any .md file is modified, so you can see what the actual HTML documentation looks like in real time as you edit the source. nlopt-2.6.1/doc/docs/000077500000000000000000000000001345435414600143625ustar00rootroot00000000000000nlopt-2.6.1/doc/docs/Citing_NLopt.md000066400000000000000000000010521345435414600172330ustar00rootroot00000000000000--- # Citing NLopt --- If you use NLopt in work that leads to a publication, we would appreciate it if you would kindly cite NLopt in your manuscript. Please cite *both* the NLopt library *and* the authors of the specific algorithm(s) that you employed in your work. Cite NLopt as something like: - Steven G. Johnson, The NLopt nonlinear-optimization package, The authors and appropriate citations for the specific optimization algorithms in NLopt are listed in the [NLopt Algorithms](NLopt_Algorithms.md) page. nlopt-2.6.1/doc/docs/NLopt_Algorithms.md000066400000000000000000001252361345435414600201420ustar00rootroot00000000000000--- # NLopt Algorithms --- NLopt includes implementations of a number of different optimization algorithms. These algorithms are listed below, including links to the original source code (if any) and citations to the relevant articles in the literature (see [Citing NLopt](Citing_NLopt.md)). Even where I found available free/open-source code for the various algorithms, I modified the code at least slightly (and in some cases noted below, substantially) for inclusion into NLopt. I apologize in advance to the authors for any new bugs I may have inadvertantly introduced into their code. Nomenclature ------------ Each algorithm in NLopt is identified by a named constant, which is passed to the NLopt routines in the various languages in order to select a particular algorithm. These constants are mostly of the form `NLOPT_{G,L}{N,D}_xxxx`, where `G`/`L` denotes global/local optimization and `N`/`D` denotes derivative-free/gradient-based algorithms, respectively. For example, the `NLOPT_LN_COBYLA` constant refers to the COBYLA algorithm (described below), which is a local (`L`) derivative-free (`N`) optimization algorithm. Two exceptions are the MLSL and augmented Lagrangian algorithms, denoted by `NLOPT_G_MLSL` and `NLOPT_AUGLAG`, since whether or not they use derivatives (and whether or not they are global, in `AUGLAG`'s case) is determined by what subsidiary optimization algorithm is specified. Many of the algorithms have several variants, which are grouped together below. Comparing algorithms -------------------- For any given optimization problem, it is a good idea to compare several of the available algorithms that are applicable to that problem—in general, one often finds that the "best" algorithm strongly depends upon the problem at hand. However, comparing algorithms requires a little bit of care because the function-value/parameter tolerance tests are not all implemented in exactly the same way for different algorithms. So, for example, the same fractional 10−4 tolerance on the function value might produce a much more accurate minimum in one algorithm compared to another, and matching them might require some experimentation with the tolerances. Instead, a more fair and reliable way to compare two different algorithms is to run one until the function value is converged to some value *f*A, and then run the second algorithm with the minf_max [termination test](NLopt_Introduction#Termination_conditions.md) set to minf_max=*f*A. That is, ask how long it takes for the two algorithms to reach the same function value. Better yet, run some algorithm for a really long time until the minimum *f*M is located to high precision. Then run the different algorithms you want to compare with the termination test: minf_max=*f*M+Δ*f*. That is, ask how long it takes for the different algorithms to obtain the minimum to within an absolute tolerance Δ*f*, for some Δ*f*. (This is *totally different* from using the ftol_abs termination test, because the latter uses only a crude estimate of the error in the function values, and moreover the estimate varies between algorithms.) Global optimization ------------------- All of the global-optimization algorithms currently require you to specify bound constraints on all the optimization parameters. Of these algorithms, only ISRES, AGS, and ORIG_DIRECT support nonlinear inequality constraints, and only ISRES supports nonlinear equality constraints. (However, any of them can be applied to nonlinearly constrained problems by combining them with the [augmented Lagrangian method](#Augmented_Lagrangian_algorithm.md) below.) **Something you should consider** is that, after running the global optimization, it is often worthwhile to then use the global optimum as a starting point for a local optimization to "polish" the optimum to a greater accuracy. (Many of the global optimization algorithms devote more effort to searching the global parameter space than in finding the precise position of the local optimum accurately.) ### DIRECT and DIRECT-L DIRECT is the DIviding RECTangles algorithm for global optimization, described in: - D. R. Jones, C. D. Perttunen, and B. E. Stuckmann, "Lipschitzian optimization without the lipschitz constant," *J. Optimization Theory and Applications*, vol. 79, p. 157 (1993). and DIRECT-L is the "locally biased" variant proposed by: - J. M. Gablonsky and C. T. Kelley, "A locally-biased form of the DIRECT algorithm," *J. Global Optimization*, vol. 21 (1), p. 27-37 (2001). These are deterministic-search algorithms based on systematic division of the search domain into smaller and smaller hyperrectangles. The Gablonsky version makes the algorithm "more biased towards local search" so that it is more efficient for functions without too many local minima. NLopt contains several implementations of both of these algorithms. I would tend to try `NLOPT_GN_DIRECT_L` first; YMMV. First, it contains a from-scratch re-implementation of both algorithms, specified by the constants `NLOPT_GN_DIRECT` and `NLOPT_GN_DIRECT_L`, respectively. Second, there is a slightly randomized variant of DIRECT-L, specified by `NLOPT_GN_DIRECT_L_RAND`, which uses some randomization to help decide which dimension to halve next in the case of near-ties. The DIRECT and DIRECT-L algorithms start by rescaling the bound constraints to a hypercube, which gives all dimensions equal weight in the search procedure. If your dimensions do *not* have equal weight, e.g. if you have a "long and skinny" search space and your function varies at about the same speed in all directions, it may be better to use unscaled variants of these algorthms, which are specified as `NLOPT_GNL_DIRECT_NOSCAL`, `NLOPT_GN_DIRECT_L_NOSCAL`, and `NLOPT_GN_DIRECT_L_RAND_NOSCAL`, respectively. However, the unscaled variations make the most sense (if any) with the original DIRECT algorithm, since the design of DIRECT-L to some extent relies on the search region being a hypercube (which causes the subdivided hyperrectangles to have only a small set of side lengths). Finally, NLopt also includes separate implementations based on the [original Fortran code](http://www4.ncsu.edu/~ctk/SOFTWARE/DIRECTv204.tar.gz) by Gablonsky et al. (1998-2001), which are specified as `NLOPT_GN_ORIG_DIRECT` and `NLOPT_GN_ORIG_DIRECT_L`. These implementations have a number of hard-coded limitations on things like the number of function evaluations; I removed several of these limitations, but some remain. On the other hand, there seem to be slight differences between these implementations and mine; most of the time, the performance is roughly similar, but occasionally Gablonsky's implementation will do significantly better than mine or vice versa. Most of the above algorithms only handle bound constraints, and in fact require finite bound constraints (they are not applicable to unconstrained problems). They do not handle arbitrary nonlinear constraints. However, the `ORIG` versions by Gablonsky et al. include some support for arbitrary nonlinear inequality constraints. ### Controlled Random Search (CRS) with local mutation My implementation of the "controlled random search" (CRS) algorithm (in particular, the CRS2 variant) with the "local mutation" modification, as defined by: - P. Kaelo and M. M. Ali, "Some variants of the controlled random search algorithm for global optimization," *J. Optim. Theory Appl.* **130** (2), 253-264 (2006). The original CRS2 algorithm was described by: - W. L. Price, "A controlled random search procedure for global optimization," in *Towards Global Optimization 2*, p. 71-84 edited by L. C. W. Dixon and G. P. Szego (North-Holland Press, Amsterdam, 1978). - W. L. Price, "Global optimization by controlled random search," *J. Optim. Theory Appl.* **40** (3), p. 333-348 (1983). The CRS algorithms are sometimes compared to genetic algorithms, in that they start with a random "population" of points, and randomly "evolve" these points by heuristic rules. In this case, the "evolution" somewhat resembles a randomized Nelder-Mead algorithm. The published results for CRS seem to be largely empirical; limited analytical results about its convergence were derived in: - Eligius M. T. Hendrix, P. M. Ortigosa, and I. García, "On success rates for controlled random search," *J. Global Optim.* **21**, p. 239-263 (2001). The initial population size for CRS defaults to 10×(*n*+1) in *n* dimensions, but this can be changed with the [nlopt_set_population](NLopt_Reference#Stochastic_population.md) function; the initial population must be at least *n*+1. Only bound-constrained problems are supported by this algorithm. CRS2 with local mutation is specified in NLopt as `NLOPT_GN_CRS2_LM`. ### MLSL (Multi-Level Single-Linkage) This is my implementation of the "Multi-Level Single-Linkage" (MLSL) algorithm for global optimization by a sequence of local optimizations from random starting points, proposed by: - A. H. G. Rinnooy Kan and G. T. Timmer, "Stochastic global optimization methods," *Mathematical Programming*, vol. 39, p. 27-78 (1987). (Actually 2 papers — part I: clustering methods, p. 27, then part II: multilevel methods, p. 57.) We also include a modification of MLSL use a Sobol' [low-discrepancy sequence](https://en.wikipedia.org/wiki/Low-discrepancy_sequence) (LDS) instead of pseudorandom numbers, which was argued to improve the convergence rate by: - Sergei Kucherenko and Yury Sytsko, "Application of deterministic low-discrepancy sequences in global optimization," *Computational Optimization and Applications*, vol. 30, p. 297-318 (2005). In either case, MLSL is a "multistart" algorithm: it works by doing a sequence of local optimizations (using some other local optimization algorithm) from random or low-discrepancy starting points. MLSL is distinguished, however by a "clustering" heuristic that helps it to avoid repeated searches of the same local optima, and has some theoretical guarantees of finding all local optima in a finite number of local minimizations. The local-search portion of MLSL can use any of the other algorithms in NLopt, and in particular can use either gradient-based (`D`) or derivative-free algorithms (`N`) The local search uses the derivative/nonderivative algorithm set by `nlopt_opt_set_local_optimizer`. LDS-based MLSL with is specified as `NLOPT_G_MLSL_LDS`, while the original non-LDS original MLSL (using pseudo-random numbers, currently via the [Mersenne twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm) is indicated by `NLOPT_G_MLSL`. In both cases, you must specify the [local optimization](NLopt_Reference#Local/subsidiary_optimization_algorithm.md) algorithm (which can be gradient-based or derivative-free) via `nlopt_opt_set_local_optimizer`. **Note**: If you do not set a stopping tolerance for your local-optimization algorithm, MLSL defaults to ftol_rel=10−15 and xtol_rel=10−7 for the local searches. Note that it is perfectly reasonable to set a relatively large tolerance for these local searches, run MLSL, and then at the end run another local optimization with a lower tolerance, using the MLSL result as a starting point, to "polish off" the optimum to high precision. By default, each iteration of MLSL samples 4 random new trial points, but this can be changed with the [nlopt_set_population](NLopt_Reference#Stochastic_population.md) function. Only bound-constrained problems are supported by this algorithm. ### StoGO This is an algorithm adapted from the code downloaded from - [StoGO global optimization library](http://www2.imm.dtu.dk/~km/GlobOpt/opt.html) (link broken as of Nov. 2009, and the software seems absent from the [author's web site](http://www2.imm.dtu.dk/~km/)) by Madsen et al. StoGO is a global optimization algorithm that works by systematically dividing the search space (which must be bound-constrained) into smaller hyper-rectangles via a branch-and-bound technique, and searching them by a gradient-based local-search algorithm (a BFGS variant), optionally including some randomness (hence the "Sto", which stands for "stochastic" I believe). StoGO is written in C++, which means that it is only included when you compile the [C++ algorithms](NLopt_Installation.md) enabled, in which case (on Unix) you must link to `-lnlopt_cxx` instead of `-lnlopt`. StoGO is specified within NLopt by `NLOPT_GD_STOGO`, or `NLOPT_GD_STOGO_RAND` for the randomized variant. Some references on StoGO are: - S. Gudmundsson, "Parallel Global Optimization," M.Sc. Thesis, IMM, Technical University of Denmark, 1998. - K. Madsen, S. Zertchaninov, and A. Zilinskas, "Global Optimization using Branch-and-Bound," unpublished (1998). A preprint of this paper is included in the `stogo` subdirectory of NLopt as `paper.pdf`. - S. Zertchaninov and K. Madsen, "A C++ Programme for Global Optimization," IMM-REP-1998-04, Department of Mathematical Modelling, Technical University of Denmark, DK-2800 Lyngby, Denmark, 1998. A copy of this report is included in the `stogo` subdirectory of NLopt as `techreport.pdf`. Only bound-constrained problems are supported by this algorithm. ### AGS This algorithm adapted from [this repo](https://github.com/sovrasov/glob_search_nlp_solver). AGS can handle arbitrary objectives and nonlinear inequality constraints. Also bound constraints are required for this method. To guarantee convergence, objectives and constraints should satisfy the Lipschitz condition on the specified hyperrectangle. AGS is derivative-free and employs the Hilbert curve to reduce the source problem to the univariate one. The algorithm divides the univariate space into intervals, generating new points by using posterior probabilities. On each trial AGS tries to evaluate the constraints consequently one by one. If some constraint is violated at this point, the next ones won't be evaluated. If all constraints are preserved, i.e. the trial point is feasible, AGS will evaluate the objective. Thus, some of constraints (except the first one) and objective can be partially undefined inside the search hyperrectangle. Current implementation of AGS doesn't support vector constraints. Limitations of the machine arithmetic don't allow to build a tight approximation for Hilbert when the space dimension is greater than 5, so this implementation of AGS is restricted in that sense. It supports up to 10 dimensions, but the method can stop early in case of 6 and more ones. AGS, like StoGO, is written in C++, but it requires C++11. If the library is built with [C++](NLopt_Installation.md) and compiler supports C++11, AGS will be built too. AGS is specified within NLopt by `NLOPT_GN_AGS`. Additional parameters of AGS which are not adjustable from the common NLOpt interface are declared and described in `ags.h`. Also an example of solving a constrained problem is given in the AGS source folder. References: - Yaroslav D. Sergeyev, Dmitri L. Markin: An algorithm for solving global optimization problems with nonlinear constraints, Journal of Global Optimization, 7(4), pp 407–419, 1995 - Strongin R.G., Sergeyev Ya.D., 2000. Global optimization with non-convex constraints. Sequential and parallel algorithms. Kluwer Academic Publishers, Dordrecht. - Gergel V. and Lebedev I.: Heterogeneous Parallel Computations for Solving Global Optimization Problems. Proc. Comput. Science 66, pp. 53–62 (2015) - [Implementation](https://github.com/sovrasov/multicriterial-go) of AGS for constrained multi-objective problems. ### ISRES (Improved Stochastic Ranking Evolution Strategy) This is my implementation of the "Improved Stochastic Ranking Evolution Strategy" (ISRES) algorithm for nonlinearly-constrained global optimization (or at least semi-global; although it has heuristics to escape local optima, I'm not aware of a convergence proof), based on the method described in: - Thomas Philip Runarsson and Xin Yao, "[Search biases in constrained evolutionary optimization](http://www3.hi.is/~tpr/papers/RuYa05.pdf)," *IEEE Trans. on Systems, Man, and Cybernetics Part C: Applications and Reviews*, vol. 35 (no. 2), pp. 233-243 (2005). It is a refinement of an earlier method described in: - Thomas P. Runarsson and Xin Yao, "[Stochastic ranking for constrained evolutionary optimization](http://www3.hi.is/~tpr/software/sres/Tec311r.pdf)," *IEEE Trans. Evolutionary Computation*, vol. 4 (no. 3), pp. 284-294 (2000). This is an independent implementation by S. G. Johnson (2009) based on the papers above. Runarsson also has his own Matlab implemention available from his web page [here](http://www3.hi.is/~tpr). The evolution strategy is based on a combination of a mutation rule (with a log-normal step-size update and exponential smoothing) and differential variation (a Nelder–Mead-like update rule). The fitness ranking is simply via the objective function for problems without nonlinear constraints, but when nonlinear constraints are included the stochastic ranking proposed by Runarsson and Yao is employed. The population size for ISRES defaults to 20×(*n*+1) in *n* dimensions, but this can be changed with the [nlopt_set_population](NLopt_Reference#Stochastic_population.md) function. This method supports arbitrary nonlinear inequality and equality constraints in addition to the bound constraints, and is specified within NLopt as `NLOPT_GN_ISRES`. ### ESCH (evolutionary algorithm) This is a modified Evolutionary Algorithm for global optimization, developed by Carlos Henrique da Silva Santos's and described in the following paper and Ph.D thesis: - C. H. da Silva Santos, M. S. Gonçalves, and H. E. Hernandez-Figueroa, "Designing Novel Photonic Devices by Bio-Inspired Computing," *IEEE Photonics Technology Letters* **22** (15), pp. 1177–1179 (2010). - C. H. da Silva Santos, "[Parallel and Bio-Inspired Computing Applied to Analyze Microwave and Photonic Metamaterial Strucutures](http://www.bibliotecadigital.unicamp.br/document/?code=000767537&opt=4&lg=en_US)," Ph.D. thesis, University of Campinas, (2010). The algorithm is adapted from ideas described in: - H.-G. Beyer and H.-P. Schwefel, "Evolution Strategies: A Comprehensive Introduction," *Journal Natural Computing*, **1** (1), pp. 3–52 (2002_. - Ingo Rechenberg, "Evolutionsstrategie – Optimierung technischer Systeme nach Prinzipien der biologischen Evolution," Ph.D. thesis (1971), Reprinted by Fromman-Holzboog (1973). The method supports bound constraints only (no nonlinear constraints), and is specified within NLopt as `NLOPT_GN_ESCH`. Local derivative-free optimization ---------------------------------- Of these algorithms, only COBYLA currently supports arbitrary nonlinear inequality and equality constraints; the rest of them support bound-constrained or unconstrained problems only. (However, any of them can be applied to nonlinearly constrained problems by combining them with the [augmented Lagrangian method](#Augmented_Lagrangian_algorithm.md) below.) ### COBYLA (Constrained Optimization BY Linear Approximations) This is a derivative of Powell's implementation of the COBYLA (Constrained Optimization BY Linear Approximations) algorithm for derivative-free optimization with nonlinear inequality and equality constraints, by M. J. D. Powell, described in: - M. J. D. Powell, "A direct search optimization method that models the objective and constraint functions by linear interpolation," in *Advances in Optimization and Numerical Analysis*, eds. S. Gomez and J.-P. Hennart (Kluwer Academic: Dordrecht, 1994), p. 51-67. and reviewed in: - M. J. D. Powell, "Direct search algorithms for optimization calculations," *Acta Numerica* **7**, 287-336 (1998). It constructs successive linear approximations of the objective function and constraints via a simplex of *n*+1 points (in *n* dimensions), and optimizes these approximations in a trust region at each step. The original code itself was written in Fortran by Powell and was converted to C in 2004 by Jean-Sebastien Roy (js@jeannot.org) for the SciPy project. The version in NLopt was based on Roy's C version, downloaded from: - NLopt's version is slightly modified in a few ways. First, we incorporated all of the NLopt termination criteria. Second, we added explicit support for bound constraints (although the original COBYLA could handle bound constraints as linear constraints, it would sometimes take a step that violated the bound constraints). Third, we allow `COBYLA` to increase the trust-region radius if the predicted improvement was approximately right and the simplex is OK, following a suggestion in the [SAS manual for PROC NLP](http://www.uc.edu/sashtml/iml/chap17/sect164.htm) that seems to improve convergence speed. Fourth, we pseudo-randomize simplex steps in COBYLA algorithm, improving robustness by avoiding accidentally taking steps that don't improve conditioning (which seems to happen sometimes with active bound constraints); the algorithm remains deterministic (a deterministic seed is used), however. Also, we support unequal initial-step sizes in the different parameters (by the simple expedient of internally rescaling the parameters proportional to the initial steps), which is important when different parameters have very different scales. (The underlying COBYLA code only supports inequality constraints. Equality constraints are automatically [transformed into pairs](NLopt_Introduction#Equality_constraints.md) of inequality constraints, which in the case of this algorithm seems not to cause problems.) It is specified within NLopt as `NLOPT_LN_COBYLA`. ### BOBYQA This is an algorithm derived from the [BOBYQA subroutine](http://plato.asu.edu/ftp/other_software/bobyqa.zip) of M. J. D. Powell, converted to C and modified for the NLopt stopping criteria. BOBYQA performs derivative-free bound-constrained optimization using an iteratively constructed quadratic approximation for the objective function. See: - M. J. D. Powell, "[The BOBYQA algorithm for bound constrained optimization without derivatives](http://www.damtp.cam.ac.uk/user/na/NA_papers/NA2009_06.pdf)," Department of Applied Mathematics and Theoretical Physics, Cambridge England, technical report NA2009/06 (2009). (Because BOBYQA constructs a quadratic approximation of the objective, it may perform poorly for objective functions that are not twice-differentiable.) The NLopt BOBYQA interface supports unequal initial-step sizes in the different parameters (by the simple expedient of internally rescaling the parameters proportional to the initial steps), which is important when different parameters have very different scales. This algorithm, specified in NLopt as `NLOPT_LN_BOBYQA`, largely supersedes the NEWUOA algorithm below, which is an earlier version of the same idea by Powell. ### NEWUOA + bound constraints This is an algorithm derived from the NEWUOA subroutine of M. J. D. Powell, converted to C and modified for the NLopt stopping criteria. I also modified the code to include a variant, NEWUOA-bound, that permits efficient handling of bound constraints. This algorithm is largely superseded by BOBYQA (above). The original NEWUOA performs derivative-free unconstrained optimization using an iteratively constructed quadratic approximation for the objective function. See: - M. J. D. Powell, "[The NEWUOA software for unconstrained optimization without derivatives](http://www.optimization-online.org/DB_HTML/2005/01/1045.html)," *Proc. 40th Workshop on Large Scale Nonlinear Optimization* (Erice, Italy, 2004). (Because NEWUOA constructs a quadratic approximation of the objective, it may perform poorly for objective functions that are not twice-differentiable.) The original algorithm is specified in NLopt as `NLOPT_LN_NEWUOA`, and only supports unconstrained problems. For bound constraints, my variant is specified as `NLOPT_LN_NEWUOA_BOUND`. In the original NEWUOA algorithm, Powell solved the quadratic subproblems (in routines TRSAPP and BIGLAG) in a spherical trust region via a truncated conjugate-gradient algorithm. In my bound-constrained variant, we use the MMA algorithm for these subproblems to solve them with both bound constraints and a spherical trust region. In principle, we should also change the BIGDEN subroutine in a similar way (since BIGDEN also approximately solves a trust-region subproblem), but instead I just truncated its result to the bounds (which probably gives suboptimal convergence, but BIGDEN is called only very rarely in practice). Shortly after my addition of bound constraints to NEWUOA, Powell released his own version of NEWUOA modified for bound constraints as well as some numerical-stability and convergence enhancements, called BOBYQA. NLopt now incorporates BOBYQA as well, and it seems to largely supersede NEWUOA. **Note:** NEWUOA requires the dimension *n* of the parameter space to be ≥ 2, i.e. the implementation does not handle one-dimensional optimization problems. ### PRAXIS (PRincipal AXIS) "PRAXIS" gradient-free local optimization via the "principal-axis method" of Richard Brent, based on a C translation of Fortran code downloaded from [Netlib](https://en.wikipedia.org/wiki/Netlib): - The original Fortran code was written by Richard Brent and made available by the Stanford Linear Accelerator Center, dated 3/1/73. The appropriate reference seems to be: - Richard Brent, *Algorithms for Minimization without Derivatives* (Prentice-Hall, 1972). (Reprinted by Dover, 2002.) Specified in NLopt as `NLOPT_LN_PRAXIS` This algorithm was originally designed for unconstrained optimization. In NLopt, bound constraints are "implemented" in PRAXIS by the simple expedient of returning infinity (Inf) when the constraints are violated (this is done automatically—you don't have to do this in your own function). This seems to work, more-or-less, but appears to slow convergence significantly. If you have bound constraints, you are probably better off using COBYLA or BOBYQA. ### Nelder-Mead Simplex My implementation of almost the original Nelder-Mead simplex algorithm (specified in NLopt as `NLOPT_LN_NELDERMEAD`), as described in: - J. A. Nelder and R. Mead, "A simplex method for function minimization," *The Computer Journal* **7**, p. 308-313 (1965). This method is simple and has demonstrated enduring popularity, despite the later discovery that it fails to converge at all for some functions (and examples may be constructed in which it converges to point that is not a local minimum). Anecdotal evidence suggests that it often performs well even for noisy and/or discontinuous objective functions. I would tend to recommend the Subplex method (below) instead, however. The main change compared to the 1965 paper is that I implemented explicit support for bound constraints, using essentially the method proposed in: - M. J. Box, "A new method of constrained optimization and a comparison with other methods," *Computer J.* **8** (1), 42-52 (1965). and later reviewed in: - J. A. Richardson and J. L. Kuester, "The complex method for constrained optimization," *Commun. ACM* **16** (8), 487-489 (1973). Whenever a new point would lie outside the bound constraints, Box advocates moving it "just inside" the constraints by some fixed "small" distance of 10−8 or so. I couldn't see any advantage to using a fixed distance inside the constraints, especially if the optimum is on the constraint, so instead I move the point exactly onto the constraint in that case. The danger with implementing bound constraints in this way (or by Box's method) is that you may collapse the simplex into a lower-dimensional subspace. I'm not aware of a better way, however. In any case, this collapse of the simplex is somewhat ameliorated by restarting, such as when Nelder-Mead is used within the Subplex algorithm below. ### Sbplx (based on Subplex) This is my re-implementation of Tom Rowan's "Subplex" algorithm. As Rowan expressed a preference that other implementations of his algorithm use a different name, I called my implementation "Sbplx" (referred to in NLopt as `NLOPT_LN_SBPLX`). Subplex (a variant of Nelder-Mead that uses Nelder-Mead on a sequence of subspaces) is claimed to be much more efficient and robust than the original Nelder-Mead, while retaining the latter's facility with discontinuous objectives, and in my experience these claims seem to be true in many cases. (However, I'm not aware of any proof that Subplex is globally convergent, and perhaps it may fail for some objectives like Nelder-Mead; YMMV.) I used the description of Rowan's algorithm in his PhD thesis: - T. Rowan, "Functional Stability Analysis of Numerical Algorithms", Ph.D. thesis, Department of Computer Sciences, University of Texas at Austin, 1990. I would have preferred to use Rowan's original implementation, posted by him on Netlib: - Unfortunately, the legality of redistributing or modifying this code is unclear, because it lacks anything resembling a license statement. After some friendly emails with Rowan in which he promised to consider providing a clear open-source/free-software license, I lost touch with him and his old email address now seems invalid. Since the algorithm is not too complicated, however, I just rewrote it. There seem to be slight differences between the behavior of my implementation and his (probably due to different choices of initial subspace and other slight variations, where his paper was ambiguous), but the number of iterations to converge on my test problems seems to be quite close (within ±10% of the number of function evaluations for most problems). The only major difference between my implementation and Rowan's, as far as I can tell, is that I implemented explicit support for bound constraints (via the method in the Box paper as described above). This seems to be a big improvement in the case where the optimum lies against one of the constraints. Local gradient-based optimization --------------------------------- Of these algorithms, only MMA and SLSQP support arbitrary nonlinear inequality constraints, and only SLSQP supports nonlinear equality constraints; the rest support bound-constrained or unconstrained problems only. (However, any of them can be applied to nonlinearly constrained problems by combining them with the [augmented Lagrangian method](#Augmented_Lagrangian_algorithm.md) below.) ### MMA (Method of Moving Asymptotes) and CCSA My implementation of the globally-convergent method-of-moving-asymptotes (MMA) algorithm for gradient-based local optimization, including nonlinear inequality constraints (but *not* equality constraints), specified in NLopt as `NLOPT_LD_MMA`, as described in: - Krister Svanberg, "[A class of globally convergent optimization methods based on conservative convex separable approximations](http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.146.5196)," *SIAM J. Optim.* **12** (2), p. 555-573 (2002). This is an improved CCSA ("conservative convex separable approximation") variant of the original MMA algorithm published by Svanberg in 1987, which has become popular for topology optimization. (*Note:* "globally convergent" does *not* mean that this algorithm converges to the global optimum; it means that it is guaranteed to converge to *some* local minimum from any feasible starting point.) At each point **x**, MMA forms a local approximation using the gradient of *f* and the constraint functions, plus a quadratic "penalty" term to make the approximations "conservative" (upper bounds for the exact functions). The precise approximation MMA forms is difficult to describe in a few words, because it includes nonlinear terms consisting of a poles at some distance from *x* (outside of the current trust region), almost a kind of Pade approximant. The main point is that the approximation is both convex and separable, making it trivial to solve the approximate optimization by a dual method. Optimizing the approximation leads to a new candidate point **x**. The objective and constraints are evaluated at the candidate point. If the approximations were indeed conservative (upper bounds for the actual functions at the candidate point), then the process is restarted at the new **x**. Otherwise, the approximations are made more conservative (by increasing the penalty term) and re-optimized. (If you contact [Professor Svanberg](http://researchprojects.kth.se/index.php/kb_7902/pb_2085/pb.html), he has been willing in the past to graciously provide you with his original code, albeit under restrictions on commercial use or redistribution. The MMA implementation in NLopt, however, is completely independent of Svanberg's, whose code we have not examined; any bugs are my own, of course.) I also implemented another CCSA algorithm from the same paper, `NLOPT_LD_CCSAQ`: instead of constructing local MMA approximations, it constructs simple quadratic approximations (or rather, affine approximations plus a quadratic penalty term to stay conservative). This is the ccsa_quadratic code. It seems to have similar convergence rates to MMA for most problems, which is not surprising as they are both essentially similar. However, for the quadratic variant I implemented the possibility of [preconditioning](NLopt_Reference#Preconditioning_with_approximate_Hessians.md): including a user-supplied Hessian approximation in the local model. It is easy to incorporate this into the proof in Svanberg's paper, and to show that global convergence is still guaranteed as long as the user's "Hessian" is positive semidefinite, and it practice it can greatly improve convergence if the preconditioner is a good approximation for the real Hessian (at least for the eigenvectors of the largest eigenvalues). ### SLSQP Specified in NLopt as `NLOPT_LD_SLSQP`, this is a sequential quadratic programming (SQP) algorithm for nonlinearly constrained gradient-based optimization (supporting both inequality and equality constraints), based on the implementation by Dieter Kraft and described in: - Dieter Kraft, "A software package for sequential quadratic programming", Technical Report DFVLR-FB 88-28, Institut für Dynamik der Flugsysteme, Oberpfaffenhofen, July 1988. - Dieter Kraft, "Algorithm 733: TOMP–Fortran modules for optimal control calculations," *ACM Transactions on Mathematical Software*, vol. 20, no. 3, pp. 262-281 (1994). (I believe that SLSQP stands for something like "Sequential Least-Squares Quadratic Programming," because the problem is treated as a sequence of constrained least-squares problems, but such a least-squares problem is equivalent to a QP.) The algorithm optimizes successive second-order (quadratic/least-squares) approximations of the objective function (via BFGS updates), with first-order (affine) approximations of the constraints. The Fortran code was obtained from the SciPy project, who are responsible for [obtaining permission](http://permalink.gmane.org/gmane.comp.python.scientific.devel/6725) to distribute it under a free-software (3-clause BSD) license. The code was modified for inclusion in NLopt by S. G. Johnson in 2010, with the following changes. The code was converted to C and manually cleaned up. It was modified to be re-entrant (preserving the reverse-communication interface but explicitly saving the state in a data structure). The reverse-communication interface was wrapped with an NLopt-style interface, with NLopt stopping conditions. The inexact line search was modified to evaluate the functions including gradients for the first step, since this removes the need to evaluate the function+gradient a second time for the same point in the common case when the inexact line search concludes after a single step; this is motivated by the fact that NLopt's interface combines the function and gradient computations. Since roundoff errors sometimes pushed SLSQP's parameters slightly outside the bound constraints (not allowed by NLopt), we added checks to force the parameters within the bounds. We fixed [a bug](http://projects.scipy.org/scipy/ticket/1231) in the LSEI subroutine (use of uninitialized variables) for the case where the number of equality constraints equals the dimension of the problem. The LSQ subroutine was modified to handle infinite lower/upper bounds (in which case those constraints are omitted). **Note:** Because the SLSQP code uses dense-matrix methods (ordinary BFGS, not low-storage BFGS), it requires *O*(*n*2) storage and *O*(*n*3) time in *n* dimensions, which makes it less practical for optimizing more than a few thousand parameters. ### Low-storage BFGS This algorithm in NLopt (specified by NLOPT_LD_LBFGS), is based on a Fortran implementation of the low-storage BFGS algorithm written by Prof. Ladislav Luksan, and graciously posted online under the GNU LGPL at: - The original L-BFGS algorithm, based on variable-metric updates via Strang recurrences, was described by the papers: - J. Nocedal, "Updating quasi-Newton matrices with limited storage," *Math. Comput.* **35**, 773-782 (1980). - D. C. Liu and J. Nocedal, "On the limited memory BFGS method for large scale optimization," ''Math. Programming' **45**, p. 503-528 (1989). I converted Prof. Luksan's code to C with the help of [f2c](https://en.wikipedia.org/wiki/f2c), and made a few minor modifications (mainly to include the NLopt termination criteria). One of the parameters of this algorithm is the number *M* of gradients to "remember" from previous optimization steps: increasing *M* increases the memory requirements but may speed convergence. NLopt sets *M* to a heuristic value by default, but this can be [changed by the set_vector_storage function](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md). ### Preconditioned truncated Newton This algorithm in NLopt, is based on a Fortran implementation of a preconditioned inexact truncated Newton algorithm written by Prof. Ladislav Luksan, and graciously posted online under the GNU LGPL at: - NLopt includes several variations of this algorithm by Prof. Luksan. First, a variant preconditioned by the low-storage BFGS algorithm with steepest-descent restarting, specified as `NLOPT_LD_TNEWTON_PRECOND_RESTART`. Second, simplified versions `NLOPT_LD_TNEWTON_PRECOND` (same without restarting), `NLOPT_LD_TNEWTON_RESTART` (same without preconditioning), and `NLOPT_LD_TNEWTON` (same without restarting or preconditioning). The algorithms are based on the ones described by: - R. S. Dembo and T. Steihaug, "Truncated Newton algorithms for large-scale optimization," *Math. Programming* **26**, p. 190-212 (1982). I converted Prof. Luksan's code to C with the help of [f2c](https://en.wikipedia.org/wiki/f2c), and made a few minor modifications (mainly to include the NLopt termination criteria). One of the parameters of this algorithm is the number *M* of gradients to "remember" from previous optimization steps: increasing *M* increases the memory requirements but may speed convergence. NLopt sets *M* to a heuristic value by default, but this can be [changed by the set_vector_storage function](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md). ### Shifted limited-memory variable-metric This algorithm in NLopt, is based on a Fortran implementation of a shifted limited-memory variable-metric algorithm by Prof. Ladislav Luksan, and graciously posted online under the GNU LGPL at: - There are two variations of this algorithm: `NLOPT_LD_VAR2`, using a rank-2 method, and `NLOPT_LD_VAR1`, using a rank-1 method. The algorithms are based on the ones described by: - J. Vlcek and L. Luksan, "Shifted limited-memory variable metric methods for large-scale unconstrained minimization," *J. Computational Appl. Math.* **186**, p. 365-390 (2006). I converted Prof. Luksan's code to C with the help of [f2c](https://en.wikipedia.org/wiki/f2c), and made a few minor modifications (mainly to include the NLopt termination criteria). One of the parameters of this algorithm is the number *M* of gradients to "remember" from previous optimization steps: increasing *M* increases the memory requirements but may speed convergence. NLopt sets *M* to a heuristic value by default, but this can be [changed by the set_vector_storage function](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md). Augmented Lagrangian algorithm ------------------------------ There is one algorithm in NLopt that fits into all of the above categories, depending on what subsidiary optimization algorithm is specified, and that is the augmented Lagrangian method described in: - Andrew R. Conn, Nicholas I. M. Gould, and Philippe L. Toint, "A globally convergent augmented Lagrangian algorithm for optimization with general constraints and simple bounds," *SIAM J. Numer. Anal.* vol. 28, no. 2, p. 545-572 (1991). - E. G. Birgin and J. M. Martínez, "[Improving ultimate convergence of an augmented Lagrangian method](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.72.6121)," *Optimization Methods and Software* vol. 23, no. 2, p. 177-195 (2008). This method combines the objective function and the nonlinear inequality/equality constraints (if any) in to a single function: essentially, the objective plus a "penalty" for any violated constraints. This modified objective function is then passed to *another* optimization algorithm with *no* nonlinear constraints. If the constraints are violated by the solution of this sub-problem, then the size of the penalties is increased and the process is repeated; eventually, the process must converge to the desired solution (if it exists). The subsidiary optimization algorithm is specified by the `nlopt_set_local_optimizer` function, described in the [NLopt Reference](NLopt_Reference#Local/subsidiary_optimization_algorithm.md). (Don't forget to set a stopping tolerance for this subsidiary optimizer!) Since all of the actual optimization is performed in this subsidiary optimizer, the subsidiary algorithm that you specify determines whether the optimization is gradient-based or derivative-free. In fact, you can even specify a global optimization algorithm for the subsidiary optimizer, in order to perform global nonlinearly constrained optimization (although specifying a good stopping criterion for this subsidiary global optimizer is tricky). The augmented Lagrangian method is specified in NLopt as `NLOPT_AUGLAG`. We also provide a variant, `NLOPT_AUGLAG_EQ`, that only uses penalty functions for equality constraints, while inequality constraints are passed through to the subsidiary algorithm to be handled directly; in this case, the subsidiary algorithm must handle inequality constraints (e.g. MMA or COBYLA). While NLopt uses an independent re-implementation of the Birgin and Martínez algorithm, those authors provide their own free-software implementation of the method as part of the [TANGO](http://www.ime.usp.br/~egbirgin/tango/) project, and implementations can also be found in [semi-free](http://www.gnu.org/philosophy/categories.html#semi-freeSoftware) packages like [LANCELOT](http://www.numerical.rl.ac.uk/lancelot/blurb.html). nlopt-2.6.1/doc/docs/NLopt_C-plus-plus_Reference.md000066400000000000000000000453461345435414600221360ustar00rootroot00000000000000--- # NLopt C-plus-plus Reference --- NLopt is written in C and the C NLopt programming interface (API), as described in the [NLopt Reference](NLopt_Reference.md), is directly callable from C++. However, we also provide a C++ header file, nlopt.hpp, that wraps a more natural C++ interface around the NLopt API, which may be more convenient for C++ programmers. (This C++ API is also the basis for the NLopt wrappers in some other languages, such as [Python](NLopt_Python_Reference.md).) The main distinctions of the C++ API are: - Use of the `nlopt::` namespace. - Use of a bona-fide C++ `nlopt::opt` class, instead of `nlopt_opt`, with constructors, destructors, etcetera. - Use of `std::vector` instead of array arguments. - Use of exceptions instead of returning error codes, and exception-safety in the objective/constraint functions. - Overloading and related C++ features to simplify some parts of the API. The main purpose of this section is to document the syntax and unique features of the C++ API; for more detail on the underlying features, please refer to the C documentation in the [NLopt Reference](NLopt_Reference.md). Compiling and linking your program to NLopt ------------------------------------------- An NLopt program in C++ should include the NLopt C++ header file: `#include ` On Unix, you would normally link your program exactly as for the C API, with a command something like: *`compiler`*` `*`...source/object` `files...`*` -lnlopt -lm -o myprogram` where *compiler* is `g++` or whatever is appropriate for your machine/system. The `nlopt::opt` object ----------------------- The NLopt API revolves around an object of type `nlopt::opt`. Via methods of this object, all of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera), and then one finally calls the `nlopt::opt::optimize` method in order to perform the optimization. The object should normally be created via the constructor: ``` nlopt::opt(nlopt::algorithm, unsigned n); ``` given an `algorithm` (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values) and the dimensionality of the problem (`n`, the number of optimization parameters). Whereas the C algorithms are specified by `nlopt_algorithm` constants of the form `NLOPT_MMA`, `NLOPT_COBYLA`, etcetera, the C++ `nlopt::algorithm` values are of the form `nlopt::MMA`, `nlopt::COBYLA`, etcetera (with the `NLOPT_` prefix replaced by the `nlopt::` namespace). There are also a copy constructor `nlopt::opt(nlopt::opt` `const&)` and an assignment `operator=(nlopt::opt` `const&)`, both of which make a copy of a given object (equivalent to `nlopt_copy` in the C API). If there is an error in the constructor (or copy constructor, or assignment), a `std::bad_alloc` exception is thrown. There is, of course, a `~nlopt::opt()` destructor, so the object will be automatically deallocated once it goes out of scope. The algorithm and dimension parameters of the object are immutable (cannot be changed without constructing a new object), but you can query them for a given object by the methods: ``` nlopt::algorithm nlopt::opt::get_algorithm() const; unsigned nlopt::opt::get_dimension() const; ``` You can get a (0-terminated) C-style string description of the algorithm via: ``` const char *nlopt::opt::get_algorithm_name() const; ``` (These accessor methods, along with the other methods below, will throw an exception if you use them on an object initialized with the default no-argument constructor, i.e. if you didn't specify an algorithm or dimensionality yet.) Objective function ------------------ The objective function is specified by calling one of the methods: ``` void nlopt::opt::set_min_objective(nlopt::vfunc f, void* f_data); void nlopt::opt::set_max_objective(nlopt::vfunc f, void* f_data); ``` depending on whether one wishes to minimize or maximize the objective function `f`, respectively. The function `f` should be of the form: ```  double f(const std::vector`` &x, std::vector`` &grad, void* f_data); ``` The return value should be the value of the function at the point `x`, where `x` is a vector of length `n` of the optimization parameters (the same as the dimension passed to the constructor). In addition, if the argument `grad` is not empty, i.e. `!grad.empty()` or equivalently `grad.size()>0`, then `grad` is a vector of length `n` which should (upon return) be set to the gradient of the function with respect to the optimization parameters at `x`. That is, `grad[i]` should upon return contain the partial derivative $\partial f / \partial x_i$, for $0 \leq i < n$, if `grad` is non-empty. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be empty and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be empty for some calls.) The `f_data` argument is the same as the one passed to `nlopt_set_min_objective` or `nlopt_set_max_objective`, and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from `void*` by a typecast.) You can just pass `NULL` for `f_data` if you don't want to pass any additional information. Note that the `nlopt::opt` object does *not* make a copy of whatever is pointed to by your `f_data` pointer; you must not deallocate its contents until *after* you are done calling `nlopt::opt::optimize`. (There is a low-level way to make the nlopt::opt object "take ownership" of the f_data pointer, which is mainly used for wrapping other languages.) Technically, in order to use `std::vector` arguments for your objective function, wrapping the C API which only uses `double*`, NLopt has to make a copy of the C `double*` array to convert it to `std::vector`. This incurs a slight memory and time overhead, which is likely to be negligible in most applications, but can be avoided by instead passing a C-style objective function: ``` void nlopt::opt::set_min_objective(nlopt::func f, void* f_data); void nlopt::opt::set_max_objective(nlopt::func f, void* f_data); ``` where `f` is of the same form as the [C objective function](NLopt_Reference#Objective_function.md). Bound constraints ----------------- The [bound constraints](NLopt_Reference#Bound_constraints.md) can be specified by calling the methods: ``` void nlopt::opt::set_lower_bounds(const std::vector`` &lb); void nlopt::opt::set_upper_bounds(const std::vector`` &ub); ``` where `lb` and `ub` are vectors of length *n* (the same as the dimension passed to the `nlopt::opt` constructor). For convenience, these are overloaded with functions that take a single number as arguments, in order to set the lower/upper bounds for all optimization parameters to a single constant: ``` void nlopt::opt::set_lower_bounds(double lb); void nlopt::opt::set_upper_bounds(double ub); ``` To retrieve the values of the lower/upper bounds, you can call one of: ``` void nlopt::opt::get_lower_bounds(std::vector`` &lb); void nlopt::opt::get_upper_bounds(std::vector`` &ub); std::vector`` nlopt::opt::get_lower_bounds(); std::vector`` nlopt::opt::get_upper_bounds(); ``` where the first two functions set their arguments (which must be vectors of length `n`) to copies of the bounds, and the second two functions return copies of the bounds as new vectors. Nonlinear constraints --------------------- Just as for [nonlinear constraints in C](NLopt_Reference#Nonlinear_constraints.md), you can specify nonlinear inequality and equality constraints by the methods: ``` void nlopt::opt::add_inequality_constraint(nlopt::vfunc fc, void *fc_data, double tol=0); void nlopt::opt::add_equality_constraint(nlopt::vfunc h, void *h_data, double tol=0); ``` where the arguments `fc` and `h` have the same form as the objective function above. Just as for the objective function, these constraint functions can either take `std::vector` arguments or can take double\* arguments exactly as in the C API. To remove all of the inequality and/or equality constraints from a given problem, you can call the following methods: ``` void nlopt::opt::remove_inequality_constraints(); void nlopt::opt::remove_equality_constraints(); ``` ### Vector-valued constraints Just as for [nonlinear constraints in C](NLopt_Reference#Vector-valued_constraints.md), you can specify nonlinear inequality and equality constraints by the methods: ``` void nlopt::opt::add_inequality_mconstraint(nlopt::mfunc c, void *c_data, const vector`` &tol); void nlopt::opt::add_equality_mconstraint(nlopt::mfunc c, void *c_data, const vector`` &tol); ``` Here, `tol` is a vector of the tolerances in each constraint dimension; the dimensionality *m* of the constraint is determined by `tol.size()`. The constraint function `c` is of the same form as in C. (You can add multiple vector-valued constraints and/or scalar constraints in the same problem.) Stopping criteria ----------------- As explained in the [C API Reference](NLopt_Reference#Stopping_criteria.md) and the [Introduction](NLopt_Introduction#Termination_conditions.md)), you have multiple options for different stopping criteria that you can specify. (Unspecified stopping criteria are disabled; i.e., they have innocuous defaults.) For each stopping criteria, there are (at least) two method: a `set` method to specify the stopping criterion, and a `get` method to retrieve the current value for that criterion. The meanings of each criterion are exactly the same as in the C API. ``` void nlopt::opt::set_stopval(double stopval); double nlopt::opt::get_stopval() const; ``` Stop when an objective value of at least stopval is found. ``` void nlopt::opt::set_ftol_rel(double tol); double nlopt::opt::get_ftol_rel() const; ``` Set relative tolerance on function value. ``` void nlopt::opt::set_ftol_abs(double tol); double nlopt::opt::get_ftol_abs() const; ``` Set absolute tolerance on function value. ``` void nlopt::opt::set_xtol_rel(double tol); double nlopt::opt::get_xtol_rel() const; ``` Set relative tolerance on optimization parameters. ``` void nlopt::opt::set_xtol_abs(const std::vector`` &tol); void nlopt::opt::set_xtol_abs(double tol); void nlopt::opt::get_xtol_abs(std::vector`` &tol) const; std::vector`` nlopt::opt::get_xtol_abs() const; ``` Set absolute tolerances on optimization parameters. The `tol` vector must be of length `n` (the dimension specified in the `nlopt::opt` constructor). The second `set_xtol_abs` variant sets all `n` tolerances to the same value `tol`. The first `get_xtol_abs` variant modifies its argument to a copy of the current tolerances, whereas the second variant returns a copy. ``` void nlopt::opt::set_maxeval(int maxeval); int nlopt::opt::get_maxeval() const; ``` Stop when the number of function evaluations exceeds `maxeval`. ``` void nlopt::opt::set_maxtime(double maxtime); double nlopt::opt::get_maxtime() const; ``` Stop when the optimization time (in seconds) exceeds `maxtime`. ``` int nlopt::opt::get_numevals() const; ``` Request the number of evaluations. ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. You can do this by throwing *any* exception inside your objective/constraint functions: the exception will be caught, the optimization will be halted gracefully, and another exception (possibly not the same one) will be rethrown. See [Exceptions](#Exceptions.md), below. The C++ equivalent of `nlopt_forced_stop` from the [C API](NLopt_Reference#Forced_termination.md) is to throw an `nlopt::forced_stop` exception. Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given object `opt`, you can perform the optimization by calling: ``` nlopt::result nlopt::opt::optimize(std::vector`` &x, double &opt_f); ``` On input, `x` is a vector of length `n` (the dimension of the problem from the `nlopt::opt` constructor) giving an initial guess for the optimization parameters. On successful return, `x` contains the optimized values of the optimization parameters, and `opt_f` contains the corresponding value of the objective function. The return value (see below) is positive on success, indicating the reason for termination. On failure (negative return codes), it throws an exception (see [Exceptions](#Exceptions.md), below). You can also call the following methods to retrieve the `opt_f` value from the last `optimize` call, and the return value (including negative/failure return values) from the last `optimize` call: ``` double nlopt::opt::last_optimum_value() const; nlopt::result nlopt::opt::last_optimize_result() const; ``` ### Return values The possible return values are the same as the [return values in the C API](NLopt_Reference#Return_values.md), except that the `NLOPT_` prefix is replaced with the `nlopt::` namespace. That is, `NLOPT_SUCCESS` becomes `nlopt::SUCCESS`, etcetera. Exceptions ---------- The [Error codes (negative return values)](NLopt_Reference#Error_codes_(negative_return_values).md) in the C API are replaced in the C++ API by thrown exceptions. The following exceptions are thrown by the various routines: ``` std::runtime_error ``` Generic failure, equivalent to `NLOPT_FAILURE`. ``` std::invalid_argument ``` Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera), equivalent to `NLOPT_INVALID_ARGS`. ``` std::bad_alloc ``` Ran out of memory (a memory allocation failed), equivalent to `NLOPT_OUT_OF_MEMORY`. `nlopt::roundoff_limited` (subclass of `std::runtime_error`) Halted because roundoff errors limited progress, equivalent to `NLOPT_ROUNDOFF_LIMITED`. `nlopt::forced_stop` (subclass of `std::runtime_error`) Halted because of a [forced termination](#Forced_termination.md): the user called `nlopt::opt::force_stop()` from the user’s objective function or threw an `nlopt::forced_stop` exception. Equivalent to `NLOPT_FORCED_STOP`. If your objective/constraint functions throw *any* exception during the execution of `nlopt::opt::optimize`, it will be caught by NLopt and the optimization will be halted gracefully, and `nlopt::opt::optimize` will re-throw an exception. However, the exception that is re-thrown by `nlopt::opt::optimize` will be one of the five exceptions above; if the exception thrown by your code was not one of these five, it will be converted to a generic `std::runtime_error` exception. (The reason for this is that C++ has no clean way to save an arbitrary exception and rethrow it later, outside the original `catch` statement.) Therefore, if you want to do something special in response to a particular exception that is not one of these five, you should catch it yourself in your function, handle it however you want, and re-throw if desired. Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: ``` void nlopt::opt::set_local_optimizer(const nlopt::opt &local_opt); ``` Here, `local_opt` is another `nlopt::opt` object whose parameters are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `local_opt` are ignored.) The dimension `n` of `local_opt` must match that of `opt`. This function makes a copy of the `local_opt` object, so you can freely destroy your original `local_opt` afterwards. Initial step size ----------------- Just as in the C API, you can [get and set the initial step sizes](NLopt_Reference#Initial_step_size.md) for derivative-free optimization algorithms. The C++ equivalents of the C functions are the following methods: ``` void nlopt::opt::set_initial_step(const std::vector`` &dx); void nlopt::opt::set_initial_step(double dx); void nlopt::opt::get_initial_step(const std::vector`` &x, std::vector`` &dx) const; std::vector`` nlopt::opt::get_initial_step(const std::vector`` &x) const; ``` Stochastic population --------------------- Just as in the C API, you can [get and set the initial population](NLopt_Reference#Stochastic_population.md) for stochastic optimization algorithms, by the methods: ``` void nlopt::opt::set_population(unsigned pop); unsigned nlopt::opt::get_population() const; ``` (A `pop` of zero implies that the heuristic default will be used.) Pseudorandom numbers -------------------- For stochastic optimization algorithms, we use pseudorandom numbers generated by the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm, based on code from Makoto Matsumoto. By default, the [seed](https://en.wikipedia.org/wiki/Random_seed) for the random numbers is generated from the system time, so that you will get a different sequence of pseudorandom numbers each time you run your program. If you want to use a "deterministic" sequence of pseudorandom numbers, i.e. the same sequence from run to run, you can set the seed by calling: ``` void nlopt::srand(unsigned long seed); ``` To reset the seed based on the system time, you can call: ``` void nlopt::srand_time(); ``` (Normally, you don't need to call this as it is called automatically. However, it might be useful if you want to "re-randomize" the pseudorandom numbers after calling `nlopt::srand` to set a deterministic seed.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Just as in the C API, you can get and set the [number *M* of stored vectors](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md) for limited-memory quasi-Newton algorithms, via the methods: ``` void nlopt::opt::set_vector_storage(unsigned M); unsigned nlopt::opt::get_vector_storage() const; ``` (The default is *M*=0, in which case NLopt uses a heuristic nonzero value.) Version number -------------- To determine the version number of NLopt at runtime, you can call: ``` void nlopt::version(int &major, int &minor, int &bugfix); ``` For example, NLopt version 3.1.4 would return `major=3`, `minor=1`, and `bugfix=4`. You can also retrieve these three values individually by calling: ``` int nlopt::version_major(); int nlopt::version_minor(); int nlopt::version_bugfix(); ``` nlopt-2.6.1/doc/docs/NLopt_Deprecated_API_Reference.md000066400000000000000000001006641345435414600225360ustar00rootroot00000000000000--- # NLopt Deprecated API Reference --- NLopt is a library, not a stand-alone program—it is designed to be called from your own program in C, C++, Fortran, Matlab, GNU Octave, or other languages. This reference section describes the original programming interface (API) of NLopt, used in versions of NLopt prior to 2.0. This interface is still supported in NLopt 2.0 (and will continue to be supported indefinitely if possible), for backwards compatibility, but is now deprecated in favor of the new object-style API in the [NLopt Reference](NLopt_Reference.md). The reason why this API is deprecated is that it is not easily extensible. A single optimization function was appropriate when NLopt started out as a library just handling bound constraints, but as more and more optimization parameters were added it became difficult to do this in a backwards-compatible way. (Also, functions with dozens of parameters at some point become unreadable.) Other sources of information include the Unix [man pages](https://en.wikipedia.org/wiki/Manual_page_(Unix)) for the functions. On Unix, you can run e.g. `man` `nlopt_minimize` for documentation of the `nlopt_minimize` function. In Matlab and GNU Octave, the corresponding command is to type `help` `nlopt_minimize`. Linking your program to NLopt ----------------------------- For programs in compiled languages like C or Fortran, when you compile your program you will have to link it to the NLopt library. This is *in addition* to including the header file (`#include` in C/C++). On Unix, you would normally link with a command something like: *`compiler`*` `*`...source/object` `files...`*` -lnlopt -lm -o myprogram` where *compiler* is `cc`, `f77`, `g++`, or whatever is appropriate for your machine/language. *Note:* the `-lnlopt` `-lm` options, which link to the NLopt library (and the math library, which it requires), must come *after* your source/object files. In general, the rule is that if *A* depends upon *B*, then *A* must come before *B* in the link command. *Note:* the above example assumes that you have installed the NLopt library in a place where the compiler knows to find it (e.g. in a standard directory like `/usr/lib` or `/usr/local/lib`). If you installed somewhere else (e.g. in your home directory if you are not a system administrator), then you will need to use a `-L` flag to tell the compiler where to find the library. See [the installation manual](NLopt_Installation#Changing_the_installation_directory.md). C/C++ programming interface --------------------------- To use NLopt from C or C++, you should first include the NLopt header file: `#include ` Then, you should write functions to express your objective and constraints. Finally, you should call the function `nlopt_minimize_constrained` (for nonlinearly constrained optimization) or `nlopt_minimize` (for unconstrained or box-constrained optimization) to perform the optimization. There are also a couple of other utility routines described below. ### `nlopt_minimize_constrained` ``` nlopt_result nlopt_minimize_constrained(nlopt_algorithm algorithm,                                         int n,                                         nlopt_func f, void* f_data,                                         int m,                                         nlopt_func fc, void* fc_data, ptrdiff_t fc_datum_size,                                         const double* lb, const double* ub,                                         double* x,                                         double* minf,                                         double minf_max,                                         double ftol_rel, double ftol_abs,                                         double xtol_rel, const double* xtol_abs,                                         int maxeval, double maxtime); ``` This function attempts to minimize a nonlinear function `f` of `n` optimization parameters, subject to `m` nonlinear constraints described by the function `fc`, using the specified algorithm. The minimum function value found is returned in `minf`, with the corresponding optimization parameter values returned in the array `x` of length `n`. The input values in `x` should be a starting guess for the minimum. The inputs `lb` and `ub` are arrays of length `n` containing lower and upper bounds, respectively, on the design variables `x`. The other parameters specify termination criteria (tolerances, the maximum number of function evaluations, etcetera) and other information described in more detail below. The return value is an integer code indicating success (positive) or failure (negative), as described below. #### Parameters The parameters specifying the optimization problem are: - `algorithm` — which optimization algorithm to use; its values are one of a set of predefined constants like`NLOPT_LD_MMA`, `NLOPT_GN_DIRECT`, etcetera, as described on the [NLopt Algorithms](NLopt_Algorithms.md) page. - `n` — the dimension *n* ≥ 0 of the optimization problem, the number of optimization parameters. - `f` — the objective function (see below) - `f_data` — a pointer to any data you want to pass to the the objective function (see below) - `m` — the number of nonlinear inequality constraints (zero for no such constraints). - `fc` — the nonlinear inequality constraint function (see below). Ignored if `m` = 0. - `fc_data`, `fc_datum_size` — `fc_data` is a pointer to an array of data to pass to the constraint function `fc`. The array should of length `m`, and each element of the array should have size `fc_datum_size` bytes. (See below for more information on constraint functions.) Ignored if `m` = 0. - `lb` — pointer to an array of length `n` of lower bounds on each optimization variable. That is, the optimization variables are constrained to have `x[i]` ≥ `lb[i]`. If you don't want a particular variable to be bounded below, just set the corresponding `lb[i]` to be `-HUGE_VAL`. (`HUGE_VAL` is a standard C constant, usually giving +∞.) - `ub` — pointer to an array of length `n` of upper bounds on each optimization variable. That is, the optimization variables are constrained to have `x[i]` ≤ `ub[i]`. If you don't want a particular variable to be bounded above, just set the corresponding `ub[i]` to be `+HUGE_VAL`. Starting guess and returned optimum: - `x` — an array of length `n` of the optimization parameters `x[0]`, ..., `x[n-1]`. On input, a starting guess for the optimum parameters; on output, the best found values of the parameters. (For a *local* optimization routine, the starting guess `x` determines which local optimum is found.) The starting guess is required to satisfy the bound constraints `lb` and `ub`; it need not satisfy the nonlinear inequality constraints `fc` (although it might be more efficient if you have a feasible starting guess.) - `minf` — on output, the minimum value of the objective function that was found (corresponding to the output value of the parameters `x`). The remaining parameters specify the termination conditions. Please read the [introduction to the termination conditions](NLopt_Introduction#Termination_conditions.md) for a general overview of these criteria. (In particular, note that you do *not* need to use *all* of these conditions; typically, you will use only one or two, and set the remainder to innocuous values.) - `minf_max` — stop if the objective function value drops below `minf_max`. (Set to `-HUGE_VAL` to ignore.) - `ftol_rel`, `ftol_abs` — relative and absolute tolerances in the objective function value. (Set to zero to ignore.) - `xtol_rel`, `xtol_abs` — relative and absolute tolerances in the optimization parameter values. `xtol_abs` should either be `NULL`, in which case it is ignored (equivalent to zero tolerance), or otherwise it should point to an array of length `n` containing absolute tolerances in each parameter `x[i]`. Set any tolerance to zero for it to be ignored. - `maxeval` — stop if the objective function is evaluated at least `maxeval` times. Set to zero to ignore. - `maxtime` — stop if the elapsed wall-clock time, in seconds, exceeds `maxtime`. Set to zero to ignore. #### Return value The value returned is one of the following enumerated constants. Successful termination (positive return values): - `NLOPT_SUCCESS` (= +1) — Generic success return value. - `NLOPT_MINF_MAX_REACHED` (= +2) — Optimization stopped because `minf_max` (above) was reached. - `NLOPT_FTOL_REACHED` (= +3) — Optimization stopped because `ftol_rel` or `ftol_abs` (above) was reached. - `NLOPT_XTOL_REACHED` (= +4) — Optimization stopped because `xtol_rel` or `xtol_abs` (above) was reached. - `NLOPT_MAXEVAL_REACHED` (= +5) — Optimization stopped because `maxeval` (above) was reached. - `NLOPT_MAXTIME_REACHED` (= +6) — Optimization stopped because `maxtime` (above) was reached. Error codes (negative return values): - `NLOPT_FAILURE` (= −1) — Generic failure code. - `NLOPT_INVALID_ARGS` (= −2) — Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera). - `NLOPT_OUT_OF_MEMORY` (= −3) — Ran out of memory. - `NLOPT_ROUNDOFF_LIMITED` (= −4) — Roundoff errors led to a breakdown of the optimization algorithm. In this case, the returned minimum may still be useful. (e.g. this error occurs in NEWUOA if one tries to achieve a tolerance too close to machine precision.) ### `nlopt_minimize` ``` nlopt_result nlopt_minimize(nlopt_algorithm algorithm,                             int n,                             nlopt_func f, void* f_data,                             const double* lb, const double* ub,                             double* x,                             double* minf,                             double minf_max,                             double ftol_rel, double ftol_abs,                             double xtol_rel, const double* xtol_abs,                             int maxeval, double maxtime); ``` This function is exactly equivalent to calling `nlopt_minimize_constrained` with `m` = 0. That is, this is minimization with no nonlinear inequality constraints (although there may still be bound constraints `lb` and `ub`). ### Objective function You should define your objective function (the function you want to minimize) as a function of the following form: ``` double f(int n, const double *x, double *grad, void *f_data) {     .... } ``` The return value should be the value of the function at the point **x**, where `x` points to an array of length `n` containing the optimization parameters. (That is, the optimization parameters are `x[0]`, `x[1]`, ..., `x[n-1]`.) The dimension `n` is the same as the one passed to `nlopt_minimize` or `nlopt_minimize_constrained`. In addition, if the argument `grad` is not `NULL`, then `grad` points to an array of length `n` that should (upon return) be set to the gradient of your function *f* with respect to the design variables *x*. That is, `grad[i]` should upon return contain the partial derivative ∂`f`/∂`x[i]`, for `i`=0,...,`n-1`. Not all of the [optimization algorithms](NLopt_Algorithms.md) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be `NULL` and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be `NULL` for some calls.) The `f_data` argument is the same as the one passed to `nlopt_minimize` or `nlopt_minimize_constrained`, and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from `void*` by a typecast.) ### Nonlinear constraints The `nlopt_minimize_constrained` function allows you to specify `m` nonlinear constraints via the function `fc`, where `m` is any nonnegative integer. However, nonzero `m` is currently only supported by the `NLOPT_LD_MMA` and `NLOPT_LN_COBYLA` [algorithms](NLopt_Algorithms.md). In particular, the nonlinear constraints are of the form *fc*(*x*) ≤ 0, where the function fc is of the same form as the objective function described above: ``` double fc(int n, const double* x, double* grad, void* fc_datum); ``` The return value should be the value of the constraint function at the point `x` (an array of length `n`), where the dimension `n` is identical to the one passed to `nlopt_minimize_constrained`. As for the objective function, if the argument `grad` is not `NULL`, then `grad` points to an array of length `n` which should (upon return) be set to the gradient of the constraint function with respect to **x**. (For any algorithm listed as "derivative-free", the `grad` argument will always be `NULL` and need never be computed.) The `fc_datum` argument is based on the `fc_data` argument passed to `nlopt_minimize_constrained`, and may be used to pass any additional data through to the function, and is used to distinguish between different constraints. In particular, the constraint function `fc` will be called (at most) `m` times for each `x`, and the *i*-th constraint (0 ≤ *i* < *m*) will be passed an `fc_datum` argument equal to `fc_data` offset by *i*⋅`fc_datum_size`. For example, suppose that you have a data structure of type `foo` that describes the data needed by each constraint, and you store the information for the constraints in an array `foo` `data[m]`. In this case, you would pass `data` as the `fc_data` parameter to `nlopt_minimize_constrained`, and `sizeof(foo)` as the `fc_datum_size` parameter. Then, your `fc` function would be called `m` times for each point, and be passed `&data[0]` through `&data[m-1]` in sequence. ### Mixed global/local search algorithm Some of the [global optimization algorithms](NLopt_Algorithms#Global_optimization.md) (currently, only MLSL) combine some global search scheme with a separate local optimization algorithm for local searches. For example, MLSL performs a sequence of local searches from semi-random starting points. Using the following functions, you can control *which* local search algorithm is used for MLSL (and any similar algorithm that is added in the future), as well as specifying a maximum number of function evaluations for the local search: ``` void nlopt_set_local_search_algorithm(nlopt_algorithm deriv, nlopt_algorithm nonderiv, int maxeval); ``` Set the local gradient-based search algorithm to `deriv` (default is `NLOPT_LD_MMA`), the local derivative-free search algorithm to `nonderiv` (default is `NLOPT_LN_COBYLA`), and the maximum number of function evaluations on each local search to `maxeval` (default is `-1`, for no maximum). Conversely, you can get the current values of these parameters by calling: ``` void nlopt_get_local_search_algorithm(nlopt_algorithm *deriv, nlopt_algorithm *nonderiv, int *maxeval) ``` *Note:* these parameters have no effect on local searches that you perform yourself; they are *only* for local searches that are performed *within* another algorithm like MLSL. ### Population size for stochastic algorithms Stochastic (randomized) optimization algorithms are often parameterized by some initial "population" size (a set of sample points where the function is evaluated). NLopt tries to pick a reasonable default value for these population sizes, but in some cases the use may want finer control. This is achieved by the following two functions: ``` void nlopt_set_stochastic_population(int pop); int nlopt_get_stochastic_population(void); ``` which set and get the current (global) setting of the population parameter for stochastic algorithms. The default value of this population parameter is *zero*: a zero population is specially interpreted to mean that the algorithm should choose an algorithm-specific default value. These algorithm-specific defaults are documented with the [algorithms](NLopt_Algorithms.md) that use the population parameter. Fortran programming interface ----------------------------- NLopt is callable from Fortran 77 (and later Fortran dialects), via special Fortran-callable wrapper subroutines that are included in the NLopt library. Although the functionality is the same as that of the C routines, the Fortran routines have different names and the arguments are passed in slightly different ways, as explained below. The most noticeable difference is that all function return values in C are changed into the first argument in Fortran, because there is no portable way to call C functions that return a value from Fortran or vice versa. The other noticeable difference is that, because there is no (portable) way to pass `NULL` in Fortran, any C argument that can optionally be `NULL` is converted to two arguments in Fortran, where the second argument is a flag to say whether that argument should be treated as `NULL` (i.e., ignored). ### Constants and include files In C/C++, the `nlopt.h` header file declares the various constants (`NLOPT_LN_NELDERMEAD`, `NLOPT_FAILURE`, etcetera) used to specify the optimization algorithm, return codes, and so forth. In Fortran, the corresponding definitions are located in the `nlopt.f` file, which is installed into the same directory as `nlopt.h` (in `/usr/local/include` by default). That is, in any Fortran subroutine where you want to use NLopt subroutines, you should do: ``` include 'nlopt.f' ``` to include the constant definitions. (Like in C, most Fortran compilers allow you to pass `-I` options to specify search directories for include files, if you did not install NLopt in a standard location; see the [installation instructions](NLopt_Installation.md).) If you have some ancient Fortran compiler that does not support the `include` directive (which technically was nonstandard until Fortran 90, although most Fortran 77 compilers implement it), then I suppose you could also copy-and-paste the `nlopt.f` file directly into your source code. ### `nloptc` The Fortran analogue to the `nlopt_minimize_constrained` function is: ``` call nloptc(info, algorithm, n,             f, f_data,             m, fc, fc_data, fc_second_datum,              lb, ub,             x, minf,              minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, have_xtol_abs, maxeval, maxtime) ``` The parameters are similar to those of `nlopt_minimize_constrained` (see also the documentation above): - `info` (integer, OUT) — on output, the return value, positive on success and negative on failure (see above for the specific return codes `NLOPT_SUCCESS` etcetera). - `algorithm` (integer, IN) — integer constant (`NLOPT_LN_NELDERMEAD`, etcetera) indicating the optimization algorithm to use (defined in `nlopt.f` include file as described above) - `n` (integer, IN) — the dimension of the problem (the number of optimization parameters, as in C) - `f` (subroutine, IN) — the objective function, actually a subroutine as described below - `f_data` (any type, IN) — any additional data to pass to the objective function - `m` (integer, IN) — the number of nonlinear inequality constraints (zero if none). - `fc` (subroutine, IN) — the constraint subroutine, as described below (ignored if *m*=0) - `fc_data`, `fc_second_datum` (arbitrary types, IN) — data to pass to the constraint subroutine, as described below (ignored if *m*=0) - `lb` (double precision array(`n`), IN) — lower bounds on the optimization parameters. (For unbounded dimensions, use `-Infinity` or `-Inf` in the Fortran 2003 standard; I don't know of a standard way to do it in earlier Fortran versions, maybe `-1.0/0.0`?) - `ub` (double precision array(`n`), IN) — upper bounds on the optimization parameters. (For unbounded dimensions, use `+Infinity` or `+Inf` in the Fortran 2003 standard; I don't know of a standard way to do it in earlier Fortran versions, maybe `+1.0/0.0`?) - `x` (double precision array(`n`), IN/OUT) — on input, an initial guess for the optimization parameters; on output, the best parameters found - `minf` (double precision, OUT) — on output, the minimum value of the objective function that was found Termination conditions (see [introduction](NLopt_Introduction#Termination_conditions.md)): - `minf_max` (double precision, IN) — stop if the an objective function value ≤ `minf_max` is found (set to `-Infinity`, or a huge negative number, to ignore). - `ftol_rel`, `ftol_abs` (double precision, IN) — relative and absolute tolerances in the objective function value (ignored if zero). - `xtol_rel` (double precision, IN) — relative tolerance in the optimization parameters (ignored if zero) - `xtol_abs` (double precision array(`n`), IN) — if `have_xtol_abs` is nonzero, then `xtol_abs` is an array of the absolute tolerances in each optimization parameter (ignored if zero). - `have_xtol_abs` (integer, IN) — if zero, then `xtol_abs` is ignored - `maxeval` (integer, IN) — stop if the objective function is evaluated at least `maxeval` times (set to zero to ignore) - `maxtime` (double precision, IN) — stop if the elapsed wall-clock time exceeds `maxtime` seconds (set to zero to ignore) ### `nloptm` The Fortran analogue to the `nlopt_minimize` function is: ``` call nloptm(info, algorithm, n,             f, f_data,             lb, ub,             x, minf,              minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, have_xtol_abs, maxeval, maxtime) ``` This is exactly equivalent to calling `nloptc` with `m`=0. ### Objective function in Fortran You should define your objective function (the function you want to minimize) as a subroutine of the following form: ``` subroutine f(val, n, x, grad, need_gradient, f_data) double precision val integer n double precision x(n) double precision grad(n) integer need_gradient ``` The `n`, `x`, `need_gradient`, and `f_data` parameters are inputs, and the `val` and `grad` parameters are outputs. Upon return, `val` should be set to the value of your objective function at the point **x**. The dimension `n` is the same as the one passed to `nloptm` or `nloptc`. In addition, if the argument `need_gradient` is not zero, then `grad` is an array of length `n` that should (upon return) be set to the gradient of your function *f* with respect to the design variables *x*. That is, `grad(i)` should upon return contain the partial derivative ∂`f`/∂`x(i)`, for `i`=1,...,`n`. Not all of the [optimization algorithms](NLopt_Algorithms.md) use the gradient information: for algorithms listed as "derivative-free," the `need_gradient` argument will always be zero and need never be computed. (For algorithms that do use gradient information, however, `need_gradient` may still be zero for some calls.) You should *not* access the `grad` array *at all* if `need_gradient` is zero. The `f_data` argument is the same as the one passed to `nloptm` or `nloptc`, and may be used to pass any additional data through to the function. It can be declared as any arbitrary type that you want, as long as it is the same type as the variable you passed to `nloptm` or `nloptc` ### Nonlinear constraints in Fortran The `nloptc` function allows you to specify `m` nonlinear constraints via the subroutine `fc`, where `m` is any nonnegative integer. However, nonzero `m` is currently only supported by the `NLOPT_LD_MMA` and `NLOPT_LN_COBYLA` [algorithms](NLopt_Algorithms.md). In particular, the nonlinear constraints are of the form *fc*(*x*) ≤ 0, where the function fc is of the same form as the objective function described above: ``` subroutine fc(val, n, x, grad, need_gradient, fc_datum) ``` As above, upon return `val` should be the value of the constraint function at the point `x` (an array of length `n`), where the dimension `n` is identical to the one passed to `nloptc`. As for the objective function, if the argument `need_gradient` is not zero, then `grad` is an array of length `n` that should (upon return) be set to the gradient of the constraint function with respect to **x**. (For any algorithm listed as "derivative-free", the `need_gradient` argument will always be zero and the gradient need never be computed.) The `fc_datum` argument is based on the `fc_data` argument passed to `nloptc`, and may be used to pass any additional data through to the function, and is used to distinguish between different constraints. In particular, the constraint subroutine `fc` will be called (at most) `m` times for each `x`, and the *i*-th constraint (1 ≤ *i* ≤ *m*) will be passed an `fc_datum` argument equal to `fc_data` offset by the difference between `fc_data` and `fc_second_datum`. For example, suppose that your constraint function `fc` is parameterized by three numbers for each constraint, so you want your `fc_data` to be an array of length 3*m*: `double` `precision` `fc_data(3*m)`. Then, as the `fc_second_datum` argument to `nloptc`, you would pass `fc_data(4)`, which is the first data element for the second constraint. When `fc` is called the first time, it will be passed `fc_data(1:3)`; when it is called the second time it will be passed `fc_data(4:6)`, and so on in sequence. ### Pseudorandom numbers in Fortran The Fortran equivalent of `nlopt_srand` (above), is: ``` call nlosr(seed) ``` where `seed` is an `integer`. The Fortran equivalent of `nlopt_srand_time` (above) is: ``` call nlosrt ``` ### Version number in Fortran To determine the version number of NLopt at runtime, you can call: ``` call nloptv(major, minor, bugfix) ``` where the three arguments are `integer`s, as in `nlopt_version` above. For example, NLopt version 3.1.4 would return `major=3`, `minor=1`, and `bugfix=4`. ### Mixed global/local search algorithm in Fortran The Fortran analogues of `nlopt_set_local_search_algorithm` and `nlopt_get_local_search_algorithm` are: ``` call nlosls(deriv, nonderiv, maxeval) call nlogls(deriv, nonderiv, maxeval) ``` where the arguments are all `integer`s and have the same meaning as those of `nlopt_set_local_search_algorithm` and `nlopt_get_local_search_algorithm`, above. ### Population size for stochastic algorithms in Fortran The Fortran analogues of `nlopt_set_stochastic_population` and `nlopt_get_stochastic_population` are: ``` call nlossp(pop) call nlogsp(pop) ``` where the arguments are `integer`s and have the same meaning as the parameter of `nlopt_set_stochastic_population` and the return value of `nlopt_get_stochastic_population`, respectively. GNU Octave and Matlab interface ------------------------------- We also provide an interface to NLopt that is callable from Matlab and [GNU Octave](https://en.wikipedia.org/wiki/GNU_Octave) (a free Matlab clone). This interface consists of two functions, `nlopt_minimize_constrained` and `nlopt_minimize`, which parallel the corresponding C functions above. ### `nlopt_minimize_constrained` in Matlab ``` [xopt, fmin, retcode] = nlopt_minimize_constrained(algorithm, f, f_data, fc, fc_data, lb, ub, xinit, stop) ``` Minimize a nonlinear multivariable function `f(x,` `f_data{:})`, subject to optional nonlinear constraints described by `fc` and `fc_data` (see below), where `x` is a row vector of the optimization parameters, returning the optimal parameters found (`xopt`) along with the minimum function value (`fmin`) and a return code (`retcode`, positive on success and negative on failure). A variety of local and global optimization algorithms can be used, as specified by the `algorithm` parameter. `lb` and `ub` are row vectors giving the upper and lower bounds on `x`, `xinit` is a row vector giving the initial guess for `x`, and `stop` is a structure containing termination conditions (see below). Parameters: - `algorithm` — constant indicating the [optimization algorithm](NLopt_Algorithms.md) (predefined constants NLOPT_LN_NELDERMEAD etcetera are supplied as in C). - `f` — function handle (e.g. `@sin`) of the objective function being minimized, described below - `f_data` — cell array `{...}` of any additional arguments to pass to f (see below) - `fc` — cell array `{...}` of function handles to nonlinear inequality constraints (see below); can be empty `{}` for no nonlinear constraints - `fc_data` — cell array `{...}` of cell arrays: each element `fc_data{i}` is a cell array of additional arguments to pass to the function `fc{i}`; `length(fc_data)` must equal `length(fc)` - `lb` — row vector of lower bounds on each optimization parameter (set any component of `lb` to `-inf` for a parameter that is not bounded below) - `ub` — row vector of lower bounds on each optimization parameter (set any component of `ub` to `+inf` for a parameter that is not bounded above) - `xinit` — row vector containing a starting guess for the optimization parameters - `stop` — structure describing the termination conditions via a number of optional fields (see below) Notice that, unlike in C and Fortran, we do not explicitly pass the dimension *n* of the parameter space: *n* is implicitly the length of the `lb`, `ub`, and `xinit` vectors (which must all be the same length). #### Matlab objective function The parameter `f` should be a handle (`@`) to a function of the form: ```   [val, gradient] = f(x, ...) ``` where `x` is a row vector, `val` is the function value *f*(**x**), and `gradient` is a row vector giving the gradient of the function with respect to `x`. The gradient is only used for gradient-based optimization algorithms; some of the algorithms are derivative-free and only require f to return val (its value), so for these algorithms you need not return the gradient. f can take additional arguments `(...)` which are passed via the argument `f_data`: `f_data` is a cell array of the additional arguments to pass to `f`. (Recall that cell arrays are specified by curly brackets { ... }. For example, pass `f_data={}` for functions that require no additional arguments.) #### Matlab nonlinear constraints Some of the algorithms (currently `NLOPT_LD_MMA` and `NLOPT_LN_COBYLA`) support nonlinear constraints. These (if any) are specified by `fc` and `fc_data`. `fc` is a cell array of function handles, and `fc_data` is a cell array of cell arrays of the corresponding arguments. Both must have the same length m, the number of nonlinear constraints. That is, `fc{i}` is a handle to a function of the form: ```  [val, gradient] = fc(x, ...) ``` (where the `gradient` return value is only used for gradient-based algorithms), and the `...` arguments are given by `fc_data{i}{:}`. If you have no nonlinear constraints, i.e. `fc` = `fc_data` = `{}`, then it is equivalent to calling the the `nlopt_minimize` function below, which omits the `fc` and `fc_data` arguments. #### Matlab termination conditions `stop` describes the termination criteria, and is a structure with a number of optional fields: - `stop.fmin_max` — stop when *f* ≤ `fmin_max` is found - `stop.ftol_rel` — fractional tolerance on function value - `stop.ftol_abs` — absolute tolerance on function value - `stop.xtol_rel` — fractional tolerance on **x** - `stop.xtol_abs` — row vector of absolute tolerances on **x** components - `stop.maxeval` — maximum number of function evaluations - `stop.maxtime` — maximum run time in seconds - `stop.verbose` — > 0 indicates verbose output You do *not* need to set all of these fields; termination conditions corresponding to any fields that you do not set are ignored. As discussed in the [introduction](NLopt_Introduction#Termination_conditions.md), normally you only want one or two of these conditions. For example to set a relative **x** tolerance of 10−4 and run for no more than 5 minutes, you would do: ``` stop.xtol_rel = 1e-4; stop.maxtime = 5 * 60; ``` and not create any other fields of `stop`. ### `nlopt_minimize` in Matlab ``` [xopt, fmin, retcode] = nlopt_minimize(algorithm, f, f_data, lb, ub, xinit, stop) ``` This is equivalent to calling `nlopt_minimize_constrained` with no nonlinear constraints, i.e. `fc` = `fc_data` = `{}`. nlopt-2.6.1/doc/docs/NLopt_FAQ.md000066400000000000000000000035041345435414600164310ustar00rootroot00000000000000--- # NLopt FAQ --- General ------- ### What is NLopt? NLopt is a free/open-source library for nonlinear optimization. ### Why use NLopt, when some of the same algorithms are available elsewhere? Several of the algorithms provided by NLopt are based on free/open-source packages by other authors, which we have put together under a common interface in NLopt. If you are using one of these packages and are happy with it, great! However, our experience is that, for nonlinear optimization, the best algorithm is highly problem-dependent; the best approach is to try several different techniques and see which one works best for *you*. NLopt makes this easy by providing a single package and a common interface for many different algorithms, callable from many different languages. Installation ------------ ### Where can I install NLopt? NLopt should be straightforward to install on any Unix-like system (GNU/Linux is fine) with a C compiler (gcc is fine). It should be possible to compile under Windows, too, but to simplify life we plan to provide precompiled DLL files soon for Windows, cross-compiled using [MinGW](https://en.wikipedia.org/wiki/MinGW). Usage ----- ### I included your header file, but the compiler still complains You need to link to the NLopt library in addition to doing `#include` . On Unix, this means adding `-lnlopt` `-lm` at the *end* of your link command. ### It's not converging The most common cause of convergence problems is if you use a gradient-based algorithm and return an incorrect gradient. It seems surprisingly easy to have bugs in code to compute derivatives—you should test it by comparing to finite-difference derivatives for a few random points and directions. You could also try switching algorithms to see if it is a problem in a particular algorithm (but check the gradient first!). nlopt-2.6.1/doc/docs/NLopt_Fortran_Reference.md000066400000000000000000000445401345435414600214200ustar00rootroot00000000000000--- # NLopt Fortran Reference --- The NLopt includes an interface callable from the [Fortran programming language](https://en.wikipedia.org/wiki/Fortran). The main purpose of this section is to document the syntax and unique features of the Fortran API; for more detail on the underlying features, please refer to the C documentation in the [NLopt Reference](NLopt_Reference.md). Compiling and linking your Fortran program ------------------------------------------ To obtain the definitions of the NLopt constants in Fortran, your Fortran program/subroutine should include the following line: ``` include 'nlopt.f' ``` The `nlopt.f` file is installed into the `include` directory along with the C/C++ header files (by default, this is `/usr/local/include` ... you may need to include `-I/usr/local/include` in your Fortran compiler flags if this directory is not in your compiler's standard include path). When you compile your program you will have to link it to the NLopt library. On Unix, you would normally link with a command something like: *`compiler`*` `*`...source/object` `files...`*` -lnlopt -lm -o myprogram` where *compiler* is `f77`, `gfortran`, or whatever is appropriate for your machine. *Note:* the above example assumes that you have installed the NLopt library in a place where the compiler knows to find it (e.g. in a standard directory like `/usr/lib` or `/usr/local/lib`). If you installed somewhere else (e.g. in your home directory if you are not a system administrator), then you will need to use a `-L` flag to tell the compiler where to find the library. See [the installation manual](NLopt_Installation#Changing_the_installation_directory.md). Fortran vs. C API ----------------- As explained in the [NLopt Tutorial](NLopt_Tutorial#Example_in_Fortran.md), there are a few simple rules that define the differences between the C and Fortran APIs: - All `nlopt_` functions are converted into `nlo_` subroutines, with return values converted into the first argument. - The `nlopt_opt` type corresponds to `integer*8`. (Technically, we could use any type that is big enough to hold a pointer on all platforms; `integer*8` is big enough for pointers on both 32-bit and 64-bit machines.) - Your objective/constraint subroutines must be declared as `external`, and must be defined as described below. - `include` `'nlopt.f'` in order to get the various constants like `NLOPT_LD_MMA`. - The C `int` or `unsigned` types become a Fortran `integer`, and the C `double` type becomes `real*8` or `double` `precision` in Fortran. The `nlopt_opt` object ---------------------- The NLopt API revolves around an "object" corresponding to the C type `nlopt_opt`. This object is internally a pointer, so it should be declared as an `integer*8` in Fortran (see above). Via functions that modify this object, all of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera), and then one finally calls `nlo_optimize` in order to perform the optimization. The object should normally be created via the constructor: ``` integer*8 opt opt = 0 call nlo_create(opt, algorithm, n) ``` given an `integer` `algorithm` (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values, defined in the `nlopt.f` include file) and the `integer` dimensionality of the problem (`n`, the number of optimization parameters). Just as in C, the algorithm is specified by constants of the form `NLOPT_MMA`, `NLOPT_COBYLA`, etcetera. If the constructor succeeds, `opt` will be nonzero after nlo_create, so you can check for an error by checking whether `opt` is zero (if you do this, be sure to initialize it to zero before calling nlo_create). When you are finished with the object, you must deallocate its associated storage by calling: ``` call nlo_destroy(opt) ``` There are also a copy subroutine `call` `nlo_copy(new_opt,` `opt)` to make a copy of a given object (equivalent to `nlopt_copy` in the C API). The algorithm and dimension parameters of the object are immutable (cannot be changed without constructing a new object), but you can query them for a given object by the subroutines: ``` call nlo_get_algorithm(algorithm, opt) call nlo_get_dimension(n, opt) ``` Objective function ------------------ The objective function is specified by calling one of the methods: ``` external f call nlo_set_min_objective(ires, opt, f, f_data) call nlo_set_max_objective(ires, opt, f, f_data) ``` depending on whether one wishes to minimize or maximize the objective function `f`, respectively. `ires` is an `integer` return value which is positive on success and negative on failure (see below for more specific [return-value meanings](#Return_values.md)). The function `f` should be of the form: ```      subroutine f(result, n, x, grad, need_gradient, f_data)      integer need_gradient      double precision result, x(n), grad(n)      if (need_gradient.ne.0) then ``` `        `*`..store` `gradient` `in` `grad...`* ```      endif ``` `     result = `*`...value` `of` `f(x)...`* ```      end ``` The return value in `result` should be the value of the function at the point `x`, where `x` is an array of length `n` of the optimization parameters (the same as the dimension passed to the constructor). In addition, if the argument `need_gradient` is not zero, then `grad` is an array of length `n` which should (upon return) be set to the gradient of the function with respect to the optimization parameters at `x`. That is, `grad(i)` should upon return contain the partial derivative $\partial f / \partial x_i$, for $1 \leq i \leq n$. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be empty and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be empty for some calls.) The `f_data` argument can be used to pass through a single variable containing any data and any type to your subroutine. That is, whatever `f_data` variable you pass to `nlo_set_min_objective` is also passed to your function. NLopt does *not* pass a *copy* of your variable, it passes a reference to the original `f_data` variable. This means that you must call nlo_optimize while the `f_data` variable is still valid (e.g. it cannot be a local variable of a subroutine that has exited). Bound constraints ----------------- The [bound constraints](NLopt_Reference#Bound_constraints.md) can be specified by calling the methods: ``` double precision lb(n), ub(n) call nlo_set_lower_bounds(ires, opt, lb) call nlo_set_upper_bounds(ires, opt, ub) ``` where `lb` and `ub` are arrays of length *n* (the same as the dimension passed to the `nlopt.opt` constructor), and `ires` is an `integer` [return value](#Return_values.md) (positive on success). For convenience, we also provide subroutines that take a single number as arguments, in order to set the lower/upper bounds for all optimization parameters to a single constant `value`. ``` call nlo_set_lower_bounds1(ires, opt, value) call nlo_set_upper_bounds1(ires, opt, value) ``` To retrieve the values of the lower/upper bounds, you can call one of: ``` call nlo_get_lower_bounds(ires, opt, lb) call nlo_get_upper_bounds(ires, opt, ub) ``` To specify an unbounded dimension, you can use ±`huge(lb(1))` in Fortran to specify ±∞, where `huge` is a Fortran 90 intrinsic function. If you have a Fortran 77 compiler that does not support this intrinsic, then you can call `nlo_get_upper_bounds` or `nlo_get_lower_bounds` first to get the default ±∞ upper/lower bounds. Nonlinear constraints --------------------- Just as for [nonlinear constraints in C](NLopt_Reference#Nonlinear_constraints.md), you can specify nonlinear inequality and equality constraints by the methods: ``` call nlo_add_inequality_constraint(ires, opt, fc, fc_data, tol) call nlo_add_inequality_constraint(ires, opt, h, h_data, tol) ``` where the arguments `fc` and `h` have the same form as the objective function above. The `double` `precision` `tol` arguments specify a tolerance in judging feasibility for the purposes of stopping the optimization, as in C, and `ires` is an `integer` [return value](#Return_values.md) (positive on success). To remove all of the inequality and/or equality constraints from a given problem, you can call the following methods: ``` call nlo_remove_inequality_constraints(ires, opt) call nlo_remove_equality_constraints(ires, opt) ``` ### Vector-valued constraints Just as for [nonlinear constraints in C](NLopt_Reference#Vector-valued_constraints.md), you can specify vector-valued nonlinear inequality and equality constraints by the subroutines ``` double precision tol(m) call nlo_add_inequality_mconstraint(ires, opt, m, c, c_data, tol) call nlo_add_equality_mconstraint(ires, opt, m, c, c_data, tol) ``` Here, *m* is the dimensionality of the constraint result and `tol` is a length-*m* array of the tolerances in each constraint dimension. The constraint subroutine `c` must be of the form: ```      subroutine c(m, result, n, x, grad, need_gradient, f_data)      integer need_gradient      double precision result(m), x(n), grad(n,m)      if (need_gradient.ne.0) then ``` `        `*`..store` `gradient` `in` `grad...`* ```      endif ``` `     `*`...store` `value` `of` `c(x)` `in` `result...`* ```      end ``` This evaluates the constraint function(s) $\mathbf{c}(\mathbf{x})$ at the point `x`, an array of length `n` (the same as the dimension passed to `nlo_create`). Upon return, the output value of the constraints should be stored in `result`, an array of length `m` (the same as the dimension passed to `nlo_add_*_mconstraint`), so that `result(i)` stores *c**i*. In addition, if `grad` is non-`NULL`, then `grad` is an *n*×*m* array that should, upon return, be set to the gradients of the constraint functions with respect to `x`. That is, $\part c_i / \part x_j$ is stored in `grad(j,i)`. An inequality constraint corresponds to $c_i \le 0$ for $1 \le i \le m$, and an equality constraint corresponds to $c_i = 0$, in both cases with tolerance `tol(i)` for purposes of termination criteria. (You can add multiple vector-valued constraints and/or scalar constraints in the same problem.) Stopping criteria ----------------- As explained in the [C API Reference](NLopt_Reference#Stopping_criteria.md) and the [Introduction](NLopt_Introduction#Termination_conditions.md)), you have multiple options for different stopping criteria that you can specify. (Unspecified stopping criteria are disabled; i.e., they have innocuous defaults.) For each stopping criteria, there are (at least) two subroutines: a `set` subroutine to specify the stopping criterion, and a `get` subroutine to retrieve the current value for that criterion. The meanings of each criterion are exactly the same as in the C API. The first argument `ires` of each `set` subroutine is an `integer` [return value](#Return_values.md) (positive on success). ``` call nlo_set_stopval(ires, opt, stopval) call nlo_get_stopval(stopval, opt) ``` Stop when an objective value of at least `stopval` is found. ``` call nlo_set_ftol_rel(ires, opt, tol) call nlo_get_ftol_rel(tol, opt) ``` Set relative tolerance on function value. ``` call nlo_set_ftol_abs(ires, opt, tol) call nlo_get_ftol_abs(tol, opt) ``` Set absolute tolerance on function value. ``` call nlo_set_xtol_rel(ires, opt, tol) call nlo_get_xtol_rel(tol, opt) ``` Set relative tolerance on optimization parameters. ``` call nlo_set_xtol_abs(ires, opt, tol) call nlo_set_xtol_abs1(ires, opt, tol1) call nlo_get_xtol_abs(ires, opt, tol) ``` Set absolute tolerances on optimization parameters. The `tol` input must be an array of length `n` (the dimension specified in the `nlopt_opt` constructor). Alternatively, we provide the subroutine `nlo_set_xtol_abs1` where you pass a single number `tol1` in order to set the same tolerance for all optimization parameters. `nlo_get_xtol_abs` returns the tolerance array in `tol`. ``` call nlo_set_maxeval(ires, opt, maxeval) call nlo_get_maxeval(maxeval, opt) ``` Stop when the number of function evaluations exceeds the `integer` `maxeval`. (Zero or negative for no limit.) ``` call nlo_get_numevals(nevals, opt) ``` Request the number of evaluations. ``` call nlo_set_maxtime(ires, opt, maxtime) call nlo_get_maxtime(maxtime, opt) ``` Stop when the optimization time (in seconds) exceeds `maxtime` (`double` `precision`). (Zero or negative for no limit.) ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. In this case, it is possible to tell NLopt to halt the optimization gracefully, returning the best point found so far, by calling the following subroutine from *within* your objective or constraint functions (exactly analogous to the corresponding [C routines](NLopt_Reference#Forced_termination.md)): ``` call nlo_force_stop(ires, opt) ``` `ires` is an `integer` [return value](#Return_values.md) (positive on success). More generally, you can set and retrieve a force-stop integer code `ival`, where a nonzero value indicates a forced stop. ``` call nlo_set_force_stop(ires, opt, ival) call nlo_get_force_stop(ires, opt, ival) ``` The force-stop value is reset to zero at the beginning of `nlopt_optimize`. Passing `ival=0` to `nlo_set_force_stop` tells NLopt *not* to force a halt. Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given object `opt`, you can perform the optimization by calling: ``` double precision x(n), minf call nlo_optimize(ires, opt, x, minf) ``` On input, `x` is an array of length `n` (the dimension of the problem from the `nlopt.opt` constructor) giving an initial guess for the optimization parameters. Upon successful return, `x` contains the optimized values of the optimization parameters and `minf` contains the optimized objective-function value. `ires` is an `integer` [return value](#Return_values.md) (positive on success). ### Return values The possible return values are the same as the [return values in the C API](NLopt_Reference#Return_values.md), with the corresponding integer constants defined in the `nlopt.f` include file. Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: ``` nlo_set_local_optimizer(ires, opt, local_opt) ``` Here, `local_opt` is another `nlopt_opt` object (`integer*8`) whose parameters are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `local_opt` are ignored.) The dimension `n` of `local_opt` must match that of `opt`. `ires` is an `integer` [return value](#Return_values.md) (positive on success). This function makes a copy of the `local_opt` object, so you can freely change or destroy your original `local_opt` afterwards without affecting `opt`. Initial step size ----------------- Just as in the C API, you can [get and set the initial step sizes](NLopt_Reference#Initial_step_size.md) for derivative-free optimization algorithms. The Fortran equivalents of the C functions are the following methods: ``` double precision x(n) dx(n), dx1 call nlo_set_initial_step(ires, opt, dx) call nlo_set_initial_step1(ires, opt, dx1) call nlo_get_initial_step(ires, opt, x, dx) ``` Here, `dx` is an array of the (nonzero) initial steps for each dimension. For convenience, you can also pass a single number `dx1` to `nlo_set_initial_step1` if you wish to use the same initial steps for all dimensions. `nlo_get_initial_step` sets `dx` to the initial step that will be used for a starting guess of `x` in `nlo_optimize(ires,` `opt,` `x,` `minf)`. `ires` is an `integer` [return value](#Return_values.md) (positive on success) Stochastic population --------------------- Just as in the C API, you can [get and set the initial population](NLopt_Reference#Stochastic_population.md) for stochastic optimization algorithms, by the methods: ``` call nlo_set_population(ires, opt, ipop) call nlo_get_population(ipop, opt) ``` where `ipop` is an integer and `ires` is an `integer` [return value](#Return_values.md) (positive on success). (An `ipop` of zero implies that the heuristic default will be used.) Pseudorandom numbers -------------------- For stochastic optimization algorithms, we use pseudorandom numbers generated by the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm, based on code from Makoto Matsumoto. By default, the [seed](https://en.wikipedia.org/wiki/Random_seed) for the random numbers is generated from the system time, so that you will get a different sequence of pseudorandom numbers each time you run your program. If you want to use a "deterministic" sequence of pseudorandom numbers, i.e. the same sequence from run to run, you can set the seed by calling: ``` call nlosr(iseed) ``` where `iseed` is an `integer`. To reset the seed based on the system time, you can call: ``` call nlosrt ``` (Normally, you don't need to call this as it is called automatically. However, it might be useful if you want to "re-randomize" the pseudorandom numbers after calling `nlosr` to set a deterministic seed.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Just as in the C API, you can get and set the [number *M* of stored vectors](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md) for limited-memory quasi-Newton algorithms: ``` call nlo_set_vector_storage(ires, opt, M) call nlo_get_vector_storage(M, opt) ``` (The default is *M*=0, in which case NLopt uses a heuristic nonzero value.) Version number -------------- To determine the version number of NLopt at runtime, you can call: ``` call nloptv(major, minor, bugfix) ``` where the three arguments are `integer`s. For example, NLopt version 3.1.4 would return `major=3`, `minor=1`, and `bugfix=4`. nlopt-2.6.1/doc/docs/NLopt_Guile_Reference.md000066400000000000000000000360121345435414600210450ustar00rootroot00000000000000--- # NLopt Guile Reference --- The NLopt includes an interface callable from the [Scheme programming language](https://en.wikipedia.org/wiki/Scheme_(programming_language)) as implemented in [GNU Guile](https://en.wikipedia.org/wiki/GNU_Guile) (which allows Scheme to be used as an extension language for other programs). The main purpose of this section is to document the syntax and unique features of the Guile API; for more detail on the underlying features, please refer to the C documentation in the [NLopt Reference](NLopt_Reference.md). Using the NLopt Guile API ------------------------- To use NLopt in Python, your Python program should include the lines: ``` (use-modules (nlopt)) ``` which imports the `nlopt` module. The `nlopt-opt` class --------------------- The NLopt API revolves around an opaque "object", analogous to `nlopt::opt` in C++. Via "methods" of this object, all of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera), and then one finally calls the `opt.optimize` method in order to perform the optimization. The object should normally be created via the constructor: ``` (new-nlopt-opt algorithm n) ``` given an `algorithm` (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values) and the dimensionality of the problem (`n`, the number of optimization parameters). Whereas the C algorithms are specified by `nlopt_algorithm` constants of the form `NLOPT_MMA`, `NLOPT_COBYLA`, etcetera, the Guile `algorithm` values are of the form `nlopt-MMA`, `nlopt-COBYLA`, etcetera (i.e., underscores are turned into dashes). There are also a copy constructor `(new-nlopt-opt` `opt)` to make a copy of a given object (equivalent to `nlopt_copy` in the C API). If there is an error in the constructor (or copy constructor, or assignment), an exception is thrown. The algorithm and dimension parameters of the object are immutable (cannot be changed without constructing a new object), but you can query them for a given object by the methods: ``` (nlopt-opt-get-algorithm opt) (nlopt-opt-get-dimension opt) ``` You can get a string description of the algorithm via: ``` (nlopt-opt-get-algorithm-name opt) ``` ### Relationship to C++ interface In general, there is a simple relationship between the Guile interface and the [C++ interface](NLopt_C-plus-plus_Reference.md): - The `nlopt::` namespace becomes a prefix`nlopt-`, and `nlopt::opt` becomes `nlopt-opt-`. (Constants are prefixed with `NLOPT-`, however.) - Underscores (_) are turned into hyphens (-). - The `nlopt-opt` object becomes the first parameter of its methods. - `std::vector` is turned into a Scheme `vector` (a `list` is also supported for input parameters). Objective function ------------------ The objective function is specified by calling one of the methods: ``` (nlopt-opt-set-min-objective opt f) (nlopt-opt-set-max-objective opt f) ``` depending on whether one wishes to minimize or maximize the objective function `f`, respectively. The function `f` should be of the form: ``` (define (f x grad)    (if grad       (begin `*`...set` `grad` `to` `gradient,` `in-place...`*`))    return `*`...value` `of` `f(x)...`*`) ``` The return value should be the value of the function at the point `x`, where `x` is a `vector` of length `n` of the optimization parameters (the same as the dimension passed to the constructor). In addition, if the argument `grad` is not `#f` (false), then `grad` is a `vector` of length `n` which should (upon return) be set to the gradient of the function with respect to the optimization parameters at `x`. That is, `(vector-ref` `grad` `i)` should upon return contain the partial derivative $\partial f / \partial x_i$, for $0 \leq i < n$, if `grad` is not `#f`. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be empty and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be empty for some calls.) Note that `grad` must be modified `in-place` by your function `f`, by using `(vector-set!` `grad` `i` *`value`*`)`. Bound constraints ----------------- The [bound constraints](NLopt_Reference#Bound_constraints.md) can be specified by calling the methods: ``` (nlopt-opt-set-lower-bounds opt lb) (nlopt-opt-set-lower-bounds opt ub) ``` where `lb` and `ub` are vectors or lists of length *n* (the same as the dimension passed to the `nlopt.opt` constructor). For convenience, these are overloaded with functions that take a single number as arguments, in order to set the lower/upper bounds for all optimization parameters to a single constant. To retrieve the values of the lower/upper bounds, you can call one of: ``` (nlopt-opt-get-lower-bounds opt) (nlopt-opt-get-upper-bounds opt) ``` both of which return vectors. To specify an unbounded dimension, you can use `(inf)` or `(-` `(inf))` in Guile to specify ±∞, respectively. Nonlinear constraints --------------------- Just as for [nonlinear constraints in C](NLopt_Reference#Nonlinear_constraints.md), you can specify nonlinear inequality and equality constraints by the methods: ``` (nlopt-opt-add-inequality-constraint opt fc tol) (nlopt-opt-add-equality-constraint opt h tol) ``` where the arguments `fc` and `h` have the same form as the objective function above. The (optional) `tol` arguments specify a tolerance in judging feasibility for the purposes of stopping the optimization, as in C (defaulting to zero if they are omitted). To remove all of the inequality and/or equality constraints from a given problem, you can call the following methods: ``` (nlopt-opt-remove-inequality-constraints opt) (nlopt-opt-remove-equality-constraints opt) ``` Stopping criteria ----------------- As explained in the [C API Reference](NLopt_Reference#Stopping_criteria.md) and the [Introduction](NLopt_Introduction#Termination_conditions.md)), you have multiple options for different stopping criteria that you can specify. (Unspecified stopping criteria are disabled; i.e., they have innocuous defaults.) For each stopping criteria, there are (at least) two method: a `set` method to specify the stopping criterion, and a `get` method to retrieve the current value for that criterion. The meanings of each criterion are exactly the same as in the C API. ``` (nlopt-opt-set-stopval opt stopval) (nlopt-opt-get-stopval opt) ``` Stop when an objective value of at least `stopval` is found. ``` (nlopt-opt-set-ftol-rel opt tol) (nlopt-opt-get-ftol-rel opt tol) ``` Set relative tolerance on function value. ``` (nlopt-opt-set-ftol-abs opt tol) (nlopt-opt-get-ftol-abs opt tol) ``` Set absolute tolerance on function value. ``` (nlopt-opt-set-xtol-rel opt tol) (nlopt-opt-get-xtol-rel opt tol) ``` Set relative tolerance on optimization parameters. ``` (nlopt-opt-set-xtol-abs opt tol) (nlopt-opt-get-xtol-abs opt tol) ``` Set absolute tolerances on optimization parameters. The `tol` input must be a vector or list of length `n` (the dimension specified in the `nlopt.opt` constructor); alternatively, you can pass a single number in order to set the same tolerance for all optimization parameters. `get-xtol-abs()` returns the tolerances as a vector. ``` (nlopt-opt-set-maxeval opt maxeval) (nlopt-opt-get-maxeval opt) ``` Stop when the number of function evaluations exceeds `maxeval`. (0 or negative for no limit.) ``` (nlopt-opt-get-nevals opt) ``` Request the number of evaluations. ``` (nlopt-opt-set-maxtime opt maxtime) (nlopt-opt-get-maxtime opt) ``` Stop when the optimization time (in seconds) exceeds `maxtime`. (0 or negative for no limit.) Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given object `opt`, you can perform the optimization by calling: ``` (nlopt-opt-optimize opt x) ``` On input, `x` is a vector or list of length `n` (the dimension of the problem from the `nlopt.opt` constructor) giving an initial guess for the optimization parameters. The return value is a vector containing the optimized values of the optimization parameters. You can call the following methods to retrieve the optimized objective function value from the last `optimize` call, and also the return code (including negative/failure return values) from the last `optimize` call: ``` (nlopt-opt-last-optimum-value opt) (nlopt-opt-last-optimize-result opt) ``` The return code (see below) is positive on success, indicating the reason for termination. On failure (negative return codes), `optimize` throws an exception (see [Exceptions](#Exceptions.md), below). ### Return values The possible return values are the same as the [return values in the C API](NLopt_Reference#Return_values.md), except that the `NLOPT_` prefix is replaced with the `NLOPT-` namespace. That is, `NLOPT_SUCCESS` becomes `NLOPT-SUCCESS`, etcetera. Exceptions ---------- The [Error codes (negative return values)](NLopt_Reference#Error_codes_(negative_return_values).md) in the C API are replaced in the Guile API by thrown exceptions. The exception key takes the form of a Scheme symbol. The following exception keys are thrown by the various routines: ``` runtime-error ``` Generic failure, equivalent to `NLOPT_FAILURE`. ``` invalid-argument ``` Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera), equivalent to `NLOPT_INVALID_ARGS`. ``` bad-alloc ``` Ran out of memory (a memory allocation failed), equivalent to `NLOPT_OUT_OF_MEMORY`. `roundoff-limited` (subclass of `Exception`) Halted because roundoff errors limited progress, equivalent to `NLOPT_ROUNDOFF_LIMITED`. `forced-stop` (subclass of `Exception`) Halted because of a [forced termination](#Forced_termination.md): the user called `opt.force_stop()` from the user’s objective function. Equivalent to `NLOPT_FORCED_STOP`. Currently, NLopt does not catch any exceptions that you might throw from your objective or constraint functions. (In the future, we might catch these exceptions, halt the optimization gracefully, and then re-throw, as in Python or C++, but this is not yet implemented.) So, throwing an exception in your objective/constraint may result in a memory leak. To catch an [exception in Guile](http://www.gnu.org/software/guile/manual/html_node/Exceptions.html), you need to define a [throw-handler](http://www.gnu.org/software/guile/manual/html_node/Throw-Handlers.html) function. For example, the following code calls `nlopt-opt-optimize`, catches *any* exception (a key of `#t` in `catch`), and prints out the error return code: ``` (define xopt    (catch #t        (lambda () (nlopt-opt-optimize opt x))       (lambda (key . args)          (display "Caught exception ") (display key) (display " ") (display args) (newline)          (display "NLopt result ") (display (nlopt-opt-last-optimize-result opt)) (newline)          #f)        )) ``` Note that the [catch statement](http://www.gnu.org/software/guile/manual/html_node/Catch.html) takes three arguments: the first is a key to catch (\#t for all), the second is a [thunk](https://en.wikipedia.org/wiki/Thunk) function to do whatever it is that might throw exceptions (the equivalent of a C++ `try` block), and the third is a function that is called if there is an exception (the equivalent of a C++ `catch` block). Note that `xopt` is set to the return value of `nlopt-opt-optimize` on success, or `#f` (the return value of our throw handler) on an exception. Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: ``` (nlopt-opt-set-local-optimizer opt local-opt) ``` Here, `local-opt` is another `nlopt-opt` object whose parameters are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `local-opt` are ignored.) The dimension `n` of `local-opt` must match that of `opt`. This function makes a copy of the `local-opt` object, so you can freely change your original `local-opt` afterwards without affecting `opt`. Initial step size ----------------- Just as in the C API, you can [get and set the initial step sizes](NLopt_Reference#Initial_step_size.md) for derivative-free optimization algorithms. The Guile equivalents of the C functions are the following methods: ``` (nlopt-opt-set-initial-step opt dx) (nlopt-opt-get-initial-step opt x) ``` Here, `dx` is a vector or list of the (nonzero) initial steps for each dimension, or a single number if you wish to use the same initial steps for all dimensions. `nlopt-opt-get-initial-step` returns the initial step (vector) that will be used for a starting guess of `x` in `(nlopt-opt-optimize` `opt` `x)`. Stochastic population --------------------- Just as in the C API, you can [get and set the initial population](NLopt_Reference#Stochastic_population.md) for stochastic optimization algorithms, by the methods: ``` (nlopt-opt-set-population opt pop) (nlopt-opt-get-population opt) ``` (A `pop` of zero implies that the heuristic default will be used.) Pseudorandom numbers -------------------- For stochastic optimization algorithms, we use pseudorandom numbers generated by the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm, based on code from Makoto Matsumoto. By default, the [seed](https://en.wikipedia.org/wiki/Random_seed) for the random numbers is generated from the system time, so that you will get a different sequence of pseudorandom numbers each time you run your program. If you want to use a "deterministic" sequence of pseudorandom numbers, i.e. the same sequence from run to run, you can set the seed by calling: ``` (nlopt-srand seed) ``` where `seed` is an integer. o reset the seed based on the system time, you can call: ``` (nlopt-srand-time) ``` (Normally, you don't need to call this as it is called automatically. However, it might be useful if you want to "re-randomize" the pseudorandom numbers after calling `nlopt-srand` to set a deterministic seed.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Just as in the C API, you can get and set the [number *M* of stored vectors](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md) for limited-memory quasi-Newton algorithms, via the functions: ``` (nlopt-opt-set-vector-storage opt M) (nlopt-opt-get-vector-storage opt) ``` (The default is *M*=0, in which case NLopt uses a heuristic nonzero value.) Version number -------------- To determine the version number of NLopt at runtime, you can call: ``` (nlopt-version-major) (nlopt-version-minor) (nlopt-version-bugfix) ``` For example, NLopt version 3.1.4 would return `major=3`, `minor=1`, and `bugfix=4`. nlopt-2.6.1/doc/docs/NLopt_Installation.md000066400000000000000000000205621345435414600204660ustar00rootroot00000000000000--- # NLopt Installation --- The installation of NLopt is fairly standard and straightforward, at least on Unix-like systems (GNU/Linux is fine). It doesn't require any particular packages to be installed except for a C compiler, although you need to have [Octave](https://en.wikipedia.org/wiki/GNU_Octave) and/or Matlab installed if you want to install the Octave and/or Matlab plugins, respectively. In particular, NLopt uses the standard [CMake](https://cmake.org/) `cmake` build system, which means that you compile it via: ```sh mkdir build cd build cmake .. make ``` in the `nlopt` directory. Then install the NLopt libraries and header files via: ```sh sudo make install ``` By default, this installs the NLopt shared library (`libnlopt.so`) in `/usr/local/lib` and the NLopt header file (`nlopt.h`) in `/usr/local/include`, as well manual pages and a few other files. In the following, we describe a few details of this installation process, including how to change the installation location. Changing the installation directory ----------------------------------- You may wish to install NLopt in a directory other than `/usr/local`, especially if you do not have administrator access to your machine. You can do this using the `CMAKE_INSTALL_PREFIX` variable of the `cmake` utility. For example, suppose that you want to install into the `install` subdirectory of your home directory (`$HOME`). You would do: ```sh cmake -DCMAKE_INSTALL_PREFIX=$HOME/install .. make make install ``` This will create the directories `$HOME/install/lib` etcetera and install NLopt into them. However, now when you compile code using NLopt, you will need to tell the compiler where to find the NLopt header files (using `-I`) and libraries (using `-L`) with something like: ```sh cc -I$HOME/install/include myprogram.c -L$HOME/install/lib -lnlopt -lm -o myprogram ``` See also below for how to change the installation directories for Octave, Matlab, and Guile plugins, if you are installing those. Note also that the `-DCMAKE_INSTALL_PREFIX` flag will change the location where the Python plugins are installed, so you may need to change the [Python module search path](http://docs.python.org/tutorial/modules.html#the-module-search-path) via the `PYTHONPATH` environment variable. However, at this point you need to tell the operating system where to find the shared library, so that the runtime linker works properly. There are at least two ways to do this. First, you can use the `LD_LIBRARY_PATH` environment variable. For example, if you installed into the `/foo/bar` directory, so that the library is in `/foo/bar/lib`, then you would do ```sh export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/foo/bar/lib ``` in the [bash](https://en.wikipedia.org/wiki/Bash) shell, or ```sh setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/foo/bar/lib ``` in [csh](https://en.wikipedia.org/wiki/csh) or [w:tcsh](https://en.wikipedia.org/wiki/tcsh). Alternatively, in GNU/Linux systems, you can add the library directory to the system-wide file `/etc/ld.so.conf` and then (as root) run `/sbin/ldconfig`. Static libraries ---------------- By default, NLopt compiles as a shared library (also called a dynamic-link library). The alternative is to compile NLopt as a static library. Compiling NLopt as a static library is easy. Just add `-DBUILD_SHARED_LIBS=OFF` to the `cmake` flags, as in: ```sh cmake -DBUILD_SHARED_LIBS=OFF .. ``` Then you run `make` and `make` `install` as usual. Octave and Matlab plugins ------------------------- When you compile NLopt using the above commands, it will automatically compile plugins for both Matlab and GNU Octave (a free Matlab clone) if the latter programs are installed. On most current systems, Matlab and Octave plugins require NLopt to be compiled as a shared library (see above). ### Matlab In particular, for Matlab plugins to be installed, you should provide the Matlab installation dir, eg: ```sh cmake -DMatlab_ROOT_DIR=/opt/matlab/RYYYYx/ .. ``` Some versions of Matlab also require that you compile NLopt as a shared library in order to produce a Matlab plugin; see below. The Matlab plugins (along with help files and other `.m` files) are installed into `INSTALL_MEX_DIR`. You can override the default by passing a `INSTALL_MEX_DIR` to `cmake`, via (in addition to other `cmake` arguments): ```sh cmake -DINSTALL_MEX_DIR=dir .. ``` to install the Matlab plugins in directory *dir*. In this case, however, when you run Matlab you will either need to run in the *dir* directory or explicitly add *dir* to your Matlab path (see the Matlab `path` command). ### Octave For the Octave plugins to be installed, you need to have the Octave `mkoctfile` program in your PATH. `mkoctfile` is Octave's equivalent of `mex`. If you are using a GNU/Linux system, and you installed Octave using one of the precompiled packages for your distribution, then you probably need to install a *separate package* to get `mkoctfile`. For example, on Debian you need to install the `octave-headers` package, and on Redhat you need the `octave-devel` package. By default, the compiled Octave plugins (`.oct` files) are installed into the octave extension binary directory relatively to the installation prefix (usually something like `/usr/local/lib/octave/2.1.73/site/oct/i486-pc-linux-gnu`), and the .m script files are installed into the site extension directory relatively the the installation prefix (usually something like `/usr/local/share/octave/2.1.73/site/m/`). You can change these defaults by passing `INSTALL_OCT_DIR` and `INSTALL_M_DIR`, respectively, to the cmake script, via: ```sh cmake -DINSTALL_OCT_DIR=octdir -DINSTALL_M_DIR=mdir .. ``` Python plugins -------------- If [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) is installed on your machine, and you configured NLopt as a shared library (see above), then NLopt will automatically compile and install a Python `nlopt` module. You also need [NumPy](https://en.wikipedia.org/wiki/NumPy) to be installed, as NLopt's Python interface uses NumPy array types. To specify a particular version or location of Python, use the `PYTHON_EXECUTABLE` variable to set the full path to the `python` executable: ```sh cmake -DPYTHON_EXECUTABLE=/usr/bin/python .. ``` GNU Guile plugins ----------------- If [Guile](https://en.wikipedia.org/wiki/GNU_Guile) is installed on your machine, and you configured NLopt as a shared library (see above), then a Guile `nlopt` module will automatically be compiled and installed. Note that many GNU/Linux distributions come with only the Guile program and shared libraries pre-installed; to compile the NLopt plugin you will also need the Guile programming header files, which are usually in a `guile-dev` or `guile-devel` package that you must install separately. If you want to specify a particular version or a nonstandard location of Guile, you should use the `GUILE_CONFIG_EXECUTABLE` and `GUILE_EXECUTABLE` variables to specify the locations of the `guile-config` and `guile` programs: ```sh cmake -DGUILE_EXECUTABLE=/usr/bin/guile GUILE_CONFIG_EXECUTABLE=/usr/bin/guile-config .. ``` (The `cmake` script uses these programs to determine the compiler flags and installation directories for Guile plugins.) By default, the Guile plugin is installed in the guile extension directory defined relatively to the installation prefix. Note, however, that if you do this then Guile may not know where to load the `nlopt` module from. You can [update the Guile load path](http://www.gnu.org/software/guile/manual/html_node/Build-Config.html) by changing the `%load-path` variable in Guile or using the `GUILE_LOAD_PATH` environment variable. NLopt with C++ algorithms ------------------------- NLopt, as-is, is callable from C, C++, and Fortran, with optional Matlab and GNU Octave plugins (and even installs an `nlopt.hpp` C++ header file to allow you to call it in a more C++ style). By default, it includes subroutines written in C (or written in Fortran and converted to C) and C++. If you configure with: ```sh cmake -DNLOPT_CXX=OFF .. ``` however, it will disable algorithms implemented in C++ (StoGO and AGS algorithms). The resulting library has the *same* interface as the ordinary NLopt library, and can *still* be called from ordinary C, C++, and Fortran programs. However, one no longer has to link with the C++ standard libraries, which can sometimes be convenient for non-C++ programs, and allows libnlopt to be compatible with multiple C++ compilers simultaneously. nlopt-2.6.1/doc/docs/NLopt_Introduction.md000066400000000000000000000527731345435414600205170ustar00rootroot00000000000000--- # NLopt Introduction --- In this chapter of the manual, we begin by giving a general overview of the optimization problems that NLopt solves, the key distinctions between different types of optimization algorithms, and comment on ways to cast various problems in the form NLopt requires. We also describe the background and goals of NLopt. Optimization problems --------------------- NLopt addresses general nonlinear optimization problems of the form: $$\min_{\mathbf{x}\in\mathbb{R}^n} f(\mathbf{x})$$, where *f* is the **objective function** and **x** represents the *n* **optimization parameters** (also called *design variables* or *decision parameters*). This problem may optionally be subject to the **bound constraints** (also called *box constraints*): $$lb_i \leq x_i \leq ub_i$$ for $i=1,\ldots,n$ given lower bounds *lb* and upper bounds *ub* (which may be −∞ and/or +∞, respectively, for partially or totally unconstrained problems). (If $lb_i = ub_i$, that parameter is effectively eliminated.) One may also optionally have *m* **nonlinear inequality constraints** (sometimes called a **nonlinear programming** problem): $$fc_i(\mathbf{x}) \leq 0$$ for $i=1,\ldots,m$ for **constraint functions** *fc**i*(**x**). Some of the NLopt algorithms also support *p* **nonlinear equality constraints**: $$h_i(\mathbf{x}) = 0$$ for $i=1,\ldots,p$ (More generally, several constraints at once might be combined into a single function that returns a vector-valued result.) A point **x** that satisfies all of the bound, inequality, and equality constraints is called a **feasible point**, and the set of all feasible points is the **feasible region**. *Note:* in this introduction, we follow the usual mathematical convention of letting our indices begin with one. In the C programming language, however, NLopt follows C's zero-based conventions (e.g. *i* goes from 0 to *m*−1 for the constraints). ### Global versus local optimization NLopt includes algorithms to attempt either *global* or *local* optimization of the objective. **Global optimization** is the problem of finding the feasible point **x** that minimizes the objective *f*(**x**) over the *entire* feasible region. In general, this can be a *very difficult* problem, becoming exponentially harder as the number *n* of parameters increases. In fact, unless special information about *f* is known, it is not even possible to be certain whether one has found the true global optimum, because there might be a sudden dip of *f* hidden somewhere in the parameter space you haven't looked at yet. However, NLopt includes several global optimization algorithms that work well on reasonably well-behaved problems, if the dimension *n* is not too large. **Local optimization** is the *much easier* problem of finding a feasible point **x** that is only a *local* minimum: *f*(**x**) is less than or equal to the value of *f* for all nearby feasible points (the intersection of the feasible region with at least some small neighborhood of **x**). In general, a nonlinear optimization problem may have *many* local minima, and which one is located by an algorithm typically depends upon the starting point that the user supplies to the algorithm. Local optimization algorithms, on the other hand, can often quickly locate a local minimum even in very high-dimensional problems (especially using gradient-based algorithms). (An algorithm that is guaranteed to find some *local* minimum from any feasible starting point is, somewhat confusingly, called *globally convergent*.) In the special class of **convex optimization** problems, for which both the objective and inequality constraint functions are [convex](https://en.wikipedia.org/wiki/Convex_function) (and the equality constraints are [affine](https://en.wikipedia.org/wiki/Affine_transformation) or in any case have [convex](https://en.wikipedia.org/wiki/Convex_set) [level sets](https://en.wikipedia.org/wiki/Level_set)), there is only *one* local minimum value of *f* , so that a *local* optimization method finds a *global* optimum. There may, however, be more than one point **x** that yield the same minimum *f*(**x**), with the optimum points forming a convex subset of the (convex) feasible region. Typically, convex problems arise from functions of special analytical forms, such as linear programming problems, semidefinite programming, quadratic programming, and so on, and specialized techniques are available to solve these problems very efficiently. NLopt includes only general methods that do not assume convexity; if you have a provably convex problem, you may be better off with a different software package, such as the [CVX package](http://www.stanford.edu/~boyd/cvx/) from Stanford. ### Gradient-based versus derivative-free algorithms Especially for local optimization, the most efficient algorithms typically require the user to supply the gradient ∇*f* in addition to the value *f*(**x**) for any given point **x** (and similarly for any nonlinear constraints). This exploits the fact that, in *principle*, the gradient can almost always be computed at the same time as the value of *f* using very little additional computational effort (at worst, about the same as that of evaluating *f* a second time). If a quick way to compute the derivative of *f* is not obvious, one typically finds ∇*f* using an [adjoint method](http://math.mit.edu/~stevenj/18.336/adjoint.pdf), or possibly using [automatic differentiation](https://en.wikipedia.org/wiki/Automatic_differentiation) tools. Gradient-based methods are critical for the efficient optimization of very high-dimensional parameter spaces (e.g. *n* in the thousands or more). On the other hand, computing the gradient is sometimes cumbersome and inconvenient if the objective function is supplied as a complicated program. It may even be impossible, if *f* is not differentiable (or worse, is discontinuous). In such cases, it is often easier to use a *derivative-free* algorithm for optimization, which only requires that the user supply the function *values* *f*(**x**) for any given point **x**. Such methods typically must evaluate *f* for at *least* several-times-*n* points, however, so they are best used when *n* is small to moderate (up to hundreds). NLopt provides both derivative-free and gradient-based algorithms with a common interface. **Note**: If you find yourself computing the gradient by a finite-difference approximation (e.g. $\partial f/\partial x \approx [f(x+\Delta x) - f(x -\Delta x)]/2\Delta x$ in one dimension), then you should probably use a derivative-free algorithm instead. Finite-difference approximations are not only expensive (2*n* function evaluations for the gradient using center differences), but they are also notoriously susceptible to roundoff errors unless you are very careful. On the other hand, finite-difference approximations are very useful to *check* that your *analytical* gradient computation is correct—this is always a good idea, because in my experience it is very easy to have bugs in your gradient code, and an incorrect gradient will cause weird problems with a gradient-based optimization algorithm. ### Equivalent formulations of optimization problems There are many equivalent ways to formulate a given optimization problem, even within the framework defined above, and finding the best formulation can be something of an art. To begin with a trivial example, suppose that you want to *maximize* the function *g*(**x**). This is equivalent to minimizing the function *f*(**x**)=−*g*(**x**). Because of this, there is no need for NLopt to provide separate maximization routines in addition to its minimization routines—the user can just flip the sign to do maximization. As a convenience, however, NLopt provides a maximization interface (which performs the necessary sign flips for you, internally). A more interesting example is that of a **minimax** optimization problem, where the objective function *f*(**x**) is the maximum of *N* functions: $$f(\mathbf{x}) = \max \{ g_1(\mathbf{x}), g_2(\mathbf{x}), \ldots, g_N(\mathbf{x}) \}$$ You could, of course, pass this objective function directly to NLopt, but there is a problem: it is not everywhere differentiable (it is only piecewise differentiable, assuming *gk* is differentiable). Not only does this mean that the most efficient gradient-based algorithms are inapplicable, but even the derivative-free algorithms may be slowed down considerably. Instead, it is possible to formulate the *same* problem as a differentiable problem by adding a *dummy* variable *t* and *N* new nonlinear constraints (in addition to any other constraints): $$\min_{x\in\mathbb{R}^n, t\in\mathbb{R}} t$$ subject to $g_k(\mathbf{x}) - t \leq 0$ for $k=1,2,\ldots,N$. This solves *exactly* the same minimax problem, but now we have a differentiable objective and constraints, assuming that the functions *g**k* are individually differentiable. Notice that, in this case, the objective function by itself is the boring linear function *t*, and all of the interesting stuff is in the constraints. This is typical of many nonlinear programming problems. Yet another example would be minimizing the absolute value $|g(\mathbf{x})|$ of some function *g*(**x**). This is equivalent to minimizing $\max \{ g(\mathbf{x}), -g(\mathbf{x}) \}$, however, and can therefore be transformed into differentiable nonlinear constraints as in the minimax example above. ### Equality constraints Suppose that you have one or more **nonlinear equality constraints** $$h_i(\mathbf{x}) = 0$$. In *principle*, each equality constraint can be expressed by two inequality constraints $h_i(\mathbf{x}) \leq 0$ and $-h_i(\mathbf{x}) \leq 0$, so you might think that any code that can handle inequality constraints can automatically handle equality constraints. In practice, this is not true—if you try to express an equality constraint as a pair of nonlinear inequality constraints, some algorithms will fail to converge. Equality constraints sometimes require special handling because they reduce the *dimensionality* of the feasible region, and not just its size as for an inequality constraint. Only some of the NLopt algorithms (AUGLAG, COBYLA, and ISRES) currently support nonlinear equality constraints. #### Elimination Sometimes, it is possible to handle equality constraints by an **elimination** procedure: you use the equality constraint to explicitly solve for some parameters in terms of other unknown parameters, and then only pass the latter as optimization parameters to NLopt. For example, suppose that you have a *linear* (technically, affine) equality constraint: $$A\mathbf{x} = \mathbf{b}$$ for some constant matrix *A*. Given a particular solution **ξ** of these equations and a matrix *N* whose columns are a basis for the nullspace of *A*, one can express all possible solutions of these linear equations in the form: $$\mathbf{x} = \boldsymbol{\xi} + N\mathbf{z}$$ for unknown vectors **z**. You could then pass **z** as the optimization parameters to NLopt, rather than **x**, and thus eliminate the equality constraint. (Some care is required in [numerically computing the nullspace](https://en.wikipedia.org/wiki/Kernel_(matrix)#Numerical_computation_of_null_space) matrix *N*, because [rounding errors](https://en.wikipedia.org/wiki/Round-off_error) will tend to make the matrix *A* less singular than it should be. A standard technique is to compute the [SVD](https://en.wikipedia.org/wiki/Singular_value_decomposition) of *A* and set any singular values less than some threshold to zero.) #### Penalty functions Another popular approach to equality constraints (and inequality constraints, for that matter) is to include some sort of **penalty function** in the objective function, which penalizes **x** values that violate the constraints. A standard technique of this sort is known as the **augmented Lagrangian** approach, and a variant of this approach is implemented in NLopt's [AUGLAG algorithm](NLopt_Algorithms#Augmented_Lagrangian_algorithm.md). (For inequality constraints, a variant of the penalty idea is a **barrier method**: this is simply a penalty that diverges as you approach the constraint, which forces the optimization to stay within the feasible region.) Termination conditions ---------------------- For any optimization algorithm, one must supply some **termination conditions** specifying when the algorithm halts. Ideally, the algorithm should halt when the optimum is found to within some desired tolerance. In practice, however, because the true optimum is not known *a priori*, one uses some heuristic estimate for the error in the solution instead of the actual error. NLopt gives the user a choice of several different termination conditions. You do *not* need to specify *all* of these termination conditions for any given problem. You should just set the conditions you want; NLopt will terminate when the *first* one of the specified termination conditions is met (i.e. the *weakest* condition you specify is what matters). The termination conditions supported by NLopt are: ### Function value and parameter tolerances First, you can specify a fractional tolerance ftol_rel and an absolute tolerance ftol_abs on the function values. Ideally, these would be the maximum fractional and absolute error compared to the exact minimum function value, but this is impossible because the minimum is not known. Instead most algorithms implement these as a tolerance for the decrease Δf in the function value from one iteration to next (or something similar to that): the algorithm stops if |Δf|/|f| is less than ftol_rel, or |Δf| is less than ftol_abs. Similarly, you can specify a fractional tolerance xtol_rel and an absolute tolerance xtol_abs*i* on the parameters **x**. Again, it is practically impossible for these to be tolerances on the actual error Δ**x** compared to the (unknown) minimum point, so in practice Δ**x** is usually some measure of how much **x** changes by from one iteration to the next, or the diameter of a search region, or something like that. Then the algorithm stops when either |Δ*x**i*| < xtol_abs*i* or when |Δ*x**i*|/|*x**i*| < xtol_rel. However, there is some variation in how the different algorithms implement **x** tolerance tests; for example, some of them check instead whether |Δ**x**|/|**x**| < xtol_rel, where |•| is some norm. - Note: generally, you can only ask for about *half* as many decimal places in the xtol as in the ftol. The reason is that, near the minimum, $\Delta f \approx f'' (\Delta x)^2 / 2$ from the [Taylor expansion](https://en.wikipedia.org/wiki/Taylor_expansion), and so (assuming $f'' \approx 1$ for simplicity) a change in *x* by 10–7 gives a change in *f* by around 10–14. In particular, this means that it is generally hopeless to request an xtol_rel much smaller than the *square root* of [machine precision](https://en.wikipedia.org/wiki/Machine_epsilon). In most cases, the fractional tolerance (tol_rel) is the most useful one to specify, because it is independent of any absolute scale factors or units. Absolute tolerance (tol_abs) is mainly useful if you think that the minimum function value or parameters might occur at or close to zero. If you don't want to use a particular tolerance termination, you can just set that tolerance to zero and it will be ignored. ### Stopping function value Another termination test that NLopt supports is that you can tell the optimization to stop when the objective function value *f*(**x**) reaches some specified value, `stopval`, for any feasible point **x**. This termination test is especially useful when [comparing algorithms](NLopt_Algorithms#Comparing_algorithms.md) for a given problem. After running one algorithm for a long time to find the minimum to the desired accuracy, you can ask how many iterations algorithms require to obtain the optimum to the same accuracy or to some better accuracy. ### Bounds on function evaluations and wall-clock time Finally, one can also set a termination condition by specifying a maximum number of function evaluations (maxeval) or a maximum [wall-clock time](https://en.wikipedia.org/wiki/Wall_clock_time) (maxtime). That is, the simulation terminates when the number of function evaluations reaches maxeval, or when the total elapsed time exceeds some specified maxtime. These termination conditions are useful if you want to ensure that the algorithm gives you *some* answer in a reasonable amount of time, even if it is not absolutely optimal, and are also useful ways to control global optimization. Note that these are only rough maximums; a given algorithm may exceed the specified maximum time or number of function evaluations slightly. ### Termination tests for global optimization In general, deciding when to terminate a global optimization algorithm is a rather difficult problem, because there is no way to be certain (without special information about a particular *f*) that you have truly reached the global minimum, or even come close. You never know when there might be a much smaller value of the objective function lurking in some tiny corner of the feasible region. Because of this, the most reasonable termination criterion for global optimization problems seems to be setting bounds on the run time. That is, set an upper bound on how long you are willing to wait for an answer, and use that as the maximum run time. Another strategy is to start with a shorter run time, and repeatedly double the run time until the answer stops changing to your satisfaction. (Although there can be no guarantee that increasing the time further won't lead to a much better answer, there's not much you can do about it.) I would advise you *not* to use function-value (ftol) or parameter tolerances (xtol) in global optimization. I made a half-hearted attempt to implement these tests in the various global-optimization algorithms, but it doesn't seem like there is any really satisfactory way to go about this, and I can't claim that my choices were especially compelling. For the [MLSL](NLopt_Algorithms#MLSL_(Multi-Level_Single-Linkage).md) algorithm, you need to set the ftol and xtol [parameters of the local optimization algorithm](NLopt_Reference#Local/subsidiary_optimization_algorithm.md) control the tolerances of the *local* searches, *not* of the global search; you should definitely set these, lest the algorithm spend an excessive amount of time trying to run local searches to machine precision. Background and goals of NLopt ----------------------------- NLopt was started because some of the students in our group needed to use an optimization algorithm for a nonlinear problem, but it wasn't clear which algorithm would work best (or work at all). One student started by downloading one implementation from the Web, figuring out how to plug it into her Matlab program, getting it to work, only to find that it didn't converge very quickly so she needed another one, and so on... Then another student went through the same process, only his program was in C and he needed to get the algorithms to work with that language, and he obtained a different set of algorithms. It quickly became apparent that the duplication of effort was untenable, and the considerable labor required to decipher each new subroutine, figure out how to build it, figure out how to bridge the gap from one language (e.g. Fortran) to another (e.g. Matlab or C), and so on, was so substantial that it was hard to justify trying more than one or two. Even though the first two algorithms tried might converge poorly, or might be severely limited in the types of constraints they could handle, or have other limitations, effective experimentation was impractical. Instead, since I had some experience in wrapping C and Fortran routines and making them callable from C and Matlab and other languages, it made sense to put together a common wrapper interface for a few of the more promising of the free/open-source subroutines I could find online. Soon, it became clear that I wanted at least one decent algorithm in each major category (constrained/unconstrained, global/local, gradient-based/derivative-free, bound/nonlinear constraints), but there wasn't always free code available. Reading the literature turned up tantalizing hints of algorithms that were claimed to be very powerful, but again had no free code. And some algorithms had free code, but only in a language like Matlab that was impractical to use in stand-alone fashion from C. So, in addition to wrapping existing code, I began to write my own implementations of various algorithms that struck my interest or seemed to fill a need. Initially, my plan was to handle only bound constraints, and leave general nonlinear constraints to others—who needs such things? That attitude lasted until we found that we needed to solve a 10,000-dimensional minimax-type problem, which seemed intractable unless gradient-based algorithms could be brought to bear...as discussed above, this requires nonlinear constraints to make the problem differentiable. After some reading, I came across the MMA algorithm, which turned out to be easy to implement (300 lines of C), and worked beautifully (at least for my problem), so I expanded the NLopt interface to support nonlinear constraints. Overall, I've found that this has been surprisingly fun. Every once in a while, I come across a new algorithm to try, and now that I've implemented a few algorithms and built up a certain amount of infrastructure, it is relatively easy to add new ones (much more so than when I first started out). So, I expect that NLopt will continue to grow, albeit perhaps more slowly now that it seems to include decent algorithms for a wide variety of problems. nlopt-2.6.1/doc/docs/NLopt_License_and_Copyright.md000066400000000000000000000035731345435414600222640ustar00rootroot00000000000000--- # NLopt License and Copyright --- The NLopt library is under the [GNU Lesser General Public License](https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License) (LGPL), and the copyrights are owned by a variety of authors. In general, the different code in NLopt comes from different sources, and have a variety of licenses. For example, all of the *new* code we wrote for NLopt is under the [MIT License](https://en.wikipedia.org/wiki/MIT_License) (which imposes essentially no practical restrictions, and is hence compatible with the LGPL). The *combination* of all of this software is under the conjunction of the license terms, and in particular they are limited by the most restrictive of the licenses for the portions, which in this case is the LGPL. (The other portions of NLopt are under LGPL-compatible, less-restrictive licenses like the MIT license. So, if you remove the LGPL portions, which are currently code [by Ladislav Luksan](http://www.uivt.cas.cz/~luksan/subroutines.html), the remainder reverts to a looser license.) New code written for NLopt, including tutorial code at [NLopt Tutorial](NLopt_Tutorial.md), is Copyright © 2007-2019 Massachusetts Institute of Technology and other authors, and comes with **no warranty**: **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.** Please [cite NLopt](Citing_NLopt.md) and the authors of the respective algorithms in any publication for which you find it useful. (This is not a legal requirement, just a polite request.) nlopt-2.6.1/doc/docs/NLopt_Matlab_Reference.md000066400000000000000000000233441345435414600212040ustar00rootroot00000000000000--- # NLopt Matlab Reference --- The NLopt includes interfaces callable from the [Matlab](https://en.wikipedia.org/wiki/MATLAB) and [GNU Octave](https://en.wikipedia.org/wiki/GNU_Octave) (a free-software Matlab-like program), using identical syntax. The main purpose of this section is to document the syntax and unique features of the Matlab API; for more detail on the underlying features, please refer to the C documentation in the [NLopt Reference](NLopt_Reference.md). Using the NLopt Matlab API -------------------------- On Unix, the Matlab and Octave interfaces should automatically be installed in places where they will be found at runtime, assuming you have Matlab and Octave correctly installed on your machine, as documented in the [Installation manual](NLopt_Installation.md). On Windows, we provide a precompiled [.zip](https://en.wikipedia.org/wiki/.zip) file of the NLopt library, which includes a `matlab` directory. In this directory are a set of `.m` files (mostly implementing constants and documentation) and a `nlopt-optimize.c` file which can be compiled into a [w:MEX file](https://en.wikipedia.org/wiki/MEX_file) callable from Matlab. All of these files must be placed somewhere in your Matlab path or in your working directory if you want to use them. The `opt` structure ------------------- The NLopt API revolves around an [Matlab structure](http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/f2-88951.html), analogous to the `nlopt_opt` object in C and similar objects in NLopt's interfaces for other languages. All of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera) simply by assigning fields to this structure, and then one finally calls the `nlopt_optimize(opt)` function in order to perform the optimization. Every `opt` structure should specify the algorithm, via: `opt.algorithm = `*`algorithm`* given an *`algorithm`* (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values) and the dimensionality of the problem (`n`, the number of optimization parameters). Just as in C, algorithms are specified by predefined constants of the form `NLOPT_MMA`, `NLOPT_COBYLA`, etcetera. *You need not set all the fields* of the structure; any fields that are not specified take on innocuous default values (the same as if you did not specify those parameters in the C interface). The dimension *n* of the problem (the number of optimization parameters) is determined implicitly by the length of the vector you pass to `nlopt_optimize` as the initial guess. An error will occur if you use vectors of inconsistent lengths (e.g. you set `opt.lower_bounds` to be a different length). Objective function ------------------ The objective function is specified setting either the `opt.min_objective` or `opt.max_objective` field to a [function handle](http://www.mathworks.com/access/helpdesk/help/techdoc/ref/function_handle.html) for the objective function *f*, depending on whether one wishes to minimize or maximize `f`, respectively. The function `f` should be of the form: ``` function [val, gradient] = myfunc(x) ``` `   val = `*`...value` `of` `f(x)...`* ```    if (nargout > 1) ``` `       gradient = `*`...gradient` `at` `x...`* ```    end ``` The first return value should be the value of the function at the point `x`, where `x` row or column vector of the `n` of the *n* optimization parameters (the same length as the initial guess passed to `nlopt_optimize`). (Whether `x` is a row or column vector depends on whether the initial guess you pass to `nlopt_optimize` is a row or column vector, respectively.) In addition, if the caller requests two return values (`nargout` `>` `1`), then the second return value `gradient` should be a vector (row or column) of length `n` that is the gradient of the function with respect to the optimization parameters at `x`. That is, `grad(i)` should upon return contain the partial derivative $\partial f / \partial x_i$, for $1 < i \leq n$. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `nargout` will always be 1 and the gradient need never be computed. If your objective function returns [NaN](https://en.wikipedia.org/wiki/NaN) (`nan` in Matlab), that will force the optimization to terminate, equivalent to calling [nlopt_force_stop](NLopt_Reference#Forced_termination.md) in C. Bound constraints ----------------- The [bound constraints](NLopt_Reference#Bound_constraints.md) can be specified by setting `opt.lower_bounds` and/or `opt.upper_bounds` to vectors of length *n* (the same as the length of the initial guess passed to `nlopt_optimize`). To specify an unbounded dimension, you can use ±`inf` in Matlab to specify ±∞. Nonlinear constraints --------------------- Just as for [nonlinear constraints in C](NLopt_Reference#Nonlinear_constraints.md), you can specify nonlinear inequality and equality constraints by setting `opt.fc` and `opt.h` to be [cell arrays](http://blogs.mathworks.com/loren/2006/06/21/cell-arrays-and-their-contents/) of function handles (of the same form as the objective function above) for the inequality and equality constraints, respectively. Recall that a cell array is specified via `{...}` in Matlab, e.g. `{` `@constraint1,` `@constraint2` `}`. Optionally, you can specify a tolerance in judging feasibility for the purposes of stopping the optimization, as in C. Tolerances are specified as fields `opt.fc_tol` and `opt.h_tol`, which (if they are set) should be vectors (not cell arrays) of tolerances, of the same lengths as `opt.fc` and `opt.h`, respectively. (If they are not specified, the tolerances default to zero.) Stopping criteria ----------------- As explained in the [C API Reference](NLopt_Reference#Stopping_criteria.md) and the [Introduction](NLopt_Introduction#Termination_conditions.md)), you have multiple options for different stopping criteria that you can specify. (Unspecified stopping criteria are disabled; i.e., they have innocuous defaults.) The various stopping criteria can be specified via the following fields of your structure. ``` opt.stopval ``` Stop when an objective value of at least `stopval` is found. ``` opt.ftol_rel ``` Set relative tolerance on function value. ``` opt.ftol_abs ``` Set absolute tolerance on function value. ``` opt.xtol_rel ``` Set relative tolerance on optimization parameters. ``` opt.xtol_abs ``` Set absolute tolerances on optimization parameters. The `opt.xtol_abs` value must be a vector of length `n` (the same length as the initial guess passed to `nlopt_optimize`) of the tolerances. ``` opt.maxeval ``` Stop when the number of function evaluations exceeds `maxeval`. (0 or negative for no limit.) An integer. ``` opt.maxtime ``` Stop when the optimization time (in seconds) exceeds `maxtime`. (0 or negative for no limit.) Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given structure `opt`, you can perform the optimization by calling: ``` [xopt, fmin, retcode] = nlopt_optimize(opt, x); ``` On input, `x` is a vector (row or column) of length `n` (this specifies the dimension of the problem, and must be consistent with vectors you use elsewhere as mentioned above) giving an initial guess for the optimization parameters. The return value `xopt` is a vector (row or column, same as `x`) containing the optimized values of the optimization parameters. The second return value `fmin` is the optimized value of the objective function, and the third value is a return code (negative on failure and positive on success). Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by setting the `opt.local_optimizer` field to *another* optimization structure. For example, `opt.local_optimizer.algorithm` `=` `NLOPT_LN_BOBYQA;` `opt.local_optimizer.ftol_rel` `=` `1e-4` will set the local optimizer to use BOBYQA and a relative function tolerance of `1e-4`. The fields of `opt.local_optimizer` are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `opt.local_optimizer` are ignored.) Initial step size ----------------- Just as in the C API, you can [get and set the initial step sizes](NLopt_Reference#Initial_step_size.md) for derivative-free optimization algorithms. In Matlab, you set the `opt.initial_step` field to a vector of the (nonzero) initial steps for each dimension. Stochastic population --------------------- Just as in the C API, you can [get and set the initial population](NLopt_Reference#Stochastic_population.md) for stochastic optimization algorithms, by setting `opt.population` to an (integer) initial population. (An `opt.population` of zero implies that the heuristic default will be used.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Just as in the C API, you can set the [number *M* of stored vectors for limited-memory quasi-Newton algorithms](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md), via: ``` opt.vector_storage ``` (The default is 0, in which case NLopt uses a heuristic nonzero value.) Verbose output -------------- If you set `opt.verbose` to `1`, the Matlab interface will output information as the optimization progresses, such as the objective function values. Of course, your objective function and constraints can also output anything you wish, using `disp` and similar Matlab functions. nlopt-2.6.1/doc/docs/NLopt_Python_Reference.md000066400000000000000000000414171345435414600212660ustar00rootroot00000000000000--- # NLopt Python Reference --- The NLopt includes an interface callable from the [Python programming language](https://en.wikipedia.org/wiki/Python_(programming_language)). The main purpose of this section is to document the syntax and unique features of the Python API; for more detail on the underlying features, please refer to the C documentation in the [NLopt Reference](NLopt_Reference.md). Using the NLopt Python API -------------------------- To use NLopt in Python, your Python program should include the lines: ``` import nlopt from numpy import * ``` which imports the `nlopt` module, and also imports the numpy ([NumPy](https://en.wikipedia.org/wiki/NumPy)) that defines the array data types used for communicating with NLopt. The `nlopt.opt` class --------------------- The NLopt API revolves around an object of type `nlopt.opt`. Via methods of this object, all of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera), and then one finally calls the `opt.optimize` method in order to perform the optimization. The object should normally be created via the constructor: ``` opt = nlopt.opt(algorithm, n) ``` given an `algorithm` (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values) and the dimensionality of the problem (`n`, the number of optimization parameters). Whereas the C algorithms are specified by `nlopt_algorithm` constants of the form `NLOPT_LD_MMA`, `NLOPT_LN_COBYLA`, etcetera, the Python `algorithm` values are of the form `nlopt.LD_MMA`, `nlopt.LN_COBYLA`, etcetera (with the `NLOPT_` prefix replaced by the `nlopt.` namespace). There are also a copy constructor `nlopt.opt(opt)` to make a copy of a given object (equivalent to `nlopt_copy` in the C API). If there is an error in the constructor (or copy constructor, or assignment), a `MemoryError` exception is thrown. The algorithm and dimension parameters of the object are immutable (cannot be changed without constructing a new object), but you can query them for a given object by the methods: ``` opt.get_algorithm() opt.get_dimension() ``` You can get a string description of the algorithm via: ``` opt.get_algorithm_name() ``` Objective function ------------------ The objective function is specified by calling one of the methods: ``` opt.set_min_objective(f) opt.set_max_objective(f) ``` depending on whether one wishes to minimize or maximize the objective function `f`, respectively. The function `f` should be of the form: ``` def f(x, grad):    if grad.size > 0: ``` `       `*`...set` `grad` `to` `gradient,` `in-place...`* `   return `*`...value` `of` `f(x)...`* The return value should be the value of the function at the point `x`, where `x` is a NumPy array of length `n` of the optimization parameters (the same as the dimension passed to the constructor). In addition, if the argument `grad` is not empty, i.e. `grad.size>0`, then `grad` is a NumPy array of length `n` which should (upon return) be set to the gradient of the function with respect to the optimization parameters at `x`. That is, `grad[i]` should upon return contain the partial derivative $\partial f / \partial x_i$, for $0 \leq i < n$, if `grad` is non-empty. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be empty and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be empty for some calls.) Note that `grad` must be modified *in-place* by your function `f`. Generally, this means using indexing operations `grad[...]` `=` `...` to overwrite the contents of `grad`, as described below. ### Assigning results in-place Your objective and constraint functions must overwrite the contents of the `grad` (gradient) argument in-place (although of course you can allocate whatever additional storage you might need, in addition to overwriting `grad`). However, typical Python assignment operations do *not* do this. For example: ``` grad = 2*x ``` might seem like the gradient of the function `sum(x**2)`, but it will *not work* with NLopt because this expression actually allocates a *new* array to store `2*x` and re-assigns `grad` to point to it, rather than overwriting the old contents of `grad`. Instead, you should do: ``` grad[:] = 2*x ``` Assigning any [slice or view](http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html) `grad[...]` of the array will overwrite the contents, which is what NLopt needs you to do. So, you should generally use indexing expressions `grad[...]` `=` `...` to assign the gradient result. In specific cases, there are a few other NumPy and SciPy functions that are documented to operate in-place on their arguments, and you can also use such functions to modify `grad` if you want. If a function is not *explicitly documented to modify its arguments in-place*, however, you should assume that it does *not*. Bound constraints ----------------- The [bound constraints](NLopt_Reference#Bound_constraints.md) can be specified by calling the methods: ``` opt.set_lower_bounds(lb) opt.set_upper_bounds(ub) ``` where `lb` and `ub` are arrays (NumPy arrays or Python lists) of length *n* (the same as the dimension passed to the `nlopt.opt` constructor). For convenience, these are overloaded with functions that take a single number as arguments, in order to set the lower/upper bounds for all optimization parameters to a single constant. To retrieve the values of the lower/upper bounds, you can call one of: ``` opt.get_lower_bounds() opt.get_upper_bounds() ``` both of which return NumPy arrays. To specify an unbounded dimension, you can use ±`float('inf')` (or ±`numpy.inf`) in Python to specify ±∞. Nonlinear constraints --------------------- Just as for [nonlinear constraints in C](NLopt_Reference#Nonlinear_constraints.md), you can specify nonlinear inequality and equality constraints by the methods: ``` opt.add_inequality_constraint(fc, tol=0) opt.add_equality_constraint(h, tol=0) ``` where the arguments `fc` and `h` have the same form as the objective function above. The optional `tol` arguments specify a tolerance in judging feasibility for the purposes of stopping the optimization, as in C. To remove all of the inequality and/or equality constraints from a given problem, you can call the following methods: ``` opt.remove_inequality_constraints() opt.remove_equality_constraints() ``` ### Vector-valued constraints Just as for [nonlinear constraints in C](NLopt_Reference#Vector-valued_constraints.md), you can specify vector-valued nonlinear inequality and equality constraints by the methods ``` opt.add_inequality_mconstraint(c, tol) opt.add_inequality_mconstraint(c, tol) ``` Here, `tol` is an array (NumPy array or Python list) of the tolerances in each constraint dimension; the dimensionality *m* of the constraint is determined by `tol.size`. The constraint function `c` must be of the form: ``` def c(result, x, grad):    if grad.size > 0: ``` `       `*`...set` `grad` `to` `gradient,` `in-place...`* `   result[0] = `*`...value` `of` `c``0``(x)...`* `   result[1] = `*`...value` `of` `c``1``(x)...`* ```    ... ``` `result` is a NumPy array whose length equals the dimensionality *m* of the constraint (same as the length of `tol` above), which upon return should be set *in-place* ([see above](#Assigning_results_in-place.md)) to the constraint results at the point `x` (a NumPy array whose length *n* is the same as the dimension passed to the constructor). Any return value of the function is ignored. In addition, if the argument `grad` is not empty, i.e. `grad.size>0`, then `grad` is a 2d NumPy array of size *m*×*n* which should (upon return) be set in-place ([see above](#Assigning_results_in-place.md)) to the gradient of the function with respect to the optimization parameters at `x`. That is, `grad[i,j]` should upon return contain the partial derivative $\partial c_i / \partial x_j$ if `grad` is non-empty. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be empty and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be empty for some calls.) An inequality constraint corresponds to $c_i \le 0$ for $0 \le i < m$, and an equality constraint corresponds to $c_i = 0$, in both cases with tolerance `tol[i]` for purposes of termination criteria. (You can add multiple vector-valued constraints and/or scalar constraints in the same problem.) Stopping criteria ----------------- As explained in the [C API Reference](NLopt_Reference#Stopping_criteria.md) and the [Introduction](NLopt_Introduction#Termination_conditions.md)), you have multiple options for different stopping criteria that you can specify. (Unspecified stopping criteria are disabled; i.e., they have innocuous defaults.) For each stopping criteria, there are (at least) two methods: a `set` method to specify the stopping criterion, and a `get` method to retrieve the current value for that criterion. The meanings of each criterion are exactly the same as in the C API. ``` opt.set_stopval(stopval) opt.get_stopval() ``` Stop when an objective value of at least `stopval` is found. ``` opt.set_ftol_rel(tol) opt.get_ftol_rel() ``` Set relative tolerance on function value. ``` opt.set_ftol_abs(tol) opt.get_ftol_abs() ``` Set absolute tolerance on function value. ``` opt.set_xtol_rel(tol) opt.get_xtol_rel() ``` Set relative tolerance on optimization parameters. ``` opt.set_xtol_abs(tol) opt.get_xtol_abs() ``` Set absolute tolerances on optimization parameters. The `tol` input must be an array (NumPy array or Python list) of length `n` (the dimension specified in the `nlopt.opt` constructor); alternatively, you can pass a single number in order to set the same tolerance for all optimization parameters. `get_xtol_abs()` returns the tolerances as a NumPy array. ``` opt.set_maxeval(maxeval) opt.get_maxeval() ``` Stop when the number of function evaluations exceeds `maxeval`. (0 or negative for no limit.) ``` opt.set_maxtime(maxtime) opt.get_maxtime() ``` Stop when the optimization time (in seconds) exceeds `maxtime`. (0 or negative for no limit.) ``` opt.get_numevals() ``` Request the number of evaluations. ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. You can do this by raise *any* exception inside your objective/constraint functions:the optimization will be halted gracefully, and the same exception will be raised to the caller. See [Exceptions](#Exceptions.md), below. The Python equivalent of `nlopt_forced_stop` from the [C API](NLopt_Reference#Forced_termination.md) is to throw an `nlopt.ForcedStop` exception. Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given object `opt`, you can perform the optimization by calling: ``` xopt = opt.optimize(x) ``` On input, `x` is an array (NumPy array or Python list) of length `n` (the dimension of the problem from the `nlopt.opt` constructor) giving an initial guess for the optimization parameters. The return value `xopt` is a NumPy array containing the optimized values of the optimization parameters. You can call the following methods to retrieve the optimized objective function value from the last `optimize` call, and also the return code (including negative/failure return values) from the last `optimize` call: ``` opt_val = opt.last_optimum_value() result = opt.last_optimize_result() ``` The return code (see below) is positive on success, indicating the reason for termination. On failure (negative return codes), `optimize()` throws an exception (see [Exceptions](#Exceptions.md), below). ### Return values The possible return values are the same as the [return values in the C API](NLopt_Reference#Return_values.md), except that the `NLOPT_` prefix is replaced with the `nlopt.` namespace. That is, `NLOPT_SUCCESS` becomes `nlopt.SUCCESS`, etcetera. Exceptions ---------- The [Error codes (negative return values)](NLopt_Reference#Error_codes_(negative_return_values).md) in the C API are replaced in the Python API by thrown exceptions. The following exceptions are thrown by the various routines: ``` RunTimeError ``` Generic failure, equivalent to `NLOPT_FAILURE`. ``` ValueError ``` Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera), equivalent to `NLOPT_INVALID_ARGS`. ``` MemoryError ``` Ran out of memory (a memory allocation failed), equivalent to `NLOPT_OUT_OF_MEMORY`. `nlopt.RoundoffLimited` (subclass of `Exception`) Halted because roundoff errors limited progress, equivalent to `NLOPT_ROUNDOFF_LIMITED`. `nlopt.ForcedStop` (subclass of `Exception`) Halted because of a [forced termination](#Forced_termination.md): the user called `opt.force_stop()` from the user’s objective function or threw an `nlopt.ForcedStop` exception. Equivalent to `NLOPT_FORCED_STOP`. If your objective/constraint functions throw *any* exception during the execution of `opt.optimize`, it will be caught by NLopt and the optimization will be halted gracefully, and `opt.optimize` will re-throw the *same* exception to its caller. Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: ``` opt.set_local_optimizer(local_opt) ``` Here, `local_opt` is another `nlopt.opt` object whose parameters are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `local_opt` are ignored.) The dimension `n` of `local_opt` must match that of `opt`. This function makes a copy of the `local_opt` object, so you can freely change your original `local_opt` afterwards without affecting `opt`. Initial step size ----------------- Just as in the C API, you can [get and set the initial step sizes](NLopt_Reference#Initial_step_size.md) for derivative-free optimization algorithms. The Python equivalents of the C functions are the following methods: ``` opt.set_initial_step(dx) opt.get_initial_step(x) ``` Here, `dx` is an array (NumPy array or Python list) of the (nonzero) initial steps for each dimension, or a single number if you wish to use the same initial steps for all dimensions. `opt.get_initial_step(x)` returns the initial step that will be used for a starting guess of `x` in `opt.optimize(x)`. Stochastic population --------------------- Just as in the C API, you can [get and set the initial population](NLopt_Reference#Stochastic_population.md) for stochastic optimization algorithms, by the methods: ``` opt.set_population(pop) opt.get_population() ``` (A `pop` of zero implies that the heuristic default will be used.) Pseudorandom numbers -------------------- For stochastic optimization algorithms, we use pseudorandom numbers generated by the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm, based on code from Makoto Matsumoto. By default, the [seed](https://en.wikipedia.org/wiki/Random_seed) for the random numbers is generated from the system time, so that you will get a different sequence of pseudorandom numbers each time you run your program. If you want to use a "deterministic" sequence of pseudorandom numbers, i.e. the same sequence from run to run, you can set the seed by calling: ``` nlopt.srand(seed) ``` where `seed` is an integer. To reset the seed based on the system time, you can call: ``` nlopt.srand_time() ``` (Normally, you don't need to call this as it is called automatically. However, it might be useful if you want to "re-randomize" the pseudorandom numbers after calling `nlopt.srand` to set a deterministic seed.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Just as in the C API, you can get and set the [number *M* of stored vectors](NLopt_Reference#Vector_storage_for_limited-memory_quasi-Newton_algorithms.md) for limited-memory quasi-Newton algorithms, via the methods: ``` opt.set_vector_storage(M) opt.get_vector_storage() ``` (The default is *M*=0, in which case NLopt uses a heuristic nonzero value.) Version number -------------- To determine the version number of NLopt at runtime, you can call: ``` nlopt.version_major() nlopt.version_minor() nlopt.version_bugfix() ``` For example, NLopt version 3.1.4 would return `major=3`, `minor=1`, and `bugfix=4`. nlopt-2.6.1/doc/docs/NLopt_R_Reference.md000066400000000000000000000006511345435414600202010ustar00rootroot00000000000000--- # NLopt R Reference --- An NLopt interface for [GNU R](https://en.wikipedia.org/wiki/GNU_R) was developed by [Jelmer Ypma](http://www.ucl.ac.uk/~uctpjyy) at [University College London](https://en.wikipedia.org/wiki/University_College_London) (UCL), and is currently available as a separate download (with documentation) from: - [](http://www.ucl.ac.uk/~uctpjyy/nloptr.html) nlopt-2.6.1/doc/docs/NLopt_Reference.md000066400000000000000000000700701345435414600177220ustar00rootroot00000000000000--- # NLopt Reference --- NLopt is a library, not a stand-alone program—it is designed to be called from your own program in C, C++, Fortran, Matlab, GNU Octave, or other languages. This reference section describes the programming interface (API) of NLopt in the C language. The reference manuals for other languages can be found at: - [NLopt C++ Reference](NLopt_C-plus-plus_Reference.md) - [NLopt Fortran Reference](NLopt_Fortran_Reference.md) - [NLopt Matlab Reference](NLopt_Matlab_Reference.md) - [NLopt Python Reference](NLopt_Python_Reference.md) - [NLopt Guile Reference](NLopt_Guile_Reference.md) - [NLopt Julia Reference](https://github.com/stevengj/NLopt.jl) The old API from versions of NLopt prior to 2.0 is deprecated, but continues to be supported for backwards compatibility. You can find it described in the [NLopt Deprecated API Reference](NLopt_Deprecated_API_Reference.md). Other sources of information include the Unix [man page](https://en.wikipedia.org/wiki/Manual_page_(Unix)): On Unix, you can run e.g. `man` `nlopt` for documentation of C API. In Matlab and GNU Octave, the corresponding command is to type `help` `nlopt_optimize`. Compiling and linking your program to NLopt ------------------------------------------- An NLopt program in C should include the NLopt header file: `#include ` For programs in compiled languages like C or Fortran, when you compile your program you will have to link it to the NLopt library. This is *in addition* to including the header file (`#include` in C or `#include` in C++). On Unix, you would normally link with a command something like: *`compiler`*` `*`...source/object` `files...`*` -lnlopt -lm -o myprogram` where *compiler* is `cc`, `f77`, `g++`, or whatever is appropriate for your machine/language. *Note:* the `-lnlopt` `-lm` options, which link to the NLopt library (and the math library, which it requires), must come *after* your source/object files. In general, the rule is that if *A* depends upon *B*, then *A* must come before *B* in the link command. *Note:* the above example assumes that you have installed the NLopt library in a place where the compiler knows to find it (e.g. in a standard directory like `/usr/lib` or `/usr/local/lib`). If you installed somewhere else (e.g. in your home directory if you are not a system administrator), then you will need to use a `-L` flag to tell the compiler where to find the library. See [the installation manual](NLopt_Installation#Changing_the_installation_directory.md). The `nlopt_opt` object ---------------------- The NLopt API revolves around an "object" of type `nlopt_opt` (an opaque pointer type). Via this object, all of the parameters of the optimization are specified (dimensions, algorithm, stopping criteria, constraints, objective function, etcetera), and then one finally passes this object to `nlopt_optimize` in order to perform the optimization. The object is created by calling: ``` nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n); ``` which returns a newly allocated `nlopt_opt` object (or NULL if there was an error, e.g. out of memory), given an `algorithm` (see [NLopt Algorithms](NLopt_Algorithms.md) for possible values) and the dimensionality of the problem (`n`, the number of optimization parameters). When you are finished with the object, you must deallocate it by calling: ``` void nlopt_destroy(nlopt_opt opt); ``` Simple assignment (`=`) makes two pointers to the same object. To make an independent copy of an object, use: ``` nlopt_opt nlopt_copy(const nlopt_opt opt); ``` The algorithm and dimension parameters of the object are immutable (cannot be changed without creating a new object), but you can query them for a given object by calling: ``` nlopt_algorithm nlopt_get_algorithm(const nlopt_opt opt); unsigned nlopt_get_dimension(const nlopt_opt opt); ``` You can get a descriptive (null-terminated) string corresponding to a particular algorithm by calling: ``` const char *nlopt_algorithm_name(nlopt_algorithm algorithm); ``` Objective function ------------------ The objective function is specified by calling one of: ``` nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void* f_data); nlopt_result nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void* f_data); ``` depending on whether one wishes to minimize or maximize the objective function `f`, respectively. The function `f` should be of the form: ```  double f(unsigned n, const double* x, double* grad, void* f_data); ``` The return value should be the value of the function at the point `x`, where `x` points to an array of length `n` of the optimization parameters. The dimension `n` is identical to the one passed to `nlopt_create`. In addition, if the argument `grad` is not `NULL`, then `grad` points to an array of length `n` which should (upon return) be set to the gradient of the function with respect to the optimization parameters at `x`. That is, `grad[i]` should upon return contain the partial derivative $\partial f / \partial x_i$, for $0 \leq i < n$, if `grad` is non-`NULL`. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the `grad` argument will always be `NULL` and need never be computed. (For algorithms that do use gradient information, however, `grad` may still be `NULL` for some calls.) The `f_data` argument is the same as the one passed to `nlopt_set_min_objective` or `nlopt_set_max_objective`, and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from `void*` by a typecast.) Bound constraints ----------------- Most of the algorithms in NLopt are designed for minimization of functions with simple bound constraints on the inputs. That is, the input vectors `x[i]` are constrainted to lie in a hyperrectangle `lb[i]` ≤ `x[i]` ≤ `ub[i]` for 0 ≤ `i` < `n`. NLopt guarantees that your objective function and any nonlinear constraints will *never* be evaluated outside of these bounds (unlike nonlinear constraints, which may be violated at intermediate steps). These bounds are specified by passing arrays `lb` and `ub` of length `n` (the dimension of the problem, from `nlopt_create`) to one or both of the functions: ``` nlopt_result nlopt_set_lower_bounds(nlopt_opt opt, const double* lb); nlopt_result nlopt_set_upper_bounds(nlopt_opt opt, const double* ub); ``` (Note that these functions make a copy of the `lb` and `ub` arrays, so subsequent changes to the caller's `lb` and `ub` arrays have no effect on the `opt` object.) If a lower/upper bound is not set, the default is no bound (unconstrained, i.e. a bound of infinity); it is possible to have lower bounds but not upper bounds or vice versa. Alternatively, the user can call one of the above functions and explicitly pass a lower bound of `-HUGE_VAL` and/or an upper bound of `+HUGE_VAL` for some optimization parameters to make them have no lower/upper bound, respectively. (`HUGE_VAL` is the standard C constant for a floating-point infinity, found in the `math.h` header file.) It is permitted to set `lb[i]` `==` `ub[i]` in one or more dimensions; this is equivalent to fixing the corresponding `x[i]` parameter, eliminating it from the optimization. Note, however, that some of the algorithms in NLopt, in particular most of the global-optimization algorithms, do not support unconstrained optimization and will return an error in `nlopt_optimize` if you do not supply finite lower and upper bounds. For convenience, the functions `nlopt_set_*_bounds1` are supplied in order to set the lower/upper bounds for all optimization parameters to a single constant (so that you don’t have to fill an array with a constant value), along with `nlopt_set_*_bound` to set the bound for a single variable `x[i]`: ``` nlopt_result nlopt_set_lower_bounds1(nlopt_opt opt, double lb); nlopt_result nlopt_set_upper_bounds1(nlopt_opt opt, double ub); nlopt_result nlopt_set_lower_bound(nlopt_opt opt, int i, double lb); nlopt_result nlopt_set_upper_bound(nlopt_opt opt, int i, double ub); ``` The values of the lower and upper bounds can be retrieved by calling: ``` nlopt_result nlopt_get_lower_bounds(const nlopt_opt opt, double* lb); nlopt_result nlopt_get_upper_bounds(const nlopt_opt opt, double* ub); ``` where `lb` and `ub` are arrays of length `n` that, upon successful return, are set to copies of the lower and upper bounds, respectively. Nonlinear constraints --------------------- Several of the algorithms in NLopt (`MMA`, `COBYLA`, and `ORIG_DIRECT`) also support arbitrary nonlinear inequality constraints, and some additionally allow nonlinear equality constraints (`ISRES` and `AUGLAG`). For these algorithms, you can specify as many nonlinear constraints as you wish by calling the following functions multiple times. In particular, a nonlinear inequality constraint of the form `fc`(*x*) ≤ 0, where the function `fc` is of the same form as the objective function described above, can be specified by calling: ``` nlopt_result nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void* fc_data, double tol); ``` Just as for the objective function, `fc_data` is a pointer to arbitrary user data that will be passed through to the fc function whenever it is called. The parameter `tol` is a tolerance that is used for the purpose of stopping criteria *only*: a point *x* is considered feasible for judging whether to stop the optimization if `fc`(*x*) ≤ `tol`. A tolerance of zero means that NLopt will try not to consider any x to be converged unless `fc` is strictly non-positive; generally, at least a small positive tolerance is advisable to reduce sensitivity to rounding errors. (The [return value](#Return_Values.md) is negative if there was an error, e.g. an invalid argument or an out-of-memory situation.) Similarly, a nonlinear equality constraint of the form `h`(*x*) = 0, where the function `h` is of the same form as the objective function described above, can be specified by calling: ``` nlopt_result nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func h, void* h_data, double tol); ``` Just as for the objective function, `h_data` is a pointer to arbitrary user data that will be passed through to the `h` function whenever it is called. The parameter tol is a tolerance that is used for the purpose of stopping criteria *only*: a point *x* is considered feasible for judging whether to stop the optimization if |`h`(*x*)| ≤ `tol`. For equality constraints, a small positive tolerance is strongly advised in order to allow NLopt to converge even if the equality constraint is slightly nonzero. (For any algorithm listed as "derivative-free" below, the `grad` argument to `fc` or `h` will always be `NULL` and need never be computed.) To remove all of the inequality and/or equality constraints from a given problem `opt`, you can call the following functions: ``` nlopt_result nlopt_remove_inequality_constraints(nlopt_opt opt); nlopt_result nlopt_remove_equality_constraints(nlopt_opt opt); ``` ### Vector-valued constraints In some applications with multiple constraints, it is more convenient to define a single function that returns the values (and gradients) of all constraints at once. For example, different constraint functions might share computations in some way. Or, if you have a large number of constraints, you may wish to compute them in parallel. This possibility is supported by the following function, which defines multiple constraints at once, or equivalently a vector-valued constraint function $\mathbf{c}: \mathbb{R}^n \to \mathbb{R}^m$: ``` nlopt_result nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m,                                               nlopt_mfunc c, void* c_data, const double *tol); nlopt_result nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m,                                             nlopt_mfunc c, void* c_data, const double *tol); ``` Here, `m` is the dimensionality of the constraint result and `tol` points to an array of length `m` of the tolerances in each constraint dimension (or `NULL` for zero tolerances). The constraint function must be of the form: ```  void c(unsigned m, double *result, unsigned n, const double* x, double* grad, void* f_data); ``` This evaluates the constraint function(s) $\mathbf{c}(\mathbf{x})$ at the point `x`, an array of length `n` (the same as the dimension passed to `nlopt_create`). Upon return, the output value of the constraints should be stored in `result`, an array of length `m` (the same as the dimension passed to `nlopt_add_*_mconstraint`), so that `result[i]` stores *c**i*. In addition, if `grad` is non-`NULL`, then `grad` points to an array of length `m*n` which should, upon return, be set to the gradients of the constraint functions with respect to `x`. The `n` dimension of `grad` is stored contiguously, so that $\part c_i / \part x_j$ is stored in `grad[i*n` `+` `j]`. An inequality constraint corresponds to $c_i \le 0$ for $0 \le i < m$, and an equality constraint corresponds to $c_i = 0$, in both cases with tolerance `tol[i]` for purposes of termination criteria. (You can add multiple vector-valued constraints and/or scalar constraints in the same problem.) Stopping criteria ----------------- Multiple stopping criteria for the optimization are supported (see also the [Introduction](NLopt_Introduction#Termination_conditions.md)), as specified by the functions to modify a given optimization problem `opt`. The optimization halts whenever any one of these criteria is satisfied. In some cases, the precise interpretation of the stopping criterion depends on the optimization algorithm above (although we have tried to make them as consistent as reasonably possible), and some algorithms do not support all of the stopping criteria. **Note:** you do not need to use *all* of the stopping criteria! In most cases, you only need one or two, and can omit the remainder (all criteria are disabled by default). For each stopping criteria, there are (at least) two functions: a `set` function to specify the stopping criterion, and a `get` function to retrieve the current value for that criterion. ``` nlopt_result nlopt_set_stopval(nlopt_opt opt, double stopval); double nlopt_get_stopval(const nlopt_opt opt); ``` Stop when an objective value of at least stopval is found: stop minimizing when an objective value ≤ `stopval` is found, or stop maximizing a value ≥ `stopval` is found. (Setting `stopval` to `-HUGE_VAL` for minimizing or `+HUGE_VAL` for maximizing disables this stopping criterion.) ``` nlopt_result nlopt_set_ftol_rel(nlopt_opt opt, double tol); double nlopt_get_ftol_rel(const nlopt_opt opt); ``` Set relative tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the objective function value by less than `tol` multiplied by the absolute value of the function value. (If there is any chance that your optimum function value is close to zero, you might want to set an absolute tolerance with `nlopt_set_ftol_abs` as well.) Criterion is disabled if `tol` is non-positive. ``` nlopt_result nlopt_set_ftol_abs(nlopt_opt opt, double tol); double nlopt_get_ftol_abs(const nlopt_opt opt); ``` Set absolute tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the function value by less than `tol`. Criterion is disabled if `tol` is non-positive. ``` nlopt_result nlopt_set_xtol_rel(nlopt_opt opt, double tol); double nlopt_get_xtol_rel(const nlopt_opt opt); ``` Set relative tolerance on optimization parameters: stop when an optimization step (or an estimate of the optimum) changes every parameter by less than `tol` multiplied by the absolute value of the parameter. (If there is any chance that an optimal parameter is close to zero, you might want to set an absolute tolerance with `nlopt_set_xtol_abs` as well.) Criterion is disabled if `tol` is non-positive. ``` nlopt_result nlopt_set_xtol_abs(nlopt_opt opt, const double* tol); nlopt_result nlopt_get_xtol_abs(const nlopt_opt opt, double *tol); ``` Set absolute tolerances on optimization parameters. `tol` is a pointer to an array of length `n` (the dimension from `nlopt_create`) giving the tolerances: stop when an optimization step (or an estimate of the optimum) changes every parameter `x[i]` by less than `tol[i]`. (Note that this function makes a copy of the `tol` array, so subsequent changes to the caller's `tol` have no effect on `opt`.) In `nlopt_get_xtol_abs`, `tol` must be an array of length `n`, which upon successful return contains a copy of the current tolerances. For convenience, the following function may be used to set the absolute tolerances in all `n` optimization parameters to the same value: ``` nlopt_result nlopt_set_xtol_abs1(nlopt_opt opt, double tol); ``` Criterion is disabled if `tol` is non-positive. ``` nlopt_result nlopt_set_maxeval(nlopt_opt opt, int maxeval); int nlopt_get_maxeval(nlopt_opt opt); ``` Stop when the number of function evaluations exceeds `maxeval`. (This is not a strict maximum: the number of function evaluations may exceed maxeval slightly, depending upon the algorithm.) Criterion is disabled if `maxeval` is non-positive. ``` nlopt_result nlopt_set_maxtime(nlopt_opt opt, double maxtime); double nlopt_get_maxtime(nlopt_opt opt); ``` Stop when the optimization time (in seconds) exceeds `maxtime`. (This is not a strict maximum: the time may exceed maxtime slightly, depending upon the algorithm and on how slow your function evaluation is.) Criterion is disabled if `maxtime` is non-positive. ``` int nlopt_get_numevals(nlopt_opt opt); ``` Request the number of evaluations. ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. (This is used to implement exception handling in the NLopt wrappers for C++ and other languages.) In this case, it is possible to tell NLopt to halt the optimization gracefully, returning the best point found so far, by calling the following function from *within* your objective or constraint functions: ``` nlopt_result nlopt_force_stop(nlopt_opt opt); ``` This causes `nlopt_optimize` to halt, returning the `NLOPT_FORCED_STOP` error code (below). It has no effect if not called during `nlopt_optimize`. If you want to provide a bit more information, you can call ``` nlopt_result nlopt_set_force_stop(nlopt_opt opt, int val) ``` to set a forced-stop integer value `val`, which can be later retrieved by calling: ``` int nlopt_get_force_stop(nlopt_opt opt) ``` which returns the last force-stop value that was set since the last `nlopt_optimize`. The force-stop value is reset to zero at the beginning of `nlopt_optimize`. Passing `val=0` to `nlopt_set_force_stop` tells NLopt *not* to force a halt. Performing the optimization --------------------------- Once all of the desired optimization parameters have been specified in a given object `opt`, you can perform the optimization by calling: ``` nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *opt_f); ``` On input, `x` is an array of length `n` (the dimension of the problem from `nlopt_create`) giving an initial guess for the optimization parameters. On successful return, `x` contains the optimized values of the parameters, and `opt_f` contains the corresponding value of the objective function. The return value (see below) is positive on success and negative on failure. Return values ------------- Most of the NLopt functions return an enumerated constant of type `nlopt_result`, which takes on one of the following values: ### Successful termination (positive return values) ``` NLOPT_SUCCESS` `=` `1 ``` Generic success return value. ``` NLOPT_STOPVAL_REACHED` `=` `2 ``` Optimization stopped because `stopval` (above) was reached. ``` NLOPT_FTOL_REACHED` `=` `3 ``` Optimization stopped because `ftol_rel` or `ftol_abs` (above) was reached. ``` NLOPT_XTOL_REACHED` `=` `4 ``` Optimization stopped because `xtol_rel` or `xtol_abs` (above) was reached. ``` NLOPT_MAXEVAL_REACHED` `=` `5 ``` Optimization stopped because `maxeval` (above) was reached. ``` NLOPT_MAXTIME_REACHED` `=` `6 ``` Optimization stopped because `maxtime` (above) was reached. ### Error codes (negative return values) ``` NLOPT_FAILURE` `=` `-1 ``` Generic failure code. ``` NLOPT_INVALID_ARGS` `=` `-2 ``` Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera). ``` NLOPT_OUT_OF_MEMORY` `=` `-3 ``` Ran out of memory. ``` NLOPT_ROUNDOFF_LIMITED` `=` `-4 ``` Halted because roundoff errors limited progress. (In this case, the optimization still typically returns a useful result.) ``` NLOPT_FORCED_STOP` `=` `-5 ``` Halted because of a [forced termination](#Forced_termination.md): the user called `nlopt_force_stop(opt)` on the optimization’s `nlopt_opt` object `opt` from the user’s objective function or constraints. Local/subsidiary optimization algorithm --------------------------------------- Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: ``` nlopt_result nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt); ``` Here, `local_opt` is another `nlopt_opt` object whose parameters are used to determine the local search algorithm, its stopping criteria, and other algorithm parameters. (However, the objective function, bounds, and nonlinear-constraint parameters of `local_opt` are ignored.) The dimension `n` of `local_opt` must match that of `opt`. This function makes a copy of the `local_opt` object, so you can freely destroy your original `local_opt` afterwards. Initial step size ----------------- For derivative-free local-optimization algorithms, the optimizer must somehow decide on some initial step size to perturb *x* by when it begins the optimization. This step size should be big enough that the value of the objective changes significantly, but not too big if you want to find the local optimum nearest to *x*. By default, NLopt chooses this initial step size heuristically from the bounds, tolerances, and other information, but this may not always be the best choice. You can modify the initial step size by calling: ``` nlopt_result nlopt_set_initial_step(nlopt_opt opt, const double* dx); ``` Here, `dx` is an array of length `n` (the dimension of the problem from `nlopt_create`) containing the (nonzero) initial step size for each component of the optimization parameters `x`. If you pass `NULL` for `dx`, then NLopt will use its heuristics to determine the initial step size. For convenience, if you want to set the step sizes in every direction to be the same value, you can instead call: ``` nlopt_result nlopt_set_initial_step1(nlopt_opt opt, double dx); ``` You can get the initial step size by calling: ``` nlopt_result nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx); ``` Here, `x` is the same as the initial guess that you plan to pass to `nlopt_optimize` – if you have not set the initial step and NLopt is using its heuristics, its heuristic step size may depend on the initial *x*, which is why you must pass it here. Both `x` and `dx` are arrays of length `n` (the dimension of the problem from `nlopt_create`), where `dx` on successful return contains the initial step sizes. Stochastic population --------------------- Several of the stochastic search algorithms (e.g., `CRS`, `MLSL`, and `ISRES`) start by generating some initial "population" of random points *x*. By default, this initial population size is chosen heuristically in some algorithm-specific way, but the initial population can by changed by calling: ``` nlopt_result nlopt_set_population(nlopt_opt opt, unsigned pop); ``` (A `pop` of zero implies that the heuristic default will be used.) Pseudorandom numbers -------------------- For stochastic optimization algorithms, we use pseudorandom numbers generated by the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) algorithm, based on code from Makoto Matsumoto. By default, the [seed](https://en.wikipedia.org/wiki/Random_seed) for the random numbers is generated from the system time, so that you will get a different sequence of pseudorandom numbers each time you run your program. If you want to use a "deterministic" sequence of pseudorandom numbers, i.e. the same sequence from run to run, you can set the seed by calling: ``` void nlopt_srand(unsigned long seed); ``` Some of the algorithms also support using low-discrepancy sequences (LDS), sometimes known as quasi-random numbers. NLopt uses the Sobol LDS, which is implemented for up to 1111 dimensions. To reset the seed based on the system time, you can call: ``` void nlopt_srand_time(void); ``` (Normally, you don't need to call this as it is called automatically. However, it might be useful if you want to "re-randomize" the pseudorandom numbers after calling `nlopt_srand` to set a deterministic seed.) Vector storage for limited-memory quasi-Newton algorithms --------------------------------------------------------- Some of the NLopt algorithms are limited-memory "quasi-Newton" algorithms, which "remember" the gradients from a finite number *M* of the previous optimization steps in order to construct an approximate 2nd derivative matrix. The bigger *M* is, the more storage the algorithms require, but on the other hand they *may* converge faster for larger *M*. By default, NLopt chooses a heuristic value of *M*, but this can be changed/retrieved by calling: ``` nlopt_result nlopt_set_vector_storage(nlopt_opt opt, unsigned M); unsigned nlopt_get_vector_storage(const nlopt_opt opt); ``` Passing *M*=0 (the default) tells NLopt to use a heuristic value. By default, NLopt currently sets *M* to 10 or at most 10 [MiB](W:Mebibyte.md) worth of vectors, whichever is larger. Preconditioning with approximate Hessians ----------------------------------------- If you know the Hessian (second-derivative) matrix of your objective function, i.e. the matrix *H* with $H_{ij} = \frac{\partial^2 f}{\partial x_i \partial x_j}$ for an objective *f*, then in principle this could be used to accelerate local optimization. In fact, even a reasonable *approximation* for *H* could be useful if it captures information about the largest eigenvalues of *H* and the corresponding eigenvectors. Such an approximate Hessian is often called a *preconditioner* in the context of iterative solvers, so we adopt that terminology here. Currently, support for preconditioners in NLopt is somewhat experimental, and is only used in the `NLOPT_LD_CCSAQ` algorithm. You specify a preconditioned objective function by calling one of: ``` nlopt_result nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); nlopt_result nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); ``` which are identical to `nlopt_set_min_objective` and `nlopt_set_max_objective`, respectively, except that they additionally specify a preconditioner `pre`, which is a function of the form: ``` void pre(unsigned n, const double *x, const double *v, double *vpre, void *f_data); ``` This function should take a vector *v* and should compute *vpre = H(x) v* where *H* is an approximate second derivative at *x*. The CCSAQ algorithm **requires** that your matrix *H* be [positive semidefinite](https://en.wikipedia.org/wiki/Positive-definite_matrix#Positive-semidefinite), i.e. that it be real-symmetric with nonnegative eigenvalues. Version number -------------- To determine the version number of NLopt at runtime, you can call: ``` void nlopt_version(int *major, int *minor, int *bugfix); ``` For example, NLopt version 3.1.4 would return `*major=3`, `*minor=1`, and `*bugfix=4`. nlopt-2.6.1/doc/docs/NLopt_Tutorial.md000066400000000000000000000745061345435414600176370ustar00rootroot00000000000000--- # NLopt Tutorial --- In this tutorial, we illustrate the usage of NLopt in various languages via one or two trivial examples. Example nonlinearly constrained problem --------------------------------------- ![right|thumb|400px|Feasible region for a simple example optimization problem with two nonlinear (cubic) constraints.](images/NLopt-example-constraints.png) As a first example, we'll look at the following simple nonlinearly constrained minimization problem: $$\min_{\mathbf{x}\in\mathbb{R}^2} \sqrt{x_2}$$ subject to $x_2 \geq 0$, $x_2 \geq (a_1 x_1 + b_1)^3$, and $x_2 \geq (a_2 x_1 + b_2)^3$ for parameters *a*1=2, *b*1=0, *a*2=-1, *b*2=1. The feasible region defined by these constraints is plotted at right: *x*2 is constrained to lie above the maximum of two cubics, and the optimum point is located at the intersection (1/3, 8/27) where the objective function takes on the value $\sqrt{8/27} \approx 0.5443310539518\ldots$. (This problem is especially trivial, because by formulating it in terms of the cube root of *x*2 you can turn it into a linear-programming problem, but we won't do that here.) In principle, we don't need the bound constraint *x*2≥0, since the nonlinear constraints already imply a positive-*x*2 feasible region. However, NLopt doesn't guarantee that, on the way to finding the optimum, it won't violate the nonlinear constraints at some intermediate steps, while it *does* guarantee that all intermediate steps will satisfy the bound constraints. So, we will explicitly impose *x*2≥0 in order to ensure that the √*x*2 in our objective is real. **Note:** The objective function here is not differentiable at *x*2=0. This doesn't cause problems in the examples below, but may cause problems with some other algorithms if they try to evaluate the gradient at *x*2=0 (e.g. I've seen it cause AUGLAG with a gradient-based solver to fail). To prevent this, you might want to use a small nonzero lower bound instead, e.g. *x*2≥10−6. Example in C/C++ ---------------- To implement the above example in C or C++, we would first do: ```c #include  #include  ``` to include the NLopt header file as well as the standard math header file (needed for things like the `sqrt` function and the `HUGE_VAL` constant), then we would define our objective function as: ```c double myfunc(unsigned n, const double *x, double *grad, void *my_func_data) {     if (grad) {         grad[0] = 0.0;         grad[1] = 0.5 / sqrt(x[1]);     }     return sqrt(x[1]); } ``` There are several things to notice here. First, since this is C, our indices are zero-based, so we have `x[0]` and `x[1]` instead of *x*1 and *x*2. The return value of our function is the objective $\sqrt{x_2}$. Also, if the parameter `grad` is not `NULL`, then we set `grad[0]` and `grad[1]` to the partial derivatives of our objective with respect to `x[0]` and `x[1]`. The gradient is only needed for [gradient-based algorithms](NLopt_Introduction#Gradient-based_versus_derivative-free_algorithms.md); if you use a derivative-free optimization algorithm, `grad` will always be `NULL` and you need never compute any derivatives. Finally, we have an extra parameter `my_func_data` that can be used to pass additional data to `myfunc`, but no additional data is needed here so that parameter is unused. For the constraints, on the other hand, we *will* have additional data. Each constraint is parameterized by two numbers *a* and *b*, so we will declare a data structure to hold this information: ```c typedef struct {     double a, b; } my_constraint_data; ``` Then, we implement our constraint function as follows. ```c double myconstraint(unsigned n, const double *x, double *grad, void *data) {     my_constraint_data *d = (my_constraint_data *) data;     double a = d->a, b = d->b;     if (grad) {         grad[0] = 3 * a * (a*x[0] + b) * (a*x[0] + b);         grad[1] = -1.0;     }     return ((a*x[0] + b) * (a*x[0] + b) * (a*x[0] + b) - x[1]);  } ``` The form of the constraint function is the same as that of the objective function. Here, the `data` parameter will actually be a pointer to `my_constraint_data` (because this is the type that we will pass to `nlopt_minimize_constrained` below), so we use a typecast to get the constraint data. NLopt always expects constraints to be of the form `myconstraint`(**x**) ≤ 0, so we implement the constraint *x*2 ≥ (*a* *x*1 + *b*)3 as the function (*a* *x*1 + *b*)3 − *x*2. Again, we only compute the gradient if `grad` is non-`NULL`, which will never occur if we use a derivative-free optimization algorithm. Now, to specify this optimization problem, we create an "object" of type `nlopt_opt` (an opaque pointer type) and set its various parameters: ```c double lb[2] = { -HUGE_VAL, 0 }; /* lower bounds */ nlopt_opt opt; ``` ```c opt = nlopt_create(NLOPT_LD_MMA, 2); /* algorithm and dimensionality */ nlopt_set_lower_bounds(opt, lb); nlopt_set_min_objective(opt, myfunc, NULL); ``` Note that we do not need to set an upper bound (`nlopt_set_upper_bounds`), since we are happy with the default upper bounds (+∞). To add the two inequality constraints, we do: ```c my_constraint_data data[2] = { {2,0}, {-1,1} }; ``` ```c nlopt_add_inequality_constraint(opt, myconstraint, &data[0], 1e-8); nlopt_add_inequality_constraint(opt, myconstraint, &data[1], 1e-8); ``` Here, the `1e-8` is an optional tolerance for the constraint: for purposes of convergence testing, a point will be considered feasible if the constraint is violated (is positive) by that tolerance (10−8). A nonzero tolerance is a good idea for many algorithms lest tiny errors prevent convergence. Speaking of convergence tests, we should also set one or more stopping criteria, e.g. a relative tolerance on the optimization parameters **x**: ```c nlopt_set_xtol_rel(opt, 1e-4); ``` There are many more possible parameters that you can set to control the optimization, which are described in detail by the [reference manual](NLopt_Reference.md), but these are enough for our example here (any unspecified parameters are set to innocuous defaults). At this point, we can call nlopt_optimize to actually perform the optimization, starting with some initial guess: ```c double x[2] = { 1.234, 5.678 };  /* `*`some` `initial` `guess`*` */ double minf; /* `*`the` `minimum` `objective` `value,` `upon` `return`*` */ if (nlopt_optimize(opt, x, &minf) < 0) {     printf("nlopt failed!\n"); } else {     printf("found minimum at f(%g,%g) = %0.10g\n", x[0], x[1], minf); } ``` `nlopt_optimize` will return a negative result code on failure, but this usually only happens if you pass invalid parameters, it runs out of memory, or something like that. (Actually, most of the other NLopt functions also return an error code that you can check if you are paranoid.) (However, if it returns the failure code `NLOPT_ROUNDOFF_LIMITED`, indicating a breakdown due to roundoff errors, the minimum found may still be useful and you may want to still use it.) Otherwise, we print out the minimum function value and the corresponding parameters **x**. Finally, we should call nlopt_destroy to dispose of the `nlopt_opt` object when we are done with it: ```c nlopt_destroy(opt); ``` Assuming we save this in a file tutorial.c, we would compile and link (on Unix) with: ``` cc tutorial.c -o tutorial -lnlopt -lm ``` The result of running the program should then be something like: ``` found minimum at f(0.333334,0.296296) = 0.544330847 ``` That is, it found the correct parameters to about 5 significant digits and the correct minimum function value to about 6 significant digits. (This is better than we specified; this often occurs because the local optimization routines usually try to be conservative in estimating the error.) ### Number of evaluations Let's modify our program to print out the number of function evaluations that were required to obtain this result. First, we'll change our objective function to: ```c int count = 0; double myfunc(int n, const double *x, double *grad, void *my_func_data) {     ++count;     if (grad) {         grad[0] = 0.0;         grad[1] = 0.5 / sqrt(x[1]);     }     return sqrt(x[1]); } ``` using a global variable `count` that is incremented for each function evaluation. (We could also pass a pointer to a counter variable as `my_func_data`, if we wanted to avoid global variables.) Then, adding a `printf`: ```c printf("found minimum after %d evaluations\n", count); ``` we obtain: ``` found minimum after 11 evaluations found minimum at f(0.333334,0.296296) = 0.544330847 ``` For such a simple problem, a gradient-based local optimization algorithm like MMA can converge very quickly! ### Switching to a derivative-free algorithm We can also try a derivative-free algorithm. Looking at the [NLopt Algorithms](NLopt_Algorithms.md) list, another algorithm in NLopt that handles nonlinear constraints is COBYLA, which is derivative-free. To use it, we just change `NLOPT_LD_MMA` ("LD" means local optimization, derivative/gradient-based) into `NLOPT_LN_COBYLA` ("LN" means local optimization, no derivatives), and obtain: ``` found minimum after 31 evaluations found minimum at f(0.333329,0.2962) = 0.544242301 ``` In such a low-dimensional problem, derivative-free algorithms usually work quite well—in this case, it only triples the number of function evaluations. However, the comparison is not perfect because, for the same relative **x** tolerance of 10−4, COBYLA is a bit less conservative and only finds the solution to 3 significant digits. To do a fairer comparison of the two algorithms, we could set the **x** tolerance to zero and ask how many function evaluations each one requires to get the correct answer to three decimal places. We can specify this by using the `stopval` termination criterion, which allows us to halt the process as soon as a feasible point attains an objective function value less than `stopval`. In this case, we would set `stopval` to $\sqrt(8/27)+10^{-3}$, replacing `nlopt_set_xtol_rel` with the statement: ```c nlopt_set_stopval(opt, sqrt(8./27.)+1e-3); ``` corresponding to the last line of arguments to `nlopt_minimize_constrained` being `sqrt(8./27.)+1e-3,` `0.0,` `0.0,` `0.0,` `NULL,` `0,` `0.0`. If we do this, we find that COBYLA requires 25 evaluations while MMA requires 10. The advantage of gradient-based algorithms over derivative-free algorithms typically grows for higher-dimensional problems. On the other hand, derivative-free algorithms are much easier to use because you don't need to worry about how to compute the gradient (which might be tricky if the function is very complicated). Example in C++ -------------- Although it is perfectly possible to use the C interface from C++, many C++ programmers will find it more natural to use real C++ objects instead of opaque `nlopt_opt` pointers, `std::vector` instead of arrays, and exceptions instead of error codes. NLopt provides a C++ header file `nlopt.hpp` that you can use for this purpose, which simply wraps a C++ object interface around the C interface above. ```cpp #include #include #include #include  ``` The equivalent of the above example would then be: ```cpp nlopt::opt opt(nlopt::LD_MMA, 2); std::vector lb(2); lb[0] = -HUGE_VAL; lb[1] = 0; opt.set_lower_bounds(lb); opt.set_min_objective(myfunc, NULL); my_constraint_data data[2] = { {2,0}, {-1,1} }; opt.add_inequality_constraint(myconstraint, &data[0], 1e-8); opt.add_inequality_constraint(myconstraint, &data[1], 1e-8); opt.set_xtol_rel(1e-4); std::vector x(2); x[0] = 1.234; x[1] = 5.678; double minf; try{ nlopt::result result = opt.optimize(x, minf); std::cout << "found minimum at f(" << x[0] << "," << x[1] << ") = " << std::setprecision(10) << minf << std::endl; } catch(std::exception &e) { std::cout << "nlopt failed: " << e.what() << std::endl; } ``` There is no need to deallocate the `opt` object; its destructor will do that for you once it goes out of scope. Also, there is no longer any need to check for error codes; the NLopt C++ functions will throw exceptions if there is an error, which you can `catch` normally. Here, we are using the same objective and constraint functions as in C, taking `double*` array arguments. Alternatively, you can define objective and constraint functions to take `std::vector` arguments if you prefer. (Using `std::vector` in the objective/constraint imposes a slight overhead because NLopt must copy the `double*` data to a `std::vector`, but this overhead is unlikely to be significant in most real applications.) That is, you would do: ```cpp double myvfunc(const std::vector &x, std::vector &grad, void *my_func_data) {     if (!grad.empty()) {         grad[0] = 0.0;         grad[1] = 0.5 / sqrt(x[1]);     }     return sqrt(x[1]); } ``` ```cpp double myvconstraint(const std::vector &x, std::vector &grad, void *data) {     my_constraint_data *d = reinterpret_cast(data);     double a = d->a, b = d->b;     if (!grad.empty()) {         grad[0] = 3 * a * (a*x[0] + b) * (a*x[0] + b);         grad[1] = -1.0;     }     return ((a*x[0] + b) * (a*x[0] + b) * (a*x[0] + b) - x[1]); } ``` Notice that, instead of checking whether `grad` is `NULL`, we check whether it is empty. (The vector arguments, if non-empty, are guaranteed to be of the same size as the dimension of the problem that you specified.) We then specify these in the same way as before: ```cpp opt.set_min_objective(myvfunc, NULL); opt.add_inequality_constraint(myvconstraint, &data[0], 1e-8); opt.add_inequality_constraint(myvconstraint, &data[1], 1e-8); ``` Note that the data pointers passed to these functions must remain valid (or rather, what they point to must remain valid) until you are done with `opt`. (It might have been nicer to use `shared_ptr`, but I don't like to rely on bleeding-edge language features.) Instead of passing a separate data pointer, some users may wish to define a C++ [function object](https://en.wikipedia.org/wiki/Function_object) class that contains all of the data needed by their function, with an overloaded `operator()` method to implement the function call. You can easily do this with a two-line helper function. If your function class is MyFunction, then you could define a static member function: ```cpp static double wrap(const std::vector`` &x, std::vector`` &grad, void *data) {     return (*reinterpret_cast``(data))(x, grad); } ``` which you would then use e.g. by `opt.set_min_objective(MyFunction::wrap, &some_MyFunction)`. Again, you have to make sure that `some_MyFunction` does not go out of scope before you are done calling `nlopt::opt::optimize`. To link your program, just link to the C NLopt library (`-lnlopt` `-lm` on Unix). Example in Matlab or GNU Octave ------------------------------- To implement this objective function in Matlab (or GNU Octave), we would write a file myfunc.m that looks like: ```matlab function [val, gradient] = myfunc(x)     val = sqrt(x(2));     if (nargout > 1)         gradient = [0, 0.5 / val];     end ``` Notice that we check the Matlab builtin variable `nargout` (the number of output arguments) to decide whether to compute the gradient. If we use a derivative-free optimization algorithm below, then `nargout` will always be 1 and the gradient need never be computed. Our constraint function looks similar, except that it is parameterized by the coefficients *a* and *b*. We can just add these on as extra parameters, in a file `myconstraint.m`: ```matlab function [val, gradient] = myconstraint(x,a,b)     val = (a*x(1) + b)^3 - x(2);     if (nargout > 1)         gradient = [3*a*(a*x(1) + b)^2, -1];     end ``` The equivalent of the `nlopt_opt` is just a [structure](http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/f2-88951.html), with fields corresponding to any parameters that we want to set. (Any structure fields that we don't include are equivalent to not setting those parameters, and using the defaults instead). You can get more information on the available parameters by typing `help` `nlopt_optimize` in Matlab. The equivalent of the C example above is to define an `opt` structure by: ```matlab opt.algorithm = NLOPT_LD_MMA opt.lower_bounds = [-inf, 0] opt.min_objective = @myfunc opt.fc = { (@(x) myconstraint(x,2,0)), (@(x) myconstraint(x,-1,1)) } opt.fc_tol = [1e-8, 1e-8]; opt.xtol_rel = 1e-4 ``` We do not need to specify the dimension of the problem; this is implicitly specified by the size of the initial-guess vector passed to `nlopt_optimize` below (and must match the sizes of other vectors like `opt.lower_bounds`). The inequality constraints are specified as a [cell array](http://blogs.mathworks.com/loren/2006/06/21/cell-arrays-and-their-contents/) `opt.fc` of function handles (and the corresponding tolerances are in an array `opt.fc_tol`); notice how we use `@(x)` to define an anonymous/inline function in order to pass additional arguments to `myconstraint`. Finally, we call `nlopt_optimize`: ```matlab [xopt, fmin, retcode] = nlopt_optimize(opt, [1.234 5.678]) ``` `nlopt_optimize` returns three things: `xopt`, the optimal parameters found; `fmin`, the corresponding value of the objective function, and a return code `retcode` (positive on success and negative on failure). The output of the above command is: ``` xopt =  0.3333  0.2963 fmin = 0.5443 retcode = 4 ``` (The [return code](NLopt_Reference#Return_values.md) `4` corresponds to `NLOPT_XTOL_REACHED`, which means it converged to the specified *x* tolerance.) To switch to a derivative-free algorithm like COBYLA, we just change `opt.algorithm` parameter: ```matlab opt.algorithm = NLOPT_LN_COBYLA ``` ### Matlab verbose output It is often useful to print out some status message to see what is happening, especially if your function evaluation is much slower or if a large number of evaluations are required (e.g. for global optimization). You can, of course, modify your function to print out whatever you want. As a shortcut, however, you can set a verbose option in NLopt's Matlab interface by: ```matlab opt.verbose = 1; ``` If we do this, then running the MMA algorithm as above yields: ```matlab nlopt_minimize_constrained eval #1: 2.38286 nlopt_minimize_constrained eval #2: 2.35613 nlopt_minimize_constrained eval #3: 2.24586 nlopt_minimize_constrained eval #4: 2.0191 nlopt_minimize_constrained eval #5: 1.74093 nlopt_minimize_constrained eval #6: 1.40421 nlopt_minimize_constrained eval #7: 1.0223 nlopt_minimize_constrained eval #8: 0.685203 nlopt_minimize_constrained eval #9: 0.552985 nlopt_minimize_constrained eval #10: 0.544354 nlopt_minimize_constrained eval #11: 0.544331 ``` This shows the objective function values at each intermediate step of the optimization. As in the C example above, it converges in 11 steps. The COBYLA algorithm requires a few more iterations, because it doesn't exploit the gradient information: ```matlab nlopt_optimize eval #1: 2.38286 nlopt_optimize eval #2: 2.38286 nlopt_optimize eval #3: 3.15222 nlopt_optimize eval #4: 1.20627 nlopt_optimize eval #5: 0.499441 nlopt_optimize eval #6: 0.709216 nlopt_optimize eval #7: 0.20341 nlopt_optimize eval #8: 0.745201 nlopt_optimize eval #9: 0.989693 nlopt_optimize eval #10: 0.324679 nlopt_optimize eval #11: 0.804318 nlopt_optimize eval #12: 0.541431 nlopt_optimize eval #13: 0.561137 nlopt_optimize eval #14: 0.531346 nlopt_optimize eval #15: 0.515784 nlopt_optimize eval #16: 0.541724 nlopt_optimize eval #17: 0.541422 nlopt_optimize eval #18: 0.541504 nlopt_optimize eval #19: 0.541499 nlopt_optimize eval #20: 0.541514 nlopt_optimize eval #21: 0.541352 nlopt_optimize eval #22: 0.542089 nlopt_optimize eval #23: 0.542575 nlopt_optimize eval #24: 0.543027 nlopt_optimize eval #25: 0.544911 nlopt_optimize eval #26: 0.541793 nlopt_optimize eval #27: 0.545225 nlopt_optimize eval #28: 0.544331 nlopt_optimize eval #29: 0.544256 nlopt_optimize eval #30: 0.544242 nlopt_optimize eval #31: 0.544116 ``` Notice that some of the objective function values are below the minimum of 0.54433 — these are simply values of the objective function at infeasible points (violating the nonlinear constraints). Example in Python ----------------- The same example in Python is: ```python import nlopt from numpy import * def myfunc(x, grad):     if grad.size > 0:         grad[0] = 0.0         grad[1] = 0.5 / sqrt(x[1])     return sqrt(x[1]) def myconstraint(x, grad, a, b):     if grad.size > 0:         grad[0] = 3 * a * (a*x[0] + b)**2         grad[1] = -1.0     return (a*x[0] + b)**3 - x[1] opt = nlopt.opt(nlopt.LD_MMA, 2) opt.set_lower_bounds([-float('inf'), 0]) opt.set_min_objective(myfunc) opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,2,0), 1e-8) opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,-1,1), 1e-8) opt.set_xtol_rel(1e-4) x = opt.optimize([1.234, 5.678]) minf = opt.last_optimum_value() print("optimum at ", x[0], x[1]) print("minimum value = ", minf) print("result code = ", opt.last_optimize_result()) ``` Notice that the `optimize` method returns only the location of the optimum (as a NumPy array), and that the value of the optimum and the result code are obtained by `last_optimum_value` and `last_optimize_result` values. Like in C++, the NLopt functions raise exceptions on errors, so we don't need to check return codes to look for errors. The objective and constraint functions take NumPy arrays as arguments; if the `grad` argument is non-empty it must be modified *in-place* to the value of the gradient. Notice how we use Python's `lambda` construct to pass additional parameters to the constraints. Alternatively, we could define the objective/constraints as classes with a `__call__(self,` `x,` `grad)` method so that they can behave like functions. The result of running the above code should be: ```python optimum at  0.333333331366 0.296296292697 minimum value =  0.544331050646 result =  4 ``` finding the same correct optimum as in the C interface (of course). (The [return code](NLopt_Reference#Return_values.md) `4` corresponds to `nlopt.XTOL_REACHED`, which means it converged to the specified *x* tolerance.) ### Important: Modifying `grad` in-place The grad argument of your objective/constraint functions must be modified *in-place*. If you use an operation like ```python grad = 2*x ``` however, Python allocates a new array to hold `2*x` and reassigns grad to point to it, rather than modifying the original contents of grad. **This will not work.** Instead, you should do: ```python grad[:] = 2*x ``` which *overwrites* the old contents of grad with `2*x`. See also the [NLopt Python Reference](NLopt_Python_Reference#Assigning_results_in-place.md). Example in GNU Guile (Scheme) ----------------------------- In [GNU Guile](https://en.wikipedia.org/wiki/GNU_Guile), which is an implementation of the [Scheme programming language](https://en.wikipedia.org/wiki/Scheme_(programming_language)), the equivalent of the example above would be: ```guile (use-modules (nlopt)) (define (myfunc x grad)   (if grad       (begin         (vector-set! grad 0 0.0)         (vector-set! grad 1 (/ 0.5 (sqrt (vector-ref x 1))))))   (sqrt (vector-ref x 1))) (define (myconstraint x grad a b)   (let ((x0 (vector-ref x 0)) (x1 (vector-ref x 1)))     (if grad         (begin           (vector-set! grad 0 (* 3 a (expt (+ (* a x0) b) 2)))           (vector-set! grad 1 -1.0)))     (- (expt (+ (* a x0) b) 3) x1))) (define opt (new-nlopt-opt NLOPT-LD-MMA 2)) (nlopt-opt-set-lower-bounds opt (vector (- (inf)) 0)) (nlopt-opt-set-min-objective opt myfunc) (nlopt-opt-add-inequality-constraint opt (lambda (x grad)                                            (myconstraint x grad 2 0))                                      1e-8) (nlopt-opt-add-inequality-constraint opt (lambda (x grad)                                            (myconstraint x grad -1 1))                                      1e-8) (nlopt-opt-set-xtol-rel opt 1e-4) (define x (nlopt-opt-optimize opt (vector 1.234 5.678))) (define minf (nlopt-opt-last-optimum-value opt)) (define result (nlopt-opt-last-optimize-result opt)) ``` Note that the objective/constraint functions take two arguments, `x` and `grad`, and return a number. `x` is a vector whose length is the dimension of the problem; grad is either false (`#f`) if it is not needed, or a `vector` that must be modified *in-place* to the gradient of the function. On error conditions, the NLopt functions throw [exceptions](http://www.gnu.org/software/guile/manual/html_node/Exceptions.html) that can be caught by your Scheme code if you wish. The heavy use of side-effects here is a bit unnatural in Scheme, but is used in order to closely map to the C++ interface. (Notice that `nlopt::` C++ functions map to `nlopt-` Guile functions, and `nlopt::opt::` methods map to `nlopt-opt-` functions that take the `opt` object as the first argument.) Of course, you are free to wrap your own Scheme-like functional interface around this if you wish. Example in Fortran ------------------ In [Fortran](https://en.wikipedia.org/wiki/Fortran), the equivalent of the C example above would be as follows. First, we would write our functions as: ```fortran      subroutine myfunc(val, n, x, grad, need_gradient, f_data)      double precision val, x(n), grad(n)      integer n, need_gradient      if (need_gradient.ne.0) then         grad(1) = 0.0         grad(2) = 0.5 / dsqrt(x(2))      endif      val = dsqrt(x(2))      end ``` ```fortran      subroutine myconstraint(val, n, x, grad, need_gradient, d)      integer need_gradient      double precision val, x(n), grad(n), d(2), a, b      a = d(1)      b = d(2)      if (need_gradient.ne.0) then         grad(1) = 3. * a * (a*x(1) + b)**2         grad(2) = -1.0      endif      val = (a*x(1) + b)**3 - x(2)      end ``` Notice that that the "functions" are actually subroutines. This is because it turns out to be hard to call Fortran functions from C or vice versa in any remotely portable way. Therefore: - In the NLopt Fortran interface, all C functions become subroutines in Fortran, with the return value becoming the first argument. So, here the first argument `val` is used for the return value. Also, because there is no way in Fortran to pass `NULL` for the `grad` argument, we add an additional `need_gradient` argument which is nonzero if the gradient needs to be computed. Finally, the last argument is the equivalent of the `void*` argument in the C API, and can be used to pass a single argument of any type through to the objective/constraint functions: here, we use it in `myconstraint` to pass an array of two values for the constants *a* and *b*. Then, to run the optimization, we can use the following Fortran program: ```fortran      program main      external myfunc, myconstraint      double precision lb(2)      integer*8 opt      double precision d1(2), d2(2)      double precision x(2), minf      integer ires      include 'nlopt.f'            call nlo_create(opt, NLOPT_LD_MMA, 2)      call nlo_get_lower_bounds(ires, opt, lb)      lb(2) = 0.0      call nlo_set_lower_bounds(ires, opt, lb)      call nlo_set_min_objective(ires, opt, myfunc, 0)            d1(1) = 2.      d1(2) = 0.      call nlo_add_inequality_constraint(ires, opt,      $     myconstraint, d1, 1.D-8)      d2(1) = -1.      d2(2) = 1.      call nlo_add_inequality_constraint(ires, opt,     $     myconstraint, d2, 1.D-8)            call nlo_set_xtol_rel(ires, opt, 1.D-4)            x(1) = 1.234      x(2) = 5.678      call nlo_optimize(ires, opt, x, minf)      if (ires.lt.0) then         write(*,*) 'nlopt failed!'      else         write(*,*) 'found min at ', x(1), x(2)         write(*,*) 'min val = ', minf      endif            call nlo_destroy(opt)            end ``` There are a few things to note here: - All `nlopt_` functions are converted into `nlo_` subroutines, with return values converted into the first argument. - The "`nlopt_opt`" variable `opt` is declared as `integer*8`. (Technically, we could use any type that is big enough to hold a pointer on all platforms; `integer*8` is big enough for pointers on both 32-bit and 64-bit machines.) - The subroutines must be declared as `external`. - We `include` `'nlopt.f'` in order to get the various constants like `NLOPT_LD_MMA`. There is no standard Fortran 77 equivalent of C's `HUGE_VAL` constant, so instead we just call `nlo_get_lower_bounds` to get the default lower bounds (-∞) and then change one of them. In Fortran 90 (and supported as an extension in many Fortran 77 compilers), there is a `huge` intrinsic function that we could have used instead: ```fortran      lb(1) = -huge(lb(1)) ``` Example in Julia ---------------- The same example in the [Julia programming language](https://en.wikipedia.org/wiki/Julia_(programming_language)) can be found at the [NLopt.jl](https://github.com/stevengj/NLopt.jl) web page. nlopt-2.6.1/doc/docs/NLopt_manual.md000066400000000000000000000014501345435414600172750ustar00rootroot00000000000000--- # NLopt manual --- Welcome to the manual for [NLopt](index.md), our nonlinear optimization library. The manual is divided into a the following sections: - [NLopt Introduction](NLopt_Introduction.md) — overview of the library and the problems that it solves - [NLopt Installation](NLopt_Installation.md) — installation instructions - [NLopt Tutorial](NLopt_Tutorial.md) — some simple examples in C, Fortran, and Octave/Matlab - [NLopt Reference](NLopt_Reference.md) — reference manual, listing the NLopt API functions - [NLopt Algorithms](NLopt_Algorithms.md) — the optimization algorithms available in NLopt (including literature citations and links to original source code, where available) - [NLopt License and Copyright](NLopt_License_and_Copyright.md) — legal information nlopt-2.6.1/doc/docs/NLopt_on_Windows.md000066400000000000000000000045611345435414600201540ustar00rootroot00000000000000--- # NLopt on Windows --- NLopt on Windows ---------------- NLopt works fine on Microsoft Windows computers, and you can compile it directly using the included [CMake](https://en.wikipedia.org/wiki/CMake) build scripts. To simplify installation, there are also precompiled 32-bit and 64-bit Windows [DLLs](https://en.wikipedia.org/wiki/Dynamic-link_library) (along with binaries for many other systems) at [NLoptBuilder/releases](https://github.com/stevengj/NLoptBuilder/releases). In particular, the Windows builds are - [NLopt.v2.6.0.i686-w64-mingw32.tar.gz](https://github.com/stevengj/NLoptBuilder/releases/download/v2.6.0/NLopt.v2.6.0.i686-w64-mingw32.tar.gz) (32-bit) - [NLopt.v2.6.0.x86_64-w64-mingw32.tar.gz](https://github.com/stevengj/NLoptBuilder/releases/download/v2.6.0/NLopt.v2.6.0.x86_64-w64-mingw32.tar.gz) (64-bit) These `.tar.gz` files unpack (with a variety of Windows software, e.g. 7-zip) into a folder with a `bin` subdirectory that contains `libnlopt.dll`. To link with this in your compiler, you will typically also want the [import library](https://stackoverflow.com/questions/3573475/how-does-the-import-library-work-details) for the DLL, which can be found in the `lib` subdirectory and is called `libnlopt.dll.a` (this can be used similarly to the `.lib` files you may be used to). Unofficial Python binaries for Windows are available from Christoph Gohike: - [Python binaries for 64-bit Windows](http://www.lfd.uci.edu/~gohlke/pythonlibs/#nlopt) ### Octave plugin To build the NLopt plugin for [GNU Octave](https://en.wikipedia.org/wiki/GNU_Octave) (a free Matlab clone, which uses the [same NLopt interface as in Matlab](NLopt_Matlab_Reference.md)), you will need the following additional steps. (See [Octave for Windows](https://wiki.octave.org/Octave_for_Microsoft_Windows) on the Octave web page to download Octave.) 1. First, download the `.dll` and import library (`.dll.a`) from above. 2. Download [`nlopt_optimize-oct.cc`](https://github.com/stevengj/nlopt/raw/master/src/octave/nlopt_optimize-oct.cc) and put it in the same directory as the `.dll` and `.dll.a` files. 3. Compile the Octave plugin (`.oct` file) with `mkoctfile -lnlopt --output nlopt_optimize.oct nlopt_optimize-oct.cc` (`mkoctfile` is a program included with Octave). 4. Finally, move `libnlopt.dll` to the *octave*``bin` directory (the location of `octave.exe`) so that Octave can find it. nlopt-2.6.1/doc/docs/images/000077500000000000000000000000001345435414600156275ustar00rootroot00000000000000nlopt-2.6.1/doc/docs/images/NLopt-example-constraints.png000066400000000000000000000312231345435414600233700ustar00rootroot00000000000000PNG  IHDR>_ pHYsgRtIME 6y"tEXtCreation Time13-Nov-2008 16:26:53B$tEXtSoftwareMATLAB, The Mathworks, Inc.R IDATxQv@Qx+?4yb (ꏴmYH"omu  (A J%A B!@P (A J%A B!@P (A J%A B!@P (A J%A B!@P (A J%A B!@P (A J%A B!@P (A J%A B!@P6iv]ݵ%@5L `uCN`֬)gCM~LC"ްM@-LA BCX* ,Nd (AXL!p%YwB@ܽ$z84H1HCk!@PW^xܽ!ux_;|Q-!@P0_WoEztaֺ_Ϳ)8|*0}p:B _֋&%Y/zA 2ehjȎ@/ @^ c5!@PȈW@^ J%\<Ϧފ@!@P (Adz B!@PA B!p3E"A BN֋H%m J%=@x;A J7^4 (A fh&!@P (A\z|B!@PYA B!pEs#A B ֋fH%$A B -E%A B !Es `I۶_yi{k sƃ3!,P. ¬}ZנKP4E'2?r aaK"X/ZBa gƃd$֋P1@,dhAL A,&0"%X/ZA J?eșADә'^D (A ^P (A ^\ (A ^h (A v^t (A ^ (A fh!@P (A|zjB!@P5A B!A B!A B!z* B!xV (A X/Z1A JY/Z7A J J%֋F ` (A ah (Ax0A JY/ JMc<ҟ7m;+Kc:8NA@"֋A ¬M2!JzQtk^YFHzLжmuCmB  0 N~Hh(0 <퐋)8^A JjiNg( 1}":(p pDYaֆE}5h(p ,,֋2p !@P (AX/ʘ J@ƃLB!@PB^w (A Y/,A  J%f֋@%Zƃ,A B !@P (A^-!@Pjc>{Rۮ~=.V׫m9#_շ\(r7ۿ~e~%&n>|>n[p[F˾c|Vc}&|#ێr%I>}ٶۊლP@.bT}ڶZ( ᧅ7q K"\fn6ٯg,n(mUd_n ѻ'x9%5/ `p o2ǿ:;njp.ݪ|.f?~` (g9qg]lcΖl7  B|;zO:>}6n9w pRL sY%Nـn߼7( w1!dueviV"0>  ApgȔy6{Zr#AP}vׯtd&Mc _pA%j3P^WRW#Hpv*ͷ_bPAP{^]p/xs>#2v.;P(8xqedt5z~NL.qF?on6 {-& oҼƖX؞S{9}Ϲڀ7l1Ar`(@Pmi/zn-/[nqj__ol?o~ 3ܡm<ф@06tP5H>C !S>&PE֋AYx>iYB2 P-?CpLrRƃdH@.d3$O (A %[ (A 3A Tɜ J@ƃO%|ƃA%p2E) J) Ji) J9) J ) JQƃJ%A% EA Bx B!a3  4& s N7 Txz ,{[I @~MuS[Ԅ21A8o5]( +zMPApى( !!;A rP¬(A1 @} |%P@(pV0@aA l>4b 5`=@ƃ,ʅz}*8|JAjjª(AGc S lN1 PA"Pdaq|>ۨA(Ie Dv]Ӷi^T U%*;뚮3*15ahBࣶm?~%@+q&!X> hBnƃ-A&jaA&z0"MTxAiB@ƥ :n04MN 0:Ma B4!P*A8H4(ܽ뚶}4Mzܽ-LOe0S2eTAuu]zy2R>OmO9!5։{ ,-~^ @,W_}7"4x%DSp:AV*#@t8i5!pAHIe'Vr aj8 p1AHDarۛ|ڎয়r.wz 58Vt!e/BMq;9%́@:ƃ HA BjshB(m~p˟M_B8A&n˭ a_kVD!Dr>Md<FkBȟ ׸ݯj;Mc<q\f:ifA>j/&43-]<wbT2dA{3!"]׼^?F'j'|aZ閏ƃ/D&f hBg<w1uPYtG 85Fe„Y> wdA@Lƃp/S ;L|BQ|ܽܜGJhBxr ɑ&Ağ7u]Ӷ! !rH!Tx!ɝ&AȊ Rp) zW)rD{2!)AȐ 0")&B,íP)RANd/b&!p l2g<93uPa'5ȉ^X> ;B  +ƃ?S [> 9P.^n"&QHdWNzFpAR !2*[A(ȟ7꺦mQ!1!~FpA(eG@Rj0~gi5 !@:j0?7 S<ϯ-뀾/`BHD]׼^?Fp&oBQ!A=Gje(Y> pQ#(Tvh[M{5h/7KFigfORc8ÒQQd,E1!P!00ir &aJpɅ'WՍB(%0QxEf.r>%b)OΰRGu?UNS!_:B&&z|eo܁[xNaf~F.l}Hxs/|p+F9ʹ4!hٴ[ >eBƼ½|ڼaEWuK.$_ҍJ9BƜ8 s{&}h˟ⳟ{)X2 +,A58vTjU.ޟJdWNepՌO~v5Rߚ% ;WuNH*SF oZr\yեj><ճ erQ :q~M}VEl$7ʽ߷s~:Q>-S{%+HJ$Lz/[eUFVक़V^;KN3! BBHay7X]ܸ_?]KT8  =E'?pMZy6y<'*`Yc(b)u;aaӍ{ oɤ۟ 1! `snl7B8Q!9̢Ir[}z<,R<i 9584>nC}6Ut5˙Ɍ F Nnz6B8Q!1vIKPi맂NsOL{y1èڃgݶ#9l>Snƃv;c0!Zk#̨v f\='gMFv]X΅Rl$H5\ly;}੟~׫s^n | Š&f+XvQ 6T{, sV 6 }g~K 80_WQd%ᡃ&)5{܎<([ 8ʑgcS;No39B!_`Y@>rHM.0۳o@R›¸ ae,Ԅ%u&v{m%OC`m g)wɨ+CLW&[&K} K-VHJF`ym^n &PB+K|m9 a@FSX 4_Ag,+j`_rSVK%ץ`k0<R Ũe'ES&SI@[A A劅p1W# 5g(+H'3Ҝ,jzƃ),m\A:|UB`f^ɹFHJ '- ՄP!lնM޽ZxDZB Bؤޅ232RpQXWY nsv94DLD.)tVYΧ9g2-ԇS@:&~f3>'}]XA j;TmXσr7G7$Ln>~ az a,^n:&Te's5:G0-A!B0.yDIDAT<Lm@ p BRbǓٍqmAw s_l~+B= pp+n90o4[z!v~o5FʧO#o\?_Whˌ1YM -oVor3}|^YYH y BE4O]g]G,4'B0ʨA8E{2!$##6oeU`ﴰQ@ 3uYEe+R@L]+T0=,rKnԷonQA5sU KFaP`kTBvj( $kΩ,nx>ƻP곰yj( $#q * )C7I g*an9907p{)kg`A2># !25G@ B> !,5TbYee)\\aS{)J*&P15ԵBc~!jz.6 !`0!p>R( Bq e…Ía#{^ۮLy ep Nj. 2 a B;)C i|ܽ9z=z$R@d&y_´闉  ȑ,t,B|=c\_]Џ4>۶8 PP4{)fZ+x=@4Ëg82-,%&Y*`;AOL]+d1 daV~E B5`BP '& DV BB l!*z6 BVWa5FeP1{))I@  QQ}!@De؈Cd0pe46, Dc/7BiQSB!938 #eHn enqIì:` !_pzRna0 `aII` )S wzu5`Bi \Cp>enRJ ,í@C qxOtx !W&+{R^;ðy  mxǃԂ BVW5qؖBSA{)5kJ^W{2SA< B!0ŢIAB6!a֠d2 Y] l4[eR8LvB " "+w'UtuHxP IMsZ!/8l &2 p{)X2 @,}ZW^V.-P4]!;اĕ.f/7iT+(g0iJArSdf q.e8 @Dv ldžC'N^n y\ 84A(LMQcO2>UiGB TOdWNuץ!2d/7iTreM;úS#@~`(5{/dqKdWNJ1V8!ԁ@Y9 @RT e/7iTsʁN^n yT>4`/7iT8MsZ!/&Co@5Pmk@}Aoޮ8 T"@Xʴ؁~JK@9v^V8 4b#' WwtO)n@V!d&\K( <Ӂ[l9{Ml-A  _c8B@bJ~O!MD- 0Ea:]s(`9>kmjB|bh 0oBMp>A_f'bdE}<8ΐkdȊ "&IRL|[ A@i,> TC8ϾW˼|!7&L^):?p `'ΐ⟄D}Gqa4:1)!dwPt'?GIQv 8%7"mN."G9?@0_]-ϠAm? :#P Z(m0a4畟z ,@0xB5MAe') Bd (HI­ p9 Aȃ (ȃ t E@ID pd$ mBX 9:!@"J[:!!  $#A%HB3AHt l oBT1=AH %)c!q DR#A8 RM @2\IAHL $3pAH6 \K)wJ }!7p7A Ar!)9\B @~!IAȕ $-AH=A٤ Br)EA @!9s Ir L N=A KP AfPA6PAA d K N2`@~ `BȈe #1ax `bsђ}Sp3_ټBhLq[ 4 ,AKFu]wJũA`Ą0D70A`%S&LX$+e0dRjXcBX3/]+r "+tE  ,Rp !@P&1eB J%j$gAY2 f5p_ P|&%ߊ^ nuH6 󾙈.ďw{(n^3!5s:AXO>:@o֐nq =` JלPJ.;`P20Nr˼ud4i}A:6= 1[bu)]&= !@P&>lv~7 {y 2!,j1:d5̄~ u %X= !@PlO|lyx'" 39 ɧ>7WZ}Iy, (%A B!@P (A J m;Hu?Ek!ouP KF`PjB1~jBX~T!18cPBHP7AX8 @}!|$ %!jBpmz tv$`$phBCB!`O&1ޤw +"DEǟ7*a0@q,st]g0@Y!@P (A J%A B!@P (A mm;qLe(@P (A J%A B!@P (A J%A B!@P (A J%A B!@P? x[IENDB`nlopt-2.6.1/doc/docs/images/Nlopt-logo.png000066400000000000000000000670461345435414600204040ustar00rootroot00000000000000PNG  IHDR Z\ pHYs&&mIDATx USqۤHBz2DxyLBJP )SГD<$DD%Jd($Ф&ͷ6;߽:-3s~<W;}2oِ֬!Cn*$ rrr8Kҥ;lܸQ"AI@}wRJ5id$ Mch ɀd /uI ( H"_1H%6lob$ꫯih 1BI@όq( H"I[b֭ۯ_5kH#JH!hPDjԨa-x@I@1c1.>}dffJ`( H]v5&ȸ⋝+"P,N=Tc┪UJh$_՘C9/=#QzaL S~;і-[>yIh$N;͘~@D( H85CH'Lx^k?~D"BI@zUV% 6o{ҥŋ7K:uI`( H5k:={tlf͌#`_( H%K% ,pqUKh$F^qN;Ϟ{| QЫjԮ]["E$ <57om۶vaxٳ%PJ F!:u2cڵk'81AI@\tEƸΞkB.\a+WnR z7o|۷o%񖙙mfZBM41cy)۷٣( >}:5jԐnǜtIR Ӻukce6klȐ![nxU1ӵkWr)x̨Q?;Ϙ"Rti%qyѬYFIAMNN΅^h>C[PW5 ټy!b8eѢERP㔮2es+ĕk s=xLǎO7&҄ A6n(P4JgŊ3u(dΜ9xa}4h`*UI&-Q?3uW.8 64c,-qNtҁ^sEI@x[k#+zm4kL ^7on}]tꫯ>nݺu]" 8Zח-[/)^xffl߾\rƸG1o<Q^kT]vxL.] ZZ"`( 7xq(d̙xLJrssUVƸΥ^*?ăIxuj׮m 0@ F˗/o=Z"`( u֕(Q$R02rHc\RJ@I@y[kTjUK?o LZvI%1mQN$ٳ1LcZ1cH%F!k׮=蠃%KfeeIIok*T p`֛oix^kT[o5cz!%u5$jܸ1sKQeԩx1/%i<55jDQC7n,U17H /4c*%i>3c\B |@R$ hT\Y!C 1c.)Ism:5$ 5%s113gΔ.'UBc\F rJbh3hݺ1s7JLFK1LAAAժUqAIDhTPI~1sH1̤IqRJmٲE" *DkԨQƸN2 I'1ӦMbok7n,-Jum:Ht?yc<[obk(-JܵF!7n,W1^rA_^?5EI@T֨P={JF ( J/x̱+Ģ$+:v$pݺu>@3'O6uXk|DIwcƌ1uH?q FuiذD?( ]vƸN wq1gϖ|KjՌq7xC"xL+Ud$Z?xL%mQ%6n(J6ٵY_$JF PF 4ӧO7cW.E$AIƍ3uZj1G k@$I#j\yRTQ1ꫯJ+Wl$UT1K222-Z$y̌3qbŊ]V"O6ac\'ԩ1]v5u|? @xkBV^F%ZB7|1BI;(QbӦMR0?1~:5Iw~c\'pt֬YqzۿF PBAAAժUq ( 30M#o|صFҥKc" mGI@DIll߾7KJ*%3=sy׍qOϵF! R?.%˗/O4|ݺu1cDH{gZ%K8s*UUשY{D5jHΝ;8 c\K/R$W_}1KE6uz%$1i ÇDI8 I&xt&رcK.Ds,X`hQfffFF1~>$ 0@"lҤIk׾סCo"lәXz1/HH5rnO't)Rx#8b_@sQ.\Xzu2D;O%Ft&Ӛ<5ڶm+!ɶ~yB.Smǎ/A$ Tয়~Hj?ꨣ!ݻwR*[n=CenڴGhҥ~Yg'EI[3{%b>}ԩy?O?TJtpok>l)&rS0~7:"- 7n,Q3!\DRի4Coma̙Re_qVs=qE>D誫)%Ғ0tߧモHz76lj̕W^i|uꂷ?h"Dh DZnߧSNI;֭sڂ3K.U1H̨֭Qh9ЫW/c\'iUZU"JB^^^  qƁ6nxmaСRO6c,XPfMc\'i))0n8ciӦI$mڴiȐ!͚5+]1N[n=k,)ϧ'Z~A"JBNC:w,mٲi _}rC9+ԉS>`c◳:KIXkQI^1Ȟ[o>lذ͛SO=UJu]/=zb"$̙3ǘ"2}thN[9rdVy)2{lcyIF`_\I^]Ji~#vˁK%\bLQD>#c;@IXn~Mk<5w0p@cG}T"HSގEsF !Pzco ;5oAc4[;j~ѴvBViy6lcgD~nݺ2eð$JΝ;˗/o3[4sF>ѣԶ.HߦïzF{F1?SyRm۶0gϖk$| >DHn}YpJ^&S{x=sjviW;.hqǵf:4˳P}2IKVK锟٘X%v{J½krH$Я@?պGe/TlDv>0CRd_E/v JqgzuzjEG^#9zuſc]bfˬ\o?燩{~M0l0cbZ#p@, 3f0&9g/z UA\t:wk\>n _9I㎓)n%'4&\qM8SG4=.VWuHM_`CH6N4v!|[]kԹsgY?|c"A}virn'{}z-;N+h.*DN6fY{oIhڴi ]VZL"%l̟3|pD+'ϞQe{q|T}]^f,|[on{fv[)%r-[W.${6{U&R_%N_|fGݻw׏8cvǙ!EU5 {wOF>aAϨ`'{N;{uM<%=5k4{bRtIhڴsI'͙3wU^tb*V(w6D{ނ|~ja݋jv3Z+(FKz,YbLTM%aǎe˖ 8㌬п߳$8mVN'fĉ90g~Z7}Տ,KJB߿;jt)4h1>$vKzzeɦ駟g}M~.  wJҥDg71~vfN&{[aUh5pcǭ-aP%]v΄c][]֭;䓝M"EX6q-u^"=8UWС]/j[vmD-aܟKBAAA*U=ٳgKH%oc̔Hƭ?ʮɨXm{@+֩Ez+{B|D-aܟKԩSK(1vXWIp|wJ߿ȉݯko#8U6~~UaD-aܟKz!G>}Zn-oCؽ{HĽ-;lwh")3o}ԪU˗PdI)&ap)t*{yxzT3{w$/thc]|$™g)$5nQg[s{â:kڙFw^$eY{;(P#&ѴzIFJBg$ x,Hrؑ=‹yWJxh 'xXk<$ijL/KoiH6R7ߦ;M BbŌ_ 7.x@IQQIgt]` W~x%؆Rf[~1b ɷxCIЪ>@G^G4O\/f*:$P\x`J`&Kjtuhgz^E r&~&̐뮻N!5ޤcI/{Ϣ'%#6lUK~!'{CJцF* :en`oxD")!'Ow>>W\sN)ڰx.%a*uzY}o+kDRγCU._%I<R$|3S q眆>.nphlIͷ[.{ۢw*#M8=WI~'!EeE2q) 7=1x8=X]-zH)$QI/ЇߪfLC]ntÿ^1?%)J\ mIMknʀ9/J~g%<5~IpIزSTp=|z e";_}_7]rذ(a%!k]q^-'-H'yrjy%R0Z#%wh<[<ϞwJ.FGpx>ŵ$ZO_vFD]?>]\'ilnSO`WJY;DmU̔+<2ҎڴMc( @n{¥F >( @gۗ %A$X7H k@PHk{µݥ؄F n( ?,A lO;%͓ؒPZm*x$w؞жkXk≒駹*^q%Z#gg%ᤖΑk@QmVlOxUɏ%WSmI(^OH%F۷_%"EIbglO8 (zEOѣmDĆ: OfŊK6QX6ޖiA>۶mS1 m %=R{e nڴi]t1H-o%T KMAAAժUId>={%oڒu$Kh 9J[;r&,^sժU3&B[ =Q- %Eҁ2ydH,Ju=C[BIay\⌒ImI8m&y m%|q ^K-$Qh J?g)մR)((4iRN~Ÿ{=ܒ%K$@ Qj˾p^{ɿ$m[Y&m $qn*]m{kH~|AIѶ$Th؄AI@^nVqh J0q@( @b<ϖ3P~QزC\g{KJm %H_H$y[̔ʶm6n("EI@>̑Hζqs[֭[R1cH$4}׳08GJR[XjUrBh4J`whL{;)ⴅo\1ɒB~~~֭ S( @ߢ# f8 &-dee5hԪUK"D$SP6l;ժUk޼>{ٳM6UT1fwXk@( @v'-$IZ#\$Ia,[2h|)P D[`Pdi 3^~e /_ `( @X^寴=Ϥ 'Bb֮]+@};S'ԜRBIsْPjmL;#$mnݺȉ*f)h$I$7_mm&w(P'@\յӛPNP2f KkcmJ %H:u R7qk 5S^]jO-6 ,^eBu..}'z0~vUTZ#Dd]zW_-.,^vJ_߆$GK 7M3fmFԆ 2&<ʚ5|逐[uiGLC}Pd}oa/4O#Y|l 5B, S~ؙ2E@Z/WꛙRCI԰ZSrX'eo 5B, ={J$bά7m\okT3I)J=`87>.w=KBŊZZ"XD*Jۨup#h)UBI׬v/T/qXk, (WN?I|rƠ9_LVWFC]*J( @RV"{2dHZ15TN _ ouzK/R+ mܪJW ЫKd/SN⋍sJ(~z 2_6 jT^PJPd2TM$=z/^ܘiذD1J/Hk6ꂻ›|2IJPd_==KӞ%7ސ"FIei9*R|ΗR7 &βף4gDe˖+5ڸqD1J/Hu 7h)CIᖞAyZ#xDIe@z6回HDIa:r6(|ɬ5G_PӮWpF==XJPx]{vr$+VׯQF5k_nn^QؙoשI% 3B,) HFh/UG|CIe.MRL.բDP|@غC7?n^HU `-W5qD_P|@Jp~Ϟu~۾$;%oķ*%{ls4WJPٲC\g/a* z{WÆu矏p5//]Z?M)_^P2Ы%F -Rz_ګXiD($<pRe( H+׫vIP~$\.^:=KBOJIYSܸ:ZF(]( @PMk_(QOsJƞ%᫯&X%apQaV}=ݞl}i{|o=aJyD$'O_S!( @5xP"@4, [9X%a|Q~n}`]]' ndTnۚD"2gjkNIzs VooV'@NV̙5C[z}}f֚5ϗH2eD'X%!;[i_ouuW?NKyvw{ON5s~J7О-v:9ՉHih^^( @΃v/Dm ;=n]U;Lodd#t)"5k;T.[ibA^McV?]ϝW/8S{bSڨm/ΏLX¯v'߱k5ǒN&Wx( @9N^$4xnU#cb2p=cm"~2?CmvOpZ%E'{AP{yr~!}$7/$r@997N?sαoD_"%Kvm=LIJ6J__%S }CxSNgkk"x}m_wiJ%HW^Z>)}Y@4˘JtMJBRڲWph,hxeH1 u_Z$NQ[S͋B_Gsp@ ,ȴW$XPt&MRӦ2&Gɒj%!lߩ^Cwxp4[o,;&ST{.LB$ ڰЯn䷤  E5{$%GOЉ\/l˶;ɖ~^_K%J:^ +]MۤͨQvNUMaD۲ct|Xd%c ohc%=|m^0 ( @p~]p&GJh{IѸiPc XROmYJMMNjiwg L޽ץRd:;~^cGg+ %!Ae3 l(P Yxϥ2 G̵gυ])R%H5-Ⱥ4ĉZUƤYSKH$mPa sEH7r9po4 ̾Iy1BIR55RdN5i"c|$ޙ;Ù;{9 r.jdIГOJ$EQblyko/ۭRز,5OWV|)6w#v׃[jh಍B e-^es.$@ Ԣgy=W!n٢~\%IEXvfޣZb6EhZvݓS{ n( @*{erSzڹaԬSKzK'(cŊ%r( 1vsU<'}8^om>m%He;rG,:ɘhSF *tj)ɓ%Z( 13Wm{w<czn6kŦ;"yO^[JmϬ(C&G( @;{-ȞT|b_5f2}%7NJkr>WMzX 5|^j[ɓU8Jԋ/JI;u2QʊAIuup)9S\Wlj^H+Z??Ru]w}6<{;-]#=μcq1-#o~-)ίًnԫ2GaC]+'?qpDR%'~lou.}I|5{^n{&ma*=} ң"$ JR RPڵeQzɹunYx<"$W$ eUI{k镑6;(2?SGEAh\]LbϢdDIŐr|Xc$% 1^FŊ3F r^}kJib%!:tp#Iĥs- 5nўSbuuꭺ =]t{¬mu-+Ѥ>7FR:)ԕ]`_ $YO)./_۾]+c\w)qFo/%p(lݡh%ztvo7mThb/Osy 0( @1P5Јo%2cvڹO+%sz1^ࠟχM$ $xIg~zg[]tE{o%; ǵС*r|_L_v8$y'\ēך5*_^Ƹ?.P t2B%5uZpC@Y~/8i$;U;w%~*]mϤL2f)m;OƸ'$,K'*vW[ih?Hu *Xwi\Mۤd˯xqn)Vy=+`$4?3'ω-c{GmC;y!QV ]ptsO/__)Ҹq7NfYgw㢋4Ȗ-:(nܟT]D uDS{;C O٨ KFb }PXR `51'%C~YƸq*B$1FŊ JB B= x?-}t3M/J Ps;#n}qn4i"Mvw_K 7( x4ogSo@r$Pj%n7seYt2Q"ACIدg b K2ɌFh;kfɧnT}-\)%02hZJm%4}OC5n-TND( @`nɿ}+H +dI-[&_F1̙ J>4W\ۆ^ ou[A$Ax=?\eOuDQ#b\~)(P2xQ %(3ΕҎj۲uտ_Q25Z"Ho `Bۡ6|H/OyReJ1.F~R];byDū'պ{CXAwV9'1Y"H{ ` Cߎ;sUO adj3n,_.$Ѳ,2|b{suM7iuo$P mz-/|ʨc:#srq1=WJdgew ( {XQW'FqEsИ3$SkGMlCgt2x )su2ŸR%wꬶtbKeEvQ} ށZV( @ C=*K/ W0C[,1RzwdQD˶lȹ"<;ްh~G|'xk`O CTTDs`$bxY^%JBIuTWz-Ȕ/p2Tҩ FI*jzW]nA޺#dbo/#^ c\mXKn/De)~<.8 hv(1BI,K-|}̃R2S"R2Ř8Q"%!sq]>!F;§׏.`( @n:fGn}Kϯ]zHqH׮2x-+۰a . ] .;su2, un{ `?( @C= o1 Se7GxK)iVƸFIDW_^H@qIxqxx*dj1+{_K/Jlۡ?~Ŵ0ZEiBƸSJD_Ƹ?,HגڴߗΚ`"KBo@$L'1-X5y:u92XN"]vDZQ?g?ɏLZط,E*( @nzP}o_NjFhڂb1 2eq1.z';/J„v##jiɏX{HF[oRDIfźǂhl=rL"F=>)('OEUtyDvYBƸg%H0o*6턖zԎhRϼu%%ʢt5>A"[wسNyR,rq1N=U"㨣\]=H ;EZ`ԬztjZw߭GhB)IfNji/2vԎɏVFtc( @Y[>]>޵A 4w{6l1.FejbwW^"KtV?mJ¶Rɿiv7hEIizNƕ]s]hoޟҥeLD /28|ii_~"Q|RK{( yjLKVK>wej1J7MO%mjLcΊu*}%Sq1v쐈4fq1F**Ԅ jXƤpew}|Ip__{U)HSK>ejqN;Cܠ$}ejoCUl$s2Ř=["2h^:P\Ƥ8=btcWiPf/)ڝO}ts/}N[h̓ %?kUF;8@5;GkݮNƸcJD[ƸOvcKƸCHDYƸ.EzdL:bԱ[R$>Kd?k=kD?P1sQx?|JVolv*|RƸ}HD6b|A71;VլYRcTIX2|$K&3PԱrזGΜ/۲u1ʛo6Fd1%]]ڷ1i=ToI 88%aV{2s螘? 8Ю#oG9FhT}{V?F1.FR'?!mv1>N oxOquUwsH救a+4i)E )+vRdqU6}BFN?tjL+T1>W^* #'7<}CAIRټkkV5҅w-˗OK`\n *EW%dʪUkn=EֶmRܓB%a|{sD@$)n6{+~YMjeNƸ.kyFƸJiv)$ɩ'ڽT1GRܓ*%!srJ4xnQ X( @+PLvb˨Mps*C)]s2hH8)S 9驧OJkZ)I-;_[ۗ*%GwMvRiFƸU銣LedWz%!$+9q:IMKBb6h%i*DIh5Cn~nb8b)jIp{eQ$<2nJ&J|.[&۷tibTl)`=&W $7Im׹$|=ѹ, J"@`QDe3!xc)\uq7ޮIdK%Qq7{Nc\f.3D $9af9.c܍&_NjS]ߍ $7I0w:HƸ HqL`KM:4" ( U պ ZD]U^&=$G61_*L:);wJJ0KBNjwׁSo7( |0kJշ?JӲq7J֊RgXzx;MJ¯wc)^ fIGA WJ>Jto'ܨMXθV)]Ƹe4) O1.FiR%?nPU7,v"c\~͝w/%I2SKo1.FRR/}( UPf̔ 3I޲iӗQ>\J%c\ %OI0tq1O).Y\Ƹ xmlww (FI৛Ӆ^ݭݪ5G:,Qm/) &BB˲$oyqTV}Яۧ\B.S~IƸ7 &"GONy_nVR%@D訠.Gҧ$ΚeWZG9NW=pYgiVɿIIm>$ Pď?NdLl3˯Tɮb]wu릾}eKmMu dLlGz )I4fdQ-47>n6- %@.:z])ySO=jIX@g!c\%ۧjiDCIWEG5k}l.HƤV^IVc9餴_禽DDIoEGgޡ)_ ej)^I0|P+#!&UuuIz+i ޖg~ƀ'I5jղS@KB~6lnQ' cw)coki ~mg!is`g8|kp4ioW%ti'lY8mI{uz>7"%@b~Eݤ-;$3~51%K\TG{ēg?g3>JXyN1gP˖v gqM]/JBvRZZZا?IH{ /*VNJOb%Ktv 1F#ڸQJyIHㆰ3WwOƋiGGIHe%_̵Rvz֕WCdLRJԼ=m˭%LP-]>+]mQ$VnjzRIԳ6 nOnW"%eҶ$wKe|cud؅ g\#;Gy=)ٹS|Wzv'ECUӦviKI.=KB6ڼYJ,T+{( OT}\$%$;vݺ鮻tMrw=seFvPձzK/駟''V8B~(ov;n'nEI#vrZe'MZΞ5J#F/4y-ҦMR %J5hj)Ӯ}UVkyɃ )ݤcJ$Qҡ$(VRgW3 '̐?$H_Lݓ %ZL"ui^%`/Ic[$)YʗW0$uN>׮"E$H"9:6;wD/eJAn]{JݤIv[QfqDI\f,A $gJBÆOᔁW^kX͜+؇FWz~D%@yaĔkdwpG\* ?/)١oI@jǜqru@QRvaըD%@2\JW#jQRZ^9UzKD IMeM;sa%5d}6ogJP$iM+ %!E[w݊JU ]5|sBvDbYm?% 2ImVUo|N"FIHEw>a %@k.O%@0l١OI$F( )>Rj\/.Qƌ*{Db*>>S2$=J ykn( )aAu+B %@.@( ϑzp+( fN΁.Q򵜊 *3wndgB!QnX(^OΔ(PRh2T28G"~$ٯKw% :Au׋v>Tz"_PpUQUvo׬͗H( upڰU"FI`B;7j|` m \̓?Pۘ)6MgoDDIC_))S8>,;;[a( ;C*QOcI$ٲC5n?7=! =\//W5\[oeeeI ۵7WiJxFIn'[tRPPO83sGbjժ3̙~ 'Ov(=۟ygZ, 4dɒrI'uiܸqyyyRT$Hk7٭] R~D<$ǓTKj*T0qeV͛7K^BI:~YCӦ_$~ی3?pcNRׯwbw9R/˫P`7̛f\r gqFn~'$H5OlBIHzy^m&|Dc9m۶| |΢je1.uQ}}5wDCƸKٲe6mڿ5kHТE 籜ab3vÆ>1D-dLcA'8?t#?8p6;\FFƅ^O/KBZ!TesrAC"1xt4U %9G/CJ?S%ᩧj QquI)nڔؐSN17N?iS' t  6mJ-ۗXb_|q޽?:8@KkĩNUي^뫊$ QfQ, b*PQALBHE@QpAA KDAA&BF{gs! 9&?*ky\{؛vf/unDŞuDWkk{T/ '***&&fԩŶ%PpMwzM)%![/U"J~%XVA'N$JΞccYvI ~Y"JvjYVZ-[4i҉A!J/79ZxP2PK; a"8~YVYSNlll5Ee$ٺl]v{!YV㩧$EkTyhϔ|[V[n\\ܬYRS+Z R$I3ΕHI`ǐ!-iGQDU7L†LHeYQQڹS"n:n{P"Əߴi7|СC'$D|Z-Tl[ۧeYݺ)-M"I~m(Mrr>ޣ$P:KHءٳ5fzVz~s3GwK=8<6/jQD8sEkLnEfpsB%L7J@U$h&i/ojw|UNC;["%@D;Zfrvzgm%ET]w9>P"`ye?&K@x$tj5L΋מ qB6( Y^3Q;RK!dYf?x}I@8$fVӵ UUyxJ8vq3ik҃uG6;7wNC( ` f֘|]8LyG% P8if=ٚ33HG$ ,Qžږ$~΍7 +BIR=D3tyWs|RsPҼJ.-L p$]ty&lOl>Z^"@I*6NUFt˴1gDe) :k 2 Tß["CIrd昃h 8 6a'O!?a*JmK: ! }1~x2r$We"~Dftɥ{ڷzDP%_i;̇8xfzsEŘYkH. 1iON`J"<*]pkxuPQXOn&RI.%7 [J%YfbɝU\M~n~9q%@Mv3f:u-+-ЀΡNqjmγq8/MyvDx&W'ӳ%2esdaf`G°$¥iB;pX{8G55W&j7 ?"[F>g}$y4CIPmڥjoء O>mHDJ:`44!EI>^:Sum_ȣ+$aަpڼ[ _|眦 JH1]3Ͳ'k%Wn#͇G7%1ѯۙurX:]<6J"B F"%@z}jwlN΍/'yuiu׫K@U$@)sAJpY*gu173xqJzy }4%+8+N&( `ffq4s8i@.y%sǫzkzx&-S'm3?ْ~լAAIgMgɊjJO-0 Qθrҏ%* ycK1Z{J!L8yR<;C N%@D+=AͦejT3}]t6*f8i^qO IV7?rቒf^>pr`V(Ekw0狞U//H%$N렉67b?՛$ Qݏ$+z|]|?ާ/HQ1JSewD=JO93'* ,sW3) 3:qC T_9fCp_]^U DIgiϻJ3'5C~^U7V^0 ljdstzgGve"$@6[t\]|K:Ưn6G3yz*kuI&h @Q,{:'|V,Z vjᆕ;;w],CIrp wo0r[I.tn~:$E^mUW>@P (2NFSۄ˖0_ZQw )8L~%4JT@ߑ&>P㕒"( 9S[A4jnҜ9۵sDFi6-IENDB`nlopt-2.6.1/doc/docs/index.md000066400000000000000000000106171345435414600160200ustar00rootroot00000000000000--- # NLopt --- ![center|600px](images/Nlopt-logo.png) NLopt ----- **NLopt** is a free/open-source library for **nonlinear optimization**, providing a common interface for a number of different free optimization routines available online as well as original implementations of various other algorithms. Its features include: - Callable from [C](NLopt_Reference.md), [C++](NLopt_C-plus-plus_Reference.md), [Fortran](NLopt_Fortran_Reference.md), [Matlab or GNU Octave](NLopt_Matlab_Reference.md), [Python](NLopt_Python_Reference.md), [GNU Guile](NLopt_Guile_Reference.md), [Julia](https://github.com/stevengj/NLopt.jl), [GNU R](NLopt_R_Reference.md), [Lua](https://github.com/rochus-keller/LuaNLopt), [OCaml](https://bitbucket.org/mkur/nlopt-ocaml) and [Rust](https://github.com/jesskfullwood/rust-nlopt). - A common interface for [many different algorithms](NLopt_Algorithms.md)—try a different algorithm just by changing one parameter. - Support for large-scale optimization (some algorithms scalable to millions of parameters and thousands of constraints). - Both global and local optimization algorithms. - Algorithms using function values only (derivative-free) and also algorithms exploiting user-supplied gradients. - Algorithms for unconstrained optimization, bound-constrained optimization, and general nonlinear inequality/equality constraints. - Free/open-source software under the [GNU LGPL](https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License) (and looser licenses for some portions of NLopt). See the [NLopt Introduction](NLopt_Introduction.md) for a further overview of the types of problems it addresses. Download and installation ------------------------- Version 2.6.1 of NLopt is the latest version available from GitHub: - [v2.6.1.tar.gz](https://github.com/stevengj/nlopt/archive/v2.6.1.tar.gz) See the [NLopt release notes](https://github.com/stevengj/nlopt/blob/master/NEWS.md) for the release history. NLopt is designed to be installed on any Unix-like system (GNU/Linux is fine) with a C compiler, using the standard ``` cmake . && make && sudo make install ``` procedure. See the [NLopt Installation](NLopt_Installation.md) instructions for more information. For Microsoft Windows, see [NLopt on Windows](NLopt_on_Windows.md) for more information and precompiled libraries. For **developers**, the latest development sources can be found at [](https://github.com/stevengj/nlopt). Documentation and Mailing Lists ------------------------------- See the [NLopt manual](NLopt_Introduction.md) for information on how to use NLopt and what optimization algorithms it includes. Please [cite NLopt](Citing_NLopt.md) and the authors of the algorithm(s) you use in any publication that stems from your use of NLopt. ### Mailing Lists The NLopt mailing lists (and their archives) are another source of information about NLopt. Subscribe to the (read-only) [nlopt-announce mailing list](http://ab-initio.mit.edu/cgi-bin/mailman/listinfo/nlopt-announce) to receive an email when NLopt is updated in the future. Subscribe to the (unmoderated) [nlopt-discuss mailing list](http://ab-initio.mit.edu/cgi-bin/mailman/listinfo/nlopt-discuss) for discussion of questions and ideas about using NLopt. As an alternative to the *nlopt-announce* mailing list, an [Atom newsfeed](https://en.wikipedia.org/wiki/Atom_(standard)) for NLopt releases is available from the [Freshmeat.net NLopt page](http://freshmeat.net/projects/nlopt). Acknowledgements ---------------- We are grateful to the many authors who have published useful optimization algorithms implemented in NLopt, especially those who have provided free/open-source implementations of their algorithms. *Please cite* these authors if you use their code or the implementation of their algorithm in NLopt. See the documentation for the appropriate citation for each of the [algorithms in NLopt](NLopt_Algorithms.md) — please see the [Citing NLopt](Citing_NLopt.md) information. Contact and Feedback -------------------- For bug reports and feature requests, please [file a github issue](https://github.com/stevengj/nlopt/issues). If you have questions or problems regarding NLopt, you are encouraged query the [nlopt-discuss mailing list](http://ab-initio.mit.edu/cgi-bin/mailman/listinfo/nlopt-discuss) (see above). As your first resort, please look at the [nlopt-discuss archives](http://ab-initio.mit.edu/pipermail/nlopt-discuss/). nlopt-2.6.1/doc/requirements.txt000066400000000000000000000000251345435414600167130ustar00rootroot00000000000000python-markdown-math nlopt-2.6.1/mkdocs.yml000066400000000000000000000026051345435414600146730ustar00rootroot00000000000000site_name: NLopt Documentation site_author: S. G. Johnson et al. repo_url: https://github.com/stevengj/nlopt/ edit_uri: edit/master/doc/docs docs_dir: 'doc/docs' site_dir: 'doc/site' theme: readthedocs python: version: 2 # for unicode setup_py_install: True markdown_extensions: - wikilinks - toc: title: Table of Contents - attr_list - fenced_code - mdx_math: enable_dollar_delimiter: True extra_javascript: ['https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML','mathjaxhelper.js'] pages: - NLopt: - Overview: index.md - FAQ: NLopt_FAQ.md - NLopt manual: - NLopt manual: NLopt_manual.md - Introduction: NLopt_Introduction.md - Installation: NLopt_Installation.md - Tutorial: NLopt_Tutorial.md - NLopt reference: - General reference: NLopt_Reference.md - C++ reference: NLopt_C-plus-plus_Reference.md - Fortran reference: NLopt_Fortran_Reference.md - Matlab reference: NLopt_Matlab_Reference.md - Python reference: NLopt_Python_Reference.md - Guile reference: NLopt_Guile_Reference.md - R reference: NLopt_R_Reference.md - Deprecated API reference: NLopt_Deprecated_API_Reference.md - NLopt algorithms: - NLopt algorithms: NLopt_Algorithms.md - NLopt on Windows: NLopt_on_Windows.md - License and Copyright: NLopt_License_and_Copyright.md - Citing NLopt: Citing_NLopt.md nlopt-2.6.1/nlopt.pc.in000066400000000000000000000004071345435414600147530ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: NLopt Description: nonlinear optimization libary Version: @NLOPT_VERSION_STRING@ Libs: -L${libdir} -lnlopt Libs.private: -lm Cflags: -I${includedir} nlopt-2.6.1/nlopt_config.h.in000066400000000000000000000113551345435414600161310ustar00rootroot00000000000000/*============================================================================== # NLOPT CMake configuration file # # NLopt is a free/open-source library for nonlinear optimization, providing # a common interface for a number of different free optimization routines # available online as well as original implementations of various other # algorithms # WEBSITE: http://ab-initio.mit.edu/wiki/index.php/NLopt # AUTHOR: Steven G. Johnson # # This config.cmake.h.in file was created to compile NLOPT with the CMAKE utility. # Benoit Scherrer, 2010 CRL, Harvard Medical School # Copyright (c) 2008-2009 Children's Hospital Boston # # Minor changes to the source was applied to make possible the compilation with # Cmake under Linux/Win32 #============================================================================*/ /* Bugfix version number. */ #define BUGFIX_VERSION @NLOPT_BUGFIX_VERSION@ /* Define to enable extra debugging code. */ #undef DEBUG /* Define to 1 if you have the `BSDgettimeofday' function. */ #undef HAVE_BSDGETTIMEOFDAY /* Define if the copysign function/macro is available. */ #cmakedefine HAVE_COPYSIGN /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DLFCN_H /* Define if the fpclassify() function/macro is available. */ #cmakedefine HAVE_FPCLASSIFY /* Define to 1 if you have the header file. */ #cmakedefine HAVE_GETOPT_H /* Define to 1 if you have the `getpid' function. */ #cmakedefine HAVE_GETPID /* Define if syscall(SYS_gettid) available. */ #undef HAVE_GETTID_SYSCALL /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H /* Define if the isinf() function/macro is available. */ #cmakedefine HAVE_ISINF /* Define if the isnan() function/macro is available. */ #cmakedefine HAVE_ISNAN /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MEMORY_H /* Define to 1 if you have the `qsort_r' function. */ #cmakedefine HAVE_QSORT_R /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRING_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H /* Define to 1 if you have the `time' function. */ #cmakedefine HAVE_TIME /* Define to 1 if the system has the type `uint32_t'. */ #cmakedefine HAVE_UINT32_T /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Major version number. */ #define MAJOR_VERSION @NLOPT_MAJOR_VERSION@ /* Minor version number. */ #define MINOR_VERSION @NLOPT_MINOR_VERSION@ /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* replacement for broken HUGE_VAL macro, if needed */ #undef REPLACEMENT_HUGE_VAL /* The size of `unsigned int', as computed by sizeof. */ #define SIZEOF_UNSIGNED_INT @SIZEOF_UNSIGNED_INT@ /* The size of `unsigned long', as computed by sizeof. */ #define SIZEOF_UNSIGNED_LONG @SIZEOF_UNSIGNED_LONG@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to C thread-local keyword, or to nothing if this is not supported in your compiler. */ #define THREADLOCAL @THREADLOCAL@ /* Define to 1 if you can safely include both and . */ #cmakedefine TIME_WITH_SYS_TIME /* Version number of package */ #undef VERSION /* Define if compiled including C++-based routines */ #cmakedefine NLOPT_CXX /* Define if compiled including C++11-based routines */ #cmakedefine NLOPT_CXX11 /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif nlopt-2.6.1/src/000077500000000000000000000000001345435414600134545ustar00rootroot00000000000000nlopt-2.6.1/src/algs/000077500000000000000000000000001345435414600144025ustar00rootroot00000000000000nlopt-2.6.1/src/algs/ags/000077500000000000000000000000001345435414600151545ustar00rootroot00000000000000nlopt-2.6.1/src/algs/ags/COPYRIGHT000066400000000000000000000020661345435414600164530ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2018 Sovrasov V. 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. nlopt-2.6.1/src/algs/ags/README000066400000000000000000000015061345435414600160360ustar00rootroot00000000000000An implementation of the algorithm AGS to solve constrained nonlinear programming problems with Lipschitzian functions. AGS was introduced by prof. R.G. Strongin (see R. G. Strongin, D. L. Markin, ,Minimization of multiextremal functions under nonconvex constraints, Cybernetics 22(4), 486-493. Translated from Russian. Consultant Bureau. New York, 1986.). The method exploits Peano-type curve to reduce dimension of the source bounded multidimensional constrained NLP problem and then solves a univariate one. AGS is proven to converge to a global optima if all objectives and constraints satisfy Lipschitz condition in a given hyperrectangle, the reliability parameter r is large enough and accuracy parameter eps is zero. Contributed to NLopt by Vladislav Sovrasov from https://github.com/sovrasov/glob_search_nlp_solvernlopt-2.6.1/src/algs/ags/ags.cc000066400000000000000000000067641345435414600162520ustar00rootroot00000000000000// A C-callable front-end to the AGS global-optimization library. // -- Vladislav Sovrasov #include "ags.h" #include "solver.hpp" #include #include #include #include double ags_eps = 0; double ags_r = 3; double eps_res = 0.001; unsigned evolvent_density = 12; int ags_refine_loc = 0; int ags_verbose = 0; int ags_minimize(unsigned n, nlopt_func func, void *data, unsigned m, nlopt_constraint *fc, double *x, double *minf, const double *l, const double *u, nlopt_stopping *stop) { int ret_code = NLOPT_SUCCESS; if (n > ags::solverMaxDim) return NLOPT_INVALID_ARGS; if(m != nlopt_count_constraints(m, fc) || m > ags::solverMaxConstraints) return NLOPT_INVALID_ARGS; if (ags_verbose && n > 5) std::cout << "Warning: AGS is unstable when dimension > 5" << std::endl; std::vector lb(l, l + n); std::vector ub(u, u + n); std::vector functions; for (unsigned i = 0; i < m; i++) { if (fc[i].m != 1) return NLOPT_INVALID_ARGS; functions.push_back([fc, n, i](const double* x) { double val = 0; nlopt_eval_constraint(&val, NULL, &fc[i], n, x); return val; }); } functions.push_back([func, data, n, stop](const double* x) { ++ *(stop->nevals_p); return func(n, x, NULL, data);}); ags::SolverParameters params; params.r = ags_r; params.itersLimit = stop->maxeval != 0 ? stop->maxeval : std::numeric_limits::max(); params.eps = ags_eps; params.evolventDensity = evolvent_density; params.epsR = eps_res; params.stopVal = stop->minf_max; params.refineSolution = (bool)ags_refine_loc; ags::NLPSolver solver; solver.SetParameters(params); solver.SetProblem(functions, lb, ub); ags::Trial optPoint; try { auto external_stop_func = [stop, &ret_code](){ if (nlopt_stop_time(stop)) { ret_code = NLOPT_MAXTIME_REACHED; return true; } else if (nlopt_stop_forced(stop)) { ret_code = NLOPT_FORCED_STOP; return true; } else return false; }; optPoint = solver.Solve(external_stop_func); } catch (const std::exception& exp) { std::cerr << "AGS internal error: " << std::string(exp.what()) << std::endl; return NLOPT_FAILURE; } if (ags_verbose) { auto calcCounters = solver.GetCalculationsStatistics(); auto holderConstEstimations = solver.GetHolderConstantsEstimations(); std::cout << std::string(20, '-') << "AGS statistics: " << std::string(20, '-') << std::endl; for (size_t i = 0; i < calcCounters.size() - 1; i++) std::cout << "Number of calculations of constraint # " << i << ": " << calcCounters[i] << "\n"; std::cout << "Number of calculations of objective: " << calcCounters.back() << "\n";; for (size_t i = 0; i < holderConstEstimations.size() - 1; i++) std::cout << "Estimation of Holder constant of function # " << i << ": " << holderConstEstimations[i] << "\n"; std::cout << "Estimation of Holder constant of objective: " << holderConstEstimations.back() << "\n"; if (optPoint.idx != (int)m) std::cout << "Feasible point not found" << "\n"; std::cout << std::string(40, '-') << std::endl; } if ((int)m == optPoint.idx) { memcpy(x, optPoint.y, n*sizeof(x[0])); *minf = optPoint.g[optPoint.idx]; } else //feasible point not found. return NLOPT_FAILURE; if (solver.GetCalculationsStatistics()[0] >= params.itersLimit) return NLOPT_MAXEVAL_REACHED; return ret_code; } nlopt-2.6.1/src/algs/ags/ags.h000066400000000000000000000030001345435414600160700ustar00rootroot00000000000000/* A C-callable front-end to the AGS global-optimization library. -- Vladislav Sovrasov */ #ifndef AGS_H #define AGS_H #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* The algorithm supports 3 types of stop criterions: stop by execution time, stop by value and stop by exceeding limit of iterations. */ int ags_minimize(unsigned n, nlopt_func func, void *data, unsigned m, nlopt_constraint *fc, double *x, double *minf, const double *l, const double *u, nlopt_stopping *stop); extern double ags_eps; /* method tolerance in Holder metric on 1d interval. Less value -- better search precision, less probability of early stop. */ extern double ags_r; /* reliability parameter. Higher value of r -- slower convergence, higher chance to cache the global minima. */ extern double eps_res; /* parameter which prevents method from paying too much attention to constraints. Greater values of this parameter speed up convergence, but global minima can be lost. */ extern unsigned evolvent_density; /* density of evolvent. By default density is 2^-12 on hybercube [0,1]^N, which means that maximum search accuracyis 2^-12. If search hypercube is large the density can be increased accordingly to achieve better accuracy. */ extern int ags_refine_loc; /* refine the final optimum using built-in local optimizer */ extern int ags_verbose; /* print additional info */ #ifdef __cplusplus } #endif #endif nlopt-2.6.1/src/algs/ags/data_types.hpp000066400000000000000000000027751345435414600200350ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #pragma once #include #include #define NLP_SOLVER_ERROR(msg) throw std::runtime_error(std::string(msg)) #define NLP_SOLVER_ASSERT(expr, msg) if(!(expr)) NLP_SOLVER_ERROR(msg) namespace ags { const unsigned solverMaxDim = 10; const unsigned solverMaxConstraints = 10; template class IGOProblem { public: ~IGOProblem() {} virtual fptype Calculate(const fptype* y, int fNumber) const = 0; virtual int GetConstraintsNumber() const = 0; virtual int GetDimension() const = 0; virtual void GetBounds(fptype* left, fptype* right) const = 0; virtual int GetOptimumPoint(fptype* y) const = 0; virtual fptype GetOptimumValue() const = 0 ; }; struct Trial { double x; double y[solverMaxDim]; double g[solverMaxConstraints + 1]; int idx; Trial() {} Trial(double _x) : x(_x) {} }; struct Interval { Trial pl; Trial pr; double R; double delta; Interval() {} Interval(const Trial& _pl, const Trial& _pr) : pl(_pl), pr(_pr) {} }; struct CompareIntervals { bool operator() (const Interval* i1, const Interval* i2) const { return i1->pl.x < i2->pl.x; } }; class CompareByR { public: bool operator() (const Interval* i1, const Interval* i2) const { return i1->R < i2->R; } }; } nlopt-2.6.1/src/algs/ags/evolvent.cc000066400000000000000000000101361345435414600173260ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #include "evolvent.hpp" #include #include #include using namespace ags; void mapd(double x, int m, double* y, int n, int key = 1); /* map x to y */ Evolvent::Evolvent() { mIsInitialized = false; } Evolvent::~Evolvent() { } Evolvent::Evolvent(int dimension, int tightness, const double* lb, const double* ub) { assert(tightness > 2); mDimension = dimension; mTightness = tightness; mShiftScalars.resize(mDimension); mRho.resize(mDimension); for (int i = 0; i < mDimension; i++) { mRho[i] = ub[i] - lb[i]; mShiftScalars[i] = 0.5*(lb[i] + ub[i]); } mIsInitialized = true; } void Evolvent::TransformToStandardCube(const double *y, double *z) { for (int i = 0; i < mDimension; i++) z[i] = (y[i] - mShiftScalars[i]) / mRho[i]; } void Evolvent::TransformToSearchDomain(const double *y, double *z) { for (int i = 0; i < mDimension; i++) z[i] = mRho[i]*y[i] + mShiftScalars[i]; } void Evolvent::GetImage(double x, double y[]) { if(mDimension != 1) mapd(x, mTightness, y, mDimension); else y[0] = x - 0.5; TransformToSearchDomain(y, y); } void mapd(double x, int m, double* y, int n, int key) { /* mapping y(x) : 1 - center, 2 - line, 3 - node */ // use key = 1 int n1, nexp, l, iq, iu[10], iv[10]; double d, mne, dd, dr;//,tmp; double p, r; int iw[11]; int it, is = 0, i, j, k; void node(int is, int n1, int nexp, int& l, int& iq, int iu[], int iv[]); p = 0.0; n1 = n - 1; for (nexp = 1, i = 0; i 2) { dr = mne / nexp; dr = dr - fmod(dr, 1.0); //dr=(dr>0)?floor(dr):ceil(dr); dd = mne - dr; dr = d*dd; dd = dr - fmod(dr, 1.0); //dd=(dr>0)?floor(dr):ceil(dr); dr = dd + (dd - 1) / (nexp - 1); dd = dr - fmod(dr, 1.0); //dd=(dr>0)?floor(dr):ceil(dr); d = dd*(1. / (mne - 1.0)); } for (j = 0; j0) || ((iq == 0) && (is == 0))) k = l; else if (iq<0) k = (it == n1) ? 0 : n1; r = r*0.5; it = l; for (i = 0; i= iff) { if ((is == iff) && (is != 1)) { l = i; iq = -1; } is = is - iff; k2 = 1; } else { k2 = -1; if ((is == (iff - 1)) && (is != 0)) { l = i; iq = 1; } } j = -k1*k2; iv[i] = j; iu[i] = j; k1 = k2; } iv[l] = iv[l] * iq; iv[n1] = -iv[n1]; } } nlopt-2.6.1/src/algs/ags/evolvent.hpp000066400000000000000000000013731345435414600175330ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #pragma once #include namespace ags { class Evolvent { protected: int mDimension; int mTightness; std::vector mRho; std::vector mShiftScalars; void TransformToStandardCube(const double *y, double *z); void TransformToSearchDomain(const double *y, double *z); bool mIsInitialized; public: Evolvent(); Evolvent(int dimension, int tightness, const double* lb, const double* ub); ~Evolvent(); virtual void GetImage(double x, double y[]); }; } nlopt-2.6.1/src/algs/ags/local_optimizer.cc000066400000000000000000000077311345435414600206670ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #include "local_optimizer.hpp" #include #include #include using namespace ags; #define MAX_LOCAL_ITERATIONS_NUMBER 20 void HookeJeevesOptimizer::SetParameters(double eps, double step, double stepMult) { NLP_SOLVER_ASSERT(eps > 0 && step > 0 && stepMult > 0, "Wrong papameters of the local optimizer"); mEps = eps; mStep = step; mStepMultiplier = stepMult; } Trial HookeJeevesOptimizer::Optimize(std::shared_ptr> problem, const Trial& startPoint, std::vector& trialsCounters) { mProblem = problem; mStartPoint = startPoint; mTrialsCounters = std::vector(mProblem->GetConstraintsNumber() + 1, 0); int k = 0, i=0; bool needRestart = true; /* currentFvalue will be initialized below, init here to avoid maybe-uninitialized warning */ double currentFValue = 0.0, nextFValue; while (i < MAX_LOCAL_ITERATIONS_NUMBER) { i++; if (needRestart) { k = 0; mCurrentPoint = mStartPoint; mCurrentResearchDirection = mStartPoint; currentFValue = ComputeObjective(mCurrentPoint.y); needRestart = false; } std::swap(mPreviousResearchDirection, mCurrentResearchDirection); mCurrentResearchDirection = mCurrentPoint; nextFValue = MakeResearch(mCurrentResearchDirection.y); if (currentFValue > nextFValue) { DoStep(); k++; currentFValue = nextFValue; } else if (mStep > mEps) { if (k != 0) std::swap(mStartPoint, mPreviousResearchDirection); else mStep /= mStepMultiplier; needRestart = true; } else break; } mPreviousResearchDirection.idx = 0; while (mPreviousResearchDirection.idx < mProblem->GetConstraintsNumber()) { mTrialsCounters[mPreviousResearchDirection.idx]++; mPreviousResearchDirection.g[mPreviousResearchDirection.idx] = mProblem->Calculate(mPreviousResearchDirection.y, mPreviousResearchDirection.idx); if (mPreviousResearchDirection.g[mPreviousResearchDirection.idx] > 0) break; mPreviousResearchDirection.idx++; } if (mPreviousResearchDirection.idx == mProblem->GetConstraintsNumber()) { mPreviousResearchDirection.g[mPreviousResearchDirection.idx] = mProblem->Calculate(mPreviousResearchDirection.y, mPreviousResearchDirection.idx); mTrialsCounters[mPreviousResearchDirection.idx]++; } for(size_t i = 0; i < mTrialsCounters.size(); i++) trialsCounters[i] += mTrialsCounters[i]; return mPreviousResearchDirection; } void HookeJeevesOptimizer::DoStep() { for (int i = 0; i < mProblem->GetDimension(); i++) mCurrentPoint.y[i] = (1 + mStepMultiplier)*mCurrentResearchDirection.y[i] - mStepMultiplier*mPreviousResearchDirection.y[i]; } double HookeJeevesOptimizer::ComputeObjective(const double* x) const { for (int i = 0; i <= mProblem->GetConstraintsNumber(); i++) { double value = mProblem->Calculate(x, i); mTrialsCounters[i]++; if (i < mProblem->GetConstraintsNumber() && value > 0) return std::numeric_limits::max(); else if (i == mProblem->GetConstraintsNumber()) return value; } return std::numeric_limits::max(); } double HookeJeevesOptimizer::MakeResearch(double* startPoint) { double bestValue = ComputeObjective(startPoint); for (int i = 0; i < mProblem->GetDimension(); i++) { startPoint[i] += mStep; double rightFvalue = ComputeObjective(startPoint); if (rightFvalue > bestValue) { startPoint[i] -= 2 * mStep; double leftFValue = ComputeObjective(startPoint); if (leftFValue > bestValue) startPoint[i] += mStep; else bestValue = leftFValue; } else bestValue = rightFvalue; } return bestValue; } nlopt-2.6.1/src/algs/ags/local_optimizer.hpp000066400000000000000000000017441345435414600210670ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #pragma once #include "data_types.hpp" #include #include namespace ags { class HookeJeevesOptimizer { private: double mEps; double mStep; double mStepMultiplier; mutable std::vector mTrialsCounters; std::shared_ptr> mProblem; Trial mCurrentPoint; Trial mStartPoint; Trial mCurrentResearchDirection; Trial mPreviousResearchDirection; void DoStep(); double ComputeObjective(const double* x) const; double MakeResearch(double*); public: void SetParameters(double eps, double step, double stepMult); Trial Optimize(std::shared_ptr> problem, const Trial& startPoint, std::vector& trialsCounters); }; } nlopt-2.6.1/src/algs/ags/solver.cc000066400000000000000000000312271345435414600170020ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #include "solver.hpp" #include #include #include using namespace ags; namespace { const double zeroHLevel = 1e-12; class ProblemInternal : public IGOProblem { private: std::vector mFunctions; std::vector mLeftBound; std::vector mRightBound; unsigned mDimension; unsigned mConstraintsNumber; public: ProblemInternal(const std::vector& functions, const std::vector& leftBound, const std::vector& rightBound) { mFunctions = functions; mConstraintsNumber = mFunctions.size() - 1; mDimension = leftBound.size(); mLeftBound = leftBound; mRightBound = rightBound; } double Calculate(const double* y, int fNumber) const { return mFunctions[fNumber](y); } int GetConstraintsNumber() const { return mConstraintsNumber; } int GetDimension() const { return mDimension; } void GetBounds(double* left, double* right) const { for(size_t i = 0; i < mDimension; i++) { left[i] = mLeftBound[i]; right[i] = mRightBound[i]; } } int GetOptimumPoint(double*) const {return 0;} double GetOptimumValue() const {return 0;} }; } NLPSolver::NLPSolver() {} void NLPSolver::SetParameters(const SolverParameters& params) { mParameters = params; } void NLPSolver::SetProblem(std::shared_ptr> problem) { mProblem = problem; NLP_SOLVER_ASSERT(mProblem->GetConstraintsNumber() <= (int)solverMaxConstraints, "Current implementation supports up to " + std::to_string(solverMaxConstraints) + " nonlinear inequality constraints"); InitLocalOptimizer(); } void NLPSolver::SetProblem(const std::vector& functions, const std::vector& leftBound, const std::vector& rightBound) { NLP_SOLVER_ASSERT(leftBound.size() == rightBound.size(), "Inconsistent dimensions of bounds"); NLP_SOLVER_ASSERT(leftBound.size() > 0, "Zero problem dimension"); mProblem = std::make_shared(functions, leftBound, rightBound); NLP_SOLVER_ASSERT(mProblem->GetConstraintsNumber() <= (int)solverMaxConstraints, "Current implementation supports up to " + std::to_string(solverMaxConstraints) + " nonlinear inequality constraints"); InitLocalOptimizer(); } std::vector NLPSolver::GetCalculationsStatistics() const { return mCalculationsCounters; } std::vector NLPSolver::GetHolderConstantsEstimations() const { return mHEstimations; } void NLPSolver::InitLocalOptimizer() { std::vector leftBound(mProblem->GetDimension()); std::vector rightBound(mProblem->GetDimension()); mProblem->GetBounds(leftBound.data(), rightBound.data()); double maxSize = 0; for(size_t i = 0; i < leftBound.size(); i++) maxSize = std::max(rightBound[i] - leftBound[i], maxSize); NLP_SOLVER_ASSERT(maxSize > 0, "Empty search domain"); mLocalOptimizer.SetParameters(maxSize / 1000, maxSize / 100, 2); } void NLPSolver::InitDataStructures() { double leftDomainBound[solverMaxDim], rightDomainBound[solverMaxDim]; mProblem->GetBounds(leftDomainBound, rightDomainBound); mEvolvent = Evolvent(mProblem->GetDimension(), mParameters.evolventDensity, leftDomainBound, rightDomainBound); mNextPoints.resize(mParameters.numPoints); mOptimumEstimation.idx = -1; mZEstimations.resize(mProblem->GetConstraintsNumber() + 1); std::fill(mZEstimations.begin(), mZEstimations.end(), std::numeric_limits::max()); mNextIntervals.resize(mParameters.numPoints); mHEstimations.resize(mProblem->GetConstraintsNumber() + 1); std::fill(mHEstimations.begin(), mHEstimations.end(), 1.0); mCalculationsCounters.resize(mProblem->GetConstraintsNumber() + 1); std::fill(mCalculationsCounters.begin(), mCalculationsCounters.end(), 0); mQueue = PriorityQueue(); mIterationsCounter = 0; mMinDelta = std::numeric_limits::max(); mMaxIdx = -1; } void NLPSolver::ClearDataStructures() { for (const auto& ptr : mSearchInformation) delete ptr; mSearchInformation.clear(); mQueue = PriorityQueue(); } Trial NLPSolver::Solve() { return Solve([](){return false;}); } Trial NLPSolver::Solve(std::function externalStopFunc) { mNeedStop = false; InitDataStructures(); FirstIteration(); do { InsertIntervals(); EstimateOptimum(); if (mNeedRefillQueue || mQueue.size() < mParameters.numPoints) RefillQueue(); CalculateNextPoints(); MakeTrials(); mNeedStop = mNeedStop || mMinDelta < mParameters.eps || externalStopFunc(); mIterationsCounter++; } while(mIterationsCounter < mParameters.itersLimit && !mNeedStop); ClearDataStructures(); if (mParameters.refineSolution && mOptimumEstimation.idx == mProblem->GetConstraintsNumber()) { auto localTrial = mLocalOptimizer.Optimize(mProblem, mOptimumEstimation, mCalculationsCounters); int idx = mOptimumEstimation.idx; if (localTrial.idx == idx && localTrial.g[idx] < mOptimumEstimation.g[idx]) mOptimumEstimation = localTrial; } return mOptimumEstimation; } void NLPSolver::FirstIteration() { Trial leftBound = Trial(0); leftBound.idx = -1; Trial rightBound = Trial(1.); rightBound.idx = -1; for (size_t i = 1; i <= mParameters.numPoints; i++) { mNextPoints[i - 1] = Trial((double)i / (mParameters.numPoints + 1)); mEvolvent.GetImage(mNextPoints[i - 1].x, mNextPoints[i - 1].y); } MakeTrials(); EstimateOptimum(); for (size_t i = 0; i <= mParameters.numPoints; i++) { Interval* pNewInterval; if (i == 0) pNewInterval = new Interval(leftBound, mNextPoints[i]); else if (i == mParameters.numPoints) pNewInterval = new Interval(mNextPoints[i - 1], rightBound); else pNewInterval = new Interval(mNextPoints[i - 1], mNextPoints[i]); pNewInterval->delta = pow(pNewInterval->pr.x - pNewInterval->pl.x, 1. / mProblem->GetDimension()); mMinDelta = std::min(mMinDelta, pNewInterval->delta); auto insRes = mSearchInformation.insert(pNewInterval); UpdateAllH(insRes.first); } RefillQueue(); CalculateNextPoints(); MakeTrials(); mIterationsCounter += 2; } void NLPSolver::MakeTrials() { for (size_t i = 0; i < mNextPoints.size(); i++) { int idx = 0; while(idx < mProblem->GetConstraintsNumber()) { mNextPoints[i].idx = idx; double val = mProblem->Calculate(mNextPoints[i].y, idx); mCalculationsCounters[idx]++; mNextPoints[i].g[idx] = val; if (val > 0) break; idx++; } if(idx > mMaxIdx) { mMaxIdx = idx; for(int i = 0; i < mMaxIdx; i++) mZEstimations[i] = -mParameters.epsR*mHEstimations[i]; mNeedRefillQueue = true; } if (idx == mProblem->GetConstraintsNumber()) { mCalculationsCounters[idx]++; mNextPoints[i].idx = idx; mNextPoints[i].g[idx] = mProblem->Calculate(mNextPoints[i].y, idx); } if(mNextPoints[i].idx == mMaxIdx && mNextPoints[i].g[mMaxIdx] < mZEstimations[mMaxIdx]) { mZEstimations[mMaxIdx] = mNextPoints[i].g[mMaxIdx]; mNeedRefillQueue = true; } } } void NLPSolver::InsertIntervals() { for (size_t i = 0; i < mParameters.numPoints; i++) { Interval* pOldInterval = mNextIntervals[i]; Interval* pNewInterval = new Interval(mNextPoints[i], pOldInterval->pr); pOldInterval->pr = mNextPoints[i]; pOldInterval->delta = pow(pOldInterval->pr.x - pOldInterval->pl.x, 1. / mProblem->GetDimension()); pNewInterval->delta = pow(pNewInterval->pr.x - pNewInterval->pl.x, 1. / mProblem->GetDimension()); mMinDelta = std::min(mMinDelta, pNewInterval->delta); mMinDelta = std::min(mMinDelta, pOldInterval->delta); auto insResult = mSearchInformation.insert(pNewInterval); bool wasInserted = insResult.second; if(!wasInserted) throw std::runtime_error("Error during interval insertion."); UpdateAllH(insResult.first); UpdateAllH(--insResult.first); if(!mNeedRefillQueue) { pNewInterval->R = CalculateR(pNewInterval); mNextIntervals[i]->R = CalculateR(mNextIntervals[i]); mQueue.push(pNewInterval); mQueue.push(pOldInterval); } } } void NLPSolver::CalculateNextPoints() { for(size_t i = 0; i < mParameters.numPoints; i++) { mNextIntervals[i] = mQueue.top(); mQueue.pop(); mNextPoints[i].x = GetNextPointCoordinate(mNextIntervals[i]); if (mNextPoints[i].x >= mNextIntervals[i]->pr.x || mNextPoints[i].x <= mNextIntervals[i]->pl.x) mNeedStop = true; //std::cout << "Warning: resolution of evolvent is not enough to continue the search"; mEvolvent.GetImage(mNextPoints[i].x, mNextPoints[i].y); } } void NLPSolver::RefillQueue() { mQueue = PriorityQueue(); for (const auto& pInterval : mSearchInformation) { pInterval->R = CalculateR(pInterval); mQueue.push(pInterval); } mNeedRefillQueue = false; } void NLPSolver::EstimateOptimum() { for (size_t i = 0; i < mNextPoints.size(); i++) { if (mOptimumEstimation.idx < mNextPoints[i].idx || (mOptimumEstimation.idx == mNextPoints[i].idx && mOptimumEstimation.g[mOptimumEstimation.idx] > mNextPoints[i].g[mNextPoints[i].idx])) { mOptimumEstimation = mNextPoints[i]; mNeedRefillQueue = true; if (mOptimumEstimation.idx == mProblem->GetConstraintsNumber() && mOptimumEstimation.g[mOptimumEstimation.idx] < mParameters.stopVal) mNeedStop = true; } } } void NLPSolver::UpdateH(double newValue, int index) { if (newValue > mHEstimations[index] || (mHEstimations[index] == 1.0 && newValue > zeroHLevel)) { mHEstimations[index] = newValue; mNeedRefillQueue = true; } } void NLPSolver::UpdateAllH(std::set::iterator iterator) { Interval* pInterval = *iterator; if (pInterval->pl.idx < 0) return; if (pInterval->pl.idx == pInterval->pr.idx) UpdateH(fabs(pInterval->pr.g[pInterval->pr.idx] - pInterval->pl.g[pInterval->pl.idx]) / pInterval->delta, pInterval->pl.idx); else { auto rightIterator = iterator; auto leftIterator = iterator; //right lookup ++rightIterator; while(rightIterator != mSearchInformation.end() && (*rightIterator)->pl.idx < pInterval->pl.idx) ++rightIterator; if (rightIterator != mSearchInformation.end() && (*rightIterator)->pl.idx >= pInterval->pl.idx) { int idx = pInterval->pl.idx; UpdateH(fabs((*rightIterator)->pl.g[idx] - pInterval->pl.g[idx]) / pow((*rightIterator)->pl.x - pInterval->pl.x, 1. / mProblem->GetDimension()), idx); } //left lookup --leftIterator; while(leftIterator != mSearchInformation.begin() && (*leftIterator)->pl.idx < pInterval->pl.idx) --leftIterator; if (leftIterator != mSearchInformation.begin() && (*leftIterator)->pl.idx >= pInterval->pl.idx) { int idx = pInterval->pl.idx; UpdateH(fabs((*leftIterator)->pl.g[idx] - pInterval->pl.g[idx]) / pow(pInterval->pl.x - (*leftIterator)->pl.x, 1. / mProblem->GetDimension()), idx); } } } double NLPSolver::CalculateR(Interval* i) const { if(i->pl.idx == i->pr.idx) { const int v = i->pr.idx; return i->delta + pow((i->pr.g[v] - i->pl.g[v]) / (mParameters.r * mHEstimations[v]), 2) / i->delta - 2.*(i->pr.g[v] + i->pl.g[v] - 2*mZEstimations[v]) / (mParameters.r * mHEstimations[v]); } else if(i->pl.idx < i->pr.idx) return 2*i->delta - 4*(i->pr.g[i->pr.idx] - mZEstimations[i->pr.idx]) / (mParameters.r * mHEstimations[i->pr.idx]); else return 2*i->delta - 4*(i->pl.g[i->pl.idx] - mZEstimations[i->pl.idx]) / (mParameters.r * mHEstimations[i->pl.idx]); } double NLPSolver::GetNextPointCoordinate(Interval* i) const { double x; if(i->pr.idx == i->pl.idx) { const int v = i->pr.idx; double dg = i->pr.g[v] - i->pl.g[v]; x = 0.5 * (i->pr.x + i->pl.x) - 0.5*((dg > 0.) ? 1. : -1.) * pow(fabs(dg) / mHEstimations[v], mProblem->GetDimension()) / mParameters.r; } else x = 0.5 * (i->pr.x + i->pl.x); return x; } bool solver_utils::checkVectorsDiff(const double* y1, const double* y2, size_t dim, double eps) { for (size_t i = 0; i < dim; i++) { if (fabs(y1[i] - y2[i]) > eps) return true; } return false; } nlopt-2.6.1/src/algs/ags/solver.hpp000066400000000000000000000070111345435414600171760ustar00rootroot00000000000000/* Copyright (C) 2018 Sovrasov V. - All Rights Reserved * You may use, distribute and modify this code under the * terms of the MIT license. * You should have received a copy of the MIT license with * this file. If not visit https://opensource.org/licenses/MIT */ #pragma once #include "data_types.hpp" #include "evolvent.hpp" #include "local_optimizer.hpp" #include #include #include #include #include #include namespace ags { struct SolverParameters { double eps = 0.01; //method tolerance in Holder metric on 1d interval. Less value -- better search precision, less probability of early stop. double stopVal = std::numeric_limits::lowest(); //method stops after objective becomes less than this value double r = 3; //reliability parameter. Higher value of r -- slower convergence, higher chance to cache the global minima. unsigned numPoints = 1; //number of new points per iteration. > 1 is useless in current implementation. unsigned itersLimit = 20000; // max number of iterations. unsigned evolventDensity = 12; // density of evolvent. By default density is 2^-12 on hybercube [0,1]^N, // which means that maximum search accuracyis 2^-12. If search hypercube is large the density can be increased accordingly to achieve better accuracy. double epsR = 0.001; // parameter which prevents method from paying too much attention to constraints. Greater values of this parameter speed up convergence, // but global minima can be lost. bool refineSolution = false; //if true, the fibal solution will be refined with the HookJeves method. SolverParameters() {} SolverParameters(double _eps, double _r, double epsR_, unsigned _trialsLimit) : eps(_eps), r(_r), itersLimit(_trialsLimit), epsR(epsR_) {} }; class NLPSolver { protected: using PriorityQueue = std::priority_queue, CompareByR>; HookeJeevesOptimizer mLocalOptimizer; SolverParameters mParameters; std::shared_ptr> mProblem; Evolvent mEvolvent; std::vector mHEstimations; std::vector mZEstimations; std::vector mNextPoints; PriorityQueue mQueue; std::set mSearchInformation; std::vector mNextIntervals; Trial mOptimumEstimation; std::vector mCalculationsCounters; unsigned mIterationsCounter; bool mNeedRefillQueue; bool mNeedStop; double mMinDelta; int mMaxIdx; void InitLocalOptimizer(); void FirstIteration(); void MakeTrials(); void InsertIntervals(); void CalculateNextPoints(); void RefillQueue(); void EstimateOptimum(); void InitDataStructures(); void ClearDataStructures(); void UpdateAllH(std::set::iterator); void UpdateH(double newValue, int index); double CalculateR(Interval*) const; double GetNextPointCoordinate(Interval*) const; public: using FuncPtr = std::function; NLPSolver(); void SetParameters(const SolverParameters& params); void SetProblem(std::shared_ptr> problem); void SetProblem(const std::vector& functions, const std::vector& leftBound, const std::vector& rightBound); Trial Solve(std::function externalStopFunc); Trial Solve(); std::vector GetCalculationsStatistics() const; std::vector GetHolderConstantsEstimations() const; }; namespace solver_utils { bool checkVectorsDiff(const double* y1, const double* y2, size_t dim, double eps); } } nlopt-2.6.1/src/algs/ags/tst.cc000066400000000000000000000030161345435414600162750ustar00rootroot00000000000000#define _USE_MATH_DEFINES #include #include #include #include "nlopt.hpp" double f_obj(const std::vector& x, std::vector&, void*) { return -1.5*pow(x[0], 2) * exp(1 - pow(x[0], 2) - 20.25*pow(x[0] - x[1], 2)) - pow(0.5 * (x[1] - 1)*(x[0]- 1), 4) * exp(2 - pow(0.5 * (x[0] - 1), 4) - pow(x[1] - 1, 4)); } double f_c0(const std::vector& x, std::vector&, void*) { return 0.01*(pow(x[0] - 2.2, 2) + pow(x[1] - 1.2, 2) - 2.25); } double f_c1(const std::vector& x, std::vector&, void*) { return 100 * (1 - pow(x[0] - 2, 2) / 1.44 - pow(0.5*x[1], 2)); } double f_c2(const std::vector& x, std::vector&, void*) { return 10 * (x[1] - 1.5 - 1.5*sin(2*M_PI*(x[0] - 1.75))); } int ags_verbose = 1; double ags_eps = 0.001; double eps_res = 0.1; int main(int argc, char **argv) { nlopt::opt opt(nlopt::GN_AGS, 2); opt.set_lower_bounds({0, -1}); opt.set_upper_bounds({4, 3}); opt.add_inequality_constraint(f_c0, NULL, 0); opt.add_inequality_constraint(f_c1, NULL, 0); opt.add_inequality_constraint(f_c2, NULL, 0); opt.set_min_objective(f_obj, NULL); opt.set_maxeval(2000); double minf; std::vector x(2); try { nlopt::result result = opt.optimize(x, minf); std::cout << "found minimum at f(" << x[0] << "," << x[1] << ") = " << std::setprecision(10) << minf << std::endl; } catch(std::exception &e) { std::cout << "nlopt failed: " << e.what() << std::endl; } return EXIT_SUCCESS; } nlopt-2.6.1/src/algs/auglag/000077500000000000000000000000001345435414600156425ustar00rootroot00000000000000nlopt-2.6.1/src/algs/auglag/README000066400000000000000000000020211345435414600165150ustar00rootroot00000000000000This directory contains my implementation of the "augmented Lagrangian" method to express constrained optimization problems (including equality constraints) in terms of unconstrained optimization problems (or just inequality constraints, or just box constraints). I used the algorithm description (but no source code) from the outline in the paper: E. G. Birgin and J. M. Martinez, "Improving ultimate convergence of an augmented Lagrangian method," Optimization Methods and Software vol. 23, no. 2, p. 177-195 (2008). http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.72.6121 (The authors of this paper have their own free-software implementation of this idea and its variations, in the TANGO project: http://www.ime.usp.br/~egbirgin/tango/ ....I did *not* use any code from TANGO here, or even look at the TANGO code. TANGO is GPLed, and I'm trying to keep NLopt at most LGPLed.) The code in this directory is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson November 2008 nlopt-2.6.1/src/algs/auglag/auglag.c000066400000000000000000000223521345435414600172520ustar00rootroot00000000000000#include #include #include #include #include "auglag.h" int auglag_verbose = 0; #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /***************************************************************************/ typedef struct { nlopt_func f; void *f_data; int m, mm; nlopt_constraint *fc; int p, pp; nlopt_constraint *h; double rho, *lambda, *mu; double *restmp, *gradtmp; nlopt_stopping *stop; } auglag_data; /* the augmented lagrangian objective function */ static double auglag(unsigned n, const double *x, double *grad, void *data) { auglag_data *d = (auglag_data *) data; double *gradtmp = grad ? d->gradtmp : NULL; double *restmp = d->restmp; double rho = d->rho; const double *lambda = d->lambda, *mu = d->mu; double L; int i, ii; unsigned j, k; L = d->f(n, x, grad, d->f_data); ++ *(d->stop->nevals_p); if (nlopt_stop_forced(d->stop)) return L; for (ii = i = 0; i < d->p; ++i) { nlopt_eval_constraint(restmp, gradtmp, d->h + i, n, x); if (nlopt_stop_forced(d->stop)) return L; for (k = 0; k < d->h[i].m; ++k) { double h = restmp[k] + lambda[ii++] / rho; L += 0.5 * rho * h*h; if (grad) for (j = 0; j < n; ++j) grad[j] += (rho * h) * gradtmp[k*n + j]; } } for (ii = i = 0; i < d->m; ++i) { nlopt_eval_constraint(restmp, gradtmp, d->fc + i, n, x); if (nlopt_stop_forced(d->stop)) return L; for (k = 0; k < d->fc[i].m; ++k) { double fc = restmp[k] + mu[ii++] / rho; if (fc > 0) { L += 0.5 * rho * fc*fc; if (grad) for (j = 0; j < n; ++j) grad[j] += (rho * fc) * gradtmp[k*n + j]; } } } return L; } /***************************************************************************/ nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, int p, nlopt_constraint *h, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt sub_opt, int sub_has_fc) { auglag_data d; nlopt_result ret = NLOPT_SUCCESS; double ICM = HUGE_VAL, minf_penalty = HUGE_VAL, penalty; double *xcur = NULL, fcur; int i, ii, feasible, minf_feasible = 0; unsigned int k; int auglag_iters = 0; int max_constraint_dim; /* magic parameters from Birgin & Martinez */ const double tau = 0.5, gam = 10; const double lam_min = -1e20, lam_max = 1e20, mu_max = 1e20; d.f = f; d.f_data = f_data; d.m = m; d.fc = fc; d.p = p; d.h = h; d.stop = stop; /* whether we handle inequality constraints via the augmented Lagrangian penalty function, or directly in the sub-algorithm */ if (sub_has_fc) d.m = 0; else m = 0; max_constraint_dim = MAX(nlopt_max_constraint_dim(d.m, fc), nlopt_max_constraint_dim(d.p, h)); d.mm = nlopt_count_constraints(d.m, fc); d.pp = nlopt_count_constraints(d.p, h); ret = nlopt_set_min_objective(sub_opt, auglag, &d); if (ret<0) return ret; ret = nlopt_set_lower_bounds(sub_opt, lb); if (ret<0) return ret; ret = nlopt_set_upper_bounds(sub_opt, ub); if (ret<0) return ret; ret = nlopt_set_stopval(sub_opt, d.m==0 && d.p==0 ? stop->minf_max : -HUGE_VAL); if (ret<0) return ret; ret = nlopt_remove_inequality_constraints(sub_opt); if (ret<0) return ret; ret = nlopt_remove_equality_constraints(sub_opt); if (ret<0) return ret; for (i = 0; i < m; ++i) { if (fc[i].f) ret = nlopt_add_inequality_constraint(sub_opt, fc[i].f, fc[i].f_data, fc[i].tol[0]); else ret = nlopt_add_inequality_mconstraint(sub_opt, fc[i].m, fc[i].mf, fc[i].f_data, fc[i].tol); if (ret < 0) return ret; } xcur = (double *) malloc(sizeof(double) * (n + max_constraint_dim * (1 + n) + d.pp + d.mm)); if (!xcur) return NLOPT_OUT_OF_MEMORY; memcpy(xcur, x, sizeof(double) * n); d.restmp = xcur + n; d.gradtmp = d.restmp + max_constraint_dim; memset(d.gradtmp, 0, sizeof(double) * (n*max_constraint_dim + d.pp+d.mm)); d.lambda = d.gradtmp + n * max_constraint_dim; d.mu = d.lambda + d.pp; *minf = HUGE_VAL; /* starting rho suggested by B & M */ if (d.p > 0 || d.m > 0) { double con2 = 0; ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } penalty = 0; feasible = 1; for (i = 0; i < d.p; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.h + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.h[i].m; ++k) { double hi = d.restmp[k]; penalty += fabs(hi); feasible = feasible && fabs(hi) <= h[i].tol[k]; con2 += hi * hi; } } for (i = 0; i < d.m; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.fc + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.fc[i].m; ++k) { double fci = d.restmp[k]; penalty += fci > 0 ? fci : 0; feasible = feasible && fci <= fc[i].tol[k]; if (fci > 0) con2 += fci * fci; } } *minf = fcur; minf_penalty = penalty; minf_feasible = feasible; d.rho = (con2 > 0) ? MAX(1e-6, MIN(10, 2 * fabs(*minf) / con2)) : 10; } else d.rho = 1; /* whatever, doesn't matter */ if (auglag_verbose) { printf("auglag: initial rho=%g\nauglag initial lambda=", d.rho); for (i = 0; i < d.pp; ++i) printf(" %g", d.lambda[i]); printf("\nauglag initial mu = "); for (i = 0; i < d.mm; ++i) printf(" %g", d.mu[i]); printf("\n"); } do { double prev_ICM = ICM; ret = nlopt_optimize_limited(sub_opt, xcur, &fcur, stop->maxeval - *(stop->nevals_p), stop->maxtime - (nlopt_seconds() - stop->start)); if (auglag_verbose) printf("auglag: subopt return code %d\n", ret); if (ret < 0) break; ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } if (auglag_verbose) printf("auglag: fcur = %g\n", fcur); ICM = 0; penalty = 0; feasible = 1; for (i = ii = 0; i < d.p; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.h + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.h[i].m; ++k) { double hi = d.restmp[k]; double newlam = d.lambda[ii] + d.rho * hi; penalty += fabs(hi); feasible = feasible && fabs(hi) <= h[i].tol[k]; ICM = MAX(ICM, fabs(hi)); d.lambda[ii++] = MIN(MAX(lam_min, newlam), lam_max); } } for (i = ii = 0; i < d.m; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.fc + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.fc[i].m; ++k) { double fci = d.restmp[k]; double newmu = d.mu[ii] + d.rho * fci; penalty += fci > 0 ? fci : 0; feasible = feasible && fci <= fc[i].tol[k]; ICM = MAX(ICM, fabs(MAX(fci, -d.mu[ii] / d.rho))); d.mu[ii++] = MIN(MAX(0.0, newmu), mu_max); } } if (ICM > tau * prev_ICM) { d.rho *= gam; } auglag_iters++; if (auglag_verbose) { printf("auglag %d: ICM=%g (%sfeasible), rho=%g\nauglag lambda=", auglag_iters, ICM, feasible ? "" : "not ", d.rho); for (i = 0; i < d.pp; ++i) printf(" %g", d.lambda[i]); printf("\nauglag %d: mu = ", auglag_iters); for (i = 0; i < d.mm; ++i) printf(" %g", d.mu[i]); printf("\n"); } if ((feasible && (!minf_feasible || penalty < minf_penalty || fcur < *minf)) || (!minf_feasible && penalty < minf_penalty)) { ret = NLOPT_SUCCESS; if (feasible) { if (fcur < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_ftol(stop, fcur, *minf)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xcur, x)) ret = NLOPT_XTOL_REACHED; } *minf = fcur; minf_penalty = penalty; minf_feasible = feasible; memcpy(x, xcur, sizeof(double) * n); if (ret != NLOPT_SUCCESS) break; } if (nlopt_stop_forced(stop)) {ret = NLOPT_FORCED_STOP; break;} if (nlopt_stop_evals(stop)) {ret = NLOPT_MAXEVAL_REACHED; break;} if (nlopt_stop_time(stop)) {ret = NLOPT_MAXTIME_REACHED; break;} /* TODO: use some other stopping criterion on ICM? */ /* The paper uses ICM <= epsilon and DFM <= epsilon, where DFM is a measure of the size of the Lagrangian gradient. Besides the fact that these kinds of absolute tolerances (non-scale-invariant) are unsatisfying and it is not clear how the user should specify it, the ICM <= epsilon condition seems not too different from requiring feasibility, especially now that the user can provide constraint-specific tolerances analogous to epsilon. */ if (ICM == 0) {ret = NLOPT_FTOL_REACHED; break;} } while (1); done: free(xcur); return ret; } nlopt-2.6.1/src/algs/auglag/auglag.h000066400000000000000000000033131345435414600172530ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef AUGLAG_H #define AUGLAG_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ extern int auglag_verbose; nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, int p, nlopt_constraint *h, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt sub_opt, int sub_has_fc); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/bobyqa/000077500000000000000000000000001345435414600156575ustar00rootroot00000000000000nlopt-2.6.1/src/algs/bobyqa/COPYRIGHT000066400000000000000000000022771345435414600171620ustar00rootroot00000000000000/* Copyright (c) 2009 M. J. D. Powell (mjdp@cam.ac.uk) * Modifications Copyright (c) 2010 Massachusetts Institute of Technology * * 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. */ nlopt-2.6.1/src/algs/bobyqa/README000066400000000000000000000016741345435414600165470ustar00rootroot00000000000000This is the BOBYQA software by M. J. D. Powell, which performs derivative-free unconstrained optimization using an iteratively constructred quadratic approximation for the objective function. See: M. J. D. Powell, "The BOBYQA algorithm for bound constrained optimization without derivatives," Department of Applied Mathematics and Theoretical Physics, Cambridge England, technical report NA2009/06 (2009). http://www.damtp.cam.ac.uk/user/na/NA_papers/NA2009_06.pdf http://plato.asu.edu/ftp/other_software/bobyqa.zip The C translation by S. G. Johnson (2009) includes a few minor modifications, mainly to use the NLopt stopping criteria (and to take the objective function as an argument rather than a global). The original Fortran code was released by Powell with "no restrictions or charges", and the C translation by S. G. Johnson is released in a similar spirit under the MIT License (see the COPYRIGHT file in this directory). nlopt-2.6.1/src/algs/bobyqa/README.orig000066400000000000000000000073701345435414600175050ustar00rootroot00000000000000=========================================================================== On 8/13/09 added the paper on BOBYQA =========================================================================== For simplicity, the Makefi;e has been replaced by a one-line compile script "comp" which needs to be adjusted if the compiler name is not f77. All Fortran files are in bobyla.f. Compiling and running bobyqa should produce results similar to those in RESULTS. Hans Mittelmann, Jan 2009 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Fortran version of BOBYQA is attached. Its purpose is to seek the least value of a function F of several variables, when derivatives are not available, where F is specified by the user through a subroutine called CALFUN. The name BOBYQA denotes Bound Approximation BY Quadratic Approximation, the constraints being lower and upper bounds on every variable, which can be set to huge values for unconstrained variables. The algorithm is intended to change the variables to values that are close to a local minimum of F. The user, however, should assume responsibility for finding out if the calculations are satisfactory, by considering carefully the values of F that occur. The BOBYQA software has been developed from the method of the paper "The NEWUOA software for unconstrained minimization without derivatives", in Large-Scale Nonlinear Optimization, editors G. Di Pillo and M. Roma, Springer (2006), pages 255-297. A report that describes the details of the development is going to be written soon. The attachments in sequence are a suitable Makefile, followed by a main program and a CALFUN routine for the "Invdist2" problem, in order to provide an example for testing. Then BOBYQA and its six auxiliary routines, namely BOBYQB, ALTMOV, PRELIM, RESCUE, TRSBOX and UPDATE, are given. Finally, the computed output that the author obtained for the Invdist2 problems is listed. In addition to providing CALFUN, an initial vector of variables and the lower and upper bounds, the user has to set the values of the parameters RHOBEG, RHOEND and NPT. After scaling the individual variables if necessary, so that the magnitudes of their expected changes are similar, RHOBEG is the initial steplength for changes to the variables, a reasonable choice being the mesh size of a coarse grid search. Further, RHOEND should be suitable for a search on a very fine grid. Typically, the software calculates a vector of variables that is within distance 10*RHOEND of a local minimum. Another consideration is that every trial vector of variables is forced to satisfy the lower and upper bounds, but there has to be room to make a search in all directions. Therefore an error return occurs if the difference between the bounds on any variable is less than 2*RHOBEG. The parameter NPT specifies the number of interpolation conditions on each quadratic model, the value NPT=2*N+1 being recommended for a start, where N is the number of variables. It is often worthwhile to try other choices too, but much larger values tend to be inefficient, because the amount of routine work of each iteration is of magnitude NPT**2, and because the achievement of adequate accuracy in some matrix calculations becomes more difficult. Some excellent numerical results have been found in the case NPT=N+6 even with more than 100 variables. The way of calling BOBYQA should be clear from the Invdist2 examples and from the comments near the beginning of SUBROUTINE BOBYQA. There are no restrictions on or charges for the use of the software. I hope that the time and effort I have spent on developing the package will be helpful to much research and to many applications. January 5th, 2009 M.J.D. Powell (mjdp@cam.ac.uk) nlopt-2.6.1/src/algs/bobyqa/bobyqa.c000066400000000000000000002670421345435414600173130ustar00rootroot00000000000000/* BOBYQA derivative-free optimization code by M. J. D. Powell. Original Fortran code by Powell (2009). Converted via v2c, cleaned up, and incorporated into NLopt by S. G. Johnson (2009). See README. */ #include #include #include #include "bobyqa.h" typedef double (*bobyqa_func)(int n, const double *x, void *func_data); #define MIN2(a,b) ((a) <= (b) ? (a) : (b)) #define MAX2(a,b) ((a) >= (b) ? (a) : (b)) #define IABS(x) ((x) < 0 ? -(x) : (x)) static void update_(int *n, int *npt, double *bmat, double *zmat, int *ndim, double *vlag, double *beta, double *denom, int *knew, double *w) { /* System generated locals */ int bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2; double d__1, d__2, d__3; /* Local variables */ int i__, j, k, jp; double one, tau, temp; int nptm; double zero, alpha, tempa, tempb, ztest; /* The arrays BMAT and ZMAT are updated, as required by the new position */ /* of the interpolation point that has the index KNEW. The vector VLAG has */ /* N+NPT components, set on entry to the first NPT and last N components */ /* of the product Hw in equation (4.11) of the Powell (2006) paper on */ /* NEWUOA. Further, BETA is set on entry to the value of the parameter */ /* with that name, and DENOM is set to the denominator of the updating */ /* formula. Elements of ZMAT may be treated as zero if their moduli are */ /* at most ZTEST. The first NDIM elements of W are used for working space. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --vlag; --w; /* Function Body */ one = 1.; zero = 0.; nptm = *npt - *n - 1; ztest = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { i__2 = nptm; for (j = 1; j <= i__2; ++j) { /* L10: */ /* Computing MAX */ d__2 = ztest, d__3 = (d__1 = zmat[k + j * zmat_dim1], fabs(d__1)); ztest = MAX2(d__2,d__3); } } ztest *= 1e-20; /* Apply the rotations that put zeros in the KNEW-th row of ZMAT. */ i__2 = nptm; for (j = 2; j <= i__2; ++j) { if ((d__1 = zmat[*knew + j * zmat_dim1], fabs(d__1)) > ztest) { /* Computing 2nd power */ d__1 = zmat[*knew + zmat_dim1]; /* Computing 2nd power */ d__2 = zmat[*knew + j * zmat_dim1]; temp = sqrt(d__1 * d__1 + d__2 * d__2); tempa = zmat[*knew + zmat_dim1] / temp; tempb = zmat[*knew + j * zmat_dim1] / temp; i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { temp = tempa * zmat[i__ + zmat_dim1] + tempb * zmat[i__ + j * zmat_dim1]; zmat[i__ + j * zmat_dim1] = tempa * zmat[i__ + j * zmat_dim1] - tempb * zmat[i__ + zmat_dim1]; /* L20: */ zmat[i__ + zmat_dim1] = temp; } } zmat[*knew + j * zmat_dim1] = zero; /* L30: */ } /* Put the first NPT components of the KNEW-th column of HLAG into W, */ /* and calculate the parameters of the updating formula. */ i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { w[i__] = zmat[*knew + zmat_dim1] * zmat[i__ + zmat_dim1]; /* L40: */ } alpha = w[*knew]; tau = vlag[*knew]; vlag[*knew] -= one; /* Complete the updating of ZMAT. */ temp = sqrt(*denom); tempb = zmat[*knew + zmat_dim1] / temp; tempa = tau / temp; i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { /* L50: */ zmat[i__ + zmat_dim1] = tempa * zmat[i__ + zmat_dim1] - tempb * vlag[ i__]; } /* Finally, update the matrix BMAT. */ i__2 = *n; for (j = 1; j <= i__2; ++j) { jp = *npt + j; w[jp] = bmat[*knew + j * bmat_dim1]; tempa = (alpha * vlag[jp] - tau * w[jp]) / *denom; tempb = (-(*beta) * w[jp] - tau * vlag[jp]) / *denom; i__1 = jp; for (i__ = 1; i__ <= i__1; ++i__) { bmat[i__ + j * bmat_dim1] = bmat[i__ + j * bmat_dim1] + tempa * vlag[i__] + tempb * w[i__]; if (i__ > *npt) { bmat[jp + (i__ - *npt) * bmat_dim1] = bmat[i__ + j * bmat_dim1]; } /* L60: */ } } } /* update_ */ static nlopt_result rescue_(int *n, int *npt, const double *xl, const double *xu, /* int *maxfun */ nlopt_stopping *stop, bobyqa_func calfun, void *calfun_data, double *xbase, double *xpt, double *fval, double *xopt, double *gopt, double *hq, double *pq, double *bmat, double *zmat, int *ndim, double *sl, double *su, /* int *nf, */ double *delta, int *kopt, double *vlag, double * ptsaux, double *ptsid, double *w) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2, i__3; double d__1, d__2, d__3, d__4; /* Local variables */ double f; int i__, j, k, ih, jp, ip, iq, np, iw; double xp = 0.0, xq = 0.0, den; int ihp = 0; double one; int ihq, jpn, kpt; double sum, diff, half, beta; int kold; double winc; int nrem, knew; double temp, bsum; int nptm; double zero, hdiag, fbase, sfrac, denom, vquad, sumpq; double dsqmin, distsq, vlmxsq; /* The arguments N, NPT, XL, XU, MAXFUN, XBASE, XPT, FVAL, XOPT, */ /* GOPT, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU have the same meanings as */ /* the corresponding arguments of BOBYQB on the entry to RESCUE. */ /* NF is maintained as the number of calls of CALFUN so far, except that */ /* NF is set to -1 if the value of MAXFUN prevents further progress. */ /* KOPT is maintained so that FVAL(KOPT) is the least calculated function */ /* value. Its correct value must be given on entry. It is updated if a */ /* new least function value is found, but the corresponding changes to */ /* XOPT and GOPT have to be made later by the calling program. */ /* DELTA is the current trust region radius. */ /* VLAG is a working space vector that will be used for the values of the */ /* provisional Lagrange functions at each of the interpolation points. */ /* They are part of a product that requires VLAG to be of length NDIM. */ /* PTSAUX is also a working space array. For J=1,2,...,N, PTSAUX(1,J) and */ /* PTSAUX(2,J) specify the two positions of provisional interpolation */ /* points when a nonzero step is taken along e_J (the J-th coordinate */ /* direction) through XBASE+XOPT, as specified below. Usually these */ /* steps have length DELTA, but other lengths are chosen if necessary */ /* in order to satisfy the given bounds on the variables. */ /* PTSID is also a working space array. It has NPT components that denote */ /* provisional new positions of the original interpolation points, in */ /* case changes are needed to restore the linear independence of the */ /* interpolation conditions. The K-th point is a candidate for change */ /* if and only if PTSID(K) is nonzero. In this case let p and q be the */ /* int parts of PTSID(K) and (PTSID(K)-p) multiplied by N+1. If p */ /* and q are both positive, the step from XBASE+XOPT to the new K-th */ /* interpolation point is PTSAUX(1,p)*e_p + PTSAUX(1,q)*e_q. Otherwise */ /* the step is PTSAUX(1,p)*e_p or PTSAUX(2,q)*e_q in the cases q=0 or */ /* p=0, respectively. */ /* The first NDIM+NPT elements of the array W are used for working space. */ /* The final elements of BMAT and ZMAT are set in a well-conditioned way */ /* to the values that are appropriate for the new interpolation points. */ /* The elements of GOPT, HQ and PQ are also revised to the values that are */ /* appropriate to the final quadratic model. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xl; --xu; --xbase; --fval; --xopt; --gopt; --hq; --pq; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --sl; --su; --vlag; ptsaux -= 3; --ptsid; --w; /* Function Body */ half = .5; one = 1.; zero = 0.; np = *n + 1; sfrac = half / (double) np; nptm = *npt - np; /* Shift the interpolation points so that XOPT becomes the origin, and set */ /* the elements of ZMAT to zero. The value of SUMPQ is required in the */ /* updating of HQ below. The squares of the distances from XOPT to the */ /* other interpolation points are set at the end of W. Increments of WINC */ /* may be added later to these squares to balance the consideration of */ /* the choice of point that is going to become current. */ sumpq = zero; winc = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { distsq = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { xpt[k + j * xpt_dim1] -= xopt[j]; /* L10: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1]; distsq += d__1 * d__1; } sumpq += pq[k]; w[*ndim + k] = distsq; winc = MAX2(winc,distsq); i__2 = nptm; for (j = 1; j <= i__2; ++j) { /* L20: */ zmat[k + j * zmat_dim1] = zero; } } /* Update HQ so that HQ and PQ define the second derivatives of the model */ /* after XBASE has been shifted to the trust region centre. */ ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { w[j] = half * sumpq * xopt[j]; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L30: */ w[j] += pq[k] * xpt[k + j * xpt_dim1]; } i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; /* L40: */ hq[ih] = hq[ih] + w[i__] * xopt[j] + w[j] * xopt[i__]; } } /* Shift XBASE, SL, SU and XOPT. Set the elements of BMAT to zero, and */ /* also set the elements of PTSAUX. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { xbase[j] += xopt[j]; sl[j] -= xopt[j]; su[j] -= xopt[j]; xopt[j] = zero; /* Computing MIN */ d__1 = *delta, d__2 = su[j]; ptsaux[(j << 1) + 1] = MIN2(d__1,d__2); /* Computing MAX */ d__1 = -(*delta), d__2 = sl[j]; ptsaux[(j << 1) + 2] = MAX2(d__1,d__2); if (ptsaux[(j << 1) + 1] + ptsaux[(j << 1) + 2] < zero) { temp = ptsaux[(j << 1) + 1]; ptsaux[(j << 1) + 1] = ptsaux[(j << 1) + 2]; ptsaux[(j << 1) + 2] = temp; } if ((d__2 = ptsaux[(j << 1) + 2], fabs(d__2)) < half * (d__1 = ptsaux[( j << 1) + 1], fabs(d__1))) { ptsaux[(j << 1) + 2] = half * ptsaux[(j << 1) + 1]; } i__2 = *ndim; for (i__ = 1; i__ <= i__2; ++i__) { /* L50: */ bmat[i__ + j * bmat_dim1] = zero; } } fbase = fval[*kopt]; /* Set the identifiers of the artificial interpolation points that are */ /* along a coordinate direction from XOPT, and set the corresponding */ /* nonzero elements of BMAT and ZMAT. */ ptsid[1] = sfrac; i__2 = *n; for (j = 1; j <= i__2; ++j) { jp = j + 1; jpn = jp + *n; ptsid[jp] = (double) j + sfrac; if (jpn <= *npt) { ptsid[jpn] = (double) j / (double) np + sfrac; temp = one / (ptsaux[(j << 1) + 1] - ptsaux[(j << 1) + 2]); bmat[jp + j * bmat_dim1] = -temp + one / ptsaux[(j << 1) + 1]; bmat[jpn + j * bmat_dim1] = temp + one / ptsaux[(j << 1) + 2]; bmat[j * bmat_dim1 + 1] = -bmat[jp + j * bmat_dim1] - bmat[jpn + j * bmat_dim1]; zmat[j * zmat_dim1 + 1] = sqrt(2.) / (d__1 = ptsaux[(j << 1) + 1] * ptsaux[(j << 1) + 2], fabs(d__1)); zmat[jp + j * zmat_dim1] = zmat[j * zmat_dim1 + 1] * ptsaux[(j << 1) + 2] * temp; zmat[jpn + j * zmat_dim1] = -zmat[j * zmat_dim1 + 1] * ptsaux[(j << 1) + 1] * temp; } else { bmat[j * bmat_dim1 + 1] = -one / ptsaux[(j << 1) + 1]; bmat[jp + j * bmat_dim1] = one / ptsaux[(j << 1) + 1]; /* Computing 2nd power */ d__1 = ptsaux[(j << 1) + 1]; bmat[j + *npt + j * bmat_dim1] = -half * (d__1 * d__1); } /* L60: */ } /* Set any remaining identifiers with their nonzero elements of ZMAT. */ if (*npt >= *n + np) { i__2 = *npt; for (k = np << 1; k <= i__2; ++k) { iw = (int) (((double) (k - np) - half) / (double) (*n) ); ip = k - np - iw * *n; iq = ip + iw; if (iq > *n) { iq -= *n; } ptsid[k] = (double) ip + (double) iq / (double) np + sfrac; temp = one / (ptsaux[(ip << 1) + 1] * ptsaux[(iq << 1) + 1]); zmat[(k - np) * zmat_dim1 + 1] = temp; zmat[ip + 1 + (k - np) * zmat_dim1] = -temp; zmat[iq + 1 + (k - np) * zmat_dim1] = -temp; /* L70: */ zmat[k + (k - np) * zmat_dim1] = temp; } } nrem = *npt; kold = 1; knew = *kopt; /* Reorder the provisional points in the way that exchanges PTSID(KOLD) */ /* with PTSID(KNEW). */ L80: i__2 = *n; for (j = 1; j <= i__2; ++j) { temp = bmat[kold + j * bmat_dim1]; bmat[kold + j * bmat_dim1] = bmat[knew + j * bmat_dim1]; /* L90: */ bmat[knew + j * bmat_dim1] = temp; } i__2 = nptm; for (j = 1; j <= i__2; ++j) { temp = zmat[kold + j * zmat_dim1]; zmat[kold + j * zmat_dim1] = zmat[knew + j * zmat_dim1]; /* L100: */ zmat[knew + j * zmat_dim1] = temp; } ptsid[kold] = ptsid[knew]; ptsid[knew] = zero; w[*ndim + knew] = zero; --nrem; if (knew != *kopt) { temp = vlag[kold]; vlag[kold] = vlag[knew]; vlag[knew] = temp; /* Update the BMAT and ZMAT matrices so that the status of the KNEW-th */ /* interpolation point can be changed from provisional to original. The */ /* branch to label 350 occurs if all the original points are reinstated. */ /* The nonnegative values of W(NDIM+K) are required in the search below. */ update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1] , &beta, &denom, &knew, &w[1]); if (nrem == 0) { goto L350; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L110: */ w[*ndim + k] = (d__1 = w[*ndim + k], fabs(d__1)); } } /* Pick the index KNEW of an original interpolation point that has not */ /* yet replaced one of the provisional interpolation points, giving */ /* attention to the closeness to XOPT and to previous tries with KNEW. */ L120: dsqmin = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { if (w[*ndim + k] > zero) { if (dsqmin == zero || w[*ndim + k] < dsqmin) { knew = k; dsqmin = w[*ndim + k]; } } /* L130: */ } if (dsqmin == zero) { goto L260; } /* Form the W-vector of the chosen original interpolation point. */ i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L140: */ w[*npt + j] = xpt[knew + j * xpt_dim1]; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { sum = zero; if (k == *kopt) { } else if (ptsid[k] == zero) { i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L150: */ sum += w[*npt + j] * xpt[k + j * xpt_dim1]; } } else { ip = (int) ptsid[k]; if (ip > 0) { sum = w[*npt + ip] * ptsaux[(ip << 1) + 1]; } iq = (int) ((double) np * ptsid[k] - (double) (ip * np)); if (iq > 0) { iw = 1; if (ip == 0) { iw = 2; } sum += w[*npt + iq] * ptsaux[iw + (iq << 1)]; } } /* L160: */ w[k] = half * sum * sum; } /* Calculate VLAG and BETA for the required updating of the H matrix if */ /* XPT(KNEW,.) is reinstated in the set of interpolation points. */ i__2 = *npt; for (k = 1; k <= i__2; ++k) { sum = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L170: */ sum += bmat[k + j * bmat_dim1] * w[*npt + j]; } /* L180: */ vlag[k] = sum; } beta = zero; i__2 = nptm; for (j = 1; j <= i__2; ++j) { sum = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L190: */ sum += zmat[k + j * zmat_dim1] * w[k]; } beta -= sum * sum; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L200: */ vlag[k] += sum * zmat[k + j * zmat_dim1]; } } bsum = zero; distsq = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L210: */ sum += bmat[k + j * bmat_dim1] * w[k]; } jp = j + *npt; bsum += sum * w[jp]; i__2 = *ndim; for (ip = *npt + 1; ip <= i__2; ++ip) { /* L220: */ sum += bmat[ip + j * bmat_dim1] * w[ip]; } bsum += sum * w[jp]; vlag[jp] = sum; /* L230: */ /* Computing 2nd power */ d__1 = xpt[knew + j * xpt_dim1]; distsq += d__1 * d__1; } beta = half * distsq * distsq + beta - bsum; vlag[*kopt] += one; /* KOLD is set to the index of the provisional interpolation point that is */ /* going to be deleted to make way for the KNEW-th original interpolation */ /* point. The choice of KOLD is governed by the avoidance of a small value */ /* of the denominator in the updating calculation of UPDATE. */ denom = zero; vlmxsq = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { if (ptsid[k] != zero) { hdiag = zero; i__2 = nptm; for (j = 1; j <= i__2; ++j) { /* L240: */ /* Computing 2nd power */ d__1 = zmat[k + j * zmat_dim1]; hdiag += d__1 * d__1; } /* Computing 2nd power */ d__1 = vlag[k]; den = beta * hdiag + d__1 * d__1; if (den > denom) { kold = k; denom = den; } } /* L250: */ /* Computing MAX */ /* Computing 2nd power */ d__3 = vlag[k]; d__1 = vlmxsq, d__2 = d__3 * d__3; vlmxsq = MAX2(d__1,d__2); } if (denom <= vlmxsq * .01) { w[*ndim + knew] = -w[*ndim + knew] - winc; goto L120; } goto L80; /* When label 260 is reached, all the final positions of the interpolation */ /* points have been chosen although any changes have not been included yet */ /* in XPT. Also the final BMAT and ZMAT matrices are complete, but, apart */ /* from the shift of XBASE, the updating of the quadratic model remains to */ /* be done. The following cycle through the new interpolation points begins */ /* by putting the new point in XPT(KPT,.) and by setting PQ(KPT) to zero, */ /* except that a RETURN occurs if MAXFUN prohibits another value of F. */ L260: i__1 = *npt; for (kpt = 1; kpt <= i__1; ++kpt) { if (ptsid[kpt] == zero) { goto L340; } if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { w[j] = xpt[kpt + j * xpt_dim1]; xpt[kpt + j * xpt_dim1] = zero; temp = pq[kpt] * w[j]; i__3 = j; for (i__ = 1; i__ <= i__3; ++i__) { ++ih; /* L270: */ hq[ih] += temp * w[i__]; } } pq[kpt] = zero; ip = (int) ptsid[kpt]; iq = (int) ((double) np * ptsid[kpt] - (double) (ip * np)) ; if (ip > 0) { xp = ptsaux[(ip << 1) + 1]; xpt[kpt + ip * xpt_dim1] = xp; } if (iq > 0) { xq = ptsaux[(iq << 1) + 1]; if (ip == 0) { xq = ptsaux[(iq << 1) + 2]; } xpt[kpt + iq * xpt_dim1] = xq; } /* Set VQUAD to the value of the current model at the new point. */ vquad = fbase; if (ip > 0) { ihp = (ip + ip * ip) / 2; vquad += xp * (gopt[ip] + half * xp * hq[ihp]); } if (iq > 0) { ihq = (iq + iq * iq) / 2; vquad += xq * (gopt[iq] + half * xq * hq[ihq]); if (ip > 0) { iw = MAX2(ihp,ihq) - (i__3 = ip - iq, IABS(i__3)); vquad += xp * xq * hq[iw]; } } i__3 = *npt; for (k = 1; k <= i__3; ++k) { temp = zero; if (ip > 0) { temp += xp * xpt[k + ip * xpt_dim1]; } if (iq > 0) { temp += xq * xpt[k + iq * xpt_dim1]; } /* L280: */ vquad += half * pq[k] * temp * temp; } /* Calculate F at the new interpolation point, and set DIFF to the factor */ /* that is going to multiply the KPT-th Lagrange function when the model */ /* is updated to provide interpolation to the new function value. */ i__3 = *n; for (i__ = 1; i__ <= i__3; ++i__) { /* Computing MIN */ /* Computing MAX */ d__3 = xl[i__], d__4 = xbase[i__] + xpt[kpt + i__ * xpt_dim1]; d__1 = MAX2(d__3,d__4), d__2 = xu[i__]; w[i__] = MIN2(d__1,d__2); if (xpt[kpt + i__ * xpt_dim1] == sl[i__]) { w[i__] = xl[i__]; } if (xpt[kpt + i__ * xpt_dim1] == su[i__]) { w[i__] = xu[i__]; } /* L290: */ } ++ *(stop->nevals_p); f = calfun(*n, &w[1], calfun_data); fval[kpt] = f; if (f < fval[*kopt]) { *kopt = kpt; } if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; diff = f - vquad; /* Update the quadratic model. The RETURN from the subroutine occurs when */ /* all the new interpolation points are included in the model. */ i__3 = *n; for (i__ = 1; i__ <= i__3; ++i__) { /* L310: */ gopt[i__] += diff * bmat[kpt + i__ * bmat_dim1]; } i__3 = *npt; for (k = 1; k <= i__3; ++k) { sum = zero; i__2 = nptm; for (j = 1; j <= i__2; ++j) { /* L320: */ sum += zmat[k + j * zmat_dim1] * zmat[kpt + j * zmat_dim1]; } temp = diff * sum; if (ptsid[k] == zero) { pq[k] += temp; } else { ip = (int) ptsid[k]; iq = (int) ((double) np * ptsid[k] - (double) (ip * np)); ihq = (iq * iq + iq) / 2; if (ip == 0) { /* Computing 2nd power */ d__1 = ptsaux[(iq << 1) + 2]; hq[ihq] += temp * (d__1 * d__1); } else { ihp = (ip * ip + ip) / 2; /* Computing 2nd power */ d__1 = ptsaux[(ip << 1) + 1]; hq[ihp] += temp * (d__1 * d__1); if (iq > 0) { /* Computing 2nd power */ d__1 = ptsaux[(iq << 1) + 1]; hq[ihq] += temp * (d__1 * d__1); iw = MAX2(ihp,ihq) - (i__2 = iq - ip, IABS(i__2)); hq[iw] += temp * ptsaux[(ip << 1) + 1] * ptsaux[(iq << 1) + 1]; } } } /* L330: */ } ptsid[kpt] = zero; L340: ; } L350: return NLOPT_SUCCESS; } /* rescue_ */ static void altmov_(int *n, int *npt, double *xpt, double *xopt, double *bmat, double *zmat, int *ndim, double *sl, double *su, int *kopt, int *knew, double *adelt, double *xnew, double *xalt, double * alpha, double *cauchy, double *glag, double *hcol, double *w) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2; double d__1, d__2, d__3, d__4; /* Local variables */ int i__, j, k; double ha, gw, one, diff, half; int ilbd, isbd; double slbd; int iubd; double vlag, subd, temp; int ksav = 0; double step = 0.0, zero, curv; int iflag; double scale, csave = 0.0, tempa, tempb, tempd, const__, sumin, ggfree; int ibdsav = 0; double dderiv, bigstp, predsq, presav, distsq, stpsav = 0.0, wfixsq, wsqsav; /* The arguments N, NPT, XPT, XOPT, BMAT, ZMAT, NDIM, SL and SU all have */ /* the same meanings as the corresponding arguments of BOBYQB. */ /* KOPT is the index of the optimal interpolation point. */ /* KNEW is the index of the interpolation point that is going to be moved. */ /* ADELT is the current trust region bound. */ /* XNEW will be set to a suitable new position for the interpolation point */ /* XPT(KNEW,.). Specifically, it satisfies the SL, SU and trust region */ /* bounds and it should provide a large denominator in the next call of */ /* UPDATE. The step XNEW-XOPT from XOPT is restricted to moves along the */ /* straight lines through XOPT and another interpolation point. */ /* XALT also provides a large value of the modulus of the KNEW-th Lagrange */ /* function subject to the constraints that have been mentioned, its main */ /* difference from XNEW being that XALT-XOPT is a constrained version of */ /* the Cauchy step within the trust region. An exception is that XALT is */ /* not calculated if all components of GLAG (see below) are zero. */ /* ALPHA will be set to the KNEW-th diagonal element of the H matrix. */ /* CAUCHY will be set to the square of the KNEW-th Lagrange function at */ /* the step XALT-XOPT from XOPT for the vector XALT that is returned, */ /* except that CAUCHY is set to zero if XALT is not calculated. */ /* GLAG is a working space vector of length N for the gradient of the */ /* KNEW-th Lagrange function at XOPT. */ /* HCOL is a working space vector of length NPT for the second derivative */ /* coefficients of the KNEW-th Lagrange function. */ /* W is a working space vector of length 2N that is going to hold the */ /* constrained Cauchy step from XOPT of the Lagrange function, followed */ /* by the downhill version of XALT when the uphill step is calculated. */ /* Set the first NPT components of W to the leading elements of the */ /* KNEW-th column of the H matrix. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xopt; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --sl; --su; --xnew; --xalt; --glag; --hcol; --w; /* Function Body */ half = .5; one = 1.; zero = 0.; const__ = one + sqrt(2.); i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L10: */ hcol[k] = zero; } i__1 = *npt - *n - 1; for (j = 1; j <= i__1; ++j) { temp = zmat[*knew + j * zmat_dim1]; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L20: */ hcol[k] += temp * zmat[k + j * zmat_dim1]; } } *alpha = hcol[*knew]; ha = half * *alpha; /* Calculate the gradient of the KNEW-th Lagrange function at XOPT. */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L30: */ glag[i__] = bmat[*knew + i__ * bmat_dim1]; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { temp = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L40: */ temp += xpt[k + j * xpt_dim1] * xopt[j]; } temp = hcol[k] * temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L50: */ glag[i__] += temp * xpt[k + i__ * xpt_dim1]; } } /* Search for a large denominator along the straight lines through XOPT */ /* and another interpolation point. SLBD and SUBD will be lower and upper */ /* bounds on the step along each of these lines in turn. PREDSQ will be */ /* set to the square of the predicted denominator for each line. PRESAV */ /* will be set to the largest admissible value of PREDSQ that occurs. */ presav = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { if (k == *kopt) { goto L80; } dderiv = zero; distsq = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp = xpt[k + i__ * xpt_dim1] - xopt[i__]; dderiv += glag[i__] * temp; /* L60: */ distsq += temp * temp; } subd = *adelt / sqrt(distsq); slbd = -subd; ilbd = 0; iubd = 0; sumin = MIN2(one,subd); /* Revise SLBD and SUBD if necessary because of the bounds in SL and SU. */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp = xpt[k + i__ * xpt_dim1] - xopt[i__]; if (temp > zero) { if (slbd * temp < sl[i__] - xopt[i__]) { slbd = (sl[i__] - xopt[i__]) / temp; ilbd = -i__; } if (subd * temp > su[i__] - xopt[i__]) { /* Computing MAX */ d__1 = sumin, d__2 = (su[i__] - xopt[i__]) / temp; subd = MAX2(d__1,d__2); iubd = i__; } } else if (temp < zero) { if (slbd * temp > su[i__] - xopt[i__]) { slbd = (su[i__] - xopt[i__]) / temp; ilbd = i__; } if (subd * temp < sl[i__] - xopt[i__]) { /* Computing MAX */ d__1 = sumin, d__2 = (sl[i__] - xopt[i__]) / temp; subd = MAX2(d__1,d__2); iubd = -i__; } } /* L70: */ } /* Seek a large modulus of the KNEW-th Lagrange function when the index */ /* of the other interpolation point on the line through XOPT is KNEW. */ if (k == *knew) { diff = dderiv - one; step = slbd; vlag = slbd * (dderiv - slbd * diff); isbd = ilbd; temp = subd * (dderiv - subd * diff); if (fabs(temp) > fabs(vlag)) { step = subd; vlag = temp; isbd = iubd; } tempd = half * dderiv; tempa = tempd - diff * slbd; tempb = tempd - diff * subd; if (tempa * tempb < zero) { temp = tempd * tempd / diff; if (fabs(temp) > fabs(vlag)) { step = tempd / diff; vlag = temp; isbd = 0; } } /* Search along each of the other lines through XOPT and another point. */ } else { step = slbd; vlag = slbd * (one - slbd); isbd = ilbd; temp = subd * (one - subd); if (fabs(temp) > fabs(vlag)) { step = subd; vlag = temp; isbd = iubd; } if (subd > half) { if (fabs(vlag) < .25) { step = half; vlag = .25; isbd = 0; } } vlag *= dderiv; } /* Calculate PREDSQ for the current line search and maintain PRESAV. */ temp = step * (one - step) * distsq; predsq = vlag * vlag * (vlag * vlag + ha * temp * temp); if (predsq > presav) { presav = predsq; ksav = k; stpsav = step; ibdsav = isbd; } L80: ; } /* Construct XNEW in a way that satisfies the bound constraints exactly. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = xopt[i__] + stpsav * (xpt[ksav + i__ * xpt_dim1] - xopt[i__]); /* L90: */ /* Computing MAX */ /* Computing MIN */ d__3 = su[i__]; d__1 = sl[i__], d__2 = MIN2(d__3,temp); xnew[i__] = MAX2(d__1,d__2); } if (ibdsav < 0) { xnew[-ibdsav] = sl[-ibdsav]; } if (ibdsav > 0) { xnew[ibdsav] = su[ibdsav]; } /* Prepare for the iterative method that assembles the constrained Cauchy */ /* step in W. The sum of squares of the fixed components of W is formed in */ /* WFIXSQ, and the free components of W are set to BIGSTP. */ bigstp = *adelt + *adelt; iflag = 0; L100: wfixsq = zero; ggfree = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { w[i__] = zero; /* Computing MIN */ d__1 = xopt[i__] - sl[i__], d__2 = glag[i__]; tempa = MIN2(d__1,d__2); /* Computing MAX */ d__1 = xopt[i__] - su[i__], d__2 = glag[i__]; tempb = MAX2(d__1,d__2); if (tempa > zero || tempb < zero) { w[i__] = bigstp; /* Computing 2nd power */ d__1 = glag[i__]; ggfree += d__1 * d__1; } /* L110: */ } if (ggfree == zero) { *cauchy = zero; goto L200; } /* Investigate whether more components of W can be fixed. */ L120: temp = *adelt * *adelt - wfixsq; if (temp > zero) { wsqsav = wfixsq; step = sqrt(temp / ggfree); ggfree = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (w[i__] == bigstp) { temp = xopt[i__] - step * glag[i__]; if (temp <= sl[i__]) { w[i__] = sl[i__] - xopt[i__]; /* Computing 2nd power */ d__1 = w[i__]; wfixsq += d__1 * d__1; } else if (temp >= su[i__]) { w[i__] = su[i__] - xopt[i__]; /* Computing 2nd power */ d__1 = w[i__]; wfixsq += d__1 * d__1; } else { /* Computing 2nd power */ d__1 = glag[i__]; ggfree += d__1 * d__1; } } /* L130: */ } if (wfixsq > wsqsav && ggfree > zero) { goto L120; } } /* Set the remaining free components of W and all components of XALT, */ /* except that W may be scaled later. */ gw = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (w[i__] == bigstp) { w[i__] = -step * glag[i__]; /* Computing MAX */ /* Computing MIN */ d__3 = su[i__], d__4 = xopt[i__] + w[i__]; d__1 = sl[i__], d__2 = MIN2(d__3,d__4); xalt[i__] = MAX2(d__1,d__2); } else if (w[i__] == zero) { xalt[i__] = xopt[i__]; } else if (glag[i__] > zero) { xalt[i__] = sl[i__]; } else { xalt[i__] = su[i__]; } /* L140: */ gw += glag[i__] * w[i__]; } /* Set CURV to the curvature of the KNEW-th Lagrange function along W. */ /* Scale W by a factor less than one if that can reduce the modulus of */ /* the Lagrange function at XOPT+W. Set CAUCHY to the final value of */ /* the square of this function. */ curv = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { temp = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L150: */ temp += xpt[k + j * xpt_dim1] * w[j]; } /* L160: */ curv += hcol[k] * temp * temp; } if (iflag == 1) { curv = -curv; } if (curv > -gw && curv < -const__ * gw) { scale = -gw / curv; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = xopt[i__] + scale * w[i__]; /* L170: */ /* Computing MAX */ /* Computing MIN */ d__3 = su[i__]; d__1 = sl[i__], d__2 = MIN2(d__3,temp); xalt[i__] = MAX2(d__1,d__2); } /* Computing 2nd power */ d__1 = half * gw * scale; *cauchy = d__1 * d__1; } else { /* Computing 2nd power */ d__1 = gw + half * curv; *cauchy = d__1 * d__1; } /* If IFLAG is zero, then XALT is calculated as before after reversing */ /* the sign of GLAG. Thus two XALT vectors become available. The one that */ /* is chosen is the one that gives the larger value of CAUCHY. */ if (iflag == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { glag[i__] = -glag[i__]; /* L180: */ w[*n + i__] = xalt[i__]; } csave = *cauchy; iflag = 1; goto L100; } if (csave > *cauchy) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L190: */ xalt[i__] = w[*n + i__]; } *cauchy = csave; } L200: return; } /* altmov_ */ static void trsbox_(int *n, int *npt, double *xpt, double *xopt, double *gopt, double *hq, double *pq, double *sl, double *su, double *delta, double *xnew, double *d__, double *gnew, double *xbdi, double *s, double *hs, double *hred, double *dsq, double *crvmin) { /* System generated locals */ int xpt_dim1, xpt_offset, i__1, i__2; double d__1, d__2, d__3, d__4; /* Local variables */ int i__, j, k, ih; double ds; int iu; double dhd, dhs, cth, one, shs, sth, ssq, half, beta, sdec, blen; int iact = 0, nact; double angt, qred; int isav; double temp, zero, xsav = 0.0, xsum, angbd = 0.0, dredg = 0.0, sredg = 0.0; int iterc; double resid, delsq, ggsav = 0.0, tempa, tempb, redmax, dredsq = 0.0, redsav, onemin, gredsq = 0.0, rednew; int itcsav = 0; double rdprev, rdnext = 0.0, stplen, stepsq; int itermax = 0; /* The arguments N, NPT, XPT, XOPT, GOPT, HQ, PQ, SL and SU have the same */ /* meanings as the corresponding arguments of BOBYQB. */ /* DELTA is the trust region radius for the present calculation, which */ /* seeks a small value of the quadratic model within distance DELTA of */ /* XOPT subject to the bounds on the variables. */ /* XNEW will be set to a new vector of variables that is approximately */ /* the one that minimizes the quadratic model within the trust region */ /* subject to the SL and SU constraints on the variables. It satisfies */ /* as equations the bounds that become active during the calculation. */ /* D is the calculated trial step from XOPT, generated iteratively from an */ /* initial value of zero. Thus XNEW is XOPT+D after the final iteration. */ /* GNEW holds the gradient of the quadratic model at XOPT+D. It is updated */ /* when D is updated. */ /* XBDI is a working space vector. For I=1,2,...,N, the element XBDI(I) is */ /* set to -1.0, 0.0, or 1.0, the value being nonzero if and only if the */ /* I-th variable has become fixed at a bound, the bound being SL(I) or */ /* SU(I) in the case XBDI(I)=-1.0 or XBDI(I)=1.0, respectively. This */ /* information is accumulated during the construction of XNEW. */ /* The arrays S, HS and HRED are also used for working space. They hold the */ /* current search direction, and the changes in the gradient of Q along S */ /* and the reduced D, respectively, where the reduced D is the same as D, */ /* except that the components of the fixed variables are zero. */ /* DSQ will be set to the square of the length of XNEW-XOPT. */ /* CRVMIN is set to zero if D reaches the trust region boundary. Otherwise */ /* it is set to the least curvature of H that occurs in the conjugate */ /* gradient searches that are not restricted by any constraints. The */ /* value CRVMIN=-1.0D0 is set, however, if all of these searches are */ /* constrained. */ /* A version of the truncated conjugate gradient is applied. If a line */ /* search is restricted by a constraint, then the procedure is restarted, */ /* the values of the variables that are at their bounds being fixed. If */ /* the trust region boundary is reached, then further changes may be made */ /* to D, each one being in the two dimensional space that is spanned */ /* by the current D and the gradient of Q at XOPT+D, staying on the trust */ /* region boundary. Termination occurs when the reduction in Q seems to */ /* be close to the greatest reduction that can be achieved. */ /* Set some constants. */ /* Parameter adjustments */ xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xopt; --gopt; --hq; --pq; --sl; --su; --xnew; --d__; --gnew; --xbdi; --s; --hs; --hred; /* Function Body */ half = .5; one = 1.; onemin = -1.; zero = 0.; /* The sign of GOPT(I) gives the sign of the change to the I-th variable */ /* that will reduce Q from its value at XOPT. Thus XBDI(I) shows whether */ /* or not to fix the I-th variable at one of its bounds initially, with */ /* NACT being set to the number of fixed variables. D and GNEW are also */ /* set for the first iteration. DELSQ is the upper bound on the sum of */ /* squares of the free variables. QRED is the reduction in Q so far. */ iterc = 0; nact = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xbdi[i__] = zero; if (xopt[i__] <= sl[i__]) { if (gopt[i__] >= zero) { xbdi[i__] = onemin; } } else if (xopt[i__] >= su[i__]) { if (gopt[i__] <= zero) { xbdi[i__] = one; } } if (xbdi[i__] != zero) { ++nact; } d__[i__] = zero; /* L10: */ gnew[i__] = gopt[i__]; } delsq = *delta * *delta; qred = zero; *crvmin = onemin; /* Set the next search direction of the conjugate gradient method. It is */ /* the steepest descent direction initially and when the iterations are */ /* restarted because a variable has just been fixed by a bound, and of */ /* course the components of the fixed variables are zero. ITERMAX is an */ /* upper bound on the indices of the conjugate gradient iterations. */ L20: beta = zero; L30: stepsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] != zero) { s[i__] = zero; } else if (beta == zero) { s[i__] = -gnew[i__]; } else { s[i__] = beta * s[i__] - gnew[i__]; } /* L40: */ /* Computing 2nd power */ d__1 = s[i__]; stepsq += d__1 * d__1; } if (stepsq == zero) { goto L190; } if (beta == zero) { gredsq = stepsq; itermax = iterc + *n - nact; } if (gredsq * delsq <= qred * 1e-4 * qred) { goto L190; } /* Multiply the search direction by the second derivative matrix of Q and */ /* calculate some scalars for the choice of steplength. Then set BLEN to */ /* the length of the the step to the trust region boundary and STPLEN to */ /* the steplength, ignoring the simple bounds. */ goto L210; L50: resid = delsq; ds = zero; shs = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] == zero) { /* Computing 2nd power */ d__1 = d__[i__]; resid -= d__1 * d__1; ds += s[i__] * d__[i__]; shs += s[i__] * hs[i__]; } /* L60: */ } if (resid <= zero) { goto L90; } temp = sqrt(stepsq * resid + ds * ds); if (ds < zero) { blen = (temp - ds) / stepsq; } else { blen = resid / (temp + ds); } stplen = blen; if (shs > zero) { /* Computing MIN */ d__1 = blen, d__2 = gredsq / shs; stplen = MIN2(d__1,d__2); } /* Reduce STPLEN if necessary in order to preserve the simple bounds, */ /* letting IACT be the index of the new constrained variable. */ iact = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (s[i__] != zero) { xsum = xopt[i__] + d__[i__]; if (s[i__] > zero) { temp = (su[i__] - xsum) / s[i__]; } else { temp = (sl[i__] - xsum) / s[i__]; } if (temp < stplen) { stplen = temp; iact = i__; } } /* L70: */ } /* Update CRVMIN, GNEW and D. Set SDEC to the decrease that occurs in Q. */ sdec = zero; if (stplen > zero) { ++iterc; temp = shs / stepsq; if (iact == 0 && temp > zero) { *crvmin = MIN2(*crvmin,temp); if (*crvmin == onemin) { *crvmin = temp; } } ggsav = gredsq; gredsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { gnew[i__] += stplen * hs[i__]; if (xbdi[i__] == zero) { /* Computing 2nd power */ d__1 = gnew[i__]; gredsq += d__1 * d__1; } /* L80: */ d__[i__] += stplen * s[i__]; } /* Computing MAX */ d__1 = stplen * (ggsav - half * stplen * shs); sdec = MAX2(d__1,zero); qred += sdec; } /* Restart the conjugate gradient method if it has hit a new bound. */ if (iact > 0) { ++nact; xbdi[iact] = one; if (s[iact] < zero) { xbdi[iact] = onemin; } /* Computing 2nd power */ d__1 = d__[iact]; delsq -= d__1 * d__1; if (delsq <= zero) { goto L90; } goto L20; } /* If STPLEN is less than BLEN, then either apply another conjugate */ /* gradient iteration or RETURN. */ if (stplen < blen) { if (iterc == itermax) { goto L190; } if (sdec <= qred * .01) { goto L190; } beta = gredsq / ggsav; goto L30; } L90: *crvmin = zero; /* Prepare for the alternative iteration by calculating some scalars */ /* and by multiplying the reduced D by the second derivative matrix of */ /* Q, where S holds the reduced D in the call of GGMULT. */ L100: if (nact >= *n - 1) { goto L190; } dredsq = zero; dredg = zero; gredsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] == zero) { /* Computing 2nd power */ d__1 = d__[i__]; dredsq += d__1 * d__1; dredg += d__[i__] * gnew[i__]; /* Computing 2nd power */ d__1 = gnew[i__]; gredsq += d__1 * d__1; s[i__] = d__[i__]; } else { s[i__] = zero; } /* L110: */ } itcsav = iterc; goto L210; /* Let the search direction S be a linear combination of the reduced D */ /* and the reduced G that is orthogonal to the reduced D. */ L120: ++iterc; temp = gredsq * dredsq - dredg * dredg; if (temp <= qred * 1e-4 * qred) { goto L190; } temp = sqrt(temp); i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] == zero) { s[i__] = (dredg * d__[i__] - dredsq * gnew[i__]) / temp; } else { s[i__] = zero; } /* L130: */ } sredg = -temp; /* By considering the simple bounds on the variables, calculate an upper */ /* bound on the tangent of half the angle of the alternative iteration, */ /* namely ANGBD, except that, if already a free variable has reached a */ /* bound, there is a branch back to label 100 after fixing that variable. */ angbd = one; iact = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] == zero) { tempa = xopt[i__] + d__[i__] - sl[i__]; tempb = su[i__] - xopt[i__] - d__[i__]; if (tempa <= zero) { ++nact; xbdi[i__] = onemin; goto L100; } else if (tempb <= zero) { ++nact; xbdi[i__] = one; goto L100; } /* Computing 2nd power */ d__1 = d__[i__]; /* Computing 2nd power */ d__2 = s[i__]; ssq = d__1 * d__1 + d__2 * d__2; /* Computing 2nd power */ d__1 = xopt[i__] - sl[i__]; temp = ssq - d__1 * d__1; if (temp > zero) { temp = sqrt(temp) - s[i__]; if (angbd * temp > tempa) { angbd = tempa / temp; iact = i__; xsav = onemin; } } /* Computing 2nd power */ d__1 = su[i__] - xopt[i__]; temp = ssq - d__1 * d__1; if (temp > zero) { temp = sqrt(temp) + s[i__]; if (angbd * temp > tempb) { angbd = tempb / temp; iact = i__; xsav = one; } } } /* L140: */ } /* Calculate HHD and some curvatures for the alternative iteration. */ goto L210; L150: shs = zero; dhs = zero; dhd = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (xbdi[i__] == zero) { shs += s[i__] * hs[i__]; dhs += d__[i__] * hs[i__]; dhd += d__[i__] * hred[i__]; } /* L160: */ } /* Seek the greatest reduction in Q for a range of equally spaced values */ /* of ANGT in [0,ANGBD], where ANGT is the tangent of half the angle of */ /* the alternative iteration. */ redmax = zero; isav = 0; redsav = zero; iu = (int) (angbd * 17. + 3.1); i__1 = iu; for (i__ = 1; i__ <= i__1; ++i__) { angt = angbd * (double) i__ / (double) iu; sth = (angt + angt) / (one + angt * angt); temp = shs + angt * (angt * dhd - dhs - dhs); rednew = sth * (angt * dredg - sredg - half * sth * temp); if (rednew > redmax) { redmax = rednew; isav = i__; rdprev = redsav; } else if (i__ == isav + 1) { rdnext = rednew; } /* L170: */ redsav = rednew; } /* Return if the reduction is zero. Otherwise, set the sine and cosine */ /* of the angle of the alternative iteration, and calculate SDEC. */ if (isav == 0) { goto L190; } if (isav < iu) { temp = (rdnext - rdprev) / (redmax + redmax - rdprev - rdnext); angt = angbd * ((double) isav + half * temp) / (double) iu; } cth = (one - angt * angt) / (one + angt * angt); sth = (angt + angt) / (one + angt * angt); temp = shs + angt * (angt * dhd - dhs - dhs); sdec = sth * (angt * dredg - sredg - half * sth * temp); if (sdec <= zero) { goto L190; } /* Update GNEW, D and HRED. If the angle of the alternative iteration */ /* is restricted by a bound on a free variable, that variable is fixed */ /* at the bound. */ dredg = zero; gredsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { gnew[i__] = gnew[i__] + (cth - one) * hred[i__] + sth * hs[i__]; if (xbdi[i__] == zero) { d__[i__] = cth * d__[i__] + sth * s[i__]; dredg += d__[i__] * gnew[i__]; /* Computing 2nd power */ d__1 = gnew[i__]; gredsq += d__1 * d__1; } /* L180: */ hred[i__] = cth * hred[i__] + sth * hs[i__]; } qred += sdec; if (iact > 0 && isav == iu) { ++nact; xbdi[iact] = xsav; goto L100; } /* If SDEC is sufficiently small, then RETURN after setting XNEW to */ /* XOPT+D, giving careful attention to the bounds. */ if (sdec > qred * .01) { goto L120; } L190: *dsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MAX */ /* Computing MIN */ d__3 = xopt[i__] + d__[i__], d__4 = su[i__]; d__1 = MIN2(d__3,d__4), d__2 = sl[i__]; xnew[i__] = MAX2(d__1,d__2); if (xbdi[i__] == onemin) { xnew[i__] = sl[i__]; } if (xbdi[i__] == one) { xnew[i__] = su[i__]; } d__[i__] = xnew[i__] - xopt[i__]; /* L200: */ /* Computing 2nd power */ d__1 = d__[i__]; *dsq += d__1 * d__1; } return; /* The following instructions multiply the current S-vector by the second */ /* derivative matrix of the quadratic model, putting the product in HS. */ /* They are reached from three different parts of the software above and */ /* they can be regarded as an external subroutine. */ L210: ih = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { hs[j] = zero; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ++ih; if (i__ < j) { hs[j] += hq[ih] * s[i__]; } /* L220: */ hs[i__] += hq[ih] * s[j]; } } i__2 = *npt; for (k = 1; k <= i__2; ++k) { if (pq[k] != zero) { temp = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L230: */ temp += xpt[k + j * xpt_dim1] * s[j]; } temp *= pq[k]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L240: */ hs[i__] += temp * xpt[k + i__ * xpt_dim1]; } } /* L250: */ } if (*crvmin != zero) { goto L50; } if (iterc > itcsav) { goto L150; } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L260: */ hred[i__] = hs[i__]; } goto L120; } /* trsbox_ */ static nlopt_result prelim_(int *n, int *npt, double *x, const double *xl, const double *xu, double *rhobeg, nlopt_stopping *stop, bobyqa_func calfun, void *calfun_data, double *xbase, double *xpt, double *fval, double *gopt, double *hq, double *pq, double *bmat, double *zmat, int *ndim, double *sl, double *su, int *kopt) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2; double d__1, d__2, d__3, d__4; /* Local variables */ double f; int i__, j, k, ih, np, nfm; double one; int nfx, ipt = 0, jpt = 0; /* fbeg will be initialized below, init here to avoid maybe-uninitialized warning */ double two, fbeg = 0.0, diff, half, temp, zero, recip, stepa = 0.0, stepb = 0.0; int itemp; double rhosq; int nf; /* The arguments N, NPT, X, XL, XU, RHOBEG, and MAXFUN are the */ /* same as the corresponding arguments in SUBROUTINE BOBYQA. */ /* The arguments XBASE, XPT, FVAL, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU */ /* are the same as the corresponding arguments in BOBYQB, the elements */ /* of SL and SU being set in BOBYQA. */ /* GOPT is usually the gradient of the quadratic model at XOPT+XBASE, but */ /* it is set by PRELIM to the gradient of the quadratic model at XBASE. */ /* If XOPT is nonzero, BOBYQB will change it to its usual value later. */ /* NF is maintaned as the number of calls of CALFUN so far. */ /* KOPT will be such that the least calculated value of F so far is at */ /* the point XPT(KOPT,.)+XBASE in the space of the variables. */ /* SUBROUTINE PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */ /* BMAT and ZMAT for the first iteration, and it maintains the values of */ /* NF and KOPT. The vector X is also changed by PRELIM. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --x; --xl; --xu; --xbase; --fval; --gopt; --hq; --pq; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --sl; --su; /* Function Body */ half = .5; one = 1.; two = 2.; zero = 0.; rhosq = *rhobeg * *rhobeg; recip = one / rhosq; np = *n + 1; /* Set XBASE to the initial vector of variables, and set the initial */ /* elements of XPT, BMAT, HQ, PQ and ZMAT to zero. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { xbase[j] = x[j]; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L10: */ xpt[k + j * xpt_dim1] = zero; } i__2 = *ndim; for (i__ = 1; i__ <= i__2; ++i__) { /* L20: */ bmat[i__ + j * bmat_dim1] = zero; } } i__2 = *n * np / 2; for (ih = 1; ih <= i__2; ++ih) { /* L30: */ hq[ih] = zero; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { pq[k] = zero; i__1 = *npt - np; for (j = 1; j <= i__1; ++j) { /* L40: */ zmat[k + j * zmat_dim1] = zero; } } /* Begin the initialization procedure. NF becomes one more than the number */ /* of function values so far. The coordinates of the displacement of the */ /* next initial interpolation point from XBASE are set in XPT(NF+1,.). */ nf = 0; L50: nfm = nf; nfx = nf - *n; ++(nf); if (nfm <= *n << 1) { if (nfm >= 1 && nfm <= *n) { stepa = *rhobeg; if (su[nfm] == zero) { stepa = -stepa; } xpt[nf + nfm * xpt_dim1] = stepa; } else if (nfm > *n) { stepa = xpt[nf - *n + nfx * xpt_dim1]; stepb = -(*rhobeg); if (sl[nfx] == zero) { /* Computing MIN */ d__1 = two * *rhobeg, d__2 = su[nfx]; stepb = MIN2(d__1,d__2); } if (su[nfx] == zero) { /* Computing MAX */ d__1 = -two * *rhobeg, d__2 = sl[nfx]; stepb = MAX2(d__1,d__2); } xpt[nf + nfx * xpt_dim1] = stepb; } } else { itemp = (nfm - np) / *n; jpt = nfm - itemp * *n - *n; ipt = jpt + itemp; if (ipt > *n) { itemp = jpt; jpt = ipt - *n; ipt = itemp; } xpt[nf + ipt * xpt_dim1] = xpt[ipt + 1 + ipt * xpt_dim1]; xpt[nf + jpt * xpt_dim1] = xpt[jpt + 1 + jpt * xpt_dim1]; } /* Calculate the next value of F. The least function value so far and */ /* its index are required. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { /* Computing MIN */ /* Computing MAX */ d__3 = xl[j], d__4 = xbase[j] + xpt[nf + j * xpt_dim1]; d__1 = MAX2(d__3,d__4), d__2 = xu[j]; x[j] = MIN2(d__1,d__2); if (xpt[nf + j * xpt_dim1] == sl[j]) { x[j] = xl[j]; } if (xpt[nf + j * xpt_dim1] == su[j]) { x[j] = xu[j]; } /* L60: */ } ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); fval[nf] = f; if (nf == 1) { fbeg = f; *kopt = 1; } else if (f < fval[*kopt]) { *kopt = nf; } /* Set the nonzero initial elements of BMAT and the quadratic model in the */ /* cases when NF is at most 2*N+1. If NF exceeds N+1, then the positions */ /* of the NF-th and (NF-N)-th interpolation points may be switched, in */ /* order that the function value at the first of them contributes to the */ /* off-diagonal second derivative terms of the initial quadratic model. */ if (nf <= (*n << 1) + 1) { if (nf >= 2 && nf <= *n + 1) { gopt[nfm] = (f - fbeg) / stepa; if (*npt < nf + *n) { bmat[nfm * bmat_dim1 + 1] = -one / stepa; bmat[nf + nfm * bmat_dim1] = one / stepa; bmat[*npt + nfm + nfm * bmat_dim1] = -half * rhosq; } } else if (nf >= *n + 2) { ih = nfx * (nfx + 1) / 2; temp = (f - fbeg) / stepb; diff = stepb - stepa; hq[ih] = two * (temp - gopt[nfx]) / diff; gopt[nfx] = (gopt[nfx] * stepb - temp * stepa) / diff; if (stepa * stepb < zero) { if (f < fval[nf - *n]) { fval[nf] = fval[nf - *n]; fval[nf - *n] = f; if (*kopt == nf) { *kopt = nf - *n; } xpt[nf - *n + nfx * xpt_dim1] = stepb; xpt[nf + nfx * xpt_dim1] = stepa; } } bmat[nfx * bmat_dim1 + 1] = -(stepa + stepb) / (stepa * stepb); bmat[nf + nfx * bmat_dim1] = -half / xpt[nf - *n + nfx * xpt_dim1]; bmat[nf - *n + nfx * bmat_dim1] = -bmat[nfx * bmat_dim1 + 1] - bmat[nf + nfx * bmat_dim1]; zmat[nfx * zmat_dim1 + 1] = sqrt(two) / (stepa * stepb); zmat[nf + nfx * zmat_dim1] = sqrt(half) / rhosq; zmat[nf - *n + nfx * zmat_dim1] = -zmat[nfx * zmat_dim1 + 1] - zmat[nf + nfx * zmat_dim1]; } /* Set the off-diagonal second derivatives of the Lagrange functions and */ /* the initial quadratic model. */ } else { ih = ipt * (ipt - 1) / 2 + jpt; zmat[nfx * zmat_dim1 + 1] = recip; zmat[nf + nfx * zmat_dim1] = recip; zmat[ipt + 1 + nfx * zmat_dim1] = -recip; zmat[jpt + 1 + nfx * zmat_dim1] = -recip; temp = xpt[nf + ipt * xpt_dim1] * xpt[nf + jpt * xpt_dim1]; hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / temp; } if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; if (nf < *npt) { goto L50; } return NLOPT_SUCCESS; } /* prelim_ */ static nlopt_result bobyqb_(int *n, int *npt, double *x, const double *xl, const double *xu, double *rhobeg, double * rhoend, nlopt_stopping *stop, bobyqa_func calfun, void *calfun_data, double *minf, double *xbase, double *xpt, double *fval, double *xopt, double *gopt, double *hq, double *pq, double *bmat, double *zmat, int *ndim, double *sl, double *su, double *xnew, double *xalt, double *d__, double *vlag, double *w) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2, i__3; double d__1, d__2, d__3, d__4; /* Local variables */ double f; int i__, j, k, ih, jj, nh, ip, jp; double dx; int np; double den, one, ten, dsq, rho, sum, two, diff, half, beta, gisq; int knew; double temp, suma, sumb, bsum, fopt; int kopt, nptm; double zero, curv; int ksav; double gqsq, dist, sumw, sumz, diffa, diffb, diffc = 0.0, hdiag; int kbase; double alpha, delta, adelt, denom, fsave, bdtol, delsq; int nresc, nfsav; double ratio, dnorm, vquad, pqold, tenth; int itest; double sumpq, scaden; double errbig, cauchy, fracsq, biglsq, densav; double bdtest; double crvmin, frhosq; double distsq; int ntrits; double xoptsq; nlopt_result rc = NLOPT_SUCCESS, rc2; /* The arguments N, NPT, X, XL, XU, RHOBEG, RHOEND, and MAXFUN */ /* are identical to the corresponding arguments in SUBROUTINE BOBYQA. */ /* XBASE holds a shift of origin that should reduce the contributions */ /* from rounding errors to values of the model and Lagrange functions. */ /* XPT is a two-dimensional array that holds the coordinates of the */ /* interpolation points relative to XBASE. */ /* FVAL holds the values of F at the interpolation points. */ /* XOPT is set to the displacement from XBASE of the trust region centre. */ /* GOPT holds the gradient of the quadratic model at XBASE+XOPT. */ /* HQ holds the explicit second derivatives of the quadratic model. */ /* PQ contains the parameters of the implicit second derivatives of the */ /* quadratic model. */ /* BMAT holds the last N columns of H. */ /* ZMAT holds the factorization of the leading NPT by NPT submatrix of H, */ /* this factorization being ZMAT times ZMAT^T, which provides both the */ /* correct rank and positive semi-definiteness. */ /* NDIM is the first dimension of BMAT and has the value NPT+N. */ /* SL and SU hold the differences XL-XBASE and XU-XBASE, respectively. */ /* All the components of every XOPT are going to satisfy the bounds */ /* SL(I) .LEQ. XOPT(I) .LEQ. SU(I), with appropriate equalities when */ /* XOPT is on a constraint boundary. */ /* XNEW is chosen by SUBROUTINE TRSBOX or ALTMOV. Usually XBASE+XNEW is the */ /* vector of variables for the next call of CALFUN. XNEW also satisfies */ /* the SL and SU constraints in the way that has just been mentioned. */ /* XALT is an alternative to XNEW, chosen by ALTMOV, that may replace XNEW */ /* in order to increase the denominator in the updating of UPDATE. */ /* D is reserved for a trial step from XOPT, which is usually XNEW-XOPT. */ /* VLAG contains the values of the Lagrange functions at a new point X. */ /* They are part of a product that requires VLAG to be of length NDIM. */ /* W is a one-dimensional array that is used for working space. Its length */ /* must be at least 3*NDIM = 3*(NPT+N). */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --x; --xl; --xu; --xbase; --fval; --xopt; --gopt; --hq; --pq; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --sl; --su; --xnew; --xalt; --d__; --vlag; --w; /* Function Body */ half = .5; one = 1.; ten = 10.; tenth = .1; two = 2.; zero = 0.; np = *n + 1; nptm = *npt - np; nh = *n * np / 2; /* The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */ /* BMAT and ZMAT for the first iteration, with the corresponding values of */ /* of NF and KOPT, which are the number of calls of CALFUN so far and the */ /* index of the interpolation point at the trust region centre. Then the */ /* initial XOPT is set too. The branch to label 720 occurs if MAXFUN is */ /* less than NPT. GOPT will be updated if KOPT is different from KBASE. */ rc2 = prelim_(n, npt, &x[1], &xl[1], &xu[1], rhobeg, stop, calfun, calfun_data, &xbase[1], &xpt[xpt_offset], &fval[1], &gopt[1], &hq[1], &pq[1], &bmat[ bmat_offset], &zmat[zmat_offset], ndim, &sl[1], &su[1], &kopt); xoptsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xopt[i__] = xpt[kopt + i__ * xpt_dim1]; /* L10: */ /* Computing 2nd power */ d__1 = xopt[i__]; xoptsq += d__1 * d__1; } fsave = fval[1]; if (rc2 != NLOPT_SUCCESS) { rc = rc2; goto L720; } kbase = 1; /* Complete the settings that are required for the iterative procedure. */ rho = *rhobeg; delta = rho; nresc = *(stop->nevals_p); ntrits = 0; diffa = zero; diffb = zero; itest = 0; nfsav = *(stop->nevals_p); /* Update GOPT if necessary before the first iteration and after each */ /* call of RESCUE that makes a call of CALFUN. */ L20: if (kopt != kbase) { ih = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ++ih; if (i__ < j) { gopt[j] += hq[ih] * xopt[i__]; } /* L30: */ gopt[i__] += hq[ih] * xopt[j]; } } if (*(stop->nevals_p) > *npt) { i__2 = *npt; for (k = 1; k <= i__2; ++k) { temp = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L40: */ temp += xpt[k + j * xpt_dim1] * xopt[j]; } temp = pq[k] * temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L50: */ gopt[i__] += temp * xpt[k + i__ * xpt_dim1]; } } } } /* Generate the next point in the trust region that provides a small value */ /* of the quadratic model subject to the constraints on the variables. */ /* The int NTRITS is set to the number "trust region" iterations that */ /* have occurred since the last "alternative" iteration. If the length */ /* of XNEW-XOPT is less than HALF*RHO, however, then there is a branch to */ /* label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW. */ L60: trsbox_(n, npt, &xpt[xpt_offset], &xopt[1], &gopt[1], &hq[1], &pq[1], &sl[ 1], &su[1], &delta, &xnew[1], &d__[1], &w[1], &w[np], &w[np + *n], &w[np + (*n << 1)], &w[np + *n * 3], &dsq, &crvmin); /* Computing MIN */ d__1 = delta, d__2 = sqrt(dsq); dnorm = MIN2(d__1,d__2); if (dnorm < half * rho) { ntrits = -1; /* Computing 2nd power */ d__1 = ten * rho; distsq = d__1 * d__1; if (*(stop->nevals_p) <= nfsav + 2) { goto L650; } /* The following choice between labels 650 and 680 depends on whether or */ /* not our work with the current RHO seems to be complete. Either RHO is */ /* decreased or termination occurs if the errors in the quadratic model at */ /* the last three interpolation points compare favourably with predictions */ /* of likely improvements to the model within distance HALF*RHO of XOPT. */ /* Computing MAX */ d__1 = MAX2(diffa,diffb); errbig = MAX2(d__1,diffc); frhosq = rho * .125 * rho; if (crvmin > zero && errbig > frhosq * crvmin) { goto L650; } bdtol = errbig / rho; i__1 = *n; for (j = 1; j <= i__1; ++j) { bdtest = bdtol; if (xnew[j] == sl[j]) { bdtest = w[j]; } if (xnew[j] == su[j]) { bdtest = -w[j]; } if (bdtest < bdtol) { curv = hq[(j + j * j) / 2]; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L70: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1]; curv += pq[k] * (d__1 * d__1); } bdtest += half * curv * rho; if (bdtest < bdtol) { goto L650; } } /* L80: */ } goto L680; } ++ntrits; /* Severe cancellation is likely to occur if XOPT is too far from XBASE. */ /* If the following test holds, then XBASE is shifted so that XOPT becomes */ /* zero. The appropriate changes are made to BMAT and to the second */ /* derivatives of the current model, beginning with the changes to BMAT */ /* that do not depend on ZMAT. VLAG is used temporarily for working space. */ L90: if (dsq <= xoptsq * .001) { fracsq = xoptsq * .25; sumpq = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { sumpq += pq[k]; sum = -half * xoptsq; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L100: */ sum += xpt[k + i__ * xpt_dim1] * xopt[i__]; } w[*npt + k] = sum; temp = fracsq - half * sum; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { w[i__] = bmat[k + i__ * bmat_dim1]; vlag[i__] = sum * xpt[k + i__ * xpt_dim1] + temp * xopt[i__]; ip = *npt + i__; i__3 = i__; for (j = 1; j <= i__3; ++j) { /* L110: */ bmat[ip + j * bmat_dim1] = bmat[ip + j * bmat_dim1] + w[ i__] * vlag[j] + vlag[i__] * w[j]; } } } /* Then the revisions of BMAT that depend on ZMAT are calculated. */ i__3 = nptm; for (jj = 1; jj <= i__3; ++jj) { sumz = zero; sumw = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { sumz += zmat[k + jj * zmat_dim1]; vlag[k] = w[*npt + k] * zmat[k + jj * zmat_dim1]; /* L120: */ sumw += vlag[k]; } i__2 = *n; for (j = 1; j <= i__2; ++j) { sum = (fracsq * sumz - half * sumw) * xopt[j]; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L130: */ sum += vlag[k] * xpt[k + j * xpt_dim1]; } w[j] = sum; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L140: */ bmat[k + j * bmat_dim1] += sum * zmat[k + jj * zmat_dim1]; } } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { ip = i__ + *npt; temp = w[i__]; i__2 = i__; for (j = 1; j <= i__2; ++j) { /* L150: */ bmat[ip + j * bmat_dim1] += temp * w[j]; } } } /* The following instructions complete the shift, including the changes */ /* to the second derivative parameters of the quadratic model. */ ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { w[j] = -half * sumpq * xopt[j]; i__1 = *npt; for (k = 1; k <= i__1; ++k) { w[j] += pq[k] * xpt[k + j * xpt_dim1]; /* L160: */ xpt[k + j * xpt_dim1] -= xopt[j]; } i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; hq[ih] = hq[ih] + w[i__] * xopt[j] + xopt[i__] * w[j]; /* L170: */ bmat[*npt + i__ + j * bmat_dim1] = bmat[*npt + j + i__ * bmat_dim1]; } } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xbase[i__] += xopt[i__]; xnew[i__] -= xopt[i__]; sl[i__] -= xopt[i__]; su[i__] -= xopt[i__]; /* L180: */ xopt[i__] = zero; } xoptsq = zero; } if (ntrits == 0) { goto L210; } goto L230; /* XBASE is also moved to XOPT by a call of RESCUE. This calculation is */ /* more expensive than the previous shift, because new matrices BMAT and */ /* ZMAT are generated from scratch, which may include the replacement of */ /* interpolation points whose positions seem to be causing near linear */ /* dependence in the interpolation conditions. Therefore RESCUE is called */ /* only if rounding errors have reduced by at least a factor of two the */ /* denominator of the formula for updating the H matrix. It provides a */ /* useful safeguard, but is not invoked in most applications of BOBYQA. */ L190: nfsav = *(stop->nevals_p); kbase = kopt; rc2 = rescue_(n, npt, &xl[1], &xu[1], stop, calfun, calfun_data, &xbase[1], &xpt[xpt_offset], &fval[1], &xopt[1], &gopt[1], &hq[1], &pq[1], &bmat[bmat_offset], &zmat[zmat_offset], ndim, &sl[1], &su[1], &delta, &kopt, &vlag[1], &w[1], &w[*n + np], &w[*ndim + np]); /* XOPT is updated now in case the branch below to label 720 is taken. */ /* Any updating of GOPT occurs after the branch below to label 20, which */ /* leads to a trust region iteration as does the branch to label 60. */ xoptsq = zero; if (kopt != kbase) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xopt[i__] = xpt[kopt + i__ * xpt_dim1]; /* L200: */ /* Computing 2nd power */ d__1 = xopt[i__]; xoptsq += d__1 * d__1; } } if (rc2 != NLOPT_SUCCESS) { rc = rc2; goto L720; } nresc = *(stop->nevals_p); if (nfsav < *(stop->nevals_p)) { nfsav = *(stop->nevals_p); goto L20; } if (ntrits > 0) { goto L60; } /* Pick two alternative vectors of variables, relative to XBASE, that */ /* are suitable as new positions of the KNEW-th interpolation point. */ /* Firstly, XNEW is set to the point on a line through XOPT and another */ /* interpolation point that minimizes the predicted value of the next */ /* denominator, subject to ||XNEW - XOPT|| .LEQ. ADELT and to the SL */ /* and SU bounds. Secondly, XALT is set to the best feasible point on */ /* a constrained version of the Cauchy step of the KNEW-th Lagrange */ /* function, the corresponding value of the square of this function */ /* being returned in CAUCHY. The choice between these alternatives is */ /* going to be made when the denominator is calculated. */ L210: altmov_(n, npt, &xpt[xpt_offset], &xopt[1], &bmat[bmat_offset], &zmat[ zmat_offset], ndim, &sl[1], &su[1], &kopt, &knew, &adelt, &xnew[1] , &xalt[1], &alpha, &cauchy, &w[1], &w[np], &w[*ndim + 1]); i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L220: */ d__[i__] = xnew[i__] - xopt[i__]; } /* Calculate VLAG and BETA for the current choice of D. The scalar */ /* product of D with XPT(K,.) is going to be held in W(NPT+K) for */ /* use when VQUAD is calculated. */ L230: i__1 = *npt; for (k = 1; k <= i__1; ++k) { suma = zero; sumb = zero; sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { suma += xpt[k + j * xpt_dim1] * d__[j]; sumb += xpt[k + j * xpt_dim1] * xopt[j]; /* L240: */ sum += bmat[k + j * bmat_dim1] * d__[j]; } w[k] = suma * (half * suma + sumb); vlag[k] = sum; /* L250: */ w[*npt + k] = suma; } beta = zero; i__1 = nptm; for (jj = 1; jj <= i__1; ++jj) { sum = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L260: */ sum += zmat[k + jj * zmat_dim1] * w[k]; } beta -= sum * sum; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L270: */ vlag[k] += sum * zmat[k + jj * zmat_dim1]; } } dsq = zero; bsum = zero; dx = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* Computing 2nd power */ d__1 = d__[j]; dsq += d__1 * d__1; sum = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L280: */ sum += w[k] * bmat[k + j * bmat_dim1]; } bsum += sum * d__[j]; jp = *npt + j; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L290: */ sum += bmat[jp + i__ * bmat_dim1] * d__[i__]; } vlag[jp] = sum; bsum += sum * d__[j]; /* L300: */ dx += d__[j] * xopt[j]; } beta = dx * dx + dsq * (xoptsq + dx + dx + half * dsq) + beta - bsum; vlag[kopt] += one; /* If NTRITS is zero, the denominator may be increased by replacing */ /* the step D of ALTMOV by a Cauchy step. Then RESCUE may be called if */ /* rounding errors have damaged the chosen denominator. */ if (ntrits == 0) { /* Computing 2nd power */ d__1 = vlag[knew]; denom = d__1 * d__1 + alpha * beta; if (denom < cauchy && cauchy > zero) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { xnew[i__] = xalt[i__]; /* L310: */ d__[i__] = xnew[i__] - xopt[i__]; } cauchy = zero; goto L230; } /* Computing 2nd power */ d__1 = vlag[knew]; if (denom <= half * (d__1 * d__1)) { if (*(stop->nevals_p) > nresc) { goto L190; } /* Return from BOBYQA because of much cancellation in a denominator. */ rc = NLOPT_ROUNDOFF_LIMITED; goto L720; } /* Alternatively, if NTRITS is positive, then set KNEW to the index of */ /* the next interpolation point to be deleted to make room for a trust */ /* region step. Again RESCUE may be called if rounding errors have damaged */ /* the chosen denominator, which is the reason for attempting to select */ /* KNEW before calculating the next value of the objective function. */ } else { delsq = delta * delta; scaden = zero; biglsq = zero; knew = 0; i__2 = *npt; for (k = 1; k <= i__2; ++k) { if (k == kopt) { goto L350; } hdiag = zero; i__1 = nptm; for (jj = 1; jj <= i__1; ++jj) { /* L330: */ /* Computing 2nd power */ d__1 = zmat[k + jj * zmat_dim1]; hdiag += d__1 * d__1; } /* Computing 2nd power */ d__1 = vlag[k]; den = beta * hdiag + d__1 * d__1; distsq = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L340: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1] - xopt[j]; distsq += d__1 * d__1; } /* Computing MAX */ /* Computing 2nd power */ d__3 = distsq / delsq; d__1 = one, d__2 = d__3 * d__3; temp = MAX2(d__1,d__2); if (temp * den > scaden) { scaden = temp * den; knew = k; denom = den; } /* Computing MAX */ /* Computing 2nd power */ d__3 = vlag[k]; d__1 = biglsq, d__2 = temp * (d__3 * d__3); biglsq = MAX2(d__1,d__2); L350: ; } if (scaden <= half * biglsq) { if (*(stop->nevals_p) > nresc) { goto L190; } /* Return from BOBYQA because of much cancellation in a denominator. */ rc = NLOPT_ROUNDOFF_LIMITED; goto L720; } } /* Put the variables for the next calculation of the objective function */ /* in XNEW, with any adjustments for the bounds. */ /* Calculate the value of the objective function at XBASE+XNEW, unless */ /* the limit on the number of calculations of F has been reached. */ L360: i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MIN */ /* Computing MAX */ d__3 = xl[i__], d__4 = xbase[i__] + xnew[i__]; d__1 = MAX2(d__3,d__4), d__2 = xu[i__]; x[i__] = MIN2(d__1,d__2); if (xnew[i__] == sl[i__]) { x[i__] = xl[i__]; } if (xnew[i__] == su[i__]) { x[i__] = xu[i__]; } /* L380: */ } if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; if (rc != NLOPT_SUCCESS) goto L720; ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); if (ntrits == -1) { fsave = f; rc = NLOPT_XTOL_REACHED; if (fsave < fval[kopt]) { *minf = f; return rc; } goto L720; } if (f < stop->minf_max) { *minf = f; return NLOPT_MINF_MAX_REACHED; } /* Use the quadratic model to predict the change in F due to the step D, */ /* and set DIFF to the error of this prediction. */ fopt = fval[kopt]; vquad = zero; ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { vquad += d__[j] * gopt[j]; i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; temp = d__[i__] * d__[j]; if (i__ == j) { temp = half * temp; } /* L410: */ vquad += hq[ih] * temp; } } i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L420: */ /* Computing 2nd power */ d__1 = w[*npt + k]; vquad += half * pq[k] * (d__1 * d__1); } diff = f - fopt - vquad; diffc = diffb; diffb = diffa; diffa = fabs(diff); if (dnorm > rho) { nfsav = *(stop->nevals_p); } /* Pick the next value of DELTA after a trust region step. */ if (ntrits > 0) { if (vquad >= zero) { /* Return from BOBYQA because a trust region step has failed to reduce Q. */ rc = NLOPT_ROUNDOFF_LIMITED; /* or FTOL_REACHED? */ goto L720; } ratio = (f - fopt) / vquad; if (ratio <= tenth) { /* Computing MIN */ d__1 = half * delta; delta = MIN2(d__1,dnorm); } else if (ratio <= .7) { /* Computing MAX */ d__1 = half * delta; delta = MAX2(d__1,dnorm); } else { /* Computing MAX */ d__1 = half * delta, d__2 = dnorm + dnorm; delta = MAX2(d__1,d__2); } if (delta <= rho * 1.5) { delta = rho; } /* Recalculate KNEW and DENOM if the new F is less than FOPT. */ if (f < fopt) { ksav = knew; densav = denom; delsq = delta * delta; scaden = zero; biglsq = zero; knew = 0; i__1 = *npt; for (k = 1; k <= i__1; ++k) { hdiag = zero; i__2 = nptm; for (jj = 1; jj <= i__2; ++jj) { /* L440: */ /* Computing 2nd power */ d__1 = zmat[k + jj * zmat_dim1]; hdiag += d__1 * d__1; } /* Computing 2nd power */ d__1 = vlag[k]; den = beta * hdiag + d__1 * d__1; distsq = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L450: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1] - xnew[j]; distsq += d__1 * d__1; } /* Computing MAX */ /* Computing 2nd power */ d__3 = distsq / delsq; d__1 = one, d__2 = d__3 * d__3; temp = MAX2(d__1,d__2); if (temp * den > scaden) { scaden = temp * den; knew = k; denom = den; } /* L460: */ /* Computing MAX */ /* Computing 2nd power */ d__3 = vlag[k]; d__1 = biglsq, d__2 = temp * (d__3 * d__3); biglsq = MAX2(d__1,d__2); } if (scaden <= half * biglsq) { knew = ksav; denom = densav; } } } /* Update BMAT and ZMAT, so that the KNEW-th interpolation point can be */ /* moved. Also update the second derivative terms of the model. */ update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1], & beta, &denom, &knew, &w[1]); ih = 0; pqold = pq[knew]; pq[knew] = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = pqold * xpt[knew + i__ * xpt_dim1]; i__2 = i__; for (j = 1; j <= i__2; ++j) { ++ih; /* L470: */ hq[ih] += temp * xpt[knew + j * xpt_dim1]; } } i__2 = nptm; for (jj = 1; jj <= i__2; ++jj) { temp = diff * zmat[knew + jj * zmat_dim1]; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L480: */ pq[k] += temp * zmat[k + jj * zmat_dim1]; } } /* Include the new interpolation point, and make the changes to GOPT at */ /* the old XOPT that are caused by the updating of the quadratic model. */ fval[knew] = f; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xpt[knew + i__ * xpt_dim1] = xnew[i__]; /* L490: */ w[i__] = bmat[knew + i__ * bmat_dim1]; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { suma = zero; i__2 = nptm; for (jj = 1; jj <= i__2; ++jj) { /* L500: */ suma += zmat[knew + jj * zmat_dim1] * zmat[k + jj * zmat_dim1]; } if (nlopt_isinf(suma)) { /* SGJ: detect singularity here (happend if we run for too many iterations) ... is there another way to recover? */ rc = NLOPT_ROUNDOFF_LIMITED; goto L720; } sumb = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L510: */ sumb += xpt[k + j * xpt_dim1] * xopt[j]; } temp = suma * sumb; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L520: */ w[i__] += temp * xpt[k + i__ * xpt_dim1]; } } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L530: */ gopt[i__] += diff * w[i__]; } /* Update XOPT, GOPT and KOPT if the new calculated F is less than FOPT. */ if (f < fopt) { kopt = knew; xoptsq = zero; ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { xopt[j] = xnew[j]; /* Computing 2nd power */ d__1 = xopt[j]; xoptsq += d__1 * d__1; i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; if (i__ < j) { gopt[j] += hq[ih] * d__[i__]; } /* L540: */ gopt[i__] += hq[ih] * d__[j]; } } i__1 = *npt; for (k = 1; k <= i__1; ++k) { temp = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L550: */ temp += xpt[k + j * xpt_dim1] * d__[j]; } temp = pq[k] * temp; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L560: */ gopt[i__] += temp * xpt[k + i__ * xpt_dim1]; } } if (nlopt_stop_ftol(stop, f, fopt)) { rc = NLOPT_FTOL_REACHED; goto L720; } } /* Calculate the parameters of the least Frobenius norm interpolant to */ /* the current data, the gradient of this interpolant at XOPT being put */ /* into VLAG(NPT+I), I=1,2,...,N. */ if (ntrits > 0) { i__2 = *npt; for (k = 1; k <= i__2; ++k) { vlag[k] = fval[k] - fval[kopt]; /* L570: */ w[k] = zero; } i__2 = nptm; for (j = 1; j <= i__2; ++j) { sum = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L580: */ sum += zmat[k + j * zmat_dim1] * vlag[k]; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L590: */ w[k] += sum * zmat[k + j * zmat_dim1]; } } i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L600: */ sum += xpt[k + j * xpt_dim1] * xopt[j]; } w[k + *npt] = w[k]; /* L610: */ w[k] = sum * w[k]; } gqsq = zero; gisq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sum = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L620: */ sum = sum + bmat[k + i__ * bmat_dim1] * vlag[k] + xpt[k + i__ * xpt_dim1] * w[k]; } if (xopt[i__] == sl[i__]) { /* Computing MIN */ d__2 = zero, d__3 = gopt[i__]; /* Computing 2nd power */ d__1 = MIN2(d__2,d__3); gqsq += d__1 * d__1; /* Computing 2nd power */ d__1 = MIN2(zero,sum); gisq += d__1 * d__1; } else if (xopt[i__] == su[i__]) { /* Computing MAX */ d__2 = zero, d__3 = gopt[i__]; /* Computing 2nd power */ d__1 = MAX2(d__2,d__3); gqsq += d__1 * d__1; /* Computing 2nd power */ d__1 = MAX2(zero,sum); gisq += d__1 * d__1; } else { /* Computing 2nd power */ d__1 = gopt[i__]; gqsq += d__1 * d__1; gisq += sum * sum; } /* L630: */ vlag[*npt + i__] = sum; } /* Test whether to replace the new quadratic model by the least Frobenius */ /* norm interpolant, making the replacement if the test is satisfied. */ ++itest; if (gqsq < ten * gisq) { itest = 0; } if (itest >= 3) { i__1 = MAX2(*npt,nh); for (i__ = 1; i__ <= i__1; ++i__) { if (i__ <= *n) { gopt[i__] = vlag[*npt + i__]; } if (i__ <= *npt) { pq[i__] = w[*npt + i__]; } if (i__ <= nh) { hq[i__] = zero; } itest = 0; /* L640: */ } } } /* If a trust region step has provided a sufficient decrease in F, then */ /* branch for another trust region calculation. The case NTRITS=0 occurs */ /* when the new interpolation point was reached by an alternative step. */ if (ntrits == 0) { goto L60; } if (f <= fopt + tenth * vquad) { goto L60; } /* Alternatively, find out if the interpolation points are close enough */ /* to the best point so far. */ /* Computing MAX */ /* Computing 2nd power */ d__3 = two * delta; /* Computing 2nd power */ d__4 = ten * rho; d__1 = d__3 * d__3, d__2 = d__4 * d__4; distsq = MAX2(d__1,d__2); L650: knew = 0; i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L660: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1] - xopt[j]; sum += d__1 * d__1; } if (sum > distsq) { knew = k; distsq = sum; } /* L670: */ } /* If KNEW is positive, then ALTMOV finds alternative new positions for */ /* the KNEW-th interpolation point within distance ADELT of XOPT. It is */ /* reached via label 90. Otherwise, there is a branch to label 60 for */ /* another trust region iteration, unless the calculations with the */ /* current RHO are complete. */ if (knew > 0) { dist = sqrt(distsq); if (ntrits == -1) { /* Computing MIN */ d__1 = tenth * delta, d__2 = half * dist; delta = MIN2(d__1,d__2); if (delta <= rho * 1.5) { delta = rho; } } ntrits = 0; /* Computing MAX */ /* Computing MIN */ d__2 = tenth * dist; d__1 = MIN2(d__2,delta); adelt = MAX2(d__1,rho); dsq = adelt * adelt; goto L90; } if (ntrits == -1) { goto L680; } if (ratio > zero) { goto L60; } if (MAX2(delta,dnorm) > rho) { goto L60; } /* The calculations with the current value of RHO are complete. Pick the */ /* next values of RHO and DELTA. */ L680: if (rho > *rhoend) { delta = half * rho; ratio = rho / *rhoend; if (ratio <= 16.) { rho = *rhoend; } else if (ratio <= 250.) { rho = sqrt(ratio) * *rhoend; } else { rho = tenth * rho; } delta = MAX2(delta,rho); ntrits = 0; nfsav = *(stop->nevals_p); goto L60; } /* Return from the calculation, after another Newton-Raphson step, if */ /* it is too short to have been tried before. */ if (ntrits == -1) { goto L360; } L720: /* originally: if (fval[kopt] <= fsave) -- changed by SGJ, since this seems like a slight optimization to not update x[] unnecessarily, at the expense of possibly not returning the best x[] found so far if the algorithm is stopped suddenly (e.g. runs out of time) ... it seems safer to execute this unconditionally, and the efficiency loss seems negligible. */ { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MIN */ /* Computing MAX */ d__3 = xl[i__], d__4 = xbase[i__] + xopt[i__]; d__1 = MAX2(d__3,d__4), d__2 = xu[i__]; x[i__] = MIN2(d__1,d__2); if (xopt[i__] == sl[i__]) { x[i__] = xl[i__]; } if (xopt[i__] == su[i__]) { x[i__] = xu[i__]; } /* L730: */ } f = fval[kopt]; } *minf = f; return rc; } /* bobyqb_ */ /**************************************************************************/ #define U(n) ((unsigned) (n)) typedef struct { double *s, *xs; nlopt_func f; void *f_data; } rescale_fun_data; static double rescale_fun(int n, const double *x, void *d_) { rescale_fun_data *d = (rescale_fun_data*) d_; nlopt_unscale(U(n), d->s, x, d->xs); return d->f(U(n), d->xs, NULL, d->f_data); } nlopt_result bobyqa(int n, int npt, double *x, const double *xl, const double *xu, const double *dx, nlopt_stopping *stop, double *minf, nlopt_func f, void *f_data) { /* System generated locals */ int i__1; double d__1, d__2; /* Local variables */ int j, id, np, iw, igo, ihq, ixb, ixa, ifv, isl, jsl, ipq, ivl, ixn, ixo, ixp, isu, jsu, ndim; double temp, zero; int ibmat, izmat; double rhobeg, rhoend; double *w0 = NULL, *w; nlopt_result ret; double *s = NULL, *sxl = NULL, *sxu = NULL, *xs = NULL; rescale_fun_data calfun_data; /* SGJ 2010: rescale parameters to make the initial step sizes dx equal in all directions */ s = nlopt_compute_rescaling(U(n), dx); if (!s) return NLOPT_OUT_OF_MEMORY; for (j = 0; j < n; ++j) if (s[j] == 0 || !nlopt_isfinite(s[j])) { nlopt_stop_msg(stop, "invalid scaling %g of dimension %d: possible over/underflow?", s[j], j); ret = NLOPT_INVALID_ARGS; goto done; } /* this statement must go before goto done, so that --x occurs */ nlopt_rescale(U(n), s, x, x); --x; xs = (double *) malloc(sizeof(double) * (U(n))); if (!xs) { ret = NLOPT_OUT_OF_MEMORY; goto done; } sxl = nlopt_new_rescaled(U(n), s, xl); if (!sxl) { ret = NLOPT_OUT_OF_MEMORY; goto done; } xl = sxl; sxu = nlopt_new_rescaled(U(n), s, xu); if (!sxu) { ret = NLOPT_OUT_OF_MEMORY; goto done; } xu = sxu; nlopt_reorder_bounds(n, sxl, sxu); rhobeg = fabs(dx[0] / s[0]); /* equals all other dx[i] after rescaling */ calfun_data.s = s; calfun_data.xs = xs; calfun_data.f = f; calfun_data.f_data = f_data; /* SGJ, 2009: compute rhoend from NLopt stop info */ rhoend = stop->xtol_rel * (rhobeg); for (j = 0; j < n; ++j) if (rhoend < stop->xtol_abs[j] / fabs(s[j])) rhoend = stop->xtol_abs[j] / fabs(s[j]); /* This subroutine seeks the least value of a function of many variables, */ /* by applying a trust region method that forms quadratic models by */ /* interpolation. There is usually some freedom in the interpolation */ /* conditions, which is taken up by minimizing the Frobenius norm of */ /* the change to the second derivative of the model, beginning with the */ /* zero matrix. The values of the variables are constrained by upper and */ /* lower bounds. The arguments of the subroutine are as follows. */ /* N must be set to the number of variables and must be at least two. */ /* NPT is the number of interpolation conditions. Its value must be in */ /* the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not */ /* recommended. */ /* Initial values of the variables must be set in X(1),X(2),...,X(N). They */ /* will be changed to the values that give the least calculated F. */ /* For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper */ /* bounds, respectively, on X(I). The construction of quadratic models */ /* requires XL(I) to be strictly less than XU(I) for each I. Further, */ /* the contribution to a model from changes to the I-th variable is */ /* damaged severely by rounding errors if XU(I)-XL(I) is too small. */ /* RHOBEG and RHOEND must be set to the initial and final values of a trust */ /* region radius, so both must be positive with RHOEND no greater than */ /* RHOBEG. Typically, RHOBEG should be about one tenth of the greatest */ /* expected change to a variable, while RHOEND should indicate the */ /* accuracy that is required in the final values of the variables. An */ /* error return occurs if any of the differences XU(I)-XL(I), I=1,...,N, */ /* is less than 2*RHOBEG. */ /* MAXFUN must be set to an upper bound on the number of calls of CALFUN. */ /* The array W will be used for working space. Its length must be at least */ /* (NPT+5)*(NPT+N)+3*N*(N+5)/2. */ /* SUBROUTINE CALFUN (N,X,F) has to be provided by the user. It must set */ /* F to the value of the objective function for the current values of the */ /* variables X(1),X(2),...,X(N), which are generated automatically in a */ /* way that satisfies the bounds given in XL and XU. */ /* Return if the value of NPT is unacceptable. */ /* Parameter adjustments */ --xu; --xl; /* Function Body */ np = n + 1; if (npt < n + 2 || npt > (n + 2) * np / 2) { /* Return from BOBYQA because NPT is not in the required interval */ ret = NLOPT_INVALID_ARGS; nlopt_stop_msg(stop, "invalid number of sampling points"); goto done; } /* Partition the working space array, so that different parts of it can */ /* be treated separately during the calculation of BOBYQB. The partition */ /* requires the first (NPT+2)*(NPT+N)+3*N*(N+5)/2 elements of W plus the */ /* space that is taken by the last array in the argument list of BOBYQB. */ ndim = npt + n; ixb = 1; ixp = ixb + n; ifv = ixp + n * npt; ixo = ifv + npt; igo = ixo + n; ihq = igo + n; ipq = ihq + n * np / 2; ibmat = ipq + npt; izmat = ibmat + ndim * n; isl = izmat + npt * (npt - np); isu = isl + n; ixn = isu + n; ixa = ixn + n; id = ixa + n; ivl = id + n; iw = ivl + ndim; w0 = (double *) malloc(sizeof(double) * U((npt+5)*(npt+n)+3*n*(n+5)/2)); if (!w0) { ret = NLOPT_OUT_OF_MEMORY; goto done; } w = w0 - 1; /* Return if there is insufficient space between the bounds. Modify the */ /* initial X if necessary in order to avoid conflicts between the bounds */ /* and the construction of the first quadratic model. The lower and upper */ /* bounds on moves from the updated X are set now, in the ISL and ISU */ /* partitions of W, in order to provide useful and exact information about */ /* components of X that become within distance RHOBEG from their bounds. */ zero = 0.; i__1 = n; for (j = 1; j <= i__1; ++j) { temp = xu[j] - xl[j]; if (temp < rhobeg + rhobeg) { /* Return from BOBYQA because one of the differences XU(I)-XL(I)s is less than 2*RHOBEG. */ ret = NLOPT_INVALID_ARGS; nlopt_stop_msg(stop, "insufficient space between the bounds: %g - %g < %g", xu[j], xl[j], rhobeg+rhobeg); goto done; } jsl = isl + j - 1; jsu = jsl + n; w[jsl] = xl[j] - x[j]; w[jsu] = xu[j] - x[j]; if (w[jsl] >= -(rhobeg)) { if (w[jsl] >= zero) { x[j] = xl[j]; w[jsl] = zero; w[jsu] = temp; } else { x[j] = xl[j] + rhobeg; w[jsl] = -(rhobeg); /* Computing MAX */ d__1 = xu[j] - x[j]; w[jsu] = MAX2(d__1,rhobeg); } } else if (w[jsu] <= rhobeg) { if (w[jsu] <= zero) { x[j] = xu[j]; w[jsl] = -temp; w[jsu] = zero; } else { x[j] = xu[j] - rhobeg; /* Computing MIN */ d__1 = xl[j] - x[j], d__2 = -(rhobeg); w[jsl] = MIN2(d__1,d__2); w[jsu] = rhobeg; } } /* L30: */ } /* Make the call of BOBYQB. */ ret = bobyqb_(&n, &npt, &x[1], &xl[1], &xu[1], &rhobeg, &rhoend, stop, rescale_fun, &calfun_data, minf, &w[ixb], &w[ixp], &w[ifv], &w[ixo], &w[igo], &w[ihq], &w[ipq], &w[ibmat], &w[izmat], &ndim, &w[isl], &w[isu], &w[ixn], &w[ixa], &w[id], &w[ivl], &w[iw]); done: free(w0); free(sxl); free(sxu); free(xs); ++x; nlopt_unscale(U(n), s, x, x); free(s); return ret; } /* bobyqa_ */ nlopt-2.6.1/src/algs/bobyqa/bobyqa.h000066400000000000000000000004571345435414600173130ustar00rootroot00000000000000#ifndef BOBYQA_H #define BOBYQA_H 1 #include "nlopt-util.h" #include "nlopt.h" extern nlopt_result bobyqa(int n, int npt, double *x, const double *lb, const double *ub, const double *dx, nlopt_stopping *stop, double *minf, nlopt_func f, void *f_data); #endif /* BOBYQA_H */ nlopt-2.6.1/src/algs/cdirect/000077500000000000000000000000001345435414600160175ustar00rootroot00000000000000nlopt-2.6.1/src/algs/cdirect/README000066400000000000000000000022561345435414600167040ustar00rootroot00000000000000From-scratch re-implementation of the DIRECT and DIRECT-L algorithms described in: D. R. Jones, C. D. Perttunen, and B. E. Stuckmann, "Lipschitzian optimization without the lipschitz constant," J. Optimization Theory and Applications, vol. 79, p. 157 (1993). J. M. Gablonsky and C. T. Kelley, "A locally-biased form of the DIRECT algorithm," J. Global Optimization 21 (1), p. 27-37 (2001). I re-implemented the algorithms for a couple of reasons. First, because I was interested in the algorithms and wanted to play with them by trying some variations (originally, because I wanted to experiment with a hybrid approach combining DIRECT with local search algorithms, see hybrid.c). Second, I wanted to remove some arbitrary restrictions in the original Fortran code, e.g. a fixed upper bound on the number of function evaluations. Third, because it was fun to code. As far as I can tell, my version converges in about the same number of iterations as Gablonsky's code (with occasional slight differences due to minor differences in how I break ties, etc.). The code in this directory is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson nlopt-2.6.1/src/algs/cdirect/cdirect.c000066400000000000000000000465041345435414600176110ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include "nlopt-util.h" #include "nlopt.h" #include "cdirect.h" #include "redblack.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /***************************************************************************/ /* basic data structure: * * a hyper-rectangle is stored as an array of length L = 2n+3, where [1] * is the value (f) of the function at the center, [0] is the "size" * measure (d) of the rectangle, [3..n+2] are the coordinates of the * center (c), [n+3..2n+2] are the widths of the sides (w), and [2] * is an "age" measure for tie-breaking purposes. * * we store the hyper-rectangles in a red-black tree, sorted by (d,f) * in lexographic order, to allow us to perform quick convex-hull * calculations (in the future, we might make this data structure * more sophisticated based on the dynamic convex-hull literature). * * n > 0 always, of course. */ /* parameters of the search algorithm and various information that needs to be passed around */ typedef struct { int n; /* dimension */ int L; /* size of each rectangle (2n+3) */ double magic_eps; /* Jones' epsilon parameter (1e-4 is recommended) */ int which_diam; /* which measure of hyper-rectangle diam to use: 0 = Jones, 1 = Gablonsky */ int which_div; /* which way to divide rects: 0: orig. Jones (divide all longest sides) 1: Gablonsky (cubes divide all, rects longest) 2: Jones Encyc. Opt.: pick random longest side */ int which_opt; /* which rects are considered "potentially optimal" 0: Jones (all pts on cvx hull, even equal pts) 1: Gablonsky DIRECT-L (pick one pt, if equal pts) 2: ~ 1, but pick points randomly if equal pts ... 2 seems to suck compared to just picking oldest pt */ const double *lb, *ub; nlopt_stopping *stop; /* stopping criteria */ nlopt_func f; void *f_data; double *work; /* workspace, of length >= 2*n */ int *iwork; /* workspace, length >= n */ double minf, *xmin; /* minimum so far */ /* red-black tree of hyperrects, sorted by (d,f,age) in lexographical order */ rb_tree rtree; int age; /* age for next new rect */ double **hull; /* array to store convex hull */ int hull_len; /* allocated length of hull array */ } params; /***************************************************************************/ /* Evaluate the "diameter" (d) of a rectangle of widths w[n] We round the result to single precision, which should be plenty for the use we put the diameter to (rect sorting), to allow our performance hack in convex_hull to work (in the Jones and Gablonsky DIRECT algorithms, all of the rects fall into a few diameter values, and we don't want rounding error to spoil this) */ static double rect_diameter(int n, const double *w, const params *p) { int i; if (p->which_diam == 0) { /* Jones measure */ double sum = 0; for (i = 0; i < n; ++i) sum += w[i] * w[i]; /* distance from center to a vertex */ return ((float) (sqrt(sum) * 0.5)); } else { /* Gablonsky measure */ double maxw = 0; for (i = 0; i < n; ++i) if (w[i] > maxw) maxw = w[i]; /* half-width of longest side */ return ((float) (maxw * 0.5)); } } #define ALLOC_RECT(rect, L) if (!(rect = (double*) malloc(sizeof(double)*(L)))) return NLOPT_OUT_OF_MEMORY static int sort_fv_compare(void *fv_, const void *a_, const void *b_) { const double *fv = (const double *) fv_; int a = *((const int *) a_), b = *((const int *) b_); double fa = MIN(fv[2*a], fv[2*a+1]); double fb = MIN(fv[2*b], fv[2*b+1]); if (fa < fb) return -1; else if (fa > fb) return +1; else return 0; } static void sort_fv(int n, double *fv, int *isort) { int i; for (i = 0; i < n; ++i) isort[i] = i; nlopt_qsort_r(isort, (unsigned) n, sizeof(int), fv, sort_fv_compare); } static double function_eval(const double *x, params *p) { double f = p->f(p->n, x, NULL, p->f_data); if (f < p->minf) { p->minf = f; memcpy(p->xmin, x, sizeof(double) * p->n); } ++ *(p->stop->nevals_p); return f; } #define FUNCTION_EVAL(fv,x,p,freeonerr) fv = function_eval(x, p); if (nlopt_stop_forced((p)->stop)) { free(freeonerr); return NLOPT_FORCED_STOP; } else if (p->minf < p->stop->minf_max) { free(freeonerr); return NLOPT_MINF_MAX_REACHED; } else if (nlopt_stop_evals((p)->stop)) { free(freeonerr); return NLOPT_MAXEVAL_REACHED; } else if (nlopt_stop_time((p)->stop)) { free(freeonerr); return NLOPT_MAXTIME_REACHED; } #define THIRD (0.3333333333333333333333) #define EQUAL_SIDE_TOL 5e-2 /* tolerance to equate side sizes */ /* divide rectangle idiv in the list p->rects */ static nlopt_result divide_rect(double *rdiv, params *p) { int i; const int n = p->n; const int L = p->L; double *c = rdiv + 3; /* center of rect to divide */ double *w = c + n; /* widths of rect to divide */ double wmax = w[0]; int imax = 0, nlongest = 0; rb_node *node; for (i = 1; i < n; ++i) if (w[i] > wmax) wmax = w[imax = i]; for (i = 0; i < n; ++i) if (wmax - w[i] <= wmax * EQUAL_SIDE_TOL) ++nlongest; if (p->which_div == 1 || (p->which_div == 0 && nlongest == n)) { /* trisect all longest sides, in increasing order of the average function value along that direction */ double *fv = p->work; int *isort = p->iwork; for (i = 0; i < n; ++i) { if (wmax - w[i] <= wmax * EQUAL_SIDE_TOL) { double csave = c[i]; c[i] = csave - w[i] * THIRD; FUNCTION_EVAL(fv[2*i], c, p, 0); c[i] = csave + w[i] * THIRD; FUNCTION_EVAL(fv[2*i+1], c, p, 0); c[i] = csave; } else { fv[2*i] = fv[2*i+1] = HUGE_VAL; } } sort_fv(n, fv, isort); if (!(node = rb_tree_find(&p->rtree, rdiv))) return NLOPT_FAILURE; for (i = 0; i < nlongest; ++i) { int k; w[isort[i]] *= THIRD; rdiv[0] = rect_diameter(n, w, p); rdiv[2] = p->age++; node = rb_tree_resort(&p->rtree, node); for (k = 0; k <= 1; ++k) { double *rnew; ALLOC_RECT(rnew, L); memcpy(rnew, rdiv, sizeof(double) * L); rnew[3 + isort[i]] += w[isort[i]] * (2*k-1); rnew[1] = fv[2*isort[i]+k]; rnew[2] = p->age++; if (!rb_tree_insert(&p->rtree, rnew)) { free(rnew); return NLOPT_OUT_OF_MEMORY; } } } } else { int k; if (nlongest > 1 && p->which_div == 2) { /* randomly choose longest side */ i = nlopt_iurand(nlongest); for (k = 0; k < n; ++k) if (wmax - w[k] <= wmax * EQUAL_SIDE_TOL) { if (!i) { i = k; break; } --i; } } else i = imax; /* trisect longest side */ if (!(node = rb_tree_find(&p->rtree, rdiv))) return NLOPT_FAILURE; w[i] *= THIRD; rdiv[0] = rect_diameter(n, w, p); rdiv[2] = p->age++; node = rb_tree_resort(&p->rtree, node); for (k = 0; k <= 1; ++k) { double *rnew; ALLOC_RECT(rnew, L); memcpy(rnew, rdiv, sizeof(double) * L); rnew[3 + i] += w[i] * (2*k-1); FUNCTION_EVAL(rnew[1], rnew + 3, p, rnew); rnew[2] = p->age++; if (!rb_tree_insert(&p->rtree, rnew)) { free(rnew); return NLOPT_OUT_OF_MEMORY; } } } return NLOPT_SUCCESS; } /***************************************************************************/ /* Convex hull algorithm, used later to find the potentially optimal points. What we really have in DIRECT is a "dynamic convex hull" problem, since we are dynamically adding/removing points and updating the hull, but I haven't implemented any of the fancy algorithms for this problem yet. */ /* Find the lower convex hull of a set of points (x,y) stored in a rb-tree of pointers to {x,y} arrays sorted in lexographic order by (x,y). Unlike standard convex hulls, we allow redundant points on the hull, and even allow duplicate points if allow_dups is nonzero. The return value is the number of points in the hull, with pointers stored in hull[i] (should be an array of length >= t->N). */ static int convex_hull(rb_tree *t, double **hull, int allow_dups) { int nhull = 0; double minslope; double xmin, xmax, yminmin, ymaxmin; rb_node *n, *nmax; /* Monotone chain algorithm [Andrew, 1979]. */ n = rb_tree_min(t); if (!n) return 0; nmax = rb_tree_max(t); xmin = n->k[0]; yminmin = n->k[1]; xmax = nmax->k[0]; if (allow_dups) do { /* include any duplicate points at (xmin,yminmin) */ hull[nhull++] = n->k; n = rb_tree_succ(n); } while (n && n->k[0] == xmin && n->k[1] == yminmin); else hull[nhull++] = n->k; if (xmin == xmax) return nhull; /* set nmax = min mode with x == xmax */ #if 0 while (nmax->k[0] == xmax) nmax = rb_tree_pred(nmax); /* non-NULL since xmin != xmax */ nmax = rb_tree_succ(nmax); #else /* performance hack (see also below) */ { double kshift[2]; kshift[0] = xmax * (1 - 1e-13); kshift[1] = -HUGE_VAL; nmax = rb_tree_find_gt(t, kshift); /* non-NULL since xmin != xmax */ } #endif ymaxmin = nmax->k[1]; minslope = (ymaxmin - yminmin) / (xmax - xmin); /* set n = first node with x != xmin */ #if 0 while (n->k[0] == xmin) n = rb_tree_succ(n); /* non-NULL since xmin != xmax */ #else /* performance hack (see also below) */ { double kshift[2]; kshift[0] = xmin * (1 + 1e-13); kshift[1] = -HUGE_VAL; n = rb_tree_find_gt(t, kshift); /* non-NULL since xmin != xmax */ } #endif for (; n != nmax; n = rb_tree_succ(n)) { double *k = n->k; if (k[1] > yminmin + (k[0] - xmin) * minslope) continue; /* performance hack: most of the points in DIRECT lie along vertical lines at a few x values, and we can exploit this */ if (nhull && k[0] == hull[nhull - 1][0]) { /* x == previous x */ if (k[1] > hull[nhull - 1][1]) { double kshift[2]; /* because of the round to float in rect_diameter, above, it shouldn't be possible for two diameters (x values) to have a fractional difference < 1e-13. Note that k[0] > 0 always in DIRECT */ kshift[0] = k[0] * (1 + 1e-13); kshift[1] = -HUGE_VAL; n = rb_tree_pred(rb_tree_find_gt(t, kshift)); continue; } else { /* equal y values, add to hull */ if (allow_dups) hull[nhull++] = k; continue; } } /* remove points until we are making a "left turn" to k */ while (nhull > 1) { double *t1 = hull[nhull - 1], *t2; /* because we allow equal points in our hull, we have to modify the standard convex-hull algorithm slightly: we need to look backwards in the hull list until we find a point t2 != t1 */ int it2 = nhull - 2; do { t2 = hull[it2--]; } while (it2 >= 0 && t2[0] == t1[0] && t2[1] == t1[1]); if (it2 < 0) break; /* cross product (t1-t2) x (k-t2) > 0 for a left turn: */ if ((t1[0]-t2[0]) * (k[1]-t2[1]) - (t1[1]-t2[1]) * (k[0]-t2[0]) >= 0) break; --nhull; } hull[nhull++] = k; } if (allow_dups) do { /* include any duplicate points at (xmax,ymaxmin) */ hull[nhull++] = nmax->k; nmax = rb_tree_succ(nmax); } while (nmax && nmax->k[0] == xmax && nmax->k[1] == ymaxmin); else hull[nhull++] = nmax->k; return nhull; } /***************************************************************************/ static int small(double *w, params *p) { int i; for (i = 0; i < p->n; ++i) if (w[i] > p->stop->xtol_abs[i] && w[i] > (p->ub[i] - p->lb[i]) * p->stop->xtol_rel) return 0; return 1; } static nlopt_result divide_good_rects(params *p) { const int n = p->n; double **hull; int nhull, i, xtol_reached = 1, divided_some = 0; double magic_eps = p->magic_eps; if (p->hull_len < p->rtree.N) { p->hull_len += p->rtree.N; p->hull = (double **) realloc(p->hull, sizeof(double*)*p->hull_len); if (!p->hull) return NLOPT_OUT_OF_MEMORY; } nhull = convex_hull(&p->rtree, hull = p->hull, p->which_opt != 1); divisions: for (i = 0; i < nhull; ++i) { double K1 = -HUGE_VAL, K2 = -HUGE_VAL, K; int im, ip; /* find unequal points before (im) and after (ip) to get slope */ for (im = i-1; im >= 0 && hull[im][0] == hull[i][0]; --im) ; for (ip = i+1; ip < nhull && hull[ip][0] == hull[i][0]; ++ip) ; if (im >= 0) K1 = (hull[i][1] - hull[im][1]) / (hull[i][0] - hull[im][0]); if (ip < nhull) K2 = (hull[i][1] - hull[ip][1]) / (hull[i][0] - hull[ip][0]); K = MAX(K1, K2); if (hull[i][1] - K * hull[i][0] <= p->minf - magic_eps * fabs(p->minf) || ip == nhull) { /* "potentially optimal" rectangle, so subdivide */ nlopt_result ret = divide_rect(hull[i], p); divided_some = 1; if (ret != NLOPT_SUCCESS) return ret; xtol_reached = xtol_reached && small(hull[i] + 3+n, p); } /* for the DIRECT-L variant, we only divide one rectangle out of all points with equal diameter and function values ... note that for p->which_opt == 1, i == ip-1 should be a no-op anyway, since we set allow_dups=0 in convex_hull above */ if (p->which_opt == 1) i = ip - 1; /* skip to next unequal point for next iteration */ else if (p->which_opt == 2) /* like DIRECT-L but randomized */ i += nlopt_iurand(ip - i); /* possibly do another equal pt */ } if (!divided_some) { if (magic_eps != 0) { magic_eps = 0; goto divisions; /* try again */ } else { /* WTF? divide largest rectangle with smallest f */ /* (note that this code actually gets called from time to time, and the heuristic here seems to work well, but I don't recall this situation being discussed in the references?) */ rb_node *max = rb_tree_max(&p->rtree); rb_node *pred = max; double wmax = max->k[0]; do { /* note: this loop is O(N) worst-case time */ max = pred; pred = rb_tree_pred(max); } while (pred && pred->k[0] == wmax); return divide_rect(max->k, p); } } return xtol_reached ? NLOPT_XTOL_REACHED : NLOPT_SUCCESS; } /***************************************************************************/ /* lexographic sort order (d,f,age) of hyper-rects, for red-black tree */ int cdirect_hyperrect_compare(double *a, double *b) { if (a[0] < b[0]) return -1; if (a[0] > b[0]) return +1; if (a[1] < b[1]) return -1; if (a[1] > b[1]) return +1; if (a[2] < b[2]) return -1; if (a[2] > b[2]) return +1; return (int) (a - b); /* tie-breaker, shouldn't be needed */ } /***************************************************************************/ nlopt_result cdirect_unscaled(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, double magic_eps, int which_alg) { params p; int i; double *rnew; nlopt_result ret = NLOPT_OUT_OF_MEMORY; p.magic_eps = magic_eps; p.which_diam = which_alg % 3; p.which_div = (which_alg / 3) % 3; p.which_opt = (which_alg / (3*3)) % 3; p.lb = lb; p.ub = ub; p.stop = stop; p.n = n; p.L = 2*n+3; p.f = f; p.f_data = f_data; p.xmin = x; p.minf = HUGE_VAL; p.work = 0; p.iwork = 0; p.hull = 0; p.age = 0; rb_tree_init(&p.rtree, cdirect_hyperrect_compare); p.work = (double *) malloc(sizeof(double) * (2*n)); if (!p.work) goto done; p.iwork = (int *) malloc(sizeof(int) * n); if (!p.iwork) goto done; p.hull_len = 128; /* start with a reasonable number */ p.hull = (double **) malloc(sizeof(double *) * p.hull_len); if (!p.hull) goto done; if (!(rnew = (double *) malloc(sizeof(double) * p.L))) goto done; for (i = 0; i < n; ++i) { rnew[3+i] = 0.5 * (lb[i] + ub[i]); rnew[3+n+i] = ub[i] - lb[i]; } rnew[0] = rect_diameter(n, rnew+3+n, &p); rnew[1] = function_eval(rnew+3, &p); rnew[2] = p.age++; if (!rb_tree_insert(&p.rtree, rnew)) { free(rnew); goto done; } ret = divide_rect(rnew, &p); if (ret != NLOPT_SUCCESS) goto done; while (1) { double minf0 = p.minf; ret = divide_good_rects(&p); if (ret != NLOPT_SUCCESS) goto done; if (p.minf < minf0 && nlopt_stop_f(p.stop, p.minf, minf0)) { ret = NLOPT_FTOL_REACHED; goto done; } } done: rb_tree_destroy_with_keys(&p.rtree); free(p.hull); free(p.iwork); free(p.work); *minf = p.minf; return ret; } /* in the conventional DIRECT-type algorithm, we first rescale our coordinates to a unit hypercube ... we do this simply by wrapping cdirect() around cdirect_unscaled(). */ double cdirect_uf(unsigned n, const double *xu, double *grad, void *d_) { cdirect_uf_data *d = (cdirect_uf_data *) d_; double f; unsigned i; for (i = 0; i < n; ++i) d->x[i] = d->lb[i] + xu[i] * (d->ub[i] - d->lb[i]); f = d->f(n, d->x, grad, d->f_data); if (grad) for (i = 0; i < n; ++i) grad[i] *= d->ub[i] - d->lb[i]; return f; } nlopt_result cdirect(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, double magic_eps, int which_alg) { cdirect_uf_data d; nlopt_result ret; const double *xtol_abs_save; int i; d.f = f; d.f_data = f_data; d.lb = lb; d.ub = ub; d.x = (double *) malloc(sizeof(double) * n*4); if (!d.x) return NLOPT_OUT_OF_MEMORY; for (i = 0; i < n; ++i) { x[i] = (x[i] - lb[i]) / (ub[i] - lb[i]); d.x[n+i] = 0; d.x[2*n+i] = 1; d.x[3*n+i] = stop->xtol_abs[i] / (ub[i] - lb[i]); } xtol_abs_save = stop->xtol_abs; stop->xtol_abs = d.x + 3*n; ret = cdirect_unscaled(n, cdirect_uf, &d, d.x+n, d.x+2*n, x, minf, stop, magic_eps, which_alg); stop->xtol_abs = xtol_abs_save; for (i = 0; i < n; ++i) x[i] = lb[i]+ x[i] * (ub[i] - lb[i]); free(d.x); return ret; } nlopt-2.6.1/src/algs/cdirect/cdirect.h000066400000000000000000000051711345435414600176110ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef CDIRECT_H #define CDIRECT_H #include "nlopt-util.h" #include "nlopt.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ extern nlopt_result cdirect_unscaled(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, double magic_eps, int which_alg); extern nlopt_result cdirect(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, double magic_eps, int which_alg); extern nlopt_result cdirect_hybrid(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, nlopt_algorithm local_alg, int local_maxeval, int randomized_div); extern nlopt_result cdirect_hybrid_unscaled(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, nlopt_algorithm local_alg, int local_maxeval, int randomized_div); /* internal routines and data structures: */ extern int cdirect_hyperrect_compare(double *a, double *b); typedef struct { nlopt_func f; void *f_data; double *x; const double *lb, *ub; } cdirect_uf_data; extern double cdirect_uf(unsigned n, const double *xu, double *grad, void *d_); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* DIRECT_H */ nlopt-2.6.1/src/algs/cdirect/hybrid.c000066400000000000000000000254761345435414600174620ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include "nlopt-util.h" #include "nlopt.h" #include "cdirect.h" #include "redblack.h" /* Hybrid algorithm, inspired by DIRECT, that uses another local * optimization algorithm within each rectangle, and then looks * in the largest remaining rectangle (breaking ties by minimum * function value and then by age. * * Each hyperrect is represented by an array of length 3*n+3 consisting * of (d, -f, -a, x, c, w), where d=diameter, f=f(x), a=age, x=local optimum * c=center, w=widths. */ typedef struct { int n; /* dimension */ int L; /* 3*n+3 */ const double *lb, *ub; nlopt_stopping *stop; /* stopping criteria */ nlopt_func f; void *f_data; double minf, *xmin; /* min so far */ rb_tree rtree; /* red-black tree of rects, sorted by (d,-f,-a) */ int age; /* age for next new rect */ double *work; /* workspace of length >= 2*n */ nlopt_opt local_opt; /* local search algorithm */ int local_maxeval; int randomized_div; /* 1 to use randomized division algorithm */ } params; #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define THIRD (0.3333333333333333333333) /* 1/3 */ /************************************************************************/ static double fcount(unsigned n, const double *x, double *grad, void *p_) { params *p = (params *) p_; ++ *(p->stop->nevals_p); return p->f(n, x, grad, p->f_data); } static nlopt_result optimize_rect(double *r, params *p) { int i, n = p->n; double *lb = p->work, *ub = lb + n; double *x = r + 3, *c = x + n, *w = c + n; double t = nlopt_seconds(); double minf; nlopt_stopping *stop = p->stop; nlopt_result ret; if (stop->maxeval > 0 && *(stop->nevals_p) >= stop->maxeval) return NLOPT_MAXEVAL_REACHED; if (stop->maxtime > 0 && t - stop->start >= stop->maxtime) return NLOPT_MAXTIME_REACHED; for (i = 0; i < n; ++i) { lb[i] = c[i] - 0.5 * w[i]; ub[i] = c[i] + 0.5 * w[i]; } ret = nlopt_set_lower_bounds(p->local_opt, lb); if (ret != NLOPT_SUCCESS) return ret; ret = nlopt_set_upper_bounds(p->local_opt, ub); if (ret != NLOPT_SUCCESS) return ret; if (p->local_maxeval > 0) { ret = nlopt_set_maxeval(p->local_opt, MIN(p->local_maxeval, stop->maxeval - *(stop->nevals_p))); if (ret != NLOPT_SUCCESS) return ret; } ret = nlopt_set_maxtime(p->local_opt, stop->maxtime - (t - stop->start)); if (ret != NLOPT_SUCCESS) return ret; ret = nlopt_optimize(p->local_opt, x, &minf); r[1] = -minf; if (ret > 0) { if (minf < p->minf) { p->minf = minf; memcpy(p->xmin, x, sizeof(double) * n); if (ret == NLOPT_MINF_MAX_REACHED) return ret; } return NLOPT_SUCCESS; } return ret; } /* given a hyperrect r, randomize the starting guess within the middle third of the box (don't guess too close to edges) */ static void randomize_x(int n, double *r) { double *x = r + 3, *c = x + n, *w = c + n; int i; for (i = 0; i < n; ++i) x[i] = nlopt_urand(c[i] - w[i]*(0.5*THIRD), c[i] + w[i]*(0.5*THIRD)); } /************************************************************************/ static double longest(int n, const double *w) { double wmax = w[n-1]; for (n = n-2; n >= 0; n--) if (w[n] > wmax) wmax = w[n]; return wmax; } #define EQUAL_SIDE_TOL 5e-2 /* tolerance to equate side sizes */ static nlopt_result divide_largest(params *p) { int L = p->L; int n = p->n; rb_node *node = rb_tree_max(&p->rtree); /* just using it as a heap */ double minf_start = p->minf; double *r = node->k, *rnew = NULL; double *x = r + 3, *c = x + n, *w = c + n; const double *lb = p->lb, *ub = p->ub; int i, idiv; double wmax; nlopt_result ret; /* printf("rect:, %d, %g, %g, %g, %g\n", p->stop->nevals_p, c[0], c[1], w[0], w[1]); */ /* check xtol */ for (i = 0; i < n; ++i) if (w[i] > p->stop->xtol_rel * (ub[i] - lb[i]) && w[i] > p->stop->xtol_abs[i]) break; if (i == n) return NLOPT_XTOL_REACHED; if (p->randomized_div) { /* randomly pick among ~largest sides */ int nlongest = 0; wmax = longest(n, w); for (i = 0; i < n; ++i) if (wmax - w[i] < EQUAL_SIDE_TOL * wmax) ++nlongest; i = 1 + nlopt_iurand(nlongest); for (idiv = 0; idiv < n; ++idiv) { if (wmax - w[idiv] < EQUAL_SIDE_TOL * wmax) --i; if (!i) break; } } else { /* just pick first largest side */ wmax = w[idiv = 0]; for (i = 1; i < n; ++i) if (w[i] > wmax) wmax = w[idiv = i]; } if (fabs(x[idiv] - c[idiv]) > (0.5 * THIRD) * w[idiv]) { /* bisect */ double deltac = (x[idiv] > c[idiv] ? 0.25 : -0.25) * w[idiv]; w[idiv] *= 0.5; c[idiv] += deltac; r[0] = longest(n, w); /* new diameter */ /* r[1] unchanged since still contains local optimum x */ r[2] = p->age--; node = rb_tree_resort(&p->rtree, node); rnew = (double *) malloc(sizeof(double) * L); if (!rnew) return NLOPT_OUT_OF_MEMORY; memcpy(rnew, r, sizeof(double) * L); rnew[2] = p->age--; rnew[3+n+idiv] -= deltac*2; if (p->randomized_div) randomize_x(n, rnew); else memcpy(rnew+3, rnew+3+n, sizeof(double) * n); /* x = c */ ret = optimize_rect(rnew, p); if (ret != NLOPT_SUCCESS) { free(rnew); return ret; } if (!rb_tree_insert(&p->rtree, rnew)) { free(rnew); return NLOPT_OUT_OF_MEMORY; } } else { /* trisect */ w[idiv] *= THIRD; r[0] = longest(n, w); /* r[1] unchanged since still contains local optimum x */ r[2] = p->age--; node = rb_tree_resort(&p->rtree, node); for (i = -1; i <= +1; i += 2) { rnew = (double *) malloc(sizeof(double) * L); if (!rnew) return NLOPT_OUT_OF_MEMORY; memcpy(rnew, r, sizeof(double) * L); rnew[2] = p->age--; rnew[3+n+idiv] += w[i] * i; if (p->randomized_div) randomize_x(n, rnew); else memcpy(rnew+3, rnew+3+n, sizeof(double) * n); /* x = c */ ret = optimize_rect(rnew, p); if (ret != NLOPT_SUCCESS) { free(rnew); return ret; } if (!rb_tree_insert(&p->rtree, rnew)) { free(rnew); return NLOPT_OUT_OF_MEMORY; } } } if (p->minf < minf_start && nlopt_stop_f(p->stop, p->minf, minf_start)) return NLOPT_FTOL_REACHED; return NLOPT_SUCCESS; } /************************************************************************/ nlopt_result cdirect_hybrid_unscaled(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, nlopt_algorithm local_alg, int local_maxeval, int randomized_div) { params p; int i; double *rnew; nlopt_result ret = NLOPT_OUT_OF_MEMORY; p.n = n; p.L = 3*n+3; p.lb = lb; p.ub = ub; p.stop = stop; p.f = f; p.f_data = f_data; p.minf = HUGE_VAL; p.xmin = x; p.age = 0; p.work = 0; p.randomized_div = randomized_div; p.local_opt = 0; rb_tree_init(&p.rtree, cdirect_hyperrect_compare); p.work = (double *) malloc(sizeof(double) * (2*n)); if (!p.work) goto done; if (!(rnew = (double *) malloc(sizeof(double) * p.L))) goto done; for (i = 0; i < n; ++i) { rnew[3+i] = rnew[3+n+i] = 0.5 * (lb[i] + ub[i]); rnew[3+2*n+i] = ub[i] - lb[i]; } rnew[0] = longest(n, rnew+2*n); rnew[2] = p.age--; p.local_opt = nlopt_create(local_alg, n); if (!p.local_opt) { ret = NLOPT_INVALID_ARGS; goto done; } p.local_maxeval = local_maxeval; ret = nlopt_set_stopval(p.local_opt, stop->minf_max); if (ret != NLOPT_SUCCESS) goto done; ret = nlopt_set_ftol_rel(p.local_opt, stop->ftol_rel); if (ret != NLOPT_SUCCESS) goto done; ret = nlopt_set_ftol_abs(p.local_opt, stop->ftol_abs); if (ret != NLOPT_SUCCESS) goto done; ret = nlopt_set_xtol_rel(p.local_opt, stop->xtol_rel); if (ret != NLOPT_SUCCESS) goto done; if (stop->xtol_abs) { ret = nlopt_set_xtol_abs(p.local_opt, stop->xtol_abs); if (ret != NLOPT_SUCCESS) goto done; } ret = nlopt_set_min_objective(p.local_opt, fcount, &p); if (ret != NLOPT_SUCCESS) goto done; ret = optimize_rect(rnew, &p); if (ret != NLOPT_SUCCESS) { free(rnew); goto done; } if (!rb_tree_insert(&p.rtree, rnew)) { free(rnew); goto done; } do { ret = divide_largest(&p); } while (ret == NLOPT_SUCCESS); done: rb_tree_destroy_with_keys(&p.rtree); free(p.work); nlopt_destroy(p.local_opt); *minf = p.minf; return ret; } /* rescaled to unit hypercube so that all x[i] are weighted equally */ nlopt_result cdirect_hybrid(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop, nlopt_algorithm local_alg, int local_maxeval, int randomized_div) { cdirect_uf_data d; nlopt_result ret; const double *xtol_abs_save; int i; d.f = f; d.f_data = f_data; d.lb = lb; d.ub = ub; d.x = (double *) malloc(sizeof(double) * n*4); if (!d.x) return NLOPT_OUT_OF_MEMORY; for (i = 0; i < n; ++i) { x[i] = (x[i] - lb[i]) / (ub[i] - lb[i]); d.x[n+i] = 0; d.x[2*n+i] = 1; d.x[3*n+i] = stop->xtol_abs[i] / (ub[i] - lb[i]); } xtol_abs_save = stop->xtol_abs; stop->xtol_abs = d.x + 3*n; ret = cdirect_hybrid_unscaled(n, cdirect_uf, &d, d.x+n, d.x+2*n, x, minf, stop, local_alg, local_maxeval, randomized_div); stop->xtol_abs = xtol_abs_save; for (i = 0; i < n; ++i) x[i] = lb[i]+ x[i] * (ub[i] - lb[i]); free(d.x); return ret; } nlopt-2.6.1/src/algs/cobyla/000077500000000000000000000000001345435414600156535ustar00rootroot00000000000000nlopt-2.6.1/src/algs/cobyla/COPYRIGHT000066400000000000000000000022751345435414600171540ustar00rootroot00000000000000Copyright (c) 1992, Michael J. D. Powell (M.J.D.Powell@damtp.cam.ac.uk) Copyright (c) 2004, Jean-Sebastien Roy (js@jeannot.org) Copyright (c) 2008, Steven G. Johnson (stevenj@alum.mit.edu) 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. nlopt-2.6.1/src/algs/cobyla/README000066400000000000000000000040331345435414600165330ustar00rootroot00000000000000This code implements COBYLA (Constrained Optimization BY Linear Approximations) algorithm derivative free optimization with nonlinear inequality constraints by M. J. D. Powell, described by: M. J. D. Powell, "A direct search optimization method that models the objective and constraint functions by linear interpolation," in Advances in Optimization and Numerical Analysis, eds. S. Gomez and J.-P. Hennart (Kluwer Academic: Dordrecht, 1994), p. 51-67. and reviewed in: M. J. D. Powell, "Direct search algorithms for optimization calculations," Acta Numerica 7, 287-336 (1998). It constructs successive linear approximations of the objective function and constraints via a simplex of n+1 points (in n dimensions), and optimizes these approximations in a trust region at each step. The original code itself was written in Fortran by Powell, and apparently released without restrictions (like several of his other programs), and was converted to C in 2004 by Jean-Sebastien Roy (js@jeannot.org) for the SciPy project. The C version was released under the attached license (basically the MIT license) at: http://www.jeannot.org/~js/code/index.en.html#COBYLA It was incorporated into NLopt in 2008 by S. G. Johnson, and kept under the same MIT license. In incorporating it into NLopt, SGJ adapted it to include the NLopt stopping conditions (the original code provided an x tolerance and a maximum number of function evaluations only). The original COBYLA did not have explicit support for bound constraints; these are included as linear constraints along with any other nonlinear constraints. This is mostly fine---linear constraints are handled exactly by COBYLA's linear approximations. However, occasionally COBYLA takes a "simplex" step, either to create the initial simplex or to fix a degenerate simplex, and these steps could violate the bound constraints. SGJ modified COBYLA to explicitly honor the bound constraints in these cases, so that the objective/constraints are never evaluated outside of the bound constraints, without slowing convergence. nlopt-2.6.1/src/algs/cobyla/README.orig000066400000000000000000000054641345435414600175030ustar00rootroot00000000000000# COBYLA : constrained optimization by linear approximation # Version 1.1 # Copyright (c) 1992, Michael J. D. Powell (M.J.D.Powell@damtp.cam.ac.uk) # Copyright (c) 2004, J.S. Roy (js@jeannot.org) # See the LICENSE file for copyright information. # $Jeannot: README,v 1.7 2004/04/18 14:04:20 js Exp $ This software is a C version of COBYLA2, a contrained optimization by linear approximation package developed by Michael J. D. Powell in Fortran. The original source code can be found at : http://plato.la.asu.edu/topics/problems/nlores.html Reference article for the method: Powell, J.M.D. (1992), "A Direct Search Optimization Method that Models the Objective and Constraint Functions by Linear Interpolation", DAMTP/NA5, Cambridge, England. This package was initially built by J.S. Roy to ease integration into SciPy. See: http://www.scipy.org/ Many thanks to Michael J. D. Powell for allowing this to happen ! This software, a derivative free non-linear optimizer, aims at minimizing the value of a nonlinear function subject to nonlinear constraints. It requires to be able to evaluate the function and the value of the constraints. COBYLA will try to make all the values of the constraints positive. So if you want to input a constraint j such as variable x[i] <= MAX, set: constraint[j] = MAX - x[i] See the comments in cobyla.c for more details. This software has been converted from the Fortran into C and provides the following modifications : - reentrancy, no global variables or functions ; - ability to pass a pointer to the function to be optimized (to provide access to constants) ; - ability to end the minimization at any time ; And other small changes. The last version (and other software) is avalaible at the URL : http://www.jeannot.org/~js/code/index.en.html A Python interface module is also provided. Contents : - cobyla.c : Source - cobyla.h : Header, and API documentation - LICENSE : License and copyright information - HISTORY : Release history - README : This file - example.c : A simple example - Makefile : Make file used to build the examples - moduleCobyla.c : the source of the python module - cobyla.py : the python module wrapper - example.py : an example for the python module - setup.py : the python installer Use is described in cobyla.h. For more information, see the example. The example can be built and executed by doing : make test You may need to adjust the Makefile before building cobyla. To install the module in the current directory, use: python setup.py build_ext --inplace To test it, execute: python cobyla.py To install it globaly, use: python setup.py install If you make use of this software, or if you make modifications to it (for a specific platform for example), you are encouraged to contact the author of this Fortran to C conversion at the following email : js@jeannot.org Thanks ! nlopt-2.6.1/src/algs/cobyla/cobyla.c000066400000000000000000001553271345435414600173050ustar00rootroot00000000000000/* cobyla : contrained optimization by linear approximation */ /* * Copyright (c) 1992, Michael J. D. Powell (M.J.D.Powell@damtp.cam.ac.uk) * Copyright (c) 2004, Jean-Sebastien Roy (js@jeannot.org) * * 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. */ /* * This software is a C version of COBYLA2, a contrained optimization by linear * approximation package developed by Michael J. D. Powell in Fortran. * * The original source code can be found at : * http://plato.la.asu.edu/topics/problems/nlores.html * * Original RCS id * static char const rcsid[] = * " @(#) $Jeannot: cobyla.c,v 1.11 2004/04/18 09:51:36 js Exp $"; * */ #include #include #include #include "cobyla.h" /* SGJ, 2008: modified COBYLA code to take explicit account of bound constraints. Since bound constraints are linear, these should already be handled exactly when COBYLA optimizes it linear model. However, they were not handled properly when COBYLA created its initial simplex, or when COBYLA updated unacceptable simplices. Since NLopt guarantees that the objective will not be evaluated outside the bound constraints, this required us to handle such points by putting a slope discontinuity into the objective & constraints (below), which slows convergence considerably for smooth functions. Instead, handling them explicitly prevents this problem */ #define ENFORCE_BOUNDS 1 #define MIN2(a,b) ((a) <= (b) ? (a) : (b)) #define MAX2(a,b) ((a) >= (b) ? (a) : (b)) #define U(n) ((unsigned) (n)) /**************************************************************************/ /* SGJ, 2008: NLopt-style interface function: */ typedef struct { nlopt_func f; void *f_data; unsigned m_orig; nlopt_constraint *fc; unsigned p; nlopt_constraint *h; double *xtmp; double *lb, *ub; double *con_tol, *scale; nlopt_stopping *stop; } func_wrap_state; static int func_wrap(int ni, int mi, double *x, double *f, double *con, func_wrap_state *s) { unsigned n = U(ni); unsigned i, j, k; double *xtmp = s->xtmp; const double *lb = s->lb, *ub = s->ub; (void) mi; /* unused */ /* in nlopt, we guarante that the function is never evaluated outside the lb and ub bounds, so we need force this with xtmp ... note that this leads to discontinuity in the first derivative, which slows convergence if we don't enable the ENFORCE_BOUNDS feature above. */ for (j = 0; j < n; ++j) { if (x[j] < lb[j]) xtmp[j] = lb[j]; else if (x[j] > ub[j]) xtmp[j] = ub[j]; else xtmp[j] = x[j]; } nlopt_unscale(n, s->scale, xtmp, xtmp); *f = s->f(n, xtmp, NULL, s->f_data); if (nlopt_stop_forced(s->stop)) return 1; i = 0; for (j = 0; j < s->m_orig; ++j) { nlopt_eval_constraint(con + i, NULL, s->fc+j, n, xtmp); if (nlopt_stop_forced(s->stop)) return 1; for (k = 0; k < s->fc[j].m; ++k) con[i + k] = -con[i + k]; i += s->fc[j].m; } for (j = 0; j < s->p; ++j) { nlopt_eval_constraint(con + i, NULL, s->h+j, n, xtmp); if (nlopt_stop_forced(s->stop)) return 1; for (k = 0; k < s->h[j].m; ++k) con[(i + s->h[j].m) + k] = -con[i + k]; i += 2 * s->h[j].m; } for (j = 0; j < n; ++j) { if (!nlopt_isinf(lb[j])) con[i++] = x[j] - lb[j]; if (!nlopt_isinf(ub[j])) con[i++] = ub[j] - x[j]; } return 0; } /* * Verbosity level */ typedef enum { COBYLA_MSG_NONE = 0, /* No messages */ COBYLA_MSG_EXIT = 1, /* Exit reasons */ COBYLA_MSG_ITER = 2, /* Rho and Sigma changes */ COBYLA_MSG_INFO = 3 /* Informational messages */ } cobyla_message; /* * A function as required by cobyla * state is a void pointer provided to the function at each call * * n : the number of variables * m : the number of constraints * x : on input, then vector of variables (should not be modified) * f : on output, the value of the function * con : on output, the value of the constraints (vector of size m) * state : on input, the value of the state variable as provided to cobyla * * COBYLA will try to make all the values of the constraints positive. * So if you want to input a constraint j such as x[i] <= MAX, set: * con[j] = MAX - x[i] * The function must returns 0 if no error occurs or 1 to immediately end the * minimization. * */ typedef int cobyla_function(int n, int m, double *x, double *f, double *con, func_wrap_state *state); /* * cobyla : minimize a function subject to constraints * * n : number of variables (>=0) * m : number of constraints (>=0) * x : on input, initial estimate ; on output, the solution * minf : on output, minimum objective function * rhobeg : a reasonable initial change to the variables * stop : the NLopt stopping criteria * lb, ub : lower and upper bounds on x * message : see the cobyla_message enum * calcfc : the function to minimize (see cobyla_function) * state : used by function (see cobyla_function) * * The cobyla function returns the usual nlopt_result codes. * */ extern nlopt_result cobyla(int n, int m, double *x, double *minf, double rhobeg, double rhoend, nlopt_stopping *stop, const double *lb, const double *ub, int message, cobyla_function *calcfc, func_wrap_state *state); nlopt_result cobyla_minimize(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, unsigned p, nlopt_constraint *h, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, const double *dx) { unsigned i, j; func_wrap_state s; nlopt_result ret; double rhobeg, rhoend; s.f = f; s.f_data = f_data; s.m_orig = m; s.fc = fc; s.p = p; s.h = h; s.stop = stop; s.lb = s.ub = s.xtmp = s.con_tol = s.scale = NULL; s.scale = nlopt_compute_rescaling(n, dx); if (!s.scale) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (j = 0; j < n; ++j) if (s.scale[j] == 0 || !nlopt_isfinite(s.scale[j])) { nlopt_stop_msg(stop, "invalid scaling %g of dimension %d: possible over/underflow?", s.scale[j], j); ret = NLOPT_INVALID_ARGS; goto done; } s.lb = nlopt_new_rescaled(n, s.scale, lb); if (!s.lb) { ret = NLOPT_OUT_OF_MEMORY; goto done; } s.ub = nlopt_new_rescaled(n, s.scale, ub); if (!s.ub) { ret = NLOPT_OUT_OF_MEMORY; goto done; } nlopt_reorder_bounds(n, s.lb, s.ub); s.xtmp = (double *) malloc(sizeof(double) * n); if (!s.xtmp) { ret = NLOPT_OUT_OF_MEMORY; goto done; } /* SGJ, 2008: compute rhoend from NLopt stop info */ rhobeg = fabs(dx[0] / s.scale[0]); rhoend = stop->xtol_rel * (rhobeg); for (j = 0; j < n; ++j) if (rhoend < stop->xtol_abs[j] / fabs(s.scale[j])) rhoend = stop->xtol_abs[j] / fabs(s.scale[j]); /* each equality constraint gives two inequality constraints */ m = nlopt_count_constraints(m, fc) + 2 * nlopt_count_constraints(p, h); /* add constraints for lower/upper bounds (if any) */ for (j = 0; j < n; ++j) { if (!nlopt_isinf(lb[j])) ++m; if (!nlopt_isinf(ub[j])) ++m; } s.con_tol = (double *) malloc(sizeof(double) * m); if (m && !s.con_tol) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (j = 0; j < m; ++j) s.con_tol[j] = 0; for (j = i = 0; i < s.m_orig; ++i) { unsigned ji = j, jnext = j + fc[i].m; for (; j < jnext; ++j) s.con_tol[j] = fc[i].tol[j - ji]; } for (i = 0; i < s.p; ++i) { unsigned ji = j, jnext = j + h[i].m; for (; j < jnext; ++j) s.con_tol[j] = h[i].tol[j - ji]; ji = j; jnext = j + h[i].m; for (; j < jnext; ++j) s.con_tol[j] = h[i].tol[j - ji]; } nlopt_rescale(n, s.scale, x, x); ret = cobyla((int) n, (int) m, x, minf, rhobeg, rhoend, stop, s.lb, s.ub, COBYLA_MSG_NONE, func_wrap, &s); nlopt_unscale(n, s.scale, x, x); /* make sure e.g. rounding errors didn't push us slightly out of bounds */ for (j = 0; j < n; ++j) { if (x[j] < lb[j]) x[j] = lb[j]; if (x[j] > ub[j]) x[j] = ub[j]; } done: free(s.con_tol); free(s.xtmp); free(s.ub); free(s.lb); free(s.scale); return ret; } /**************************************************************************/ /* SGJ, 2010: I find that it seems to increase robustness of the algorithm if, on "simplex" steps (which are intended to improve the linear independence of the simplex, not improve the objective), we multiply the steps by pseudorandom numbers in [0,1). Intuitively, pseudorandom steps are likely to avoid any accidental dependency in the simplex vertices. However, since I still want COBYLA to be a deterministic algorithm, and I don't care all that much about the quality of the randomness here, I implement a simple linear congruential generator rather than use nlopt_urand, and set the initial seed deterministically. */ #if defined(HAVE_STDINT_H) # include #endif #ifndef HAVE_UINT32_T # if SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long uint32_t; # elif SIZEOF_UNSIGNED_INT == 4 typedef unsigned int uint32_t; # else # error No 32-bit unsigned integer type # endif #endif /* a simple linear congruential generator */ static uint32_t lcg_rand(uint32_t *seed) { return (*seed = *seed * 1103515245 + 12345); } static double lcg_urand(uint32_t *seed, double a, double b) { return a + lcg_rand(seed) * (b - a) / ((uint32_t) -1); } /**************************************************************************/ static nlopt_result cobylb(int *n, int *m, int *mpp, double *x, double *minf, double *rhobeg, double rhoend, nlopt_stopping *stop, const double *lb, const double *ub, int *iprint, double *con, double *sim, double *simi, double *datmat, double *a, double *vsig, double *veta, double *sigbar, double *dx, double *w, int *iact, cobyla_function *calcfc, func_wrap_state *state); static nlopt_result trstlp(int *n, int *m, double *a, double *b, double *rho, double *dx, int *ifull, int *iact, double *z__, double *zdota, double *vmultc, double *sdirn, double *dxnew, double *vmultd); /* ------------------------------------------------------------------------ */ nlopt_result cobyla(int n, int m, double *x, double *minf, double rhobeg, double rhoend, nlopt_stopping *stop, const double *lb, const double *ub, int iprint, cobyla_function *calcfc, func_wrap_state *state) { int icon, isim, isigb, idatm, iveta, isimi, ivsig, iwork, ia, idx, mpp; int *iact; double *w; nlopt_result rc; /* * This subroutine minimizes an objective function F(X) subject to M * inequality constraints on X, where X is a vector of variables that has * N components. The algorithm employs linear approximations to the * objective and constraint functions, the approximations being formed by * linear interpolation at N+1 points in the space of the variables. * We regard these interpolation points as vertices of a simplex. The * parameter RHO controls the size of the simplex and it is reduced * automatically from RHOBEG to RHOEND. For each RHO the subroutine tries * to achieve a good vector of variables for the current size, and then * RHO is reduced until the value RHOEND is reached. Therefore RHOBEG and * RHOEND should be set to reasonable initial changes to and the required * accuracy in the variables respectively, but this accuracy should be * viewed as a subject for experimentation because it is not guaranteed. * The subroutine has an advantage over many of its competitors, however, * which is that it treats each constraint individually when calculating * a change to the variables, instead of lumping the constraints together * into a single penalty function. The name of the subroutine is derived * from the phrase Constrained Optimization BY Linear Approximations. * * The user must set the values of N, M, RHOBEG and RHOEND, and must * provide an initial vector of variables in X. Further, the value of * IPRINT should be set to 0, 1, 2 or 3, which controls the amount of * printing during the calculation. Specifically, there is no output if * IPRINT=0 and there is output only at the end of the calculation if * IPRINT=1. Otherwise each new value of RHO and SIGMA is printed. * Further, the vector of variables and some function information are * given either when RHO is reduced or when each new value of F(X) is * computed in the cases IPRINT=2 or IPRINT=3 respectively. Here SIGMA * is a penalty parameter, it being assumed that a change to X is an * improvement if it reduces the merit function * F(X)+SIGMA*MAX(0.0,-C1(X),-C2(X),...,-CM(X)), * where C1,C2,...,CM denote the constraint functions that should become * nonnegative eventually, at least to the precision of RHOEND. In the * printed output the displayed term that is multiplied by SIGMA is * called MAXCV, which stands for 'MAXimum Constraint Violation'. The * argument MAXFUN is an int variable that must be set by the user to a * limit on the number of calls of CALCFC, the purpose of this routine being * given below. The value of MAXFUN will be altered to the number of calls * of CALCFC that are made. The arguments W and IACT provide real and * int arrays that are used as working space. Their lengths must be at * least N*(3*N+2*M+11)+4*M+6 and M+1 respectively. * * In order to define the objective and constraint functions, we require * a subroutine that has the name and arguments * SUBROUTINE CALCFC (N,M,X,F,CON) * DIMENSION X(*),CON(*) . * The values of N and M are fixed and have been defined already, while * X is now the current vector of variables. The subroutine should return * the objective and constraint functions at X in F and CON(1),CON(2), * ...,CON(M). Note that we are trying to adjust X so that F(X) is as * small as possible subject to the constraint functions being nonnegative. * * Partition the working space array W to provide the storage that is needed * for the main calculation. */ *(stop->nevals_p) = 0; if (n == 0) { if (iprint>=1) fprintf(stderr, "cobyla: N==0.\n"); return NLOPT_SUCCESS; } if (n < 0 || m < 0) { if (iprint>=1) fprintf(stderr, "cobyla: N<0 or M<0.\n"); return NLOPT_INVALID_ARGS; } /* workspace allocation */ w = (double*) malloc(U(n*(3*n+2*m+11)+4*m+6)*sizeof(*w)); if (w == NULL) { if (iprint>=1) fprintf(stderr, "cobyla: memory allocation error.\n"); return NLOPT_OUT_OF_MEMORY; } iact = (int*)malloc(U(m+1)*sizeof(*iact)); if (iact == NULL) { if (iprint>=1) fprintf(stderr, "cobyla: memory allocation error.\n"); free(w); return NLOPT_OUT_OF_MEMORY; } /* Parameter adjustments */ --iact; --w; --x; --lb; --ub; /* Function Body */ mpp = m + 2; icon = 1; isim = icon + mpp; isimi = isim + n * n + n; idatm = isimi + n * n; ia = idatm + n * mpp + mpp; ivsig = ia + m * n + n; iveta = ivsig + n; isigb = iveta + n; idx = isigb + n; iwork = idx + n; rc = cobylb(&n, &m, &mpp, &x[1], minf, &rhobeg, rhoend, stop, &lb[1], &ub[1], &iprint, &w[icon], &w[isim], &w[isimi], &w[idatm], &w[ia], &w[ivsig], &w[iveta], &w[isigb], &w[idx], &w[iwork], &iact[1], calcfc, state); /* Parameter adjustments (reverse) */ ++iact; ++w; free(w); free(iact); return rc; } /* cobyla */ /* ------------------------------------------------------------------------- */ static nlopt_result cobylb(int *n, int *m, int *mpp, double *x, double *minf, double *rhobeg, double rhoend, nlopt_stopping *stop, const double *lb, const double *ub, int *iprint, double *con, double *sim, double *simi, double *datmat, double *a, double *vsig, double *veta, double *sigbar, double *dx, double *w, int *iact, cobyla_function *calcfc, func_wrap_state *state) { /* System generated locals */ int sim_dim1, sim_offset, simi_dim1, simi_offset, datmat_dim1, datmat_offset, a_dim1, a_offset, i__1, i__2, i__3; double d__1, d__2; /* Local variables */ double alpha, delta, denom, tempa, barmu; double beta, cmin = 0.0, cmax = 0.0; double cvmaxm, dxsign, prerem = 0.0; double edgmax, pareta, prerec = 0.0, phimin, parsig = 0.0; double gamma_; double phi, rho, sum = 0.0; double ratio, vmold, parmu, error, vmnew; double resmax, cvmaxp; double resnew, trured; double temp, wsig, f; double weta; int i__, j, k, l; int idxnew; int iflag = 0; int iptemp; int isdirn, izdota; int ivmc; int ivmd; int mp, np, iz, ibrnch; int nbest, ifull = 0, iptem, jdrop; nlopt_result rc = NLOPT_SUCCESS; uint32_t seed = (uint32_t) (*n + *m); /* arbitrary deterministic LCG seed */ int feasible; /* SGJ, 2008: added code to keep track of minimum feasible function val */ *minf = HUGE_VAL; /* Set the initial values of some parameters. The last column of SIM holds */ /* the optimal vertex of the current simplex, and the preceding N columns */ /* hold the displacements from the optimal vertex to the other vertices. */ /* Further, SIMI holds the inverse of the matrix that is contained in the */ /* first N columns of SIM. */ /* Parameter adjustments */ a_dim1 = *n; a_offset = 1 + a_dim1 * 1; a -= a_offset; simi_dim1 = *n; simi_offset = 1 + simi_dim1 * 1; simi -= simi_offset; sim_dim1 = *n; sim_offset = 1 + sim_dim1 * 1; sim -= sim_offset; datmat_dim1 = *mpp; datmat_offset = 1 + datmat_dim1 * 1; datmat -= datmat_offset; --x; --con; --vsig; --veta; --sigbar; --dx; --w; --iact; --lb; --ub; /* Function Body */ iptem = MIN2(*n,4); iptemp = iptem + 1; np = *n + 1; mp = *m + 1; alpha = .25; beta = 2.1; gamma_ = .5; delta = 1.1; rho = *rhobeg; parmu = 0.; if (*iprint >= 2) { fprintf(stderr, "cobyla: the initial value of RHO is %12.6E and PARMU is set to zero.\n", rho); } temp = 1. / rho; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { double rhocur; sim[i__ + np * sim_dim1] = x[i__]; i__2 = *n; for (j = 1; j <= i__2; ++j) { sim[i__ + j * sim_dim1] = 0.; simi[i__ + j * simi_dim1] = 0.; } rhocur = rho; #if ENFORCE_BOUNDS /* SGJ: make sure step rhocur stays inside [lb,ub] */ if (x[i__] + rhocur > ub[i__]) { if (x[i__] - rhocur >= lb[i__]) rhocur = -rhocur; else if (ub[i__] - x[i__] > x[i__] - lb[i__]) rhocur = 0.5 * (ub[i__] - x[i__]); else rhocur = 0.5 * (x[i__] - lb[i__]); } #endif sim[i__ + i__ * sim_dim1] = rhocur; simi[i__ + i__ * simi_dim1] = 1.0 / rhocur; } jdrop = np; ibrnch = 0; /* Make the next call of the user-supplied subroutine CALCFC. These */ /* instructions are also used for calling CALCFC during the iterations of */ /* the algorithm. */ /* SGJ comment: why the hell couldn't he just use a damn subroutine? #*&!%*@ Fortran-66 spaghetti code */ L40: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; else if (*(stop->nevals_p) > 0) { if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; } if (rc != NLOPT_SUCCESS) goto L600; ++ *(stop->nevals_p); if (calcfc(*n, *m, &x[1], &f, &con[1], state)) { if (*iprint >= 1) { fprintf(stderr, "cobyla: user requested end of minimization.\n"); } rc = NLOPT_FORCED_STOP; goto L600; } resmax = 0.; feasible = 1; /* SGJ, 2010 */ if (*m > 0) { i__1 = *m; for (k = 1; k <= i__1; ++k) { d__1 = resmax, d__2 = -con[k]; resmax = MAX2(d__1,d__2); if (d__2 > state->con_tol[k-1]) feasible = 0; /* SGJ, 2010 */ } } /* SGJ, 2008: check for minf_max reached by feasible point */ if (f < stop->minf_max && feasible) { rc = NLOPT_MINF_MAX_REACHED; goto L620; /* not L600 because we want to use current x, f, resmax */ } if (*(stop->nevals_p) == *iprint - 1 || *iprint == 3) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", *(stop->nevals_p), f, resmax); i__1 = iptem; fprintf(stderr, "cobyla: X ="); for (i__ = 1; i__ <= i__1; ++i__) { if (i__>1) fprintf(stderr, " "); fprintf(stderr, "%13.6E", x[i__]); } if (iptem < *n) { i__1 = *n; for (i__ = iptemp; i__ <= i__1; ++i__) { if (!((i__-1) % 4)) fprintf(stderr, "\ncobyla: "); fprintf(stderr, "%15.6E", x[i__]); } } fprintf(stderr, "\n"); } con[mp] = f; con[*mpp] = resmax; if (ibrnch == 1) { goto L440; } /* Set the recently calculated function values in a column of DATMAT. This */ /* array has a column for each vertex of the current simplex, the entries of */ /* each column being the values of the constraint functions (if any) */ /* followed by the objective function and the greatest constraint violation */ /* at the vertex. */ i__1 = *mpp; for (k = 1; k <= i__1; ++k) { datmat[k + jdrop * datmat_dim1] = con[k]; } if (*(stop->nevals_p) > np) { goto L130; } /* Exchange the new vertex of the initial simplex with the optimal vertex if */ /* necessary. Then, if the initial simplex is not complete, pick its next */ /* vertex and calculate the function values there. */ if (jdrop <= *n) { if (datmat[mp + np * datmat_dim1] <= f) { x[jdrop] = sim[jdrop + np * sim_dim1]; } else { /* improvement in function val */ double rhocur = x[jdrop] - sim[jdrop + np * sim_dim1]; /* SGJ: use rhocur instead of rho. In original code, rhocur == rho always, but I want to change this to ensure that simplex points fall within [lb,ub]. */ sim[jdrop + np * sim_dim1] = x[jdrop]; i__1 = *mpp; for (k = 1; k <= i__1; ++k) { datmat[k + jdrop * datmat_dim1] = datmat[k + np * datmat_dim1] ; datmat[k + np * datmat_dim1] = con[k]; } i__1 = jdrop; for (k = 1; k <= i__1; ++k) { sim[jdrop + k * sim_dim1] = -rhocur; temp = 0.f; i__2 = jdrop; for (i__ = k; i__ <= i__2; ++i__) { temp -= simi[i__ + k * simi_dim1]; } simi[jdrop + k * simi_dim1] = temp; } } } if (*(stop->nevals_p) <= *n) { /* evaluating initial simplex */ jdrop = *(stop->nevals_p); /* SGJ: was += rho, but using sim[jdrop,jdrop] enforces consistency if we change the stepsize above to stay in [lb,ub]. */ x[jdrop] += sim[jdrop + jdrop * sim_dim1]; goto L40; } L130: ibrnch = 1; /* Identify the optimal vertex of the current simplex. */ L140: phimin = datmat[mp + np * datmat_dim1] + parmu * datmat[*mpp + np * datmat_dim1]; nbest = np; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = datmat[mp + j * datmat_dim1] + parmu * datmat[*mpp + j * datmat_dim1]; if (temp < phimin) { nbest = j; phimin = temp; } else if (temp == phimin && parmu == 0.) { if (datmat[*mpp + j * datmat_dim1] < datmat[*mpp + nbest * datmat_dim1]) { nbest = j; } } } /* Switch the best vertex into pole position if it is not there already, */ /* and also update SIM, SIMI and DATMAT. */ if (nbest <= *n) { i__1 = *mpp; for (i__ = 1; i__ <= i__1; ++i__) { temp = datmat[i__ + np * datmat_dim1]; datmat[i__ + np * datmat_dim1] = datmat[i__ + nbest * datmat_dim1] ; datmat[i__ + nbest * datmat_dim1] = temp; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = sim[i__ + nbest * sim_dim1]; sim[i__ + nbest * sim_dim1] = 0.; sim[i__ + np * sim_dim1] += temp; tempa = 0.; i__2 = *n; for (k = 1; k <= i__2; ++k) { sim[i__ + k * sim_dim1] -= temp; tempa -= simi[k + i__ * simi_dim1]; } simi[nbest + i__ * simi_dim1] = tempa; } } /* Make an error return if SIGI is a poor approximation to the inverse of */ /* the leading N by N submatrix of SIG. */ error = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = *n; for (j = 1; j <= i__2; ++j) { temp = 0.; if (i__ == j) { temp += -1.; } i__3 = *n; for (k = 1; k <= i__3; ++k) if (sim[k + j * sim_dim1] != 0) { temp += simi[i__ + k * simi_dim1] * sim[k + j * sim_dim1]; } d__1 = error, d__2 = fabs(temp); error = MAX2(d__1,d__2); } } if (error > .1) { if (*iprint >= 1) { fprintf(stderr, "cobyla: rounding errors are becoming damaging.\n"); } rc = NLOPT_ROUNDOFF_LIMITED; goto L600; } /* Calculate the coefficients of the linear approximations to the objective */ /* and constraint functions, placing minus the objective function gradient */ /* after the constraint gradients in the array A. The vector W is used for */ /* working space. */ i__2 = mp; for (k = 1; k <= i__2; ++k) { con[k] = -datmat[k + np * datmat_dim1]; i__1 = *n; for (j = 1; j <= i__1; ++j) { w[j] = datmat[k + j * datmat_dim1] + con[k]; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = 0.; i__3 = *n; for (j = 1; j <= i__3; ++j) { temp += w[j] * simi[j + i__ * simi_dim1]; } if (k == mp) { temp = -temp; } a[i__ + k * a_dim1] = temp; } } /* Calculate the values of sigma and eta, and set IFLAG=0 if the current */ /* simplex is not acceptable. */ iflag = 1; parsig = alpha * rho; pareta = beta * rho; i__1 = *n; for (j = 1; j <= i__1; ++j) { wsig = 0.; weta = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { d__1 = simi[j + i__ * simi_dim1]; wsig += d__1 * d__1; d__1 = sim[i__ + j * sim_dim1]; weta += d__1 * d__1; } vsig[j] = 1. / sqrt(wsig); veta[j] = sqrt(weta); if (vsig[j] < parsig || veta[j] > pareta) { iflag = 0; } } /* If a new vertex is needed to improve acceptability, then decide which */ /* vertex to drop from the simplex. */ if (ibrnch == 1 || iflag == 1) { goto L370; } jdrop = 0; temp = pareta; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (veta[j] > temp) { jdrop = j; temp = veta[j]; } } if (jdrop == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (vsig[j] < temp) { jdrop = j; temp = vsig[j]; } } } /* Calculate the step to the new vertex and its sign. */ temp = gamma_ * rho * vsig[jdrop]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dx[i__] = temp * simi[jdrop + i__ * simi_dim1]; } cvmaxp = 0.; cvmaxm = 0.; i__1 = mp; for (k = 1; k <= i__1; ++k) { sum = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { sum += a[i__ + k * a_dim1] * dx[i__]; } if (k < mp) { temp = datmat[k + np * datmat_dim1]; d__1 = cvmaxp, d__2 = -sum - temp; cvmaxp = MAX2(d__1,d__2); d__1 = cvmaxm, d__2 = sum - temp; cvmaxm = MAX2(d__1,d__2); } } dxsign = 1.; if (parmu * (cvmaxp - cvmaxm) > sum + sum) { dxsign = -1.; } /* Update the elements of SIM and SIMI, and set the next X. */ temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* SGJ, 2010: pseudo-randomize simplex steps (see LCG comments above) */ dx[i__] = dxsign * dx[i__] * lcg_urand(&seed, 0.01, 1); /* SGJ: make sure dx step says in [lb,ub] */ #if ENFORCE_BOUNDS { double xi = sim[i__ + np * sim_dim1]; fixdx: if (xi + dx[i__] > ub[i__]) dx[i__] = -dx[i__]; if (xi + dx[i__] < lb[i__]) { if (xi - dx[i__] <= ub[i__]) dx[i__] = -dx[i__]; else { /* try again with halved step */ dx[i__] *= 0.5; goto fixdx; } } } #endif sim[i__ + jdrop * sim_dim1] = dx[i__]; temp += simi[jdrop + i__ * simi_dim1] * dx[i__]; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { simi[jdrop + i__ * simi_dim1] /= temp; } i__1 = *n; for (j = 1; j <= i__1; ++j) { if (j != jdrop) { temp = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp += simi[j + i__ * simi_dim1] * dx[i__]; } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { simi[j + i__ * simi_dim1] -= temp * simi[jdrop + i__ * simi_dim1]; } } x[j] = sim[j + np * sim_dim1] + dx[j]; } goto L40; /* Calculate DX=x(*)-x(0). Branch if the length of DX is less than 0.5*RHO. */ L370: iz = 1; izdota = iz + *n * *n; ivmc = izdota + *n; isdirn = ivmc + mp; idxnew = isdirn + *n; ivmd = idxnew + *n; rc = trstlp(n, m, &a[a_offset], &con[1], &rho, &dx[1], &ifull, &iact[1], &w[ iz], &w[izdota], &w[ivmc], &w[isdirn], &w[idxnew], &w[ivmd]); if (rc != NLOPT_SUCCESS) goto L600; #if ENFORCE_BOUNDS /* SGJ: since the bound constraints are linear, we should never get a dx that lies outside the [lb,ub] constraints here, but we'll enforce this anyway just to be paranoid */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { double xi = sim[i__ + np * sim_dim1]; if (xi + dx[i__] > ub[i__]) dx[i__] = ub[i__] - xi; if (xi + dx[i__] < lb[i__]) dx[i__] = xi - lb[i__]; } #endif if (ifull == 0) { temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = dx[i__]; temp += d__1 * d__1; } if (temp < rho * .25 * rho) { ibrnch = 1; goto L550; } } /* Predict the change to F and the new maximum constraint violation if the */ /* variables are altered from x(0) to x(0)+DX. */ resnew = 0.; con[mp] = 0.; i__1 = mp; for (k = 1; k <= i__1; ++k) { sum = con[k]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { sum -= a[i__ + k * a_dim1] * dx[i__]; } if (k < mp) { resnew = MAX2(resnew,sum); } } /* Increase PARMU if necessary and branch back if this change alters the */ /* optimal vertex. Otherwise PREREM and PREREC will be set to the predicted */ /* reductions in the merit function and the maximum constraint violation */ /* respectively. */ barmu = 0.; prerec = datmat[*mpp + np * datmat_dim1] - resnew; if (prerec > 0.) { barmu = sum / prerec; } if (parmu < barmu * 1.5) { parmu = barmu * 2.; if (*iprint >= 2) { fprintf(stderr, "cobyla: increase in PARMU to %12.6E\n", parmu); } phi = datmat[mp + np * datmat_dim1] + parmu * datmat[*mpp + np * datmat_dim1]; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = datmat[mp + j * datmat_dim1] + parmu * datmat[*mpp + j * datmat_dim1]; if (temp < phi) { goto L140; } if (temp == phi && parmu == 0.f) { if (datmat[*mpp + j * datmat_dim1] < datmat[*mpp + np * datmat_dim1]) { goto L140; } } } } prerem = parmu * prerec - sum; /* Calculate the constraint and objective functions at x(*). Then find the */ /* actual reduction in the merit function. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = sim[i__ + np * sim_dim1] + dx[i__]; } ibrnch = 1; goto L40; L440: vmold = datmat[mp + np * datmat_dim1] + parmu * datmat[*mpp + np * datmat_dim1]; vmnew = f + parmu * resmax; trured = vmold - vmnew; if (parmu == 0. && f == datmat[mp + np * datmat_dim1]) { prerem = prerec; trured = datmat[*mpp + np * datmat_dim1] - resmax; } /* Begin the operations that decide whether x(*) should replace one of the */ /* vertices of the current simplex, the change being mandatory if TRURED is */ /* positive. Firstly, JDROP is set to the index of the vertex that is to be */ /* replaced. */ ratio = 0.; if (trured <= 0.f) { ratio = 1.f; } jdrop = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp += simi[j + i__ * simi_dim1] * dx[i__]; } temp = fabs(temp); if (temp > ratio) { jdrop = j; ratio = temp; } sigbar[j] = temp * vsig[j]; } /* Calculate the value of ell. */ edgmax = delta * rho; l = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (sigbar[j] >= parsig || sigbar[j] >= vsig[j]) { temp = veta[j]; if (trured > 0.) { temp = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { d__1 = dx[i__] - sim[i__ + j * sim_dim1]; temp += d__1 * d__1; } temp = sqrt(temp); } if (temp > edgmax) { l = j; edgmax = temp; } } } if (l > 0) { jdrop = l; } if (jdrop == 0) { goto L550; } /* Revise the simplex by updating the elements of SIM, SIMI and DATMAT. */ temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sim[i__ + jdrop * sim_dim1] = dx[i__]; temp += simi[jdrop + i__ * simi_dim1] * dx[i__]; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { simi[jdrop + i__ * simi_dim1] /= temp; } i__1 = *n; for (j = 1; j <= i__1; ++j) { if (j != jdrop) { temp = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp += simi[j + i__ * simi_dim1] * dx[i__]; } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { simi[j + i__ * simi_dim1] -= temp * simi[jdrop + i__ * simi_dim1]; } } } i__1 = *mpp; for (k = 1; k <= i__1; ++k) { datmat[k + jdrop * datmat_dim1] = con[k]; } /* Branch back for further iterations with the current RHO. */ if (trured > 0. && trured >= prerem * .1) { /* SGJ, 2010: following a suggestion in the SAS manual (which mentions a similar modification to COBYLA, although they didn't publish their source code), increase rho if predicted reduction is sufficiently close to the actual reduction. Otherwise, COBLYA seems to easily get stuck making very small steps. Also require iflag != 0 (i.e., acceptable simplex), again following SAS suggestion (otherwise I get convergence failure in some cases.) */ if (trured >= prerem * 0.9 && trured <= prerem * 1.1 && iflag) { rho *= 2.0; } goto L140; } L550: if (iflag == 0) { ibrnch = 0; goto L140; } /* SGJ, 2008: convergence tests for function vals; note that current best val is stored in datmat[mp + np * datmat_dim1], or in f if ifull == 1, and previous best is in *minf. This seems like a sensible place to put the convergence test, as it is the same place that Powell checks the x tolerance (rho > rhoend). */ { double fbest = ifull == 1 ? f : datmat[mp + np * datmat_dim1]; if (fbest < *minf && nlopt_stop_ftol(stop, fbest, *minf)) { rc = NLOPT_FTOL_REACHED; goto L600; } *minf = fbest; } /* Otherwise reduce RHO if it is not at its least value and reset PARMU. */ if (rho > rhoend) { rho *= .5; if (rho <= rhoend * 1.5) { rho = rhoend; } if (parmu > 0.) { denom = 0.; i__1 = mp; for (k = 1; k <= i__1; ++k) { cmin = datmat[k + np * datmat_dim1]; cmax = cmin; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { d__1 = cmin, d__2 = datmat[k + i__ * datmat_dim1]; cmin = MIN2(d__1,d__2); d__1 = cmax, d__2 = datmat[k + i__ * datmat_dim1]; cmax = MAX2(d__1,d__2); } if (k <= *m && cmin < cmax * .5) { temp = MAX2(cmax,0.) - cmin; if (denom <= 0.) { denom = temp; } else { denom = MIN2(denom,temp); } } } if (denom == 0.) { parmu = 0.; } else if (cmax - cmin < parmu * denom) { parmu = (cmax - cmin) / denom; } } if (*iprint >= 2) { fprintf(stderr, "cobyla: reduction in RHO to %12.6E and PARMU =%13.6E\n", rho, parmu); } if (*iprint == 2) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", *(stop->nevals_p), datmat[mp + np * datmat_dim1], datmat[*mpp + np * datmat_dim1]); fprintf(stderr, "cobyla: X ="); i__1 = iptem; for (i__ = 1; i__ <= i__1; ++i__) { if (i__>1) fprintf(stderr, " "); fprintf(stderr, "%13.6E", sim[i__ + np * sim_dim1]); } if (iptem < *n) { i__1 = *n; for (i__ = iptemp; i__ <= i__1; ++i__) { if (!((i__-1) % 4)) fprintf(stderr, "\ncobyla: "); fprintf(stderr, "%15.6E", x[i__]); } } fprintf(stderr, "\n"); } goto L140; } else /* rho <= rhoend */ rc = rhoend > 0 ? NLOPT_XTOL_REACHED : NLOPT_ROUNDOFF_LIMITED; /* Return the best calculated values of the variables. */ if (*iprint >= 1) { fprintf(stderr, "cobyla: normal return.\n"); } if (ifull == 1) { goto L620; } L600: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = sim[i__ + np * sim_dim1]; } f = datmat[mp + np * datmat_dim1]; resmax = datmat[*mpp + np * datmat_dim1]; L620: *minf = f; if (*iprint >= 1) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", *(stop->nevals_p), f, resmax); i__1 = iptem; fprintf(stderr, "cobyla: X ="); for (i__ = 1; i__ <= i__1; ++i__) { if (i__>1) fprintf(stderr, " "); fprintf(stderr, "%13.6E", x[i__]); } if (iptem < *n) { i__1 = *n; for (i__ = iptemp; i__ <= i__1; ++i__) { if (!((i__-1) % 4)) fprintf(stderr, "\ncobyla: "); fprintf(stderr, "%15.6E", x[i__]); } } fprintf(stderr, "\n"); } return rc; } /* cobylb */ /* ------------------------------------------------------------------------- */ static nlopt_result trstlp(int *n, int *m, double *a, double *b, double *rho, double *dx, int *ifull, int *iact, double *z__, double *zdota, double *vmultc, double *sdirn, double *dxnew, double *vmultd) { /* System generated locals */ int a_dim1, a_offset, z_dim1, z_offset, i__1, i__2; double d__1, d__2; /* Local variables */ double alpha, tempa; double beta; double optnew, stpful, sum, tot, acca, accb; double ratio, vsave, zdotv, zdotw, dd; double sd; double sp, ss, resold = 0.0, zdvabs, zdwabs, sumabs, resmax, optold; double spabs; double temp, step; int icount; int i__, j, k; int isave; int kk; int kl, kp, kw; int nact, icon = 0, mcon; int nactx = 0; /* This subroutine calculates an N-component vector DX by applying the */ /* following two stages. In the first stage, DX is set to the shortest */ /* vector that minimizes the greatest violation of the constraints */ /* A(1,K)*DX(1)+A(2,K)*DX(2)+...+A(N,K)*DX(N) .GE. B(K), K=2,3,...,M, */ /* subject to the Euclidean length of DX being at most RHO. If its length is */ /* strictly less than RHO, then we use the resultant freedom in DX to */ /* minimize the objective function */ /* -A(1,M+1)*DX(1)-A(2,M+1)*DX(2)-...-A(N,M+1)*DX(N) */ /* subject to no increase in any greatest constraint violation. This */ /* notation allows the gradient of the objective function to be regarded as */ /* the gradient of a constraint. Therefore the two stages are distinguished */ /* by MCON .EQ. M and MCON .GT. M respectively. It is possible that a */ /* degeneracy may prevent DX from attaining the target length RHO. Then the */ /* value IFULL=0 would be set, but usually IFULL=1 on return. */ /* In general NACT is the number of constraints in the active set and */ /* IACT(1),...,IACT(NACT) are their indices, while the remainder of IACT */ /* contains a permutation of the remaining constraint indices. Further, Z is */ /* an orthogonal matrix whose first NACT columns can be regarded as the */ /* result of Gram-Schmidt applied to the active constraint gradients. For */ /* J=1,2,...,NACT, the number ZDOTA(J) is the scalar product of the J-th */ /* column of Z with the gradient of the J-th active constraint. DX is the */ /* current vector of variables and here the residuals of the active */ /* constraints should be zero. Further, the active constraints have */ /* nonnegative Lagrange multipliers that are held at the beginning of */ /* VMULTC. The remainder of this vector holds the residuals of the inactive */ /* constraints at DX, the ordering of the components of VMULTC being in */ /* agreement with the permutation of the indices of the constraints that is */ /* in IACT. All these residuals are nonnegative, which is achieved by the */ /* shift RESMAX that makes the least residual zero. */ /* Initialize Z and some other variables. The value of RESMAX will be */ /* appropriate to DX=0, while ICON will be the index of a most violated */ /* constraint if RESMAX is positive. Usually during the first stage the */ /* vector SDIRN gives a search direction that reduces all the active */ /* constraint violations by one simultaneously. */ /* Parameter adjustments */ z_dim1 = *n; z_offset = 1 + z_dim1 * 1; z__ -= z_offset; a_dim1 = *n; a_offset = 1 + a_dim1 * 1; a -= a_offset; --b; --dx; --iact; --zdota; --vmultc; --sdirn; --dxnew; --vmultd; /* Function Body */ *ifull = 1; mcon = *m; nact = 0; resmax = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = *n; for (j = 1; j <= i__2; ++j) { z__[i__ + j * z_dim1] = 0.; } z__[i__ + i__ * z_dim1] = 1.; dx[i__] = 0.; } if (*m >= 1) { i__1 = *m; for (k = 1; k <= i__1; ++k) { if (b[k] > resmax) { resmax = b[k]; icon = k; } } i__1 = *m; for (k = 1; k <= i__1; ++k) { iact[k] = k; vmultc[k] = resmax - b[k]; } } if (resmax == 0.) { goto L480; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sdirn[i__] = 0.; } /* End the current stage of the calculation if 3 consecutive iterations */ /* have either failed to reduce the best calculated value of the objective */ /* function or to increase the number of active constraints since the best */ /* value was calculated. This strategy prevents cycling, but there is a */ /* remote possibility that it will cause premature termination. */ L60: optold = 0.; icount = 0; L70: if (mcon == *m) { optnew = resmax; } else { optnew = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { optnew -= dx[i__] * a[i__ + mcon * a_dim1]; } } if (icount == 0 || optnew < optold) { optold = optnew; nactx = nact; icount = 3; } else if (nact > nactx) { nactx = nact; icount = 3; } else { --icount; if (icount == 0) { goto L490; } } /* If ICON exceeds NACT, then we add the constraint with index IACT(ICON) to */ /* the active set. Apply Givens rotations so that the last N-NACT-1 columns */ /* of Z are orthogonal to the gradient of the new constraint, a scalar */ /* product being set to zero if its nonzero value could be due to computer */ /* rounding errors. The array DXNEW is used for working space. */ if (icon <= nact) { goto L260; } kk = iact[icon]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dxnew[i__] = a[i__ + kk * a_dim1]; } tot = 0.; k = *n; L100: if (k > nact) { sp = 0.; spabs = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = z__[i__ + k * z_dim1] * dxnew[i__]; sp += temp; spabs += fabs(temp); } acca = spabs + fabs(sp) * .1; accb = spabs + fabs(sp) * .2; if (spabs >= acca || acca >= accb) { sp = 0.; } if (tot == 0.) { tot = sp; } else { kp = k + 1; temp = sqrt(sp * sp + tot * tot); alpha = sp / temp; beta = tot / temp; tot = temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = alpha * z__[i__ + k * z_dim1] + beta * z__[i__ + kp * z_dim1]; z__[i__ + kp * z_dim1] = alpha * z__[i__ + kp * z_dim1] - beta * z__[i__ + k * z_dim1]; z__[i__ + k * z_dim1] = temp; } } --k; goto L100; } /* Add the new constraint if this can be done without a deletion from the */ /* active set. */ if (tot != 0.) { ++nact; zdota[nact] = tot; vmultc[icon] = vmultc[nact]; vmultc[nact] = 0.; goto L210; } /* The next instruction is reached if a deletion has to be made from the */ /* active set in order to make room for the new active constraint, because */ /* the new constraint gradient is a linear combination of the gradients of */ /* the old active constraints. Set the elements of VMULTD to the multipliers */ /* of the linear combination. Further, set IOUT to the index of the */ /* constraint to be deleted, but branch if no suitable index can be found. */ ratio = -1.; k = nact; L130: zdotv = 0.; zdvabs = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = z__[i__ + k * z_dim1] * dxnew[i__]; zdotv += temp; zdvabs += fabs(temp); } acca = zdvabs + fabs(zdotv) * .1; accb = zdvabs + fabs(zdotv) * .2; if (zdvabs < acca && acca < accb) { temp = zdotv / zdota[k]; if (temp > 0. && iact[k] <= *m) { tempa = vmultc[k] / temp; if (ratio < 0. || tempa < ratio) ratio = tempa; } if (k >= 2) { kw = iact[k]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dxnew[i__] -= temp * a[i__ + kw * a_dim1]; } } vmultd[k] = temp; } else { vmultd[k] = 0.; } --k; if (k > 0) { goto L130; } if (ratio < 0.) { goto L490; } /* Revise the Lagrange multipliers and reorder the active constraints so */ /* that the one to be replaced is at the end of the list. Also calculate the */ /* new value of ZDOTA(NACT) and branch if it is not acceptable. */ i__1 = nact; /* This pragma fixes a known problem compiling with VS2013 or VS2015 in Release */ /* see https://connect.microsoft.com/VisualStudio/feedback/details/1028781/c1001-on-release-build */ #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma loop(no_vector) #endif for (k = 1; k <= i__1; ++k) { d__1 = 0., d__2 = vmultc[k] - ratio * vmultd[k]; vmultc[k] = MAX2(d__1,d__2); } if (icon < nact) { isave = iact[icon]; vsave = vmultc[icon]; k = icon; L170: kp = k + 1; kw = iact[kp]; sp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sp += z__[i__ + k * z_dim1] * a[i__ + kw * a_dim1]; } d__1 = zdota[kp]; temp = sqrt(sp * sp + d__1 * d__1); alpha = zdota[kp] / temp; beta = sp / temp; zdota[kp] = alpha * zdota[k]; zdota[k] = temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = alpha * z__[i__ + kp * z_dim1] + beta * z__[i__ + k * z_dim1]; z__[i__ + kp * z_dim1] = alpha * z__[i__ + k * z_dim1] - beta * z__[i__ + kp * z_dim1]; z__[i__ + k * z_dim1] = temp; } iact[k] = kw; vmultc[k] = vmultc[kp]; k = kp; if (k < nact) { goto L170; } iact[k] = isave; vmultc[k] = vsave; } temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp += z__[i__ + nact * z_dim1] * a[i__ + kk * a_dim1]; } if (temp == 0.) { goto L490; } zdota[nact] = temp; vmultc[icon] = 0.; vmultc[nact] = ratio; /* Update IACT and ensure that the objective function continues to be */ /* treated as the last active constraint when MCON>M. */ L210: iact[icon] = iact[nact]; iact[nact] = kk; if (mcon > *m && kk != mcon) { k = nact - 1; sp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sp += z__[i__ + k * z_dim1] * a[i__ + kk * a_dim1]; } d__1 = zdota[nact]; temp = sqrt(sp * sp + d__1 * d__1); alpha = zdota[nact] / temp; beta = sp / temp; zdota[nact] = alpha * zdota[k]; zdota[k] = temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = alpha * z__[i__ + nact * z_dim1] + beta * z__[i__ + k * z_dim1]; z__[i__ + nact * z_dim1] = alpha * z__[i__ + k * z_dim1] - beta * z__[i__ + nact * z_dim1]; z__[i__ + k * z_dim1] = temp; } iact[nact] = iact[k]; iact[k] = kk; temp = vmultc[k]; vmultc[k] = vmultc[nact]; vmultc[nact] = temp; } /* If stage one is in progress, then set SDIRN to the direction of the next */ /* change to the current vector of variables. */ if (mcon > *m) { goto L320; } kk = iact[nact]; temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp += sdirn[i__] * a[i__ + kk * a_dim1]; } temp += -1.; temp /= zdota[nact]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sdirn[i__] -= temp * z__[i__ + nact * z_dim1]; } goto L340; /* Delete the constraint that has the index IACT(ICON) from the active set. */ L260: if (icon < nact) { isave = iact[icon]; vsave = vmultc[icon]; k = icon; L270: kp = k + 1; kk = iact[kp]; sp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sp += z__[i__ + k * z_dim1] * a[i__ + kk * a_dim1]; } d__1 = zdota[kp]; temp = sqrt(sp * sp + d__1 * d__1); alpha = zdota[kp] / temp; beta = sp / temp; zdota[kp] = alpha * zdota[k]; zdota[k] = temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = alpha * z__[i__ + kp * z_dim1] + beta * z__[i__ + k * z_dim1]; z__[i__ + kp * z_dim1] = alpha * z__[i__ + k * z_dim1] - beta * z__[i__ + kp * z_dim1]; z__[i__ + k * z_dim1] = temp; } iact[k] = kk; vmultc[k] = vmultc[kp]; k = kp; if (k < nact) { goto L270; } iact[k] = isave; vmultc[k] = vsave; } --nact; /* If stage one is in progress, then set SDIRN to the direction of the next */ /* change to the current vector of variables. */ if (mcon > *m) { goto L320; } temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp += sdirn[i__] * z__[i__ + (nact + 1) * z_dim1]; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sdirn[i__] -= temp * z__[i__ + (nact + 1) * z_dim1]; } goto L340; /* Pick the next search direction of stage two. */ L320: temp = 1. / zdota[nact]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sdirn[i__] = temp * z__[i__ + nact * z_dim1]; } /* Calculate the step to the boundary of the trust region or take the step */ /* that reduces RESMAX to zero. The two statements below that include the */ /* factor 1.0E-6 prevent some harmless underflows that occurred in a test */ /* calculation. Further, we skip the step if it could be zero within a */ /* reasonable tolerance for computer rounding errors. */ L340: dd = *rho * *rho; sd = 0.; ss = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if ((d__1 = dx[i__], fabs(d__1)) >= *rho * 1e-6f) { d__2 = dx[i__]; dd -= d__2 * d__2; } sd += dx[i__] * sdirn[i__]; d__1 = sdirn[i__]; ss += d__1 * d__1; } if (dd <= 0.) { goto L490; } temp = sqrt(ss * dd); if (fabs(sd) >= temp * 1e-6f) { temp = sqrt(ss * dd + sd * sd); } stpful = dd / (temp + sd); step = stpful; if (mcon == *m) { acca = step + resmax * .1; accb = step + resmax * .2; if (step >= acca || acca >= accb) { goto L480; } step = MIN2(step,resmax); } /* SGJ, 2010: check for error here */ if (nlopt_isinf(step)) return NLOPT_ROUNDOFF_LIMITED; /* Set DXNEW to the new variables if STEP is the steplength, and reduce */ /* RESMAX to the corresponding maximum residual if stage one is being done. */ /* Because DXNEW will be changed during the calculation of some Lagrange */ /* multipliers, it will be restored to the following value later. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dxnew[i__] = dx[i__] + step * sdirn[i__]; } if (mcon == *m) { resold = resmax; resmax = 0.; i__1 = nact; for (k = 1; k <= i__1; ++k) { kk = iact[k]; temp = b[kk]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp -= a[i__ + kk * a_dim1] * dxnew[i__]; } resmax = MAX2(resmax,temp); } } /* Set VMULTD to the VMULTC vector that would occur if DX became DXNEW. A */ /* device is included to force VMULTD(K)=0.0 if deviations from this value */ /* can be attributed to computer rounding errors. First calculate the new */ /* Lagrange multipliers. */ k = nact; L390: zdotw = 0.; zdwabs = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = z__[i__ + k * z_dim1] * dxnew[i__]; zdotw += temp; zdwabs += fabs(temp); } acca = zdwabs + fabs(zdotw) * .1; accb = zdwabs + fabs(zdotw) * .2; if (zdwabs >= acca || acca >= accb) { zdotw = 0.; } vmultd[k] = zdotw / zdota[k]; if (k >= 2) { kk = iact[k]; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dxnew[i__] -= vmultd[k] * a[i__ + kk * a_dim1]; } --k; goto L390; } if (mcon > *m) { d__1 = 0., d__2 = vmultd[nact]; vmultd[nact] = MAX2(d__1,d__2); } /* Complete VMULTC by finding the new constraint residuals. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dxnew[i__] = dx[i__] + step * sdirn[i__]; } if (mcon > nact) { kl = nact + 1; i__1 = mcon; for (k = kl; k <= i__1; ++k) { kk = iact[k]; sum = resmax - b[kk]; sumabs = resmax + (d__1 = b[kk], fabs(d__1)); i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp = a[i__ + kk * a_dim1] * dxnew[i__]; sum += temp; sumabs += fabs(temp); } acca = sumabs + fabs(sum) * .1f; accb = sumabs + fabs(sum) * .2f; if (sumabs >= acca || acca >= accb) { sum = 0.f; } vmultd[k] = sum; } } /* Calculate the fraction of the step from DX to DXNEW that will be taken. */ ratio = 1.; icon = 0; i__1 = mcon; for (k = 1; k <= i__1; ++k) { if (vmultd[k] < 0.) { temp = vmultc[k] / (vmultc[k] - vmultd[k]); if (temp < ratio) { ratio = temp; icon = k; } } } /* Update DX, VMULTC and RESMAX. */ temp = 1. - ratio; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dx[i__] = temp * dx[i__] + ratio * dxnew[i__]; } i__1 = mcon; for (k = 1; k <= i__1; ++k) { d__1 = 0., d__2 = temp * vmultc[k] + ratio * vmultd[k]; vmultc[k] = MAX2(d__1,d__2); } if (mcon == *m) { resmax = resold + ratio * (resmax - resold); } /* If the full step is not acceptable then begin another iteration. */ /* Otherwise switch to stage two or end the calculation. */ if (icon > 0) { goto L70; } if (step == stpful) { goto L500; } L480: mcon = *m + 1; icon = mcon; iact[mcon] = mcon; vmultc[mcon] = 0.; goto L60; /* We employ any freedom that may be available to reduce the objective */ /* function before returning a DX whose length is less than RHO. */ L490: if (mcon == *m) { goto L480; } *ifull = 0; L500: return NLOPT_SUCCESS; } /* trstlp */ nlopt-2.6.1/src/algs/cobyla/cobyla.h000066400000000000000000000044351345435414600173030ustar00rootroot00000000000000/* cobyla : contrained optimization by linear approximation */ /* * Copyright (c) 1992, Michael J. D. Powell (M.J.D.Powell@damtp.cam.ac.uk) * Copyright (c) 2004, Jean-Sebastien Roy (js@jeannot.org) * * 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. */ /* * This software is a C version of COBYLA2, a contrained optimization by linear * approximation package developed by Michael J. D. Powell in Fortran. * * The original source code can be found at : * http://plato.la.asu.edu/topics/problems/nlores.html */ /* $Jeannot: cobyla.h,v 1.10 2004/04/18 09:51:37 js Exp $ */ #ifndef _COBYLA_ #define _COBYLA_ #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* NLopt-style interface function */ nlopt_result cobyla_minimize(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, unsigned p, nlopt_constraint *h, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, const double *dx); #ifdef __cplusplus } #endif #endif /* _COBYLA_ */ nlopt-2.6.1/src/algs/cquad/000077500000000000000000000000001345435414600154775ustar00rootroot00000000000000nlopt-2.6.1/src/algs/cquad/README000066400000000000000000000024031345435414600163560ustar00rootroot00000000000000An experimental method for nonlinearly constrained optimization without derivatives, by SGJ, using conservative quadratic approximations. It is based on a combination of two ideas: 1) first, quadratic approximations for the function & constraints are constructed based on the techniques suggested by M. J. D. Powell for his unconstrained NEWUOA software (2004) [*]. 2) second, the quadratic approximation is successively solved and refined using conservative-approximation inner/outer iterations based on those of the MMA algorithm of Svanberg (2002). It doesn't really work very well yet (it converges extremely slowly), unfortunately, so I'm keeping it out of NLopt until/unless I have a chance to think about it yet. [*] Actually, we use a greatly simplified version of Powell's technique. Powell goes to great lengths to ensure that his quadratic approximation is constructed iteratively with only O(n^2) work at each step, where n is the number of design variables. Instead, I just use an O(n^3) method, based on the assumptions that (a) the objective function is relatively costly and (b) n is not too big (in the hundreds, not in the thousands) -- if you have thousands of unknowns, you really need to be using a gradient-based method, I think. nlopt-2.6.1/src/algs/cquad/cquad.c000066400000000000000000000432071345435414600167460ustar00rootroot00000000000000#include #include #include #include #include "cquad.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /**************************************************************************/ /* a quadratic model for n-dimensional data. in Matlab notation: model(x) = q0 + q' (x-x0) + 0.5 * (x-x0)' * Q * (x-x0) where x0 is an origin (array of length n), q is the gradient vector (length n), and Q is the n x n Hessian matrix. */ typedef struct { int n; const double *x0; /* length n vector of reference pt */ double q0, *q, *Q; /* q is a length n vector, and Q is an n x n matrix */ } quad_model; static quad_model alloc_model(int n) { quad_model model; model.n = n; model.x0 = 0; model.q0 = 0; model.q = (double *) malloc(sizeof(double) * n); model.Q = (double *) malloc(sizeof(double) * n*n); return model; } static void free_model(quad_model *model) { free(model->Q); model->Q = 0; free(model->q); model->q = 0; } /* evaluate the model for the vector x (length x) */ static double eval_model(const quad_model *model, const double *x) { double q0 = model->q0, *q = model->q, *Q = model->Q; const double *x0 = model->x0; int j, n = model->n; double val = q0; for (j = 0; j < n; ++j) { double sum = 0; int k; for (k = 0; k < n; ++k) sum += Q[j*n + k] * (x[k] - x0[k]); val += (q[j] + 0.5 * sum) * (x[j] - x0[j]); } return val; } /* gradient of the model at x -> grad */ static void eval_model_grad(const quad_model *model, const double *x, double *grad) { double *q = model->q, *Q = model->Q; const double *x0 = model->x0; int j, n = model->n; for (j = 0; j < n; ++j) { double sum = 0; int k; for (k = 0; k < n; ++k) sum += Q[j*n + k] * (x[k] - x0[k]); grad[j] = q[j] + sum; } } #define DSYSV_BLOCKSIZE 64 #define DSYSV dsysv_ /* LAPACK routine to solve a real-symmetric indefinite system A X = B */ extern void DSYSV(const char *uplo, const int *N, const int *NRHS, double *A, const int *LDA, int *ipiv, double *B, const int *LDB, double *work, const int *lwork, int *info); /* update the model when one of the x vectors has been changed. W is an N by N array (N = M + n + 1), r is length N; both uninitialized. X is an M x n array of the input vectors, inew is the index (0 <= inew < M) of the changed vector, and fnew is the function value at the new point. iwork has length N, and work has length DSYSV_BLOCKSIZE * N. See Powell (2004) for how this routine works. Here, we use the simple O((M+n)^3) technique, rather than the fancy O((M+n)^2) method described by Powell, as explained in the README. */ static void update_model(quad_model *model, double *W, double *r, int M, double *X, int inew, double fnew, int *iwork, double *work) { double *q = model->q, *Q = model->Q; const double *x0 = model->x0; double *lam = r, *c = r + M, *g = r + M+1; int i, j, k, n = model->n, N = M + n + 1, one = 1; int lwork = N * DSYSV_BLOCKSIZE, info; /* set A matrix; A = 0.5 * (X * X').^2 */ for (i = 0; i < M; ++i) { double *xi = X + i*n; for (j = 0; j < M; ++j) { double sum = 0, *xj = X + j*n; for (k = 0; k < n; ++k) sum += (xi[k] - x0[k]) * (xj[k] - x0[k]); W[i * N + j] = W[j * N + i] = 0.5 * sum * sum; } } /* update X matrix: */ for (i = 0; i < M; ++i) { double *xi = X + i*n; W[M * N + i] = W[i * N + M] = 1.0; for (k = 0; k < n; ++k) W[(M+1+k) * N + i] = W[i * N + (M+1+k)] = xi[k] - x0[k]; } memset(r, 0, sizeof(double) * N); r[inew] = fnew - eval_model(model, X + inew*n); /* solve s = W \ r, via the LAPACK symmetric-indefinite solver */ DSYSV("U", &N, &one, W, &N, iwork, r, &N, work, &lwork, &info); if (info != 0) { fprintf(stderr, "nlopt cquad: failure %d in dsysv", info); abort(); } /* update model */ model->q0 += *c; for (k = 0; k < n; ++k) q[k] += g[k]; for (i = 0; i < n; ++i) for (j = i; j < n; ++j) { double sum = 0; for (k = 0; k < M; ++k) sum += lam[k] * (X[k*n+i] - x0[i]) * (X[k*n+j] - x0[j]); Q[i*n + j] = Q[j*n + i] = Q[i*n + j] + sum; } } /* insert the new point xnew (length n) into the array of points X (M x n), given the current optimal point xopt (length n). Returns index inew of replaced point in X. */ static int insert_new_point(int n, const double *xnew, const double *xopt, int M, double *X) { int inew = 0, i, j; double dist2max = 0; /* just use a simple algorithm: replace the point farthest from xopt */ for (i = 0; i < M; ++i) { double *xi = X + i * n; double dist2 = 0; for (j = 0; j < n; ++j ) dist2 += (xi[j] - xopt[j]); if (dist2 > dist2max) { dist2max = dist2; inew = i; } } memcpy(X + inew * n, xnew, sizeof(double) * n); return inew; } /**************************************************************************/ /* a conservative quadratic model is the generic quadratic model above, plus 0.5 * |(x - xopt) / sigma|^2 * rho, where rho is nonnegative */ typedef struct { const double *xopt, *sigma; quad_model model; double rho; } conservative_model; static double cmodel_func(int n, const double *x, double *grad, void *data) { conservative_model *cmodel = (conservative_model *) data; double rho = cmodel->rho, val; const double *xopt = cmodel->xopt, *sigma = cmodel->sigma; int j; val = eval_model(&cmodel->model, x); if (grad) eval_model_grad(&cmodel->model, x, grad); for (j = 0; j < n; ++j) { double siginv = 1.0 / sigma[j]; double dx = (x[j] - xopt[j]) * siginv; val += (0.5 * rho) * dx*dx; if (grad) grad[j] += rho * dx * siginv; } return val; } /* just the rho part of the model (what Svanberg calls the "w" function) */ static double wfunc(int n, const double *x, const conservative_model *cmodel) { const double *xopt = cmodel->xopt, *sigma = cmodel->sigma; double val = 0; int j; for (j = 0; j < n; ++j) { double dx = (x[j] - xopt[j]) / sigma[j]; val += 0.5 * dx*dx; } return val; } /**************************************************************************/ /* magic minimum value for rho in MMA ... the 2002 paper says it should be a "fixed, strictly positive `small' number, e.g. 1e-5" ... grrr, I hate these magic numbers, which seem like they should depend on the objective function in some way ... in particular, note that rho is dimensionful (= dimensions of objective function) */ #define MMA_RHOMIN 1e-5 int cquad_verbose = 1; nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_func fc, void *fc_data_, ptrdiff_t fc_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_algorithm model_alg, double model_tolrel, int model_maxeval) { nlopt_result ret = NLOPT_SUCCESS; double *x0, *xcur, *sigma, *xprev, *xprevprev, fcur, gval; double *fcval_cur, *gcval, *model_lb, *model_ub; double *W, *X, *r, *work; int *iwork; int i, j, k = 0, M = 2*n + 1, N = M + n + 1; char *fc_data = (char *) fc_data_; conservative_model model, *modelc; int feasible, feasible_cur; sigma = (double *) malloc(sizeof(double) * (n*7 + m*2 + N*N + M*n + N + DSYSV_BLOCKSIZE * N)); if (!sigma) return NLOPT_OUT_OF_MEMORY; x0 = sigma + n; xcur = x0 + n; xprev = xcur + n; xprevprev = xprev + n; model_lb = xprevprev + n; model_ub = model_lb + n; fcval_cur = model_ub + n; gcval = fcval_cur + m; W = gcval + m; X = W + N*N; r = X + M*n; work = r + N; model.model.q = model.model.Q = 0; modelc = 0; iwork = (int *) malloc(sizeof(int) * N); if (!iwork) { ret = NLOPT_OUT_OF_MEMORY; goto done; } model.xopt = x; model.sigma = sigma; model.rho = 1; model.model = alloc_model(n); if (!model.model.q || !model.model.Q) { ret = NLOPT_OUT_OF_MEMORY; goto done; } model.model.x0 = x0; modelc = (conservative_model *) malloc(sizeof(conservative_model) * m); if (m > 0 && !modelc) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (i = 0; i < m; ++i) modelc[i].model.q = modelc[i].model.Q = 0; for (i = 0; i < m; ++i) { modelc[i].xopt = x; modelc[i].sigma = sigma; modelc[i].rho = 1; modelc[i].model = alloc_model(n); if (!modelc[i].model.q || !modelc[i].model.Q) { ret = NLOPT_OUT_OF_MEMORY; goto done; } modelc[i].model.x0 = x0; } feasible = 0; *minf = HUGE_VAL; { int iM = 0; double *dx = xprev; /* initial step to construct quad. model */ for (j = 0; j < n; ++j) { if (nlopt_isinf(ub[j]) || nlopt_isinf(lb[j])) sigma[j] = 1.0; /* arbitrary default */ else sigma[j] = 0.25 * (ub[j] - lb[j]); dx[j] = sigma[j]; if (x[j] + dx[j] > ub[j]) x0[j] = x[j] - dx[j]; else if (x[j] - dx[j] < lb[j]) x0[j] = x[j] + dx[j]; else x0[j] = x[j]; } /* initialize quadratic model via simple finite differences around x0, as suggested by Powell */ model.model.q0 = f(n, x0, NULL, f_data); memcpy(X + (iM++ * n), x0, n * sizeof(double)); memset(model.model.Q, 0, sizeof(double) * n*n); *(stop->nevals_p)++; feasible_cur = 1; for (i = 0; i < m; ++i) { modelc[i].model.q0 = fc(n, x0, NULL, fc_data + fc_datum_size*i); memset(modelc[i].model.Q, 0, sizeof(double) * n*n); feasible_cur = feasible_cur && (modelc[i].model.q0 <= 0); } if (feasible_cur) { *minf = model.model.q0; memcpy(x, x0, sizeof(double) * n); feasible = 1; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; memcpy(xcur, x0, sizeof(double) * n); for (j = 0; j < n; ++j) { double fmp[2], *fcmp[2]; int s; fcmp[0] = work; fcmp[1] = work + m; for (s = 0; s < 2; ++s) { xcur[j] = x0[j] + (2*s - 1) * dx[j]; fmp[s] = fcur = f(n, xcur, NULL, f_data); memcpy(X + (iM++ * n), xcur, n * sizeof(double)); *(stop->nevals_p)++; feasible_cur = 1; for (i = 0; i < m; ++i) { fcmp[s][i] = fcval_cur[i] = fc(n, xcur, NULL, fc_data + fc_datum_size*i); feasible_cur = feasible_cur && (fcval_cur[i] <= 0); } if (feasible_cur && fcur < *minf) { *minf = fcur; memcpy(x, xcur, sizeof(double) * n); feasible = 1; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; } xcur[j] = x0[j]; model.model.q[j] = (fmp[1] - fmp[0]) / (2 * dx[j]); model.model.Q[j*n+j] = (fmp[1] + fmp[0] - 2*model.model.q0) / (dx[j]*dx[j]); for (i = 0; i < m; ++i) { modelc[i].model.q[j] = (fcmp[1][i] - fcmp[0][i]) / (2 * dx[j]); modelc[i].model.Q[j*n+j] = (fcmp[1][i] + fcmp[0][i] - 2*modelc[i].model.q0) / (dx[j]*dx[j]); } } } fcur = *minf; memcpy(xcur, x, sizeof(double) * n); while (1) { /* outer iterations */ double fprev = fcur; if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n); memcpy(xprev, xcur, sizeof(double) * n); while (1) { /* inner iterations */ double min_model; int inner_done, iMnew; nlopt_result reti; /* solve model problem */ for (j = 0; j < n; ++j) { model_lb[j] = MAX(lb[j], x[j] - 0.9 * sigma[j]); model_ub[j] = MIN(ub[j], x[j] + 0.9 * sigma[j]); } model_solution: memcpy(xcur, x, sizeof(double) * n); reti = nlopt_minimize_constrained( model_alg, n, cmodel_func, &model, m, cmodel_func, modelc, sizeof(conservative_model), model_lb, model_ub, xcur, &min_model, -HUGE_VAL, model_tolrel,0., 0.,NULL, model_maxeval, stop->maxtime - (nlopt_seconds() - stop->start)); if (reti == NLOPT_FAILURE && model_alg != NLOPT_LD_MMA) { /* LBFGS etc. converge quickly but are sometimes very finicky if there are any rounding errors in the gradient, etcetera; if it fails, try again with MMA called recursively for the model */ model_alg = NLOPT_LD_MMA; if (cquad_verbose) printf("cquad: switching to MMA for model\n"); goto model_solution; } if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) { ret = reti; goto done; } got_new_xcur: /* evaluate final xcur etc. */ gval = cmodel_func(n, xcur, NULL, &model); for (i = 0; i < m; ++i) gcval[i] = cmodel_func(n, xcur, NULL, modelc + i); fcur = f(n, xcur, NULL, f_data); *(stop->nevals_p)++; feasible_cur = 1; inner_done = gval >= fcur; for (i = 0; i < m; ++i) { fcval_cur[i] = fc(n, xcur, NULL, fc_data + fc_datum_size * i); feasible_cur = feasible_cur && (fcval_cur[i] <= 0); inner_done = inner_done && (gcval[i] >= fcval_cur[i]); } if (cquad_verbose) { printf("cquad model converged to g=%g vs. f=%g:\n", gval, fcur); for (i = 0; i < MIN(cquad_verbose, m); ++i) printf(" cquad gc[%d]=%g vs. fc[%d]=%g\n", i, gcval[i], i, fcval_cur[i]); } /* update the quadratic models */ iMnew = insert_new_point(n, xcur, x, M, X); update_model(&model.model, W, r, M, X, iMnew, fcur, iwork,work); for (i = 0; i < m; ++i) update_model(&modelc[i].model, W, r, M, X, iMnew, fcval_cur[i], iwork,work); /* once we have reached a feasible solution, the algorithm should never make the solution infeasible again (if inner_done), although the constraints may be violated slightly by rounding errors etc. so we must be a little careful about checking feasibility */ if (feasible_cur) feasible = 1; if (fcur < *minf && (inner_done || feasible_cur || !feasible)) { if (cquad_verbose && !feasible_cur) printf("cquad - using infeasible point?\n"); *minf = fcur; memcpy(x, xcur, sizeof(double)*n); } if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; /* check for ill-conditioned model matrix, as indicated by a model that doesn't match f(xcur)=fcur as required */ if (0 && fabs(eval_model(&model.model, xcur) - fcur) > 1e-6 * fabs(fcur)) { if (cquad_verbose) printf("cquad conditioning problem, diff = %g\n", eval_model(&model.model, xcur) - fcur); /* pick a random point to insert, using X diameter */ for (j = 0; j < n; ++j) { double diam = 1e-3 * sigma[j]; /* minimum diam */ for (i = 0; i < M; ++i) { double diami = fabs(X[i*n+j] - x[j]); if (diami > diam) diam = diami; } diam *= 0.1; xcur[j] = x[j] + nlopt_urand(-diam, diam); } goto got_new_xcur; } if (inner_done) break; if (fcur > gval) model.rho = MIN(10*model.rho, 1.1 * (model.rho + (fcur-gval) / wfunc(n, xcur, &model))); for (i = 0; i < m; ++i) if (fcval_cur[i] > gcval[i]) modelc[i].rho = MIN(10*modelc[i].rho, 1.1 * (modelc[i].rho + (fcval_cur[i]-gcval[i]) / wfunc(n, xcur, &modelc[i]))); if (cquad_verbose) printf("cquad inner iteration: rho -> %g\n", model.rho); for (i = 0; i < MIN(cquad_verbose, m); ++i) printf(" cquad rhoc[%d] -> %g\n", i, modelc[i].rho); } if (nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; if (nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; if (ret != NLOPT_SUCCESS) goto done; /* update rho and sigma for iteration k+1 */ model.rho = MAX(0.1 * model.rho, MMA_RHOMIN); if (cquad_verbose) printf("cquad outer iteration: rho -> %g\n", model.rho); for (i = 0; i < m; ++i) modelc[i].rho = MAX(0.1 * modelc[i].rho, MMA_RHOMIN); for (i = 0; i < MIN(cquad_verbose, m); ++i) printf(" cquad rhoc[%d] -> %g\n", i, modelc[i].rho); if (k > 1) { for (j = 0; j < n; ++j) { double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]); double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1); sigma[j] *= gam; if (!nlopt_isinf(ub[j]) && !nlopt_isinf(lb[j])) { sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j])); sigma[j] = MAX(sigma[j], 0.01*(ub[j]-lb[j])); } } for (j = 0; j < MIN(cquad_verbose, n); ++j) printf(" cquad sigma[%d] -> %g\n", j, sigma[j]); } } done: free(modelc); for (i = 0; i < m; ++i) free_model(&modelc[i].model); free_model(&model.model); free(iwork); free(sigma); return ret; } nlopt-2.6.1/src/algs/cquad/cquad.h000066400000000000000000000033541345435414600167520ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef CQUAD_H #define CQUAD_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ extern int cquad_verbose; nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_func fc, void *fc_data_, ptrdiff_t fc_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_algorithm model_alg, double dual_tolrel, int dual_maxeval); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/crs/000077500000000000000000000000001345435414600151715ustar00rootroot00000000000000nlopt-2.6.1/src/algs/crs/README000066400000000000000000000012521345435414600160510ustar00rootroot00000000000000This is my implementation of the "controlled random search" (CRS2) algorithm with the "local mutation" modification, as defined by: P. Kaelo and M. M. Ali, "Some variants of the controlled random search algorithm for global optimization," J. Optim. Theory Appl. 130 (2), 253-264 (2006). The original CRS2 algorithm was described by: W. L. Price, "A controlled random search procedure for global optimization," in Towards Global Optimization 2, p. 71-84 edited by L. C. W. Dixon and G. P. Szego (North-Holland Press, Amsterdam, 1978). It is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson September 2007 nlopt-2.6.1/src/algs/crs/crs.c000066400000000000000000000225271345435414600161340ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include "crs.h" #include "redblack.h" /* Controlled Random Search 2 (CRS2) with "local mutation", as defined by: P. Kaelo and M. M. Ali, "Some variants of the controlled random search algorithm for global optimization," J. Optim. Theory Appl. 130 (2), 253-264 (2006). */ typedef struct { int n; /* # dimensions */ const double *lb, *ub; nlopt_stopping *stop; /* stopping criteria */ nlopt_func f; void *f_data; int N; /* # points in population */ double *ps; /* population array N x (n+1) of tuples [f(x), x] */ double *p; /* single point array (length n+1), for temp use */ rb_tree t; /* red-black tree of population, sorted by f(x) */ nlopt_sobol s; /* sobol data for LDS point generation, or NULL to use pseudo-random numbers */ } crs_data; /* sort order in red-black tree: keys [f(x), x] are sorted by f(x) */ static int crs_compare(double *k1, double *k2) { if (*k1 < *k2) return -1; if (*k1 > *k2) return +1; return k1 - k2; /* tie-breaker */ } /* set x to a random trial value, as defined by CRS: x = 2G - x_n, where x_0 ... x_n are distinct points in the population with x_0 the current best point and the other points are random, and G is the centroid of x_0...x_{n-1} */ static void random_trial(crs_data *d, double *x, rb_node *best) { int n = d->n, n1 = n+1, i, k, i0, jn; double *ps = d->ps, *xi; /* initialize x to x_0 = best point */ memcpy(x, best->k + 1, sizeof(double) * n); i0 = (best->k - ps) / n1; jn = nlopt_iurand(n); /* which of remaining n points is "x_n", i.e. which to reflect through ... this is necessary since we generate the remaining points in order, so just picking the last point would not be very random */ /* use "method A" from Jeffrey Scott Vitter, "An efficient algorithm for sequential random sampling," ACM Trans. Math. Soft. 13 (1), 58--67 (1987). to randomly pick n distinct points out of the remaining N-1 (not including i0!). (The same as "method S" in Knuth vol. 2.) This method requires O(N) time, which is fine in our case (there are better methods if n << N). */ { int Nleft = d->N - 1, nleft = n; int Nfree = Nleft - nleft; i = 0; i += i == i0; while (nleft > 1) { double q = ((double) Nfree) / Nleft; double v = nlopt_urand(0., 1.); while (q > v) { ++i; i += i == i0; --Nfree; --Nleft; q = (q * Nfree) / Nleft; } xi = ps + n1 * i + 1; if (jn-- == 0) /* point to reflect through */ for (k = 0; k < n; ++k) x[k] -= xi[k] * (0.5*n); else /* point to include in centroid */ for (k = 0; k < n; ++k) x[k] += xi[k]; ++i; i += i == i0; --Nleft; --nleft; } i += nlopt_iurand(Nleft); i += i == i0; xi = ps + n1 * i + 1; if (jn-- == 0) /* point to reflect through */ for (k = 0; k < n; ++k) x[k] -= xi[k] * (0.5*n); else /* point to include in centroid */ for (k = 0; k < n; ++k) x[k] += xi[k]; } for (k = 0; k < n; ++k) { x[k] *= 2.0 / n; /* renormalize */ if (x[k] > d->ub[k]) x[k] = d->ub[k]; else if (x[k] < d->lb[k]) x[k] = d->lb[k]; } } #define NUM_MUTATION 1 /* # "local mutation" steps to try if trial fails */ static nlopt_result crs_trial(crs_data *d) { rb_node *best = rb_tree_min(&d->t); rb_node *worst = rb_tree_max(&d->t); int mutation = NUM_MUTATION; int i, n = d->n; random_trial(d, d->p + 1, best); do { d->p[0] = d->f(n, d->p + 1, NULL, d->f_data); ++ *(d->stop->nevals_p); if (nlopt_stop_forced(d->stop)) return NLOPT_FORCED_STOP; if (d->p[0] < worst->k[0]) break; if (nlopt_stop_evals(d->stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(d->stop)) return NLOPT_MAXTIME_REACHED; if (mutation) { for (i = 0; i < n; ++i) { double w = nlopt_urand(0.,1.); d->p[1+i] = best->k[1+i] * (1 + w) - w * d->p[1+i]; if (d->p[1+i] > d->ub[i]) d->p[1+i] = d->ub[i]; else if (d->p[1+i] < d->lb[i]) d->p[1+i] = d->lb[i]; } mutation--; } else { random_trial(d, d->p + 1, best); mutation = NUM_MUTATION; } } while (1); memcpy(worst->k, d->p, sizeof(double) * (n+1)); rb_tree_resort(&d->t, worst); return NLOPT_SUCCESS; } static void crs_destroy(crs_data *d) { nlopt_sobol_destroy(d->s); rb_tree_destroy(&d->t); free(d->ps); } static nlopt_result crs_init(crs_data *d, int n, const double *x, const double *lb, const double *ub, nlopt_stopping *stop, nlopt_func f, void *f_data, int population, int lds) { int i; if (!population) { /* TODO: how should we set the default population size? the Kaelo and Ali paper suggests 10*(n+1), but should we add more random points if maxeval is large, or... ? */ d->N = 10 * (n + 1); /* heuristic initial population size */ } else d->N = population; if (d->N < n + 1) { /* population must be big enough for a simplex */ nlopt_stop_msg(stop, "population %d should be >= dimension + 1 = %d", d->N, n+1); return NLOPT_INVALID_ARGS; } d->n = n; d->stop = stop; d->f = f; d->f_data = f_data; d->ub = ub; d->lb = lb; d->ps = (double *) malloc(sizeof(double) * (n + 1) * (d->N + 1)); if (!d->ps) return NLOPT_OUT_OF_MEMORY; d->p = d->ps + d->N * (n+1); rb_tree_init(&d->t, crs_compare); /* we can either use pseudorandom points, as in the original CRS algorithm, or use a low-discrepancy Sobol' sequence ... I tried the latter, however, and it doesn't seem to help, probably because we are only generating a small number of random points to start with */ d->s = lds ? nlopt_sobol_create((unsigned) n) : NULL; nlopt_sobol_skip(d->s, (unsigned) d->N, d->ps + 1); /* generate initial points randomly, plus starting guess x */ memcpy(d->ps + 1, x, sizeof(double) * n); d->ps[0] = f(n, x, NULL, f_data); ++ *(stop->nevals_p); if (!rb_tree_insert(&d->t, d->ps)) return NLOPT_OUT_OF_MEMORY; if (d->ps[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; for (i = 1; i < d->N; ++i) { double *k = d->ps + i*(n+1); if (d->s) nlopt_sobol_next(d->s, k + 1, lb, ub); else { int j; for (j = 0; j < n; ++j) k[1 + j] = nlopt_urand(lb[j], ub[j]); } k[0] = f(n, k + 1, NULL, f_data); ++ *(stop->nevals_p); if (!rb_tree_insert(&d->t, k)) return NLOPT_OUT_OF_MEMORY; if (k[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; } return NLOPT_SUCCESS;; } nlopt_result crs_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int population, /* initial population (0=default) */ int lds) /* random or low-discrepancy seq. (lds) */ { nlopt_result ret; crs_data d; rb_node *best; ret = crs_init(&d, n, x, lb, ub, stop, f, f_data, population, lds); if (ret < 0) return ret; best = rb_tree_min(&d.t); *minf = best->k[0]; memcpy(x, best->k + 1, sizeof(double) * n); while (ret == NLOPT_SUCCESS) { if (NLOPT_SUCCESS == (ret = crs_trial(&d))) { best = rb_tree_min(&d.t); if (best->k[0] < *minf) { if (best->k[0] < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_f(stop, best->k[0], *minf)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, best->k + 1, x)) ret = NLOPT_XTOL_REACHED; *minf = best->k[0]; memcpy(x, best->k + 1, sizeof(double) * n); } if (ret != NLOPT_SUCCESS) { if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; } } } crs_destroy(&d); return ret; } nlopt-2.6.1/src/algs/crs/crs.h000066400000000000000000000032261345435414600161340ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef CRS_H #define CRS_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result crs_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int population, /* initial population (0=default) */ int random); /* random or low-discrepancy seq. */ #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/direct/000077500000000000000000000000001345435414600156545ustar00rootroot00000000000000nlopt-2.6.1/src/algs/direct/AUTHORS000066400000000000000000000001731345435414600167250ustar00rootroot00000000000000C conversion: Steven G. Johnson (stevenj@alum.mit.edu) Original Fortran code: Joerg.M.Gablonsky (jmgablon@mailandnews.com) nlopt-2.6.1/src/algs/direct/COPYING000066400000000000000000000030071345435414600167070ustar00rootroot00000000000000This code is based on the DIRECT 2.0.4 Fortran code by Gablonsky et al. at http://www4.ncsu.edu/~ctk/SOFTWARE/DIRECTv204.tar.gz The C version was initially converted via f2c and then cleaned up and reorganized by Steven G. Johnson (stevenj@alum.mit.edu), August 2007. ******** Copyright and license for the original Fortran DIRECT code ******** Copyright (c) 1999, 2000, 2001 North Carolina State University This program is distributed under the MIT License (see http://www.opensource.org/licenses/mit-license.php): 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. nlopt-2.6.1/src/algs/direct/DIRect.c000066400000000000000000001265531345435414600171460ustar00rootroot00000000000000/* DIRect-transp.f -- translated by f2c (version 20050501). f2c output hand-cleaned by SGJ (August 2007). */ #include #include "direct-internal.h" /* Common Block Declarations */ /* Table of constant values */ /* +-----------------------------------------------------------------------+ */ /* | Program : Direct.f | */ /* | Last modified : 07-16-2001 | */ /* | Written by : Joerg Gablonsky (jmgablon@unity.ncsu.edu) | */ /* | North Carolina State University | */ /* | Dept. of Mathematics | */ /* | DIRECT is a method to solve problems of the form: | */ /* | min f: Q --> R, | */ /* | where f is the function to be minimized and Q is an n-dimensional | */ /* | hyperrectangle given by the the following equation: | */ /* | | */ /* | Q={ x : l(i) <= x(i) <= u(i), i = 1,...,n }. | */ /* | Note: This version of DIRECT can also handle hidden constraints. By | */ /* | this we mean that the function may not be defined over the whole| */ /* | hyperrectangle Q, but only over a subset, which is not given | */ /* | analytically. | */ /* | | */ /* | We now give a brief outline of the algorithm: | */ /* | | */ /* | The algorithm starts with mapping the hyperrectangle Q to the | */ /* | n-dimensional unit hypercube. DIRECT then samples the function at | */ /* | the center of this hypercube and at 2n more points, 2 in each | */ /* | coordinate direction. Uisng these function values, DIRECT then | */ /* | divides the domain into hyperrectangles, each having exactly one of | */ /* | the sampling points as its center. In each iteration, DIRECT chooses| */ /* | some of the existing hyperrectangles to be further divided. | */ /* | We provide two different strategies of how to decide which | */ /* | hyperrectangles DIRECT divides and several different convergence | */ /* | criteria. | */ /* | | */ /* | DIRECT was designed to solve problems where the function f is | */ /* | Lipschitz continues. However, DIRECT has proven to be effective on | */ /* | more complex problems than these. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_direct_(fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs, integer *maxf, integer *maxt, double starttime, double maxtime, int *force_stop, doublereal *minf, doublereal *l, doublereal *u, integer *algmethod, integer *ierror, FILE *logfile, doublereal *fglobal, doublereal *fglper, doublereal *volper, doublereal *sigmaper, void *fcn_data) { /* System generated locals */ integer i__1, i__2; doublereal d__1; /* changed by SGJ to be dynamically allocated ... would be even better to use realloc, below, to grow these as needed */ integer MAXFUNC = *maxf <= 0 ? 101000 : (*maxf + 1000 + *maxf / 2); integer MAXDEEP = *maxt <= 0 ? MAXFUNC/5: *maxt + 1000; const integer MAXDIV = 5000; /* Local variables */ integer increase; doublereal *c__ = 0 /* was [90000][64] */, *f = 0 /* was [90000][2] */; integer i__, j, *s = 0 /* was [3000][2] */, t; doublereal *w = 0; doublereal divfactor; integer ifeasiblef, iepschange, actmaxdeep; integer actdeep_div__, iinfesiblef; integer pos1, newtosample; integer ifree, help; doublereal *oldl = 0, fmax; integer maxi; doublereal kmax, *oldu = 0; integer oops, *list2 = 0 /* was [64][2] */, cheat; doublereal delta; integer mdeep, *point = 0, start; integer *anchor = 0, *length = 0 /* was [90000][64] */, *arrayi = 0; doublereal *levels = 0, *thirds = 0; doublereal epsfix; integer oldpos, minpos, maxpos, tstart, actdeep, ifreeold, oldmaxf; integer numfunc, version; integer jones; /* FIXME: change sizes dynamically? */ #define MY_ALLOC(p, t, n) p = (t *) malloc(sizeof(t) * (n)); \ if (!(p)) { *ierror = -100; goto cleanup; } /* Note that I've transposed c__, length, and f relative to the original Fortran code. e.g. length was length(maxfunc,n) in Fortran [ or actually length(maxfunc, maxdims), but by using malloc I can just allocate n ], corresponding to length[n][maxfunc] in C, but I've changed the code to access it as length[maxfunc][n]. That is, the maxfunc direction is the discontiguous one. This makes it easier to resize dynamically (by adding contiguous rows) using realloc, without having to move data around manually. */ MY_ALLOC(c__, doublereal, MAXFUNC * (*n)); MY_ALLOC(length, integer, MAXFUNC * (*n)); MY_ALLOC(f, doublereal, MAXFUNC * 2); MY_ALLOC(point, integer, MAXFUNC); if (*maxf <= 0) *maxf = MAXFUNC - 1000; MY_ALLOC(s, integer, MAXDIV * 2); MY_ALLOC(anchor, integer, MAXDEEP + 2); MY_ALLOC(levels, doublereal, MAXDEEP + 1); MY_ALLOC(thirds, doublereal, MAXDEEP + 1); if (*maxt <= 0) *maxt = MAXDEEP; MY_ALLOC(w, doublereal, (*n)); MY_ALLOC(oldl, doublereal, (*n)); MY_ALLOC(oldu, doublereal, (*n)); MY_ALLOC(list2, integer, (*n) * 2); MY_ALLOC(arrayi, integer, (*n)); /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE Direct | */ /* | On entry | */ /* | fcn -- The argument containing the name of the user-supplied | */ /* | SUBROUTINE that returns values for the function to be | */ /* | minimized. | */ /* | n -- The dimension of the problem. | */ /* | eps -- Exceeding value. If eps > 0, we use the same epsilon for | */ /* | all iterations. If eps < 0, we use the update formula from | */ /* | Jones: | */ /* | eps = max(1.D-4*abs(minf),epsfix), | */ /* | where epsfix = abs(eps), the absolute value of eps which is| */ /* | passed to the function. | */ /* | maxf -- The maximum number of function evaluations. | */ /* | maxT -- The maximum number of iterations. | */ /* | Direct stops when either the maximum number of iterations | */ /* | is reached or more than maxf function-evalutions were made.| */ /* | l -- The lower bounds of the hyperbox. | */ /* | u -- The upper bounds of the hyperbox. | */ /* |algmethod-- Choose the method, that is either use the original method | */ /* | as described by Jones et.al. (0) or use our modification(1)| */ /* | logfile -- File-Handle for the logfile. DIRECT expects this file to be| */ /* | opened and closed by the user outside of DIRECT. We moved | */ /* | this to the outside so the user can add extra informations | */ /* | to this file before and after the call to DIRECT. | */ /* | fglobal -- Function value of the global optimum. If this value is not | */ /* | known (that is, we solve a real problem, not a testproblem)| */ /* | set this value to -1.D100 and fglper (see below) to 0.D0. | */ /* | fglper -- Terminate the optimization when the percent error | */ /* | 100(f_min - fglobal)/max(1,abs(fglobal)) < fglper. | */ /* | volper -- Terminate the optimization when the volume of the | */ /* | hyperrectangle S with f(c(S)) = minf is less then volper | */ /* | percent of the volume of the original hyperrectangle. | */ /* |sigmaper -- Terminate the optimization when the measure of the | */ /* | hyperrectangle S with f(c(S)) = minf is less then sigmaper.| */ /* | | */ /* | User data that is passed through without being changed: | */ /* | fcn_data - opaque pointer to any user data | */ /* | | */ /* | On return | */ /* | | */ /* | x -- The final point obtained in the optimization process. | */ /* | X should be a good approximation to the global minimum | */ /* | for the function within the hyper-box. | */ /* | | */ /* | minf -- The value of the function at x. | */ /* | Ierror -- Error flag. If Ierror is lower 0, an error has occurred. | */ /* | The values of Ierror mean | */ /* | Fatal errors : | */ /* | -1 u(i) <= l(i) for some i. | */ /* | -2 maxf is too large. | */ /* | -3 Initialization in DIRpreprc failed. | */ /* | -4 Error in DIRSamplepoints, that is there was an error | */ /* | in the creation of the sample points. | */ /* | -5 Error in DIRSamplef, that is an error occurred while | */ /* | the function was sampled. | */ /* | -6 Error in DIRDoubleInsert, that is an error occurred | */ /* | DIRECT tried to add all hyperrectangles with the same| */ /* | size and function value at the center. Either | */ /* | increase maxdiv or use our modification (Jones = 1). | */ /* | Termination values : | */ /* | 1 Number of function evaluations done is larger then | */ /* | maxf. | */ /* | 2 Number of iterations is equal to maxT. | */ /* | 3 The best function value found is within fglper of | */ /* | the (known) global optimum, that is | */ /* | 100(minf - fglobal/max(1,|fglobal|)) < fglper. | */ /* | Note that this termination signal only occurs when | */ /* | the global optimal value is known, that is, a test | */ /* | function is optimized. | */ /* | 4 The volume of the hyperrectangle with minf at its | */ /* | center is less than volper percent of the volume of | */ /* | the original hyperrectangle. | */ /* | 5 The measure of the hyperrectangle with minf at its | */ /* | center is less than sigmaper. | */ /* | | */ /* | SUBROUTINEs used : | */ /* | | */ /* | DIRheader, DIRInitSpecific, DIRInitList, DIRpreprc, DIRInit, DIRChoose| */ /* | DIRDoubleInsert, DIRGet_I, DIRSamplepoints, DIRSamplef, DIRDivide | */ /* | DIRInsertList, DIRreplaceInf, DIRWritehistbox, DIRsummary, Findareas | */ /* | | */ /* | Functions used : | */ /* | | */ /* | DIRgetMaxdeep, DIRgetlevel | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Parameters | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | The maximum of function evaluations allowed. | */ /* | The maximum dept of the algorithm. | */ /* | The maximum number of divisions allowed. | */ /* | The maximal dimension of the problem. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Global Variables. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | EXTERNAL Variables. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | User Variables. | */ /* | These can be used to pass user defined data to the function to be | */ /* | optimized. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Place to define, if needed, some application-specific variables. | */ /* | Note: You should try to use the arrays defined above for this. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | End of application - specific variables ! | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Internal variables : | */ /* | f -- values of functions. | */ /* |divfactor-- Factor used for termination with known global minimum. | */ /* | anchor -- anchors of lists with deepness i, -1 is anchor for list of | */ /* | NaN - values. | */ /* | S -- List of potentially optimal points. | */ /* | point -- lists | */ /* | ifree -- first free position | */ /* | c -- midpoints of arrays | */ /* | thirds -- Precalculated values of 1/3^i. | */ /* | levels -- Length of intervals. | */ /* | length -- Length of intervall (index) | */ /* | t -- actual iteration | */ /* | j -- loop-variable | */ /* | actdeep -- the actual minimal interval-length index | */ /* | Minpos -- position of the actual minimum | */ /* | file -- The filehandle for a datafile. | */ /* | maxpos -- The number of intervalls, which are truncated. | */ /* | help -- A help variable. | */ /* | numfunc -- The actual number of function evaluations. | */ /* | file2 -- The filehandle for an other datafile. | */ /* | ArrayI -- Array with the indexes of the sides with maximum length. | */ /* | maxi -- Number of directions with maximal side length. | */ /* | oops -- Flag which shows if anything went wrong in the | */ /* | initialisation. | */ /* | cheat -- Obsolete. If equal 1, we don't allow Ktilde > kmax. | */ /* | writed -- If writed=1, store final division to plot with Matlab. | */ /* | List2 -- List of indicies of intervalls, which are to be truncated. | */ /* | i -- Another loop-variable. | */ /* |actmaxdeep-- The actual maximum (minimum) of possible Interval length. | */ /* | oldpos -- The old index of the minimum. Used to print only, if there | */ /* | is a new minimum found. | */ /* | tstart -- The start of the outer loop. | */ /* | start -- The postion of the starting point in the inner loop. | */ /* | Newtosample -- The total number of points to sample in the inner loop.| */ /* | w -- Array used to divide the intervalls | */ /* | kmax -- Obsolete. If cheat = 1, Ktilde was not allowed to be larger| */ /* | than kmax. If Ktilde > kmax, we set ktilde = kmax. | */ /* | delta -- The distance to new points from center of old hyperrec. | */ /* | pos1 -- Help variable used as an index. | */ /* | version -- Store the version number of DIRECT. | */ /* | oldmaxf -- Store the original function budget. | */ /* |increase -- Flag used to keep track if function budget was increased | */ /* | because no feasible point was found. | */ /* | ifreeold -- Keep track which index was free before. Used with | */ /* | SUBROUTINE DIRReplaceInf. | */ /* |actdeep_div-- Keep track of the current depths for divisions. | */ /* | oldl -- Array used to store the original bounds of the domain. | */ /* | oldu -- Array used to store the original bounds of the domain. | */ /* | epsfix -- If eps < 0, we use Jones update formula. epsfix stores the | */ /* | absolute value of epsilon. | */ /* |iepschange-- flag iepschange to store if epsilon stays fixed or is | */ /* | changed. | */ /* |DIRgetMaxdeep-- Function to calculate the level of a hyperrectangle. | */ /* |DIRgetlevel-- Function to calculate the level and stage of a hyperrec. | */ /* | fmax -- Keep track of the maximum value of the function found. | */ /* |Ifeasiblef-- Keep track if a feasible point has been found so far. | */ /* | Ifeasiblef = 0 means a feasible point has been found, | */ /* | Ifeasiblef = 1 no feasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 09/25/00 Version counter. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 09/24/00 Add another actdeep to keep track of the current depths | */ /* | for divisions. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* |JG 01/13/01 Added epsfix for epsilon update. If eps < 0, we use Jones | */ /* | update formula. epsfix stores the absolute value of epsilon| */ /* | then. Also added flag iepschange to store if epsilon stays | */ /* | fixed or is changed. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 fmax is used to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Ifeasiblef is used to keep track if a feasible point has | */ /* | been found so far. Ifeasiblef = 0 means a feasible point | */ /* | has been found, Ifeasiblef = 1 if not. | */ /* | JG 03/09/01 IInfeasible is used to keep track if an infeasible point | */ /* | has been found. IInfeasible > 0 means a infeasible point | */ /* | has been found, IInfeasible = 0 if not. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Start of code. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --u; --l; --x; /* Function Body */ jones = *algmethod; /* +-----------------------------------------------------------------------+ */ /* | Save the upper and lower bounds. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { oldu[i__ - 1] = u[i__]; oldl[i__ - 1] = l[i__]; /* L150: */ } /* +-----------------------------------------------------------------------+ */ /* | Set version. | */ /* +-----------------------------------------------------------------------+ */ version = 204; /* +-----------------------------------------------------------------------+ */ /* | Set parameters. | */ /* | If cheat > 0, we do not allow \tilde{K} to be larger than kmax, and| */ /* | set \tilde{K} to set value if necessary. Not used anymore. | */ /* +-----------------------------------------------------------------------+ */ cheat = 0; kmax = 1e10; mdeep = MAXDEEP; /* +-----------------------------------------------------------------------+ */ /* | Write the header of the logfile. | */ /* +-----------------------------------------------------------------------+ */ direct_dirheader_(logfile, &version, &x[1], n, eps, maxf, maxt, &l[1], &u[1], algmethod, &MAXFUNC, &MAXDEEP, fglobal, fglper, ierror, &epsfix, & iepschange, volper, sigmaper); /* +-----------------------------------------------------------------------+ */ /* | If an error has occurred while writing the header (we do some checking| */ /* | of variables there), return to the main program. | */ /* +-----------------------------------------------------------------------+ */ if (*ierror < 0) { goto cleanup; } /* +-----------------------------------------------------------------------+ */ /* | If the known global minimum is equal 0, we cannot divide by it. | */ /* | Therefore we set it to 1. If not, we set the divisionfactor to the | */ /* | absolute value of the global minimum. | */ /* +-----------------------------------------------------------------------+ */ if (*fglobal == 0.) { divfactor = 1.; } else { divfactor = fabs(*fglobal); } /* +-----------------------------------------------------------------------+ */ /* | Save the budget given by the user. The variable maxf will be changed | */ /* | if in the beginning no feasible points are found. | */ /* +-----------------------------------------------------------------------+ */ oldmaxf = *maxf; increase = 0; /* +-----------------------------------------------------------------------+ */ /* | Initialiase the lists. | */ /* +-----------------------------------------------------------------------+ */ direct_dirinitlist_(anchor, &ifree, point, f, &MAXFUNC, &MAXDEEP); /* +-----------------------------------------------------------------------+ */ /* | Call the routine to initialise the mapping of x from the n-dimensional| */ /* | unit cube to the hypercube given by u and l. If an error occurred, | */ /* | give out a error message and return to the main program with the error| */ /* | flag set. | */ /* | JG 07/16/01 Changed call to remove unused data. | */ /* +-----------------------------------------------------------------------+ */ direct_dirpreprc_(&u[1], &l[1], n, &l[1], &u[1], &oops); if (oops > 0) { if (logfile) fprintf(logfile,"WARNING: Initialization in DIRpreprc failed.\n"); *ierror = -3; goto cleanup; } tstart = 2; /* +-----------------------------------------------------------------------+ */ /* | Initialise the algorithm DIRECT. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ direct_dirinit_(f, fcn, c__, length, &actdeep, point, anchor, &ifree, logfile, arrayi, &maxi, list2, w, &x[1], &l[1], &u[1], minf, &minpos, thirds, levels, &MAXFUNC, &MAXDEEP, n, n, & fmax, &ifeasiblef, &iinfesiblef, ierror, fcn_data, jones, starttime, maxtime, force_stop); /* +-----------------------------------------------------------------------+ */ /* | Added error checking. | */ /* +-----------------------------------------------------------------------+ */ if (*ierror < 0) { if (*ierror == -4) { if (logfile) fprintf(logfile, "WARNING: Error occurred in routine DIRsamplepoints.\n"); goto cleanup; } if (*ierror == -5) { if (logfile) fprintf(logfile, "WARNING: Error occurred in routine DIRsamplef..\n"); goto cleanup; } if (*ierror == -102) goto L100; } else if (*ierror == DIRECT_MAXTIME_EXCEEDED) goto L100; numfunc = maxi + 1 + maxi; actmaxdeep = 1; oldpos = 0; tstart = 2; /* +-----------------------------------------------------------------------+ */ /* | If no feasible point has been found, give out the iteration, the | */ /* | number of function evaluations and a warning. Otherwise, give out | */ /* | the iteration, the number of function evaluations done and minf. | */ /* +-----------------------------------------------------------------------+ */ if (ifeasiblef > 0) { if (logfile) fprintf(logfile, "No feasible point found in %d iterations " "and %d function evaluations.\n", tstart-1, numfunc); } else { if (logfile) fprintf(logfile, "%d, %d, %g, %g\n", tstart-1, numfunc, *minf, fmax); } /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Main loop! | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ i__1 = *maxt; for (t = tstart; t <= i__1; ++t) { /* +-----------------------------------------------------------------------+ */ /* | Choose the sample points. The indices of the sample points are stored | */ /* | in the list S. | */ /* +-----------------------------------------------------------------------+ */ actdeep = actmaxdeep; direct_dirchoose_(anchor, s, &MAXDEEP, f, minf, *eps, epsabs, levels, &maxpos, length, &MAXFUNC, &MAXDEEP, &MAXDIV, n, logfile, &cheat, & kmax, &ifeasiblef, jones); /* +-----------------------------------------------------------------------+ */ /* | Add other hyperrectangles to S, which have the same level and the same| */ /* | function value at the center as the ones found above (that are stored | */ /* | in S). This is only done if we use the original DIRECT algorithm. | */ /* | JG 07/16/01 Added Errorflag. | */ /* +-----------------------------------------------------------------------+ */ if (*algmethod == 0) { direct_dirdoubleinsert_(anchor, s, &maxpos, point, f, &MAXDEEP, &MAXFUNC, &MAXDIV, ierror); if (*ierror == -6) { if (logfile) fprintf(logfile, "WARNING: Capacity of array S in DIRDoubleInsert reached. Increase maxdiv.\n" "This means that there are a lot of hyperrectangles with the same function\n" "value at the center. We suggest to use our modification instead (Jones = 1)\n" ); goto cleanup; } } oldpos = minpos; /* +-----------------------------------------------------------------------+ */ /* | Initialise the number of sample points in this outer loop. | */ /* +-----------------------------------------------------------------------+ */ newtosample = 0; i__2 = maxpos; for (j = 1; j <= i__2; ++j) { actdeep = s[j + MAXDIV-1]; /* +-----------------------------------------------------------------------+ */ /* | If the actual index is a point to sample, do it. | */ /* +-----------------------------------------------------------------------+ */ if (s[j - 1] > 0) { /* +-----------------------------------------------------------------------+ */ /* | JG 09/24/00 Calculate the value delta used for sampling points. | */ /* +-----------------------------------------------------------------------+ */ actdeep_div__ = direct_dirgetmaxdeep_(&s[j - 1], length, &MAXFUNC, n); delta = thirds[actdeep_div__ + 1]; actdeep = s[j + MAXDIV-1]; /* +-----------------------------------------------------------------------+ */ /* | If the current dept of division is only one under the maximal allowed | */ /* | dept, stop the computation. | */ /* +-----------------------------------------------------------------------+ */ if (actdeep + 1 >= mdeep) { if (logfile) fprintf(logfile, "WARNING: Maximum number of levels reached. Increase maxdeep.\n"); *ierror = -6; goto L100; } actmaxdeep = MAX(actdeep,actmaxdeep); help = s[j - 1]; if (! (anchor[actdeep + 1] == help)) { pos1 = anchor[actdeep + 1]; while(! (point[pos1 - 1] == help)) { pos1 = point[pos1 - 1]; } point[pos1 - 1] = point[help - 1]; } else { anchor[actdeep + 1] = point[help - 1]; } if (actdeep < 0) { actdeep = (integer) f[(help << 1) - 2]; } /* +-----------------------------------------------------------------------+ */ /* | Get the Directions in which to decrease the intervall-length. | */ /* +-----------------------------------------------------------------------+ */ direct_dirget_i__(length, &help, arrayi, &maxi, n, &MAXFUNC); /* +-----------------------------------------------------------------------+ */ /* | Sample the function. To do this, we first calculate the points where | */ /* | we need to sample the function. After checking for errors, we then do | */ /* | the actual evaluation of the function, again followed by checking for | */ /* | errors. | */ /* +-----------------------------------------------------------------------+ */ direct_dirsamplepoints_(c__, arrayi, &delta, &help, &start, length, logfile, f, &ifree, &maxi, point, &x[ 1], &l[1], minf, &minpos, &u[1], n, &MAXFUNC, & MAXDEEP, &oops); if (oops > 0) { if (logfile) fprintf(logfile, "WARNING: Error occurred in routine DIRsamplepoints.\n"); *ierror = -4; goto cleanup; } newtosample += maxi; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ direct_dirsamplef_(c__, arrayi, &delta, &help, &start, length, logfile, f, &ifree, &maxi, point, fcn, &x[ 1], &l[1], minf, &minpos, &u[1], n, &MAXFUNC, & MAXDEEP, &oops, &fmax, &ifeasiblef, &iinfesiblef, fcn_data, force_stop); if (force_stop && *force_stop) { *ierror = -102; goto L100; } if (nlopt_stop_time_(starttime, maxtime)) { *ierror = DIRECT_MAXTIME_EXCEEDED; goto L100; } if (oops > 0) { if (logfile) fprintf(logfile, "WARNING: Error occurred in routine DIRsamplef.\n"); *ierror = -5; goto cleanup; } /* +-----------------------------------------------------------------------+ */ /* | Divide the intervalls. | */ /* +-----------------------------------------------------------------------+ */ direct_dirdivide_(&start, &actdeep_div__, length, point, arrayi, & help, list2, w, &maxi, f, &MAXFUNC, &MAXDEEP, n); /* +-----------------------------------------------------------------------+ */ /* | Insert the new intervalls into the list (sorted). | */ /* +-----------------------------------------------------------------------+ */ direct_dirinsertlist_(&start, anchor, point, f, &maxi, length, & MAXFUNC, &MAXDEEP, n, &help, jones); /* +-----------------------------------------------------------------------+ */ /* | Increase the number of function evaluations. | */ /* +-----------------------------------------------------------------------+ */ numfunc = numfunc + maxi + maxi; } /* +-----------------------------------------------------------------------+ */ /* | End of main loop. | */ /* +-----------------------------------------------------------------------+ */ /* L20: */ } /* +-----------------------------------------------------------------------+ */ /* | If there is a new minimum, show the actual iteration, the number of | */ /* | function evaluations, the minimum value of f (so far) and the position| */ /* | in the array. | */ /* +-----------------------------------------------------------------------+ */ if (oldpos < minpos) { if (logfile) fprintf(logfile, "%d, %d, %g, %g\n", t, numfunc, *minf, fmax); } /* +-----------------------------------------------------------------------+ */ /* | If no feasible point has been found, give out the iteration, the | */ /* | number of function evaluations and a warning. | */ /* +-----------------------------------------------------------------------+ */ if (ifeasiblef > 0) { if (logfile) fprintf(logfile, "No feasible point found in %d iterations " "and %d function evaluations\n", t, numfunc); } /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Termination Checks | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Calculate the index for the hyperrectangle at which | */ /* | minf is assumed. We then calculate the volume of this | */ /* | hyperrectangle and store it in delta. This delta can be | */ /* | used to stop DIRECT once the volume is below a certain | */ /* | percentage of the original volume. Since the original | */ /* | is 1 (scaled), we can stop once delta is below a certain | */ /* | percentage, given by volper. | */ /* +-----------------------------------------------------------------------+ */ *ierror = jones; jones = 0; actdeep_div__ = direct_dirgetlevel_(&minpos, length, &MAXFUNC, n, jones); jones = *ierror; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Use precalculated values to calculate volume. | */ /* +-----------------------------------------------------------------------+ */ delta = thirds[actdeep_div__] * 100; if (delta <= *volper) { *ierror = 4; if (logfile) fprintf(logfile, "DIRECT stopped: Volume of S_min is " "%g%% < %g%% of the original volume.\n", delta, *volper); goto L100; } /* +-----------------------------------------------------------------------+ */ /* | JG 01/23/01 Calculate the measure for the hyperrectangle at which | */ /* | minf is assumed. If this measure is smaller then sigmaper,| */ /* | we stop DIRECT. | */ /* +-----------------------------------------------------------------------+ */ actdeep_div__ = direct_dirgetlevel_(&minpos, length, &MAXFUNC, n, jones); delta = levels[actdeep_div__]; if (delta <= *sigmaper) { *ierror = 5; if (logfile) fprintf(logfile, "DIRECT stopped: Measure of S_min " "= %g < %g.\n", delta, *sigmaper); goto L100; } /* +-----------------------------------------------------------------------+ */ /* | If the best found function value is within fglper of the (known) | */ /* | global minimum value, terminate. This only makes sense if this optimal| */ /* | value is known, that is, in test problems. | */ /* +-----------------------------------------------------------------------+ */ if ((*minf - *fglobal) * 100 / divfactor <= *fglper) { *ierror = 3; if (logfile) fprintf(logfile, "DIRECT stopped: minf within fglper of global minimum.\n"); goto L100; } /* +-----------------------------------------------------------------------+ */ /* | Find out if there are infeasible points which are near feasible ones. | */ /* | If this is the case, replace the function value at the center of the | */ /* | hyper rectangle by the lowest function value of a nearby function. | */ /* | If no infeasible points exist (IInfesiblef = 0), skip this. | */ /* +-----------------------------------------------------------------------+ */ if (iinfesiblef > 0) { direct_dirreplaceinf_(&ifree, &ifreeold, f, c__, thirds, length, anchor, point, &u[1], &l[1], &MAXFUNC, &MAXDEEP, n, n, logfile, &fmax, jones); } ifreeold = ifree; /* +-----------------------------------------------------------------------+ */ /* | If iepschange = 1, we use the epsilon change formula from Jones. | */ /* +-----------------------------------------------------------------------+ */ if (iepschange == 1) { /* Computing MAX */ d__1 = fabs(*minf) * 1e-4; *eps = MAX(d__1,epsfix); } /* +-----------------------------------------------------------------------+ */ /* | If no feasible point has been found yet, set the maximum number of | */ /* | function evaluations to the number of evaluations already done plus | */ /* | the budget given by the user. | */ /* | If the budget has already be increased, increase it again. If a | */ /* | feasible point has been found, remark that and reset flag. No further | */ /* | increase is needed. | */ /* +-----------------------------------------------------------------------+ */ if (increase == 1) { *maxf = numfunc + oldmaxf; if (ifeasiblef == 0) { if (logfile) fprintf(logfile, "DIRECT found a feasible point. The " "adjusted budget is now set to %d.\n", *maxf); increase = 0; } } /* +-----------------------------------------------------------------------+ */ /* | Check if the number of function evaluations done is larger than the | */ /* | allocated budget. If this is the case, check if a feasible point was | */ /* | found. If this is a case, terminate. If no feasible point was found, | */ /* | increase the budget and set flag increase. | */ /* +-----------------------------------------------------------------------+ */ if (numfunc > *maxf) { if (ifeasiblef == 0) { *ierror = 1; if (logfile) fprintf(logfile, "DIRECT stopped: numfunc >= maxf.\n"); goto L100; } else { increase = 1; if (logfile) fprintf(logfile, "DIRECT could not find a feasible point after %d function evaluations.\n" "DIRECT continues until a feasible point is found.\n", numfunc); *maxf = numfunc + oldmaxf; } } /* L10: */ } /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | End of main loop. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | The algorithm stopped after maxT iterations. | */ /* +-----------------------------------------------------------------------+ */ *ierror = 2; if (logfile) fprintf(logfile, "DIRECT stopped: maxT iterations.\n"); L100: /* +-----------------------------------------------------------------------+ */ /* | Store the position of the minimum in x. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = c__[i__ + minpos * i__1 - i__1-1] * l[i__] + l[i__] * u[i__]; u[i__] = oldu[i__ - 1]; l[i__] = oldl[i__ - 1]; /* L50: */ } /* +-----------------------------------------------------------------------+ */ /* | Store the number of function evaluations in maxf. | */ /* +-----------------------------------------------------------------------+ */ *maxf = numfunc; /* +-----------------------------------------------------------------------+ */ /* | Give out a summary of the run. | */ /* +-----------------------------------------------------------------------+ */ direct_dirsummary_(logfile, &x[1], &l[1], &u[1], n, minf, fglobal, &numfunc, ierror); /* +-----------------------------------------------------------------------+ */ /* | Format statements. | */ /* +-----------------------------------------------------------------------+ */ cleanup: #define MY_FREE(p) if (p) free(p) MY_FREE(c__); MY_FREE(f); MY_FREE(s); MY_FREE(w); MY_FREE(oldl); MY_FREE(oldu); MY_FREE(list2); MY_FREE(point); MY_FREE(anchor); MY_FREE(length); MY_FREE(arrayi); MY_FREE(levels); MY_FREE(thirds); } /* direct_ */ nlopt-2.6.1/src/algs/direct/DIRparallel.c000066400000000000000000000460251345435414600201620ustar00rootroot00000000000000/* DIRparallel.f -- translated by f2c (version 20050501). f2c output hand-cleaned by SGJ (August 2007). */ #include "direct-internal.h" /* Table of constant values */ static integer c__0 = 0; static integer c_n1 = -1; /* +-----------------------------------------------------------------------+ */ /* | Program : Direct.f (subfile DIRseriell.f) | */ /* | Last modified : 02-22-01 | */ /* | Written by : Joerg Gablonsky | */ /* | Subroutines, which differ depending on the serial or parallel version.| */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Parallel Direct. This routine replaces the normal main routine DIRect.| */ /* | In it, we find out if this pe is the master or slave. If it is the | */ /* | master, it calls the serial DIRect main routine. The only routine that| */ /* | has to change for parallel Direct is DIRSamplef, where the actual | */ /* | sampling of the function is done. If we are on the slave, wait for | */ /* | either the coordinates of a point to sample the function or the | */ /* | termination signal. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ int direct_pardirect_(fp fcn, doublereal *x, integer *n, doublereal *eps, integer *maxf, integer *maxt, doublereal *minf, doublereal *l, doublereal *u, integer *algmethod, integer *ierror, FILE *logfile, doublereal *fglobal, doublereal *fglper, doublereal *volper, doublereal *sigmaper, void *fcn_data) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, k; integer tid; integer flag__; doublereal fval; integer tids[360], kret; integer mytid; doublereal fscale; integer nprocs; /* +-----------------------------------------------------------------------+ */ /* | Parameters | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | The maximum of function evaluations allowed. | */ /* | The maximum dept of the algorithm. | */ /* | The maximum number of divisions allowed. | */ /* | The maximal dimension of the problem. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Global Variables. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | External Variables. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | User Variables. | */ /* | These can be used to pass user defined data to the function to be | */ /* | optimized. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Parallel programming variables | */ /* +-----------------------------------------------------------------------+ */ /* maxprocs should be >= the number of processes used for DIRECT */ /* +-----------------------------------------------------------------------+ */ /* | End of parallel programming variables | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Internal variables | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 02/28/01 Begin of parallel additions | */ /* | DETERMINE MASTER PROCESSOR. GET TIDS OF ALL PROCESSORS. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --u; --l; --x; /* Function Body */ getmytidif_(&mytid); getnprocsif_(&nprocs); gettidif_(&c__0, tids); /* +-----------------------------------------------------------------------+ */ /* | If I am the master get the other tids and start running DIRECT. | */ /* | Otherwise, branch off to do function evaluations. | */ /* +-----------------------------------------------------------------------+ */ if (mytid == tids[0]) { i__1 = nprocs - 1; for (i__ = 1; i__ <= i__1; ++i__) { gettidif_(&i__, &tids[i__]); /* L46: */ } /* +-----------------------------------------------------------------------+ */ /* | Call Direct main routine. This routine calls DIRSamplef for the | */ /* | function evaluations, which are then done in parallel. | */ /* +-----------------------------------------------------------------------+ */ direct_direct_(fcn, &x[1], n, eps, maxf, maxt, minf, &l[1], &u[1], algmethod, ierror, logfile, fglobal, fglper, volper, sigmaper, fcn_data); /* +-----------------------------------------------------------------------+ */ /* | Send exit message to rest of pe's. | */ /* +-----------------------------------------------------------------------+ */ flag__ = 0; i__1 = nprocs; for (tid = 2; tid <= i__1; ++tid) { mastersendif_(&tids[tid - 1], &tids[tid - 1], n, &flag__, &flag__, &x[1], &u[1], &l[1], &x[1]); /* L200: */ } } else { /* +-----------------------------------------------------------------------+ */ /* | This is what the slaves do!! | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Receive the first point from the master processor. | */ /* +-----------------------------------------------------------------------+ */ slaverecvif_(tids, &c_n1, n, &flag__, &k, &fscale, &u[1], &l[1], &x[1] ); /* +-----------------------------------------------------------------------+ */ /* | Repeat until master signals to stop. | */ /* +-----------------------------------------------------------------------+ */ while(flag__ > 0) { /* +-----------------------------------------------------------------------+ */ /* | Evaluate f(x). | */ /* +-----------------------------------------------------------------------+ */ direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &fval, &kret, & fcn_data); /* +-----------------------------------------------------------------------+ */ /* | Send result and wait for next point / message with signal to stop. | */ /* +-----------------------------------------------------------------------+ */ slavesendif_(tids, &mytid, &k, &mytid, &fval, &kret); slaverecvif_(tids, &c_n1, n, &flag__, &k, &fscale, &u[1], &l[1], & x[1]); } } return 0; } /* pardirect_ */ /* +-----------------------------------------------------------------------+ */ /* | Subroutine for sampling. This sampling is done in parallel, the master| */ /* | prozessor is also evaluating the function sometimes. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirsamplef_(doublereal *c__, integer *arrayi, doublereal *delta, integer *sample, integer *new__, integer *length, FILE *logfile, doublereal *f, integer *free, integer *maxi, integer *point, fp fcn, doublereal *x, doublereal *l, doublereal * minf, integer *minpos, doublereal *u, integer *n, integer *maxfunc, integer *maxdeep, integer *oops, doublereal *fmax, integer * ifeasiblef, integer *iinfesiblef, void *fcn_data) { /* System generated locals */ integer length_dim1, length_offset, c_dim1, c_offset, f_dim1, f_offset, i__1; doublereal d__1; /* Local variables */ integer i__, j, k, helppoint, tid, pos; integer flag__, tids[360], kret, npts; doublereal fhelp; integer oldpos, nprocs, datarec; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 fcn must be declared external. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Removed fcn. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* | Added variable to keep track if feasible point was found. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Variables to pass user defined data to the function to be optimized. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Parallel programming variables. | */ /* +-----------------------------------------------------------------------+ */ /* JG 09/05/00 Increase this if more processors are used. */ /* +-----------------------------------------------------------------------+ */ /* | Find out the id's of all processors. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --u; --l; --x; --arrayi; --point; f_dim1 = *maxfunc; f_offset = 1 + f_dim1; f -= f_offset; length_dim1 = *maxfunc; length_offset = 1 + length_dim1; length -= length_offset; c_dim1 = *maxfunc; c_offset = 1 + c_dim1; c__ -= c_offset; /* Function Body */ getnprocsif_(&nprocs); i__1 = nprocs - 1; for (i__ = 0; i__ <= i__1; ++i__) { gettidif_(&i__, &tids[i__]); /* L46: */ } /* +-----------------------------------------------------------------------+ */ /* | Set the pointer to the first function to be evaluated, | */ /* | store this position also in helppoint. | */ /* +-----------------------------------------------------------------------+ */ pos = *new__; helppoint = pos; /* +-----------------------------------------------------------------------+ */ /* | Iterate over all points, where the function should be | */ /* | evaluated. | */ /* +-----------------------------------------------------------------------+ */ flag__ = 1; npts = *maxi + *maxi; k = 1; while(k <= npts && k < nprocs) { /* +-----------------------------------------------------------------------+ */ /* | tid is the id of the prozessor the next points is send to. | */ /* +-----------------------------------------------------------------------+ */ tid = k + 1; /* +-----------------------------------------------------------------------+ */ /* | Copy the position into the helparray x. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = c__[pos + i__ * c_dim1]; /* L60: */ } /* +-----------------------------------------------------------------------+ */ /* | Send the point. | */ /* +-----------------------------------------------------------------------+ */ mastersendif_(&tids[tid - 1], &tids[tid - 1], n, &flag__, &pos, &x[1], &u[1], &l[1], &x[1]); ++k; pos = point[pos]; /* +-----------------------------------------------------------------------+ */ /* | Get the next point. | */ /* +-----------------------------------------------------------------------+ */ } /* +-----------------------------------------------------------------------+ */ /* | Get data until it is all received. | */ /* +-----------------------------------------------------------------------+ */ datarec = 0; while(datarec < npts) { if ((doublereal) datarec / (doublereal) nprocs - datarec / nprocs < 1e-5 && k <= npts) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = c__[pos + i__ * c_dim1]; /* L165: */ } direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &fhelp, &kret, fcn_data); oldpos = pos; f[oldpos + f_dim1] = fhelp; ++datarec; /* +-----------------------------------------------------------------------+ */ /* | Remember if an infeasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ *iinfesiblef = MAX(*iinfesiblef,kret); if (kret == 0) { /* +-----------------------------------------------------------------------+ */ /* | if the function evaluation was O.K., set the flag in | */ /* | f(pos,2). | */ /* +-----------------------------------------------------------------------+ */ f[oldpos + (f_dim1 << 1)] = 0.; *ifeasiblef = 0; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* Computing MAX */ d__1 = f[pos + f_dim1]; *fmax = MAX(d__1,*fmax); } /* +-----------------------------------------------------------------------+ */ /* | Remember if an infeasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ *iinfesiblef = MAX(*iinfesiblef,kret); if (kret == 1) { /* +-----------------------------------------------------------------------+ */ /* | If the function could not be evaluated at the given point, | */ /* | set flag to mark this (f(pos,2) and store the maximum | */ /* | box-sidelength in f(pos,1). | */ /* +-----------------------------------------------------------------------+ */ f[oldpos + (f_dim1 << 1)] = 2.; f[oldpos + f_dim1] = *fmax; } /* +-----------------------------------------------------------------------+ */ /* | If the function could not be evaluated due to a failure in | */ /* | the setup, mark this. | */ /* +-----------------------------------------------------------------------+ */ if (kret == -1) { f[oldpos + (f_dim1 << 1)] = -1.; } ++k; pos = point[pos]; } /* +-----------------------------------------------------------------------+ */ /* | Recover where to store the value. | */ /* +-----------------------------------------------------------------------+ */ masterrecvif_(&c_n1, &c_n1, &oldpos, &tid, &fhelp, &kret); f[oldpos + f_dim1] = fhelp; ++datarec; /* +-----------------------------------------------------------------------+ */ /* | Remember if an infeasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ *iinfesiblef = MAX(*iinfesiblef,kret); if (kret == 0) { /* +-----------------------------------------------------------------------+ */ /* | if the function evaluation was O.K., set the flag in | */ /* | f(pos,2). | */ /* +-----------------------------------------------------------------------+ */ f[oldpos + (f_dim1 << 1)] = 0.; *ifeasiblef = 0; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* Computing MAX */ d__1 = f[oldpos + f_dim1]; *fmax = MAX(d__1,*fmax); } if (kret == 1) { /* +-----------------------------------------------------------------------+ */ /* | If the function could not be evaluated at the given point, | */ /* | set flag to mark this (f(pos,2) and store the maximum | */ /* | box-sidelength in f(pos,1). | */ /* +-----------------------------------------------------------------------+ */ f[oldpos + (f_dim1 << 1)] = 2.; f[oldpos + f_dim1] = *fmax; } /* +-----------------------------------------------------------------------+ */ /* | If the function could not be evaluated due to a failure in | */ /* | the setup, mark this. | */ /* +-----------------------------------------------------------------------+ */ if (kret == -1) { f[oldpos + (f_dim1 << 1)] = -1.; } /* +-----------------------------------------------------------------------+ */ /* | Send data until it is all sent. | */ /* +-----------------------------------------------------------------------+ */ if (k <= npts) { /* +-----------------------------------------------------------------------+ */ /* | Copy the position into the helparray x. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = c__[pos + i__ * c_dim1]; /* L160: */ } mastersendif_(&tid, &tid, n, &flag__, &pos, &x[1], &u[1], &l[1], & x[1]); ++k; pos = point[pos]; } } pos = helppoint; /* +-----------------------------------------------------------------------+ */ /* | Iterate over all evaluated points and see, if the minimal | */ /* | value of the function has changed. If this has happend, | */ /* | store the minimal value and its position in the array. | */ /* | Attention: Only valied values are checked!! | */ /* +-----------------------------------------------------------------------+ */ i__1 = *maxi + *maxi; for (j = 1; j <= i__1; ++j) { if (f[pos + f_dim1] < *minf && f[pos + (f_dim1 << 1)] == 0.) { *minf = f[pos + f_dim1]; *minpos = pos; } pos = point[pos]; /* L50: */ } } /* dirsamplef_ */ nlopt-2.6.1/src/algs/direct/DIRserial.c000066400000000000000000000165301345435414600176430ustar00rootroot00000000000000/* DIRserial-transp.f -- translated by f2c (version 20050501). f2c output hand-cleaned by SGJ (August 2007). */ #include "direct-internal.h" /* +-----------------------------------------------------------------------+ */ /* | Program : Direct.f (subfile DIRserial.f) | */ /* | Last modified : 04-12-2001 | */ /* | Written by : Joerg Gablonsky | */ /* | SUBROUTINEs, which differ depENDing on the serial or parallel version.| */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE for sampling. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirsamplef_(doublereal *c__, integer *arrayi, doublereal *delta, integer *sample, integer *new__, integer *length, FILE *logfile, doublereal *f, integer *free, integer *maxi, integer *point, fp fcn, doublereal *x, doublereal *l, doublereal * minf, integer *minpos, doublereal *u, integer *n, integer *maxfunc, const integer *maxdeep, integer *oops, doublereal *fmax, integer * ifeasiblef, integer *iinfesiblef, void *fcn_data, int *force_stop) { /* System generated locals */ integer length_dim1, length_offset, c_dim1, c_offset, i__1, i__2; doublereal d__1; /* Local variables */ integer i__, j, helppoint, pos, kret; (void) logfile; (void) free; (void) maxfunc; (void) maxdeep; (void) oops; (void) delta; (void) sample; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 fcn must be declared external. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Removed fcn. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* | Added variable to keep track IF feasible point was found. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Variables to pass user defined data to the function to be optimized. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Set the pointer to the first function to be evaluated, | */ /* | store this position also in helppoint. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --u; --l; --x; --arrayi; --point; f -= 3; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; c_dim1 = *n; c_offset = 1 + c_dim1; c__ -= c_offset; /* Function Body */ pos = *new__; helppoint = pos; /* +-----------------------------------------------------------------------+ */ /* | Iterate over all points, where the function should be | */ /* | evaluated. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *maxi + *maxi; for (j = 1; j <= i__1; ++j) { /* +-----------------------------------------------------------------------+ */ /* | Copy the position into the helparrayy x. | */ /* +-----------------------------------------------------------------------+ */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { x[i__] = c__[i__ + pos * c_dim1]; /* L60: */ } /* +-----------------------------------------------------------------------+ */ /* | Call the function. | */ /* +-----------------------------------------------------------------------+ */ if (force_stop && *force_stop) /* skip eval after forced stop */ f[(pos << 1) + 1] = *fmax; else direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &f[(pos << 1) + 1], &kret, fcn_data); if (force_stop && *force_stop) kret = -1; /* mark as invalid point */ /* +-----------------------------------------------------------------------+ */ /* | Remember IF an infeasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ *iinfesiblef = MAX(*iinfesiblef,kret); if (kret == 0) { /* +-----------------------------------------------------------------------+ */ /* | IF the function evaluation was O.K., set the flag in | */ /* | f(2,pos). Also mark that a feasible point has been found. | */ /* +-----------------------------------------------------------------------+ */ f[(pos << 1) + 2] = 0.; *ifeasiblef = 0; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* Computing MAX */ d__1 = f[(pos << 1) + 1]; *fmax = MAX(d__1,*fmax); } if (kret >= 1) { /* +-----------------------------------------------------------------------+ */ /* | IF the function could not be evaluated at the given point, | */ /* | set flag to mark this (f(2,pos) and store the maximum | */ /* | box-sidelength in f(1,pos). | */ /* +-----------------------------------------------------------------------+ */ f[(pos << 1) + 2] = 2.; f[(pos << 1) + 1] = *fmax; } /* +-----------------------------------------------------------------------+ */ /* | IF the function could not be evaluated due to a failure in | */ /* | the setup, mark this. | */ /* +-----------------------------------------------------------------------+ */ if (kret == -1) { f[(pos << 1) + 2] = -1.; } /* +-----------------------------------------------------------------------+ */ /* | Set the position to the next point, at which the function | */ /* | should e evaluated. | */ /* +-----------------------------------------------------------------------+ */ pos = point[pos]; /* L40: */ } pos = helppoint; /* +-----------------------------------------------------------------------+ */ /* | Iterate over all evaluated points and see, IF the minimal | */ /* | value of the function has changed. IF this has happEND, | */ /* | store the minimal value and its position in the array. | */ /* | Attention: Only valid values are checked!! | */ /* +-----------------------------------------------------------------------+ */ i__1 = *maxi + *maxi; for (j = 1; j <= i__1; ++j) { if (f[(pos << 1) + 1] < *minf && f[(pos << 1) + 2] == 0.) { *minf = f[(pos << 1) + 1]; *minpos = pos; } pos = point[pos]; /* L50: */ } } /* dirsamplef_ */ nlopt-2.6.1/src/algs/direct/DIRsubrout.c000066400000000000000000001654321345435414600200750ustar00rootroot00000000000000/* DIRsubrout.f -- translated by f2c (version 20050501). f2c output hand-cleaned by SGJ (August 2007). */ #include #include "direct-internal.h" /* Table of constant values */ static integer c__1 = 1; static integer c__32 = 32; static integer c__0 = 0; /* +-----------------------------------------------------------------------+ */ /* | INTEGER Function DIRGetlevel | */ /* | Returns the level of the hyperrectangle. Depending on the value of the| */ /* | global variable JONES. IF JONES equals 0, the level is given by | */ /* | kN + p, where the rectangle has p sides with a length of| */ /* | 1/3^(k+1), and N-p sides with a length of 1/3^k. | */ /* | If JONES equals 1, the level is the power of 1/3 of the length of the | */ /* | longest side hyperrectangle. | */ /* | | */ /* | On Return : | */ /* | the maximal length | */ /* | | */ /* | pos -- the position of the midpoint in the array length | */ /* | length -- the array with the dimensions | */ /* | maxfunc -- the leading dimension of length | */ /* | n -- the dimension of the problem | */ /* | | */ /* +-----------------------------------------------------------------------+ */ integer direct_dirgetlevel_(integer *pos, integer *length, integer *maxfunc, integer *n, integer jones) { /* System generated locals */ integer length_dim1, length_offset, ret_val, i__1; /* Local variables */ integer i__, k, p, help; (void) maxfunc; /* JG 09/15/00 Added variable JONES (see above) */ /* Parameter adjustments */ length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ if (jones == 0) { help = length[*pos * length_dim1 + 1]; k = help; p = 1; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if (length[i__ + *pos * length_dim1] < k) { k = length[i__ + *pos * length_dim1]; } if (length[i__ + *pos * length_dim1] == help) { ++p; } /* L100: */ } if (k == help) { ret_val = k * *n + *n - p; } else { ret_val = k * *n + p; } } else { help = length[*pos * length_dim1 + 1]; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if (length[i__ + *pos * length_dim1] < help) { help = length[i__ + *pos * length_dim1]; } /* L10: */ } ret_val = help; } return ret_val; } /* dirgetlevel_ */ /* +-----------------------------------------------------------------------+ */ /* | Program : Direct.f (subfile DIRsubrout.f) | */ /* | Last modified : 07-16-2001 | */ /* | Written by : Joerg Gablonsky | */ /* | Subroutines used by the algorithm DIRECT. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRChoose | */ /* | Decide, which is the next sampling point. | */ /* | Changed 09/25/00 JG | */ /* | Added maxdiv to call and changed S to size maxdiv. | */ /* | Changed 01/22/01 JG | */ /* | Added Ifeasiblef to call to keep track if a feasible point has| */ /* | been found. | */ /* | Changed 07/16/01 JG | */ /* | Changed if statement to prevent run-time errors. | | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirchoose_(integer *anchor, integer *s, integer *actdeep, doublereal *f, doublereal *minf, doublereal epsrel, doublereal epsabs, doublereal *thirds, integer *maxpos, integer *length, integer *maxfunc, const integer *maxdeep, const integer *maxdiv, integer *n, FILE *logfile, integer *cheat, doublereal *kmax, integer *ifeasiblef, integer jones) { /* System generated locals */ integer s_dim1, s_offset, length_dim1, length_offset, i__1; /* Local variables */ integer i__, j, k; doublereal helplower; integer i___, j___; doublereal helpgreater; integer novaluedeep = 0; doublereal help2; integer novalue; /* Parameter adjustments */ f -= 3; ++anchor; s_dim1 = *maxdiv; s_offset = 1 + s_dim1; s -= s_offset; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ helplower = HUGE_VAL; helpgreater = 0.; k = 1; if (*ifeasiblef >= 1) { i__1 = *actdeep; for (j = 0; j <= i__1; ++j) { if (anchor[j] > 0) { s[k + s_dim1] = anchor[j]; s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[ length_offset], maxfunc, n, jones); goto L12; } /* L1001: */ } L12: ++k; *maxpos = 1; return; } else { i__1 = *actdeep; for (j = 0; j <= i__1; ++j) { if (anchor[j] > 0) { s[k + s_dim1] = anchor[j]; s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[ length_offset], maxfunc, n, jones); ++k; } /* L10: */ } } novalue = 0; if (anchor[-1] > 0) { novalue = anchor[-1]; novaluedeep = direct_dirgetlevel_(&novalue, &length[length_offset], maxfunc, n, jones); } *maxpos = k - 1; i__1 = *maxdeep; for (j = k - 1; j <= i__1; ++j) { s[k + s_dim1] = 0; /* L11: */ } for (j = *maxpos; j >= 1; --j) { helplower = HUGE_VAL; helpgreater = 0.; j___ = s[j + s_dim1]; i__1 = j - 1; for (i__ = 1; i__ <= i__1; ++i__) { i___ = s[i__ + s_dim1]; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Changed IF statement into two to prevent run-time errors | */ /* | which could occur if the compiler checks the second | */ /* | expression in an .AND. statement although the first | */ /* | statement is already not true. | */ /* +-----------------------------------------------------------------------+ */ if (i___ > 0 && ! (i__ == j)) { if (f[(i___ << 1) + 2] <= 1.) { help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + ( s_dim1 << 1)]]; help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2; if (help2 <= 0.) { if (logfile) fprintf(logfile, "thirds > 0, help2 <= 0\n"); goto L60; } if (help2 < helplower) { if (logfile) fprintf(logfile, "helplower = %g\n", help2); helplower = help2; } } } /* L30: */ } i__1 = *maxpos; for (i__ = j + 1; i__ <= i__1; ++i__) { i___ = s[i__ + s_dim1]; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Changed IF statement into two to prevent run-time errors | */ /* | which could occur if the compiler checks the second | */ /* | expression in an .AND. statement although the first | */ /* | statement is already not true. | */ /* +-----------------------------------------------------------------------+ */ if (i___ > 0 && ! (i__ == j)) { if (f[(i___ << 1) + 2] <= 1.) { help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + ( s_dim1 << 1)]]; help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2; if (help2 <= 0.) { if (logfile) fprintf(logfile, "thirds < 0, help2 <= 0\n"); goto L60; } if (help2 > helpgreater) { if (logfile) fprintf(logfile, "helpgreater = %g\n", help2); helpgreater = help2; } } } /* L31: */ } if (helpgreater <= helplower) { if (*cheat == 1 && helplower > *kmax) { helplower = *kmax; } if (f[(j___ << 1) + 1] - helplower * thirds[s[j + (s_dim1 << 1)]] > MIN(*minf - epsrel * fabs(*minf), *minf - epsabs)) { if (logfile) fprintf(logfile, "> minf - epslminfl\n"); goto L60; } } else { if (logfile) fprintf(logfile, "helpgreater > helplower: %g %g %g\n", helpgreater, helplower, helpgreater - helplower); goto L60; } goto L40; L60: s[j + s_dim1] = 0; L40: ; } if (novalue > 0) { ++(*maxpos); s[*maxpos + s_dim1] = novalue; s[*maxpos + (s_dim1 << 1)] = novaluedeep; } } /* dirchoose_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRDoubleInsert | */ /* | Routine to make sure that if there are several potential optimal | */ /* | hyperrectangles of the same level (i.e. hyperrectangles that have| */ /* | the same level and the same function value at the center), all of| */ /* | them are divided. This is the way as originally described in | */ /* | Jones et.al. | */ /* | JG 07/16/01 Added errorflag to calling sequence. We check if more | */ /* | we reach the capacity of the array S. If this happens, we | */ /* | return to the main program with an error. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirdoubleinsert_(integer *anchor, integer *s, integer * maxpos, integer *point, doublereal *f, const integer *maxdeep, integer * maxfunc, const integer *maxdiv, integer *ierror) { /* System generated locals */ integer s_dim1, s_offset, i__1; /* Local variables */ integer i__, oldmaxpos, pos, help, iflag, actdeep; (void) maxdeep; (void) maxfunc; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Added flag to prevent run time-errors on some systems. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ ++anchor; f -= 3; --point; s_dim1 = *maxdiv; s_offset = 1 + s_dim1; s -= s_offset; /* Function Body */ oldmaxpos = *maxpos; i__1 = oldmaxpos; for (i__ = 1; i__ <= i__1; ++i__) { if (s[i__ + s_dim1] > 0) { actdeep = s[i__ + (s_dim1 << 1)]; help = anchor[actdeep]; pos = point[help]; iflag = 0; /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Added flag to prevent run time-errors on some systems. On | */ /* | some systems the second conditions in an AND statement is | */ /* | evaluated even if the first one is already not true. | */ /* +-----------------------------------------------------------------------+ */ while(pos > 0 && iflag == 0) { if (f[(pos << 1) + 1] - f[(help << 1) + 1] <= 1e-13) { if (*maxpos < *maxdiv) { ++(*maxpos); s[*maxpos + s_dim1] = pos; s[*maxpos + (s_dim1 << 1)] = actdeep; pos = point[pos]; } else { /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Maximum number of elements possible in S has been reached!| */ /* +-----------------------------------------------------------------------+ */ *ierror = -6; return; } } else { iflag = 1; } } } /* L10: */ } } /* dirdoubleinsert_ */ /* +-----------------------------------------------------------------------+ */ /* | INTEGER Function GetmaxDeep | */ /* | function to get the maximal length (1/length) of the n-dimensional | */ /* | rectangle with midpoint pos. | */ /* | | */ /* | On Return : | */ /* | the maximal length | */ /* | | */ /* | pos -- the position of the midpoint in the array length | */ /* | length -- the array with the dimensions | */ /* | maxfunc -- the leading dimension of length | */ /* | n -- the dimension of the problem | */ /* | | */ /* +-----------------------------------------------------------------------+ */ integer direct_dirgetmaxdeep_(integer *pos, integer *length, integer *maxfunc, integer *n) { /* System generated locals */ integer length_dim1, length_offset, i__1, i__2, i__3; /* Local variables */ integer i__, help; (void) maxfunc; /* Parameter adjustments */ length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ help = length[*pos * length_dim1 + 1]; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { /* Computing MIN */ i__2 = help, i__3 = length[i__ + *pos * length_dim1]; help = MIN(i__2,i__3); /* L10: */ } return help; } /* dirgetmaxdeep_ */ static integer isinbox_(doublereal *x, doublereal *a, doublereal *b, integer *n, integer *lmaxdim) { /* System generated locals */ integer ret_val, i__1; /* Local variables */ integer outofbox, i__; (void) lmaxdim; /* Function Body */ outofbox = 1; i__1 = *n; for (i__ = 0; i__ < i__1; ++i__) { if (a[i__] > x[i__] || b[i__] < x[i__]) { outofbox = 0; goto L1010; } /* L1000: */ } L1010: ret_val = outofbox; return ret_val; } /* isinbox_ */ /* +-----------------------------------------------------------------------+ */ /* | JG Added 09/25/00 | */ /* | | */ /* | SUBROUTINE DIRResortlist | */ /* | | */ /* | Resort the list so that the infeasible point is in the list with the | */ /* | replaced value. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ static void dirresortlist_(integer *replace, integer *anchor, doublereal *f, integer *point, integer *length, integer *n, integer * maxfunc, integer *maxdim, const integer *maxdeep, FILE *logfile, integer jones) { /* System generated locals */ integer length_dim1, length_offset, i__1; /* Local variables */ integer i__, l, pos; integer start; (void) maxdim; (void) maxdeep; /* +-----------------------------------------------------------------------+ */ /* | Get the length of the hyper rectangle with infeasible mid point and | */ /* | Index of the corresponding list. | */ /* +-----------------------------------------------------------------------+ */ /* JG 09/25/00 Replaced with DIRgetlevel */ /* l = DIRgetmaxDeep(replace,length,maxfunc,n) */ /* Parameter adjustments */ --point; f -= 3; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; ++anchor; /* Function Body */ l = direct_dirgetlevel_(replace, &length[length_offset], maxfunc, n, jones); start = anchor[l]; /* +-----------------------------------------------------------------------+ */ /* | If the hyper rectangle with infeasibel midpoint is already the start | */ /* | of the list, give out message, nothing to do. | */ /* +-----------------------------------------------------------------------+ */ if (*replace == start) { /* write(logfile,*) 'No resorting of list necessarry, since new ', */ /* + 'point is already anchor of list .',l */ } else { /* +-----------------------------------------------------------------------+ */ /* | Take the hyper rectangle with infeasible midpoint out of the list. | */ /* +-----------------------------------------------------------------------+ */ pos = start; i__1 = *maxfunc; for (i__ = 1; i__ <= i__1; ++i__) { if (point[pos] == *replace) { point[pos] = point[*replace]; goto L20; } else { pos = point[pos]; } if (pos == 0) { if (logfile) fprintf(logfile, "Error in DIRREsortlist: " "We went through the whole list\n" "and could not find the point to replace!!\n"); goto L20; } /* L10: */ } /* +-----------------------------------------------------------------------+ */ /* | If the anchor of the list has a higher value than the value of a | */ /* | nearby point, put the infeasible point at the beginning of the list. | */ /* +-----------------------------------------------------------------------+ */ L20: if (f[(start << 1) + 1] > f[(*replace << 1) + 1]) { anchor[l] = *replace; point[*replace] = start; /* write(logfile,*) 'Point is replacing current anchor for ' */ /* + , 'this list ',l,replace,start */ } else { /* +-----------------------------------------------------------------------+ */ /* | Insert the point into the list according to its (replaced) function | */ /* | value. | */ /* +-----------------------------------------------------------------------+ */ pos = start; i__1 = *maxfunc; for (i__ = 1; i__ <= i__1; ++i__) { /* +-----------------------------------------------------------------------+ */ /* | The point has to be added at the end of the list. | */ /* +-----------------------------------------------------------------------+ */ if (point[pos] == 0) { point[*replace] = point[pos]; point[pos] = *replace; /* write(logfile,*) 'Point is added at the end of the ' */ /* + , 'list ',l, replace */ goto L40; } else { if (f[(point[pos] << 1) + 1] > f[(*replace << 1) + 1]) { point[*replace] = point[pos]; point[pos] = *replace; /* write(logfile,*) 'There are points with a higher ' */ /* + ,'f-value in the list ',l,replace, pos */ goto L40; } pos = point[pos]; } /* L30: */ } L40: ; } } } /* dirresortlist_ */ /* +-----------------------------------------------------------------------+ */ /* | JG Added 09/25/00 | */ /* | SUBROUTINE DIRreplaceInf | */ /* | | */ /* | Find out if there are infeasible points which are near feasible ones. | */ /* | If this is the case, replace the function value at the center of the | */ /* | hyper rectangle by the lowest function value of a nearby function. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirreplaceinf_(integer *free, integer *freeold, doublereal *f, doublereal *c__, doublereal *thirds, integer *length, integer *anchor, integer *point, doublereal *c1, doublereal *c2, integer *maxfunc, const integer *maxdeep, integer *maxdim, integer *n, FILE *logfile, doublereal *fmax, integer jones) { /* System generated locals */ integer c_dim1, c_offset, length_dim1, length_offset, i__1, i__2, i__3; doublereal d__1, d__2; /* Local variables */ doublereal a[32], b[32]; integer i__, j, k, l; doublereal x[32], sidelength; integer help; (void) freeold; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --point; f -= 3; ++anchor; length_dim1 = *maxdim; length_offset = 1 + length_dim1; length -= length_offset; c_dim1 = *maxdim; c_offset = 1 + c_dim1; c__ -= c_offset; --c2; --c1; /* Function Body */ i__1 = *free - 1; for (i__ = 1; i__ <= i__1; ++i__) { if (f[(i__ << 1) + 2] > 0.) { /* +-----------------------------------------------------------------------+ */ /* | Get the maximum side length of the hyper rectangle and then set the | */ /* | new side length to this lengths times the growth factor. | */ /* +-----------------------------------------------------------------------+ */ help = direct_dirgetmaxdeep_(&i__, &length[length_offset], maxfunc, n); sidelength = thirds[help] * 2.; /* +-----------------------------------------------------------------------+ */ /* | Set the Center and the upper and lower bounds of the rectangles. | */ /* +-----------------------------------------------------------------------+ */ i__2 = *n; for (j = 1; j <= i__2; ++j) { sidelength = thirds[length[i__ + j * length_dim1]]; a[j - 1] = c__[j + i__ * c_dim1] - sidelength; b[j - 1] = c__[j + i__ * c_dim1] + sidelength; /* L20: */ } /* +-----------------------------------------------------------------------+ */ /* | The function value is reset to 'Inf', since it may have been changed | */ /* | in an earlier iteration and now the feasible point which was close | */ /* | is not close anymore (since the hyper rectangle surrounding the | */ /* | current point may have shrunk). | */ /* +-----------------------------------------------------------------------+ */ f[(i__ << 1) + 1] = HUGE_VAL; f[(i__ << 1) + 2] = 2.; /* +-----------------------------------------------------------------------+ */ /* | Check if any feasible point is near this infeasible point. | */ /* +-----------------------------------------------------------------------+ */ i__2 = *free - 1; for (k = 1; k <= i__2; ++k) { /* +-----------------------------------------------------------------------+ */ /* | If the point k is feasible, check if it is near. | */ /* +-----------------------------------------------------------------------+ */ if (f[(k << 1) + 2] == 0.) { /* +-----------------------------------------------------------------------+ */ /* | Copy the coordinates of the point k into x. | */ /* +-----------------------------------------------------------------------+ */ i__3 = *n; for (l = 1; l <= i__3; ++l) { x[l - 1] = c__[l + k * c_dim1]; /* L40: */ } /* +-----------------------------------------------------------------------+ */ /* | Check if the point k is near the infeasible point, if so, replace the | */ /* | value at */ /* +-----------------------------------------------------------------------+ */ if (isinbox_(x, a, b, n, &c__32) == 1) { /* Computing MIN */ d__1 = f[(i__ << 1) + 1], d__2 = f[(k << 1) + 1]; f[(i__ << 1) + 1] = MIN(d__1,d__2); f[(i__ << 1) + 2] = 1.; } } /* L30: */ } if (f[(i__ << 1) + 2] == 1.) { f[(i__ << 1) + 1] += (d__1 = f[(i__ << 1) + 1], fabs(d__1)) * 1e-6f; i__2 = *n; for (l = 1; l <= i__2; ++l) { x[l - 1] = c__[l + i__ * c_dim1] * c1[l] + c__[l + i__ * c_dim1] * c2[l]; /* L200: */ } dirresortlist_(&i__, &anchor[-1], &f[3], &point[1], &length[length_offset], n, maxfunc, maxdim, maxdeep, logfile, jones); } else { /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 | */ /* | Replaced fixed value for infeasible points with maximum value found, | */ /* | increased by 1. | */ /* +-----------------------------------------------------------------------+ */ if (! (*fmax == f[(i__ << 1) + 1])) { /* Computing MAX */ d__1 = *fmax + 1., d__2 = f[(i__ << 1) + 1]; f[(i__ << 1) + 1] = MAX(d__1,d__2); } } } /* L10: */ } /* L1000: */ } /* dirreplaceinf_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRInsert | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ static void dirinsert_(integer *start, integer *ins, integer *point, doublereal *f, integer *maxfunc) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, help; /* JG 09/17/00 Rewrote this routine. */ /* DO 10,i = 1,maxfunc */ /* IF (f(ins,1) .LT. f(point(start),1)) THEN */ /* help = point(start) */ /* point(start) = ins */ /* point(ins) = help */ /* GOTO 20 */ /* END IF */ /* IF (point(start) .EQ. 0) THEN */ /* point(start) = ins */ /* point(ins) = 0 */ /* GOTO 20 */ /* END IF */ /* start = point(start) */ /* 10 CONTINUE */ /* 20 END */ /* Parameter adjustments */ f -= 3; --point; /* Function Body */ i__1 = *maxfunc; for (i__ = 1; i__ <= i__1; ++i__) { if (point[*start] == 0) { point[*start] = *ins; point[*ins] = 0; return; } else if (f[(*ins << 1) + 1] < f[(point[*start] << 1) + 1]) { help = point[*start]; point[*start] = *ins; point[*ins] = help; return; } *start = point[*start]; /* L10: */ } } /* dirinsert_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRInsertList | */ /* | Changed 02-24-2000 | */ /* | Got rid of the distinction between feasible and infeasible points| */ /* | I could do this since infeasible points get set to a high | */ /* | function value, which may be replaced by a function value of a | */ /* | nearby function at the end of the main loop. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirinsertlist_(integer *new__, integer *anchor, integer * point, doublereal *f, integer *maxi, integer *length, integer * maxfunc, const integer *maxdeep, integer *n, integer *samp, integer jones) { /* System generated locals */ integer length_dim1, length_offset, i__1; /* Local variables */ integer j; integer pos; integer pos1, pos2, deep; (void) maxdeep; /* JG 09/24/00 Changed this to Getlevel */ /* Parameter adjustments */ f -= 3; --point; ++anchor; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ i__1 = *maxi; for (j = 1; j <= i__1; ++j) { pos1 = *new__; pos2 = point[pos1]; *new__ = point[pos2]; /* JG 09/24/00 Changed this to Getlevel */ /* deep = DIRGetMaxdeep(pos1,length,maxfunc,n) */ deep = direct_dirgetlevel_(&pos1, &length[length_offset], maxfunc, n, jones); if (anchor[deep] == 0) { if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) { anchor[deep] = pos2; point[pos2] = pos1; point[pos1] = 0; } else { anchor[deep] = pos1; point[pos2] = 0; } } else { pos = anchor[deep]; if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) { if (f[(pos2 << 1) + 1] < f[(pos << 1) + 1]) { anchor[deep] = pos2; /* JG 08/30/00 Fixed bug. Sorting was not correct when */ /* f(1,pos2) < f(1,pos1) < f(1,pos) */ if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) { point[pos2] = pos1; point[pos1] = pos; } else { point[pos2] = pos; dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc); } } else { dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc); dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc); } } else { if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) { /* JG 08/30/00 Fixed bug. Sorting was not correct when */ /* f(pos1,1) < f(pos2,1) < f(pos,1) */ anchor[deep] = pos1; if (f[(pos << 1) + 1] < f[(pos2 << 1) + 1]) { point[pos1] = pos; dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc); } else { point[pos1] = pos2; point[pos2] = pos; } } else { dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc); dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc); } } } /* L10: */ } /* JG 09/24/00 Changed this to Getlevel */ /* deep = DIRGetMaxdeep(samp,length,maxfunc,n) */ deep = direct_dirgetlevel_(samp, &length[length_offset], maxfunc, n, jones); pos = anchor[deep]; if (f[(*samp << 1) + 1] < f[(pos << 1) + 1]) { anchor[deep] = *samp; point[*samp] = pos; } else { dirinsert_(&pos, samp, &point[1], &f[3], maxfunc); } } /* dirinsertlist_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRInsertList2 (Old way to do it.) | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ static void dirinsertlist_2__(integer *start, integer *j, integer *k, integer *list2, doublereal *w, integer *maxi, integer *n) { /* System generated locals */ integer list2_dim1, list2_offset, i__1; /* Local variables */ integer i__, pos; /* Parameter adjustments */ --w; list2_dim1 = *n; list2_offset = 1 + list2_dim1; list2 -= list2_offset; /* Function Body */ pos = *start; if (*start == 0) { list2[*j + list2_dim1] = 0; *start = *j; goto L50; } if (w[*start] > w[*j]) { list2[*j + list2_dim1] = *start; *start = *j; } else { i__1 = *maxi; for (i__ = 1; i__ <= i__1; ++i__) { if (list2[pos + list2_dim1] == 0) { list2[*j + list2_dim1] = 0; list2[pos + list2_dim1] = *j; goto L50; } else { if (w[*j] < w[list2[pos + list2_dim1]]) { list2[*j + list2_dim1] = list2[pos + list2_dim1]; list2[pos + list2_dim1] = *j; goto L50; } } pos = list2[pos + list2_dim1]; /* L10: */ } } L50: list2[*j + (list2_dim1 << 1)] = *k; } /* dirinsertlist_2__ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRSearchmin | */ /* | Search for the minimum in the list. ! */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ static void dirsearchmin_(integer *start, integer *list2, integer * pos, integer *k, integer *n) { /* System generated locals */ integer list2_dim1, list2_offset; /* Parameter adjustments */ list2_dim1 = *n; list2_offset = 1 + list2_dim1; list2 -= list2_offset; /* Function Body */ *k = *start; *pos = list2[*start + (list2_dim1 << 1)]; *start = list2[*start + list2_dim1]; } /* dirsearchmin_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRSamplepoints | */ /* | Subroutine to sample the new points. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirsamplepoints_(doublereal *c__, integer *arrayi, doublereal *delta, integer *sample, integer *start, integer *length, FILE *logfile, doublereal *f, integer *free, integer *maxi, integer *point, doublereal *x, doublereal *l, doublereal *minf, integer *minpos, doublereal *u, integer *n, integer *maxfunc, const integer *maxdeep, integer *oops) { /* System generated locals */ integer length_dim1, length_offset, c_dim1, c_offset, i__1, i__2; /* Local variables */ integer j, k, pos; (void) minf; (void) minpos; (void) maxfunc; (void) maxdeep; (void) oops; /* Parameter adjustments */ --u; --l; --x; --arrayi; --point; f -= 3; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; c_dim1 = *n; c_offset = 1 + c_dim1; c__ -= c_offset; /* Function Body */ *oops = 0; pos = *free; *start = *free; i__1 = *maxi + *maxi; for (k = 1; k <= i__1; ++k) { i__2 = *n; for (j = 1; j <= i__2; ++j) { length[j + *free * length_dim1] = length[j + *sample * length_dim1]; c__[j + *free * c_dim1] = c__[j + *sample * c_dim1]; /* L20: */ } pos = *free; *free = point[*free]; if (*free == 0) { if (logfile) fprintf(logfile, "Error, no more free positions! " "Increase maxfunc!\n"); *oops = 1; return; } /* L10: */ } point[pos] = 0; pos = *start; i__1 = *maxi; for (j = 1; j <= i__1; ++j) { c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] + * delta; pos = point[pos]; c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] - * delta; pos = point[pos]; /* L30: */ } ASRT(pos <= 0); } /* dirsamplepoints_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRDivide | */ /* | Subroutine to divide the hyper rectangles according to the rules. | */ /* | Changed 02-24-2000 | */ /* | Replaced if statement by min (line 367) | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirdivide_(integer *new__, integer *currentlength, integer *length, integer *point, integer *arrayi, integer *sample, integer *list2, doublereal *w, integer *maxi, doublereal *f, integer * maxfunc, const integer *maxdeep, integer *n) { /* System generated locals */ integer length_dim1, length_offset, list2_dim1, list2_offset, i__1, i__2; doublereal d__1, d__2; /* Local variables */ integer i__, j, k, pos, pos2; integer start; (void) maxfunc; (void) maxdeep; /* Parameter adjustments */ f -= 3; --point; --w; list2_dim1 = *n; list2_offset = 1 + list2_dim1; list2 -= list2_offset; --arrayi; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ start = 0; pos = *new__; i__1 = *maxi; for (i__ = 1; i__ <= i__1; ++i__) { j = arrayi[i__]; w[j] = f[(pos << 1) + 1]; k = pos; pos = point[pos]; /* Computing MIN */ d__1 = f[(pos << 1) + 1], d__2 = w[j]; w[j] = MIN(d__1,d__2); pos = point[pos]; dirinsertlist_2__(&start, &j, &k, &list2[list2_offset], &w[1], maxi, n); /* L10: */ } ASRT(pos <= 0); i__1 = *maxi; for (j = 1; j <= i__1; ++j) { dirsearchmin_(&start, &list2[list2_offset], &pos, &k, n); pos2 = start; length[k + *sample * length_dim1] = *currentlength + 1; i__2 = *maxi - j + 1; for (i__ = 1; i__ <= i__2; ++i__) { length[k + pos * length_dim1] = *currentlength + 1; pos = point[pos]; length[k + pos * length_dim1] = *currentlength + 1; /* JG 07/10/01 pos2 = 0 at the end of the 30-loop. Since we end */ /* the loop now, we do not need to reassign pos and pos2. */ if (pos2 > 0) { pos = list2[pos2 + (list2_dim1 << 1)]; pos2 = list2[pos2 + list2_dim1]; } /* L30: */ } /* L20: */ } } /* dirdivide_ */ /* +-----------------------------------------------------------------------+ */ /* | | */ /* | SUBROUTINE DIRINFCN | */ /* | | */ /* | Subroutine DIRinfcn unscales the variable x for use in the | */ /* | user-supplied function evaluation subroutine fcn. After fcn returns | */ /* | to DIRinfcn, DIRinfcn then rescales x for use by DIRECT. | */ /* | | */ /* | On entry | */ /* | | */ /* | fcn -- The argument containing the name of the user-supplied | */ /* | subroutine that returns values for the function to be | */ /* | minimized. | */ /* | | */ /* | x -- A double-precision vector of length n. The point at | */ /* | which the derivative is to be evaluated. | */ /* | | */ /* | xs1 -- A double-precision vector of length n. Used for | */ /* | scaling and unscaling the vector x by DIRinfcn. | */ /* | | */ /* | xs2 -- A double-precision vector of length n. Used for | */ /* | scaling and unscaling the vector x by DIRinfcn. | */ /* | | */ /* | n -- An integer. The dimension of the problem. | */ /* | kret -- An Integer. If kret = 1, the point is infeasible, | */ /* | kret = -1, bad problem set up, | */ /* | kret = 0, feasible. | */ /* | | */ /* | On return | */ /* | | */ /* | f -- A double-precision scalar. | */ /* | | */ /* | Subroutines and Functions | */ /* | | */ /* | The subroutine whose name is passed through the argument fcn. | */ /* | | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirinfcn_(fp fcn, doublereal *x, doublereal *c1, doublereal *c2, integer *n, doublereal *f, integer *flag__, void *fcn_data) { /* System generated locals */ integer i__1; /* Local variables */ integer i__; /* +-----------------------------------------------------------------------+ */ /* | Variables to pass user defined data to the function to be optimized. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | Unscale the variable x. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --c2; --c1; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = (x[i__] + c2[i__]) * c1[i__]; /* L20: */ } /* +-----------------------------------------------------------------------+ */ /* | Call the function-evaluation subroutine fcn. | */ /* +-----------------------------------------------------------------------+ */ *flag__ = 0; *f = fcn(*n, &x[1], flag__, fcn_data); /* +-----------------------------------------------------------------------+ */ /* | Rescale the variable x. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = x[i__] / c1[i__] - c2[i__]; /* L30: */ } } /* dirinfcn_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRGet_I | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirget_i__(integer *length, integer *pos, integer * arrayi, integer *maxi, integer *n, integer *maxfunc) { /* System generated locals */ integer length_dim1, length_offset, i__1; /* Local variables */ integer i__, j, help; (void) maxfunc; /* Parameter adjustments */ --arrayi; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; /* Function Body */ j = 1; help = length[*pos * length_dim1 + 1]; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if (length[i__ + *pos * length_dim1] < help) { help = length[i__ + *pos * length_dim1]; } /* L10: */ } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (length[i__ + *pos * length_dim1] == help) { arrayi[j] = i__; ++j; } /* L20: */ } *maxi = j - 1; } /* dirget_i__ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRInit | */ /* | Initialise all needed variables and do the first run of the | */ /* | algorithm. | */ /* | Changed 02/24/2000 | */ /* | Changed fcn Double precision to fcn external! | */ /* | Changed 09/15/2000 | */ /* | Added distinction between Jones way to characterize rectangles | */ /* | and our way. Common variable JONES controls which way we use. | */ /* | JONES = 0 Jones way (Distance from midpoint to corner) | */ /* | JONES = 1 Our way (Length of longest side) | */ /* | Changed 09/24/00 | */ /* | Added array levels. Levels contain the values to characterize | */ /* | the hyperrectangles. | */ /* | Changed 01/22/01 | */ /* | Added variable fmax to keep track of maximum value found. | */ /* | Added variable Ifeasiblef to keep track if feasibel point has | */ /* | been found. | */ /* | Changed 01/23/01 | */ /* | Added variable Ierror to keep track of errors. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirinit_(doublereal *f, fp fcn, doublereal *c__, integer *length, integer *actdeep, integer *point, integer *anchor, integer *free, FILE *logfile, integer *arrayi, integer *maxi, integer *list2, doublereal *w, doublereal *x, doublereal *l, doublereal *u, doublereal *minf, integer *minpos, doublereal *thirds, doublereal *levels, integer *maxfunc, const integer * maxdeep, integer *n, integer *maxor, doublereal *fmax, integer * ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata, integer jones, double starttime, double maxtime, int *force_stop) { /* System generated locals */ integer c_dim1, c_offset, length_dim1, length_offset, list2_dim1, list2_offset, i__1, i__2; /* Local variables */ integer i__, j; integer new__, help, oops; doublereal help2, delta; /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* +-----------------------------------------------------------------------+ */ /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable Ifeasiblef to keep track if feasibel point | */ /* | has been found. | */ /* | JG 01/23/01 Added variable Ierror to keep track of errors. | */ /* | JG 03/09/01 Added IInfeasible to keep track if an infeasible point has| */ /* | been found. | */ /* +-----------------------------------------------------------------------+ */ /* JG 09/15/00 Added variable JONES (see above) */ /* +-----------------------------------------------------------------------+ */ /* | Variables to pass user defined data to the function to be optimized. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --point; f -= 3; ++anchor; --u; --l; --x; --w; list2_dim1 = *maxor; list2_offset = 1 + list2_dim1; list2 -= list2_offset; --arrayi; length_dim1 = *n; length_offset = 1 + length_dim1; length -= length_offset; c_dim1 = *maxor; c_offset = 1 + c_dim1; c__ -= c_offset; /* Function Body */ *minf = HUGE_VAL; /* JG 09/15/00 If Jones way of characterising rectangles is used, */ /* initialise thirds to reflect this. */ if (jones == 0) { i__1 = *n - 1; for (j = 0; j <= i__1; ++j) { w[j + 1] = sqrt(*n - j + j / 9.) * .5; /* L5: */ } help2 = 1.; i__1 = *maxdeep / *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = *n - 1; for (j = 0; j <= i__2; ++j) { levels[(i__ - 1) * *n + j] = w[j + 1] / help2; /* L8: */ } help2 *= 3.; /* L10: */ } } else { /* JG 09/15/00 Initialiase levels to contain 1/j */ help2 = 3.; i__1 = *maxdeep; for (i__ = 1; i__ <= i__1; ++i__) { levels[i__] = 1. / help2; help2 *= 3.; /* L11: */ } levels[0] = 1.; } help2 = 3.; i__1 = *maxdeep; for (i__ = 1; i__ <= i__1; ++i__) { thirds[i__] = 1. / help2; help2 *= 3.; /* L21: */ } thirds[0] = 1.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { c__[i__ + c_dim1] = .5; x[i__] = .5; length[i__ + length_dim1] = 0; /* L20: */ } direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &f[3], &help, fcndata); if (force_stop && *force_stop) { *ierror = -102; return; } f[4] = (doublereal) help; *iinfeasible = help; *fmax = f[3]; /* 09/25/00 Added this */ /* if (f(1,1) .ge. 1.E+6) then */ if (f[4] > 0.) { f[3] = HUGE_VAL; *fmax = f[3]; *ifeasiblef = 1; } else { *ifeasiblef = 0; } /* JG 09/25/00 Remove IF */ *minf = f[3]; *minpos = 1; *actdeep = 2; point[1] = 0; *free = 2; delta = thirds[1]; if (nlopt_stop_time_(starttime, maxtime)) { *ierror = DIRECT_MAXTIME_EXCEEDED; return; } direct_dirget_i__(&length[length_offset], &c__1, &arrayi[1], maxi, n, maxfunc); new__ = *free; direct_dirsamplepoints_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, & length[length_offset], logfile, &f[3], free, maxi, & point[1], &x[1], &l[1], minf, minpos, &u[1], n, maxfunc, maxdeep, &oops); /* +-----------------------------------------------------------------------+ */ /* | JG 01/23/01 Added error checking. | */ /* +-----------------------------------------------------------------------+ */ if (oops > 0) { *ierror = -4; return; } /* +-----------------------------------------------------------------------+ */ /* | JG 01/22/01 Added variable to keep track of the maximum value found. | */ /* | Added variable to keep track if feasible point was found. | */ /* +-----------------------------------------------------------------------+ */ direct_dirsamplef_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, &length[ length_offset], logfile, &f[3], free, maxi, &point[ 1], fcn, &x[1], &l[1], minf, minpos, &u[1], n, maxfunc, maxdeep, &oops, fmax, ifeasiblef, iinfeasible, fcndata, force_stop); if (force_stop && *force_stop) { *ierror = -102; return; } if (nlopt_stop_time_(starttime, maxtime)) { *ierror = DIRECT_MAXTIME_EXCEEDED; return; } /* +-----------------------------------------------------------------------+ */ /* | JG 01/23/01 Added error checking. | */ /* +-----------------------------------------------------------------------+ */ if (oops > 0) { *ierror = -5; return; } direct_dirdivide_(&new__, &c__0, &length[length_offset], &point[1], &arrayi[1], & c__1, &list2[list2_offset], &w[1], maxi, &f[3], maxfunc, maxdeep, n); direct_dirinsertlist_(&new__, &anchor[-1], &point[1], &f[3], maxi, & length[length_offset], maxfunc, maxdeep, n, &c__1, jones); } /* dirinit_ */ /* +-----------------------------------------------------------------------+ */ /* | SUBROUTINE DIRInitList | */ /* | Initialise the list. | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirinitlist_(integer *anchor, integer *free, integer * point, doublereal *f, integer *maxfunc, const integer *maxdeep) { /* System generated locals */ integer i__1; /* Local variables */ integer i__; /* f -- values of functions. */ /* anchor -- anchors of lists with deep i */ /* point -- lists */ /* free -- first free position */ /* Parameter adjustments */ f -= 3; --point; ++anchor; /* Function Body */ i__1 = *maxdeep; for (i__ = -1; i__ <= i__1; ++i__) { anchor[i__] = 0; /* L10: */ } i__1 = *maxfunc; for (i__ = 1; i__ <= i__1; ++i__) { f[(i__ << 1) + 1] = 0.; f[(i__ << 1) + 2] = 0.; point[i__] = i__ + 1; /* point(i) = 0 */ /* L20: */ } point[*maxfunc] = 0; *free = 1; } /* dirinitlist_ */ /* +-----------------------------------------------------------------------+ */ /* | | */ /* | SUBROUTINE DIRPREPRC | */ /* | | */ /* | Subroutine DIRpreprc uses an afine mapping to map the hyper-box given | */ /* | by the constraints on the variable x onto the n-dimensional unit cube.| */ /* | This mapping is done using the following equation: | */ /* | | */ /* | x(i)=x(i)/(u(i)-l(i))-l(i)/(u(i)-l(i)). | */ /* | | */ /* | DIRpreprc checks if the bounds l and u are well-defined. That is, if | */ /* | | */ /* | l(i) < u(i) forevery i. | */ /* | | */ /* | On entry | */ /* | | */ /* | u -- A double-precision vector of length n. The vector | */ /* | containing the upper bounds for the n independent | */ /* | variables. | */ /* | | */ /* | l -- A double-precision vector of length n. The vector | */ /* | containing the lower bounds for the n independent | */ /* | variables. | */ /* | | */ /* | n -- An integer. The dimension of the problem. | */ /* | | */ /* | On return | */ /* | | */ /* | xs1 -- A double-precision vector of length n, used for scaling | */ /* | and unscaling the vector x. | */ /* | | */ /* | xs2 -- A double-precision vector of length n, used for scaling | */ /* | and unscaling the vector x. | */ /* | | */ /* | | */ /* | oops -- An integer. If an upper bound is less than a lower | */ /* | bound or if the initial point is not in the | */ /* | hyper-box oops is set to 1 and iffco terminates. | */ /* | | */ /* +-----------------------------------------------------------------------+ */ /* Subroutine */ void direct_dirpreprc_(doublereal *u, doublereal *l, integer *n, doublereal *xs1, doublereal *xs2, integer *oops) { /* System generated locals */ integer i__1; /* Local variables */ integer i__; doublereal help; /* Parameter adjustments */ --xs2; --xs1; --l; --u; /* Function Body */ *oops = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* +-----------------------------------------------------------------------+ */ /* | Check if the hyper-box is well-defined. | */ /* +-----------------------------------------------------------------------+ */ if (u[i__] <= l[i__]) { *oops = 1; return; } /* L20: */ } /* +-----------------------------------------------------------------------+ */ /* | Scale the initial iterate so that it is in the unit cube. | */ /* +-----------------------------------------------------------------------+ */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { help = u[i__] - l[i__]; xs2[i__] = l[i__] / help; xs1[i__] = help; /* L50: */ } } /* dirpreprc_ */ /* Subroutine */ void direct_dirheader_(FILE *logfile, integer *version, doublereal *x, integer *n, doublereal *eps, integer *maxf, integer * maxt, doublereal *l, doublereal *u, integer *algmethod, integer * maxfunc, const integer *maxdeep, doublereal *fglobal, doublereal *fglper, integer *ierror, doublereal *epsfix, integer *iepschange, doublereal * volper, doublereal *sigmaper) { /* System generated locals */ integer i__1; /* Local variables */ integer imainver, i__, numerrors, isubsubver, ihelp, isubver; (void) maxdeep; (void) ierror; /* +-----------------------------------------------------------------------+ */ /* | Variables to pass user defined data to the function to be optimized. | */ /* +-----------------------------------------------------------------------+ */ /* Parameter adjustments */ --u; --l; --x; /* Function Body */ if (logfile) fprintf(logfile, "------------------- Log file ------------------\n"); numerrors = 0; *ierror = 0; imainver = *version / 100; ihelp = *version - imainver * 100; isubver = ihelp / 10; ihelp -= isubver * 10; isubsubver = ihelp; /* +-----------------------------------------------------------------------+ */ /* | JG 01/13/01 Added check for epsilon. If epsilon is smaller 0, we use | */ /* | the update formula from Jones. We then set the flag | */ /* | iepschange to 1, and store the absolute value of eps in | */ /* | epsfix. epsilon is then changed after each iteration. | */ /* +-----------------------------------------------------------------------+ */ if (*eps < 0.) { *iepschange = 1; *epsfix = -(*eps); *eps = -(*eps); } else { *iepschange = 0; *epsfix = 1e100; } /* +-----------------------------------------------------------------------+ */ /* | JG 07/16/01 Removed printout of contents in cdata(1). | */ /* +-----------------------------------------------------------------------+ */ /* write(logfile,*) cdata(1) */ if (logfile) { fprintf(logfile, "DIRECT Version %d.%d.%d\n" " Problem dimension n: %d\n" " Eps value: %e\n" " Maximum number of f-evaluations (maxf): %d\n" " Maximum number of iterations (MaxT): %d\n" " Value of f_global: %e\n" " Global percentage wanted: %e\n" " Volume percentage wanted: %e\n" " Measure percentage wanted: %e\n", imainver, isubver, isubsubver, *n, *eps, *maxf, *maxt, *fglobal, *fglper, *volper, *sigmaper); fprintf(logfile, *iepschange == 1 ? "Epsilon is changed using the Jones formula.\n" : "Epsilon is constant.\n"); fprintf(logfile, *algmethod == 0 ? "Jones original DIRECT algorithm is used.\n" : "Our modification of the DIRECT algorithm is used.\n"); } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (u[i__] <= l[i__]) { *ierror = -1; if (logfile) fprintf(logfile, "WARNING: bounds on variable x%d: " "%g <= xi <= %g\n", i__, l[i__], u[i__]); ++numerrors; } else { if (logfile) fprintf(logfile, "Bounds on variable x%d: " "%g <= xi <= %g\n", i__, l[i__], u[i__]); } /* L1010: */ } /* +-----------------------------------------------------------------------+ */ /* | If there are to many function evaluations or to many iteration, note | */ /* | this and set the error flag accordingly. Note: If more than one error | */ /* | occurred, we give out an extra message. | */ /* +-----------------------------------------------------------------------+ */ if (*maxf + 20 > *maxfunc) { if (logfile) fprintf(logfile, "WARNING: The maximum number of function evaluations (%d) is higher than\n" " the constant maxfunc (%d). Increase maxfunc in subroutine DIRECT\n" " or decrease the maximum number of function evaluations.\n", *maxf, *maxfunc); ++numerrors; *ierror = -2; } if (*ierror < 0) { if (logfile) fprintf(logfile, "----------------------------------\n"); if (numerrors == 1) { if (logfile) fprintf(logfile, "WARNING: One error in the input!\n"); } else { if (logfile) fprintf(logfile, "WARNING: %d errors in the input!\n", numerrors); } } if (logfile) fprintf(logfile, "----------------------------------\n"); if (*ierror >= 0) { if (logfile) fprintf(logfile, "Iteration # of f-eval. minf\n"); } /* L10005: */ } /* dirheader_ */ /* Subroutine */ void direct_dirsummary_(FILE *logfile, doublereal *x, doublereal * l, doublereal *u, integer *n, doublereal *minf, doublereal *fglobal, integer *numfunc, integer *ierror) { /* Local variables */ integer i__; /* Parameter adjustments */ --u; --l; --x; (void) ierror; /* Function Body */ if (logfile) { fprintf(logfile, "-----------------------Summary------------------\n" "Final function value: %g\n" "Number of function evaluations: %d\n", *minf, *numfunc); if (*fglobal > -1e99) fprintf(logfile, "Final function value is within %g%% of global optimum\n", 100*(*minf - *fglobal) / MAX(1.0, fabs(*fglobal))); fprintf(logfile, "Index, final solution, x(i)-l(i), u(i)-x(i)\n"); for (i__ = 1; i__ <= *n; ++i__) fprintf(logfile, "%d, %g, %g, %g\n", i__, x[i__], x[i__]-l[i__], u[i__] - x[i__]); fprintf(logfile, "-----------------------------------------------\n"); } } /* dirsummary_ */ nlopt-2.6.1/src/algs/direct/README000066400000000000000000000031351345435414600165360ustar00rootroot00000000000000The DIRECT algorithm (DIviding RECTangles) is a derivative-free global optimization algorithm invented by Jones et al.: D. R. Jones, C. D. Perttunen, and B. E. Stuckmann, "Lipschitzian optimization without the lipschitz constant," J. Optimization Theory and Applications, vol. 79, p. 157 (1993). This is a deterministic-search algorithm based on systematic division of the search domain into smaller and smaller hyperrectangles. The implementation is based on the 1998-2001 Fortran version by J. M. Gablonsky at North Carolina State University, converted to C by Steven G. Johnson. The Fortran source was downloaded from: http://www4.ncsu.edu/~ctk/SOFTWARE/DIRECTv204.tar.gz Gablonsky et al implemented a modified version of the original DIRECT algorithm, as described in: J. M. Gablonsky and C. T. Kelley, "A locally-biased form of the DIRECT algorithm," J. Global Optimization 21 (1), p. 27-37 (2001). Both the original Jones algorithm (NLOPT_GN_DIRECT) and the Gablonsky modified version (NLOPT_GN_DIRECT_L) are implemented and available from the NLopt interface. The Gablonsky version makes the algorithm "more biased towards local search" so that it is more efficient for functions without too many local minima. Also, Gablonsky et al. extended the algorithm to handle "hidden constraints", i.e. arbitrary nonlinear constraints. In NLopt, a hidden constraint is represented by returning NaN (or Inf, or HUGE_VAL) from the objective function at any points violating the constraint. Further information on the DIRECT algorithm and Gablonsky's implementation can be found in the included userguide.pdf file. nlopt-2.6.1/src/algs/direct/direct-internal.h000066400000000000000000000126141345435414600211150ustar00rootroot00000000000000#ifndef DIRECT_INTERNAL_H #define DIRECT_INTERNAL_H #include #include #include #include "direct.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef int integer; typedef double doublereal; typedef direct_objective_func fp; #define ASRT(c) if (!(c)) { fprintf(stderr, "DIRECT assertion failure at " __FILE__ ":%d -- " #c "\n", __LINE__); exit(EXIT_FAILURE); } #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* DIRsubrout.c */ extern void direct_dirheader_( FILE *logfile, integer *version, doublereal *x, integer *n, doublereal *eps, integer *maxf, integer * maxt, doublereal *l, doublereal *u, integer *algmethod, integer * maxfunc, const integer *maxdeep, doublereal *fglobal, doublereal *fglper, integer *ierror, doublereal *epsfix, integer *iepschange, doublereal * volper, doublereal *sigmaper); extern void direct_dirinit_( doublereal *f, fp fcn, doublereal *c__, integer *length, integer *actdeep, integer *point, integer *anchor, integer *free, FILE *logfile, integer *arrayi, integer *maxi, integer *list2, doublereal *w, doublereal *x, doublereal *l, doublereal *u, doublereal *minf, integer *minpos, doublereal *thirds, doublereal *levels, integer *maxfunc, const integer * maxdeep, integer *n, integer *maxor, doublereal *fmax, integer * ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata, integer jones, double starttime, double maxtime, int *force_stop); extern void direct_dirinitlist_( integer *anchor, integer *free, integer * point, doublereal *f, integer *maxfunc, const integer *maxdeep); extern void direct_dirpreprc_(doublereal *u, doublereal *l, integer *n, doublereal *xs1, doublereal *xs2, integer *oops); extern void direct_dirchoose_( integer *anchor, integer *s, integer *actdeep, doublereal *f, doublereal *minf, doublereal epsrel, doublereal epsabs, doublereal *thirds, integer *maxpos, integer *length, integer *maxfunc, const integer *maxdeep, const integer *maxdiv, integer *n, FILE *logfile, integer *cheat, doublereal *kmax, integer *ifeasiblef, integer jones); extern void direct_dirdoubleinsert_( integer *anchor, integer *s, integer *maxpos, integer *point, doublereal *f, const integer *maxdeep, integer *maxfunc, const integer *maxdiv, integer *ierror); extern integer direct_dirgetmaxdeep_(integer *pos, integer *length, integer *maxfunc, integer *n); extern void direct_dirget_i__( integer *length, integer *pos, integer *arrayi, integer *maxi, integer *n, integer *maxfunc); extern void direct_dirsamplepoints_( doublereal *c__, integer *arrayi, doublereal *delta, integer *sample, integer *start, integer *length, FILE *logfile, doublereal *f, integer *free, integer *maxi, integer *point, doublereal *x, doublereal *l, doublereal *minf, integer *minpos, doublereal *u, integer *n, integer *maxfunc, const integer *maxdeep, integer *oops); extern void direct_dirdivide_( integer *new__, integer *currentlength, integer *length, integer *point, integer *arrayi, integer *sample, integer *list2, doublereal *w, integer *maxi, doublereal *f, integer *maxfunc, const integer *maxdeep, integer *n); extern void direct_dirinsertlist_( integer *new__, integer *anchor, integer *point, doublereal *f, integer *maxi, integer *length, integer *maxfunc, const integer *maxdeep, integer *n, integer *samp, integer jones); extern void direct_dirreplaceinf_( integer *free, integer *freeold, doublereal *f, doublereal *c__, doublereal *thirds, integer *length, integer *anchor, integer *point, doublereal *c1, doublereal *c2, integer *maxfunc, const integer *maxdeep, integer *maxdim, integer *n, FILE *logfile, doublereal *fmax, integer jones); extern void direct_dirsummary_( FILE *logfile, doublereal *x, doublereal *l, doublereal *u, integer *n, doublereal *minf, doublereal *fglobal, integer *numfunc, integer *ierror); extern integer direct_dirgetlevel_( integer *pos, integer *length, integer *maxfunc, integer *n, integer jones); extern void direct_dirinfcn_( fp fcn, doublereal *x, doublereal *c1, doublereal *c2, integer *n, doublereal *f, integer *flag__, void *fcn_data); /* DIRserial.c / DIRparallel.c */ extern void direct_dirsamplef_( doublereal *c__, integer *arrayi, doublereal *delta, integer *sample, integer *new__, integer *length, FILE *logfile, doublereal *f, integer *free, integer *maxi, integer *point, fp fcn, doublereal *x, doublereal *l, doublereal * minf, integer *minpos, doublereal *u, integer *n, integer *maxfunc, const integer *maxdeep, integer *oops, doublereal *fmax, integer * ifeasiblef, integer *iinfesiblef, void *fcn_data, int *force_stop); /* DIRect.c */ extern void direct_direct_( fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs, integer *maxf, integer *maxt, double starttime, double maxtime, int *force_stop, doublereal *minf, doublereal *l, doublereal *u, integer *algmethod, integer *ierror, FILE *logfile, doublereal *fglobal, doublereal *fglper, doublereal *volper, doublereal *sigmaper, void *fcn_data); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* DIRECT_INTERNAL_H */ nlopt-2.6.1/src/algs/direct/direct.h000066400000000000000000000026761345435414600173120ustar00rootroot00000000000000#ifndef DIRECT_H #define DIRECT_H #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef double (*direct_objective_func)(int n, const double *x, int *undefined_flag, void *data); typedef enum { DIRECT_ORIGINAL, DIRECT_GABLONSKY } direct_algorithm; typedef enum { DIRECT_INVALID_BOUNDS = -1, DIRECT_MAXFEVAL_TOOBIG = -2, DIRECT_INIT_FAILED = -3, DIRECT_SAMPLEPOINTS_FAILED = -4, DIRECT_SAMPLE_FAILED = -5, DIRECT_MAXFEVAL_EXCEEDED = 1, DIRECT_MAXITER_EXCEEDED = 2, DIRECT_GLOBAL_FOUND = 3, DIRECT_VOLTOL = 4, DIRECT_SIGMATOL = 5, DIRECT_MAXTIME_EXCEEDED = 6, DIRECT_OUT_OF_MEMORY = -100, DIRECT_INVALID_ARGS = -101, DIRECT_FORCED_STOP = -102 } direct_return_code; #define DIRECT_UNKNOWN_FGLOBAL (-HUGE_VAL) #define DIRECT_UNKNOWN_FGLOBAL_RELTOL (0.0) extern direct_return_code direct_optimize( direct_objective_func f, void *f_data, int dimension, const double *lower_bounds, const double *upper_bounds, double *x, double *minf, int max_feval, int max_iter, double start, double maxtime, double magic_eps, double magic_eps_abs, double volume_reltol, double sigma_reltol, int *force_stop, double fglobal, double fglobal_reltol, FILE *logfile, direct_algorithm algorithm); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* DIRECT_H */ nlopt-2.6.1/src/algs/direct/direct_wrap.c000066400000000000000000000067261345435414600203360ustar00rootroot00000000000000/* C-style API for DIRECT functions. SGJ (August 2007). */ #include "direct-internal.h" /* Perform global minimization using (Gablonsky implementation of) DIRECT algorithm. Arguments: f, f_data: the objective function and any user data -- the objective function f(n, x, undefined_flag, data) takes 4 args: int n: the dimension, same as dimension arg. to direct_optimize const double *x: array x[n] of point to evaluate int *undefined_flag: set to 1 on return if x violates constraints or don't touch otherwise void *data: same as f_data passed to direct_optimize return value = value of f(x) dimension: the number of minimization variable dimensions lower_bounds, upper_bounds: arrays of length dimension of variable bounds x: an array of length dimension, set to optimum variables upon return minf: on return, set to minimum f value magic_eps, magic_eps_abs: Jones' "magic" epsilon parameter, and also an absolute version of the same (not multipled by minf). Jones suggests setting this to 1e-4, but 0 also works... max_feval, max_iter: maximum number of function evaluations & DIRECT iters volume_reltol: relative tolerance on hypercube volume (0 if none) sigma_reltol: relative tolerance on hypercube "measure" (??) (0 if none) fglobal: the global minimum of f, if known ahead of time -- this is mainly for benchmarking, in most cases it is not known and you should pass DIRECT_UNKNOWN_FGLOBAL fglobal_reltol: relative tolerance on how close we should find fglobal -- ignored if fglobal is DIRECT_UNKNOWN_FGLOBAL logfile: an output file to write diagnostic info to (NULL for no I/O) algorithm: whether to use the original DIRECT algorithm (DIRECT_ORIGINAL) or Gablonsky's "improved" version (DIRECT_GABLONSKY) */ direct_return_code direct_optimize( direct_objective_func f, void *f_data, int dimension, const double *lower_bounds, const double *upper_bounds, double *x, double *minf, int max_feval, int max_iter, double start, double maxtime, double magic_eps, double magic_eps_abs, double volume_reltol, double sigma_reltol, int *force_stop, double fglobal, double fglobal_reltol, FILE *logfile, direct_algorithm algorithm) { integer algmethod = algorithm == DIRECT_GABLONSKY; integer ierror; doublereal *l, *u; int i; /* convert to percentages: */ volume_reltol *= 100; sigma_reltol *= 100; fglobal_reltol *= 100; /* make sure these are ignored if <= 0 */ if (volume_reltol <= 0) volume_reltol = -1; if (sigma_reltol <= 0) sigma_reltol = -1; if (fglobal == DIRECT_UNKNOWN_FGLOBAL) fglobal_reltol = DIRECT_UNKNOWN_FGLOBAL_RELTOL; if (dimension < 1) return DIRECT_INVALID_ARGS; l = (doublereal *) malloc(sizeof(doublereal) * dimension * 2); if (!l) return DIRECT_OUT_OF_MEMORY; u = l + dimension; for (i = 0; i < dimension; ++i) { l[i] = lower_bounds[i]; u[i] = upper_bounds[i]; } direct_direct_(f, x, &dimension, &magic_eps, magic_eps_abs, &max_feval, &max_iter, start, maxtime, force_stop, minf, l, u, &algmethod, &ierror, logfile, &fglobal, &fglobal_reltol, &volume_reltol, &sigma_reltol, f_data); free(l); return (direct_return_code) ierror; } nlopt-2.6.1/src/algs/direct/tstc.c000066400000000000000000000020341345435414600167740ustar00rootroot00000000000000#include #include #include "direct.h" /* has two global minima at (0.09,-0.71) and (-0.09,0.71), plus 4 additional local minima */ static int cnt=0; double tst_obj(int n, const double *xy, int *undefined_flag, void *unused) { double x, y, f; x = xy[0]; y = xy[1]; f = ((x*x)*(4-2.1*(x*x)+((x*x)*(x*x))/3) + x*y + (y*y)*(-4+4*(y*y))); printf("feval:, %d, %g, %g, %g\n", ++cnt, x,y, f); return f; } int main(int argc, char **argv) { int n = 2; double x[2], l[2], u[2]; long int maxits = 0; int info; double minf; int force_stop = 0; maxits = argc < 2 ? 100 : atoi(argv[1]); l[0] = -3; l[1] = -3; u[0] = 3; u[1] = 3; info = direct_optimize(tst_obj, NULL, n, l, u, x, &minf, maxits, 500, 0, 0, 0, 0, 0.0, -1.0, &force_stop, DIRECT_UNKNOWN_FGLOBAL, 0, stdout, DIRECT_GABLONSKY); printf("min f = %g at (%g,%g) after %d evals, return value %d\n", minf, x[0], x[1], cnt, info); return EXIT_SUCCESS; } nlopt-2.6.1/src/algs/direct/userguide.pdf000066400000000000000000037266751345435414600203750ustar00rootroot00000000000000%PDF-1.4 %쏢 5 0 obj <> stream x]S]O@|#Jr_GR'6mnٙٙ?Fhҽ˵&۩G[ۓ1Hԛ"RKF8%QcH7U$ߋp8hfmqr!Zp4%.Hep&(CY"}. ~/OTQATC]X菈qByԲy?tbdgeC0;B2[%;48NhP<dɌ:coc3})s.FE'hؤ2c3ﺾ];j$7q> 'P.nꚱńJwi 0bIuQ]E6肮NT 4,LJzHFpZ!Gy;H{iO+RƹV{ *j%𝜆 WdQ16X-'Ovendstream endobj 6 0 obj 485 endobj 78 0 obj <> stream xZ]o6}7# aPs5͒Hk{pXղ]YQ$%]Zr`iFP$/e{Ͻ>F{~~'m/տySh5M/I?! ioo5# TQopG.L(G|;~gzTI]y˳6I>2_ FC>TW!p-y>zWVLi10$H s_H56l0 n'j-77=Cނ|m8 Q/@ڐn Nj \YiD[~a2NDrx;͒^Pj뫽BPZ$P3YS wSIY]]&oռA[#Z3mz6.DFmFݿa}D1!еtHܫ6 1^ːWO:P vGzP87) :h)H!~(MJe39FFa&`(Ɲ"QIH1֤(L7K\ :K '4ApYӫPQ:1F#s#k_gXg hT.фF3Eђ(T⡔\(zYrΒ|Y WHxwTA0 ZiMI ʍ VTT.lPݫߚڣu鸅qR';2.ˠ"V+(ELqŰEEm~*3pV?<4K0 ^g2xgݭ-?MGJW ;'7y/ >Kht3,Y.d֫.5DSFDi:m`ARI.|Y~<NpN=> hqLyvD;T6pS(Hx1VvXS`-Dfb0htq!d,&d*noKm_{zWAQP[hPOuWJ~TMќ:W#=6@oLy؈ }kd+Pl|@3e""i'S98 u_S(1\~NpXM,;Qp,!ok0CR{dH[}ºfb/@ݞ i(疃8ҭ!YbSPxN(\7sψ'DFN\?mv;<6.A4i5I"YZ=弌yc`.^'^_$5'XX:@# eʚ vJe}@7zѕG#od}v"Kˉu~.3sX˝Wj_fs.d@'>׈w"Z˱4VY¸pԙ}4?tiOerG'qدendstream endobj 79 0 obj 1772 endobj 203 0 obj <> stream xW]o6ݳ0`A^E">mM.ҥ<yPdVG_IWtCsϹ|]BmW1Iaͯn,~֣E$nB.yKgԦ%ah7]\.N_aEḊ \XYΓG\9c$gF?7iF4.[:uǀ^IhdY=Bpۇi !NsmODBM[lFKΪ:yQ_8IWƃr]Hw)S(EXEô:}ʚ*+aTXQ\Q]uO?º TXN@c$'~Cb:,}XU_<ɡppI\L6nQz)KΘ b Oi%P…4N̘bC|jŅ)"M\S?fA# ;`$@@u]ā+;zgTmhQT^\lH]qTN)72ɻ! 1TTu8?oҕL"rbcǍ+4m:7 '])o^.>U$'Uin jLyI7G$>7j*mZHOa~d0pk)mlҥ$UٴuD|cxj:1(i粍8SE'FqjfEXu>Y}NIPjsdš_\mݥ֦OϻS8/O/vd[2p]!yEaplbXgE\+d JE&D'yׇf-p3jF.Drg%1ɡM9ܷg}vC;KAwZӄ@oHfڼcj} Dfb\9:6&ޯ`7 6:mҸNp6P2ntXKLExZN \~N{Ӹr]V4s=KAoV ҷFy Cqf'>SI'xB T nDb([W 6gi134iAUfx@K&t%' eZ!!涋״YC5-nﲰeMGt83?s *PTiFç66q]o%p݀Go{a& ЧR \W?#֩9`߃lbuB ߞ|m@ߥsmGcIDIoQt&_CI{ PnM\Ӯx 1NW Jm%Ye<@:YZ]8G8x=읯u#n;ئs{zSbLЉ ݰ>YEFgendstream endobj 204 0 obj 1649 endobj 225 0 obj <> stream xZK>6KN9sA^k!8LÌnMj-wf]|A`,]IUW_qHzb;%ُgTX% *s1-.o]P\%Iܟ-W<fT) Hļ##8Q>-U~}l7zM YY̤JKFr䰄*Ug3 +^-q8_$IH-7ߜU,KKx+g` VT{k'h|InORJr7YpY38xM:kJ%)-OC'M+x5pfx롟nsʬl( anO6 o07?-=V*R=z֧aVttMQ35醃ȗ qIfOڟ }3LaLhNEqD9wJRl,e1 m@+*G;TȀ}̈4x1Z͘Y!歂Kg}8tY %( q}CB*~O#fr앶r#()k.W6ףA˾ P9VD4Wi RTrD"We)ÈViQxfQN1܍us?7FAu0gkwyb$;#]٨b8qޤ_#_:/(ĮYF<,OxWիP$i񨰯FmG,0~/$ScEATpog=58uv8a AЊLI ʬ+h`B/ Ko8nW!E%+~MNȑCaG?(ޚe,r\b:_:H)5MtfMNGHUX d%"Wm. &"d#qvFsB5H:p #!ȭ8v ?$EIꞈ 6oX/e 9v' r0RE‘2y`NZeجfTL~jد) K(ӰWA(qJ;N=6ӱ'(0`KWg3*H9;U䪠jփ_i?_Rj9wjbHS!o~7lw;tH%(VmTԹW4qNeUF`S@@BZFuE^/i.*J@5 k <ܼ Df$weug 59  *{37HVI?ĸ½8a_@΄luB&ఇ\x/T(^lx$jKO:0[NIM/**pP(ё!OoMr&{zL&IS0>=L];k~C?q8*hug6,:u'qH]@zGT8q# &OxajE&0.}4(#qmzPDnh%If1d9; 6 !o"i  W=gqՀ# a"2C[VkĸlVcd1|)a-;+@ w]g) p ~JO}0tCE-ʠXvJ RLjVejgxQ|@Bǭh?Į4i҂9`MCgK0*YTߴAK;Ef^G-E6"iaQ&iQ;}$S(e?OKS 7#2nR_DS aOOpG ,Js`MZ^>S T/(W2_> cȴl}<{e5GX`ssk g g^xZNZ NWWc:AurZ*_)P8'RS]y")}\%2MUUY*K|b9ϥxB~4f |m>O8|VYu<5w]%z4 ONZ*U&NSrwJ}tj53$9N4W4}NwXr{0QB=e2dS7|@& YĐ?;t;Z)~0͍Dd Fo\ڛxpэsplm\yY<\Os-@>sX%j3Aan4> stream xXnF3яD+K2}p*։m6Y$"p /2{̙}FguxWmU>zBhuxITX 9 )H2$JU^,_|zVdtX!8LԺ:}`$RS }ӖMYfGuiѸ!K}s2"ӐK 8b2,άWf5:IdĄH4a$=!pn2^:ԨժVQI8~])hVNI:]1>/ ';5"8uT='seoh,+6gk'˭^ ]U;}W.0i\2 <] S"̘AauFxrrH #fgD|<_.M)L 9aiןԇkd}7AEۓr/]!6E(wNF8 'sEfSުݾRr C<pQT'`1h2X,î`q`9Z^.Wjf BN2%>\)Z1h &Ƕ(m,qI"#*Юhy[p;|a@k8čt(#tyC>eeO ) =Y_J]!o~_e|+'l Ujv| !NLS~[}"+G)l?M@<-귟dXu 5Ij.iq=xw԰CPE{?"i !tq,v,iJ_wHOe a(3ZWƏ rIܜ:TweJ_uҤYL |C ܜ'}IN}jZg@o.{H/i9I""ݏVH#lh1'*p?6 Mϼ,k9h_؜$ٺjʢ5:/aEIvta94l!2GM"^a ![]^mmp sQ%³c/SZ%` yj @D.!]sz q[6;6%8Fq2C%t?֛ekL⁩j9F UW4;k0n4fb 'I7`b&wcuIUqPWDK`>5H{+~3dH_cM C90/@TM]pi^M;Ȧ-Q:G8zz=G NXz\_g~o4rbn2W "P1D{q.OpOl2zNȩa3[D3M*@](=YGӲp5(蠪ѡY5DNܒ~XALXpk[ *wNb/4:Pd2[2UX͖L^{q=& etL@HM=} ECAv$#ǩ;S._C3Wۅ^C2/N`H- :]LЧaz)=jtDDUrߧ7y{ÏP{C[,RɺAskw׸zi lnOntF o kfl$=Q21"dlB(X]E5(~0o(eC  endstream endobj 325 0 obj 1804 endobj 351 0 obj <> stream xYێFga>Ҁa_xCxlg&<%qM2IٟjZƹnԩS۟0`^~av6v,߻٧<>xW) 33t< M8cAz|vl_~!TVPu2cڢѭIXarSX8L$HY_q8H%,TDm6;9ٛ'Oa$I5F!|9Y\n~wc{sABTp!슶 ևQWe"]ژm;w?VE㡚 CcSѴe AUoB?M^UE˽-DuNgq w{sy52u!`]5 38^ M084$Kt3ptq|k/u+<b@,8mɈƦY0q#W siSMYTbcifH# {|q#S>4vҞɟ嶮i  3 i(4L:t0DG0u(\ߔM&VB8/)*re__~K =BF)+eG'D Ի&*}}4"֕abFYT 9&G6PdŃ|,FuNFhMabS2$1}2* 0% $A\=,F@Aw0jtOE=ֽ:o T#Y9嵳)x|&4 ?W ٦|g.'d̩4d7je_ˀC@-5yȤ4>U @:HBD! z2=Yű_w{à_e[7٤N QA3Br‒S54>`EHeTyi, _2!IAS8 TͨJsBY1Fh ;eϋ R' EJE\f TxjBP$sT_Ĉ*sݍ?xr&B@NgBWI0jpu^hEcn4|ڊZߩ:q;gyKX7׶M]ǜ{]8y_o#RmWXY"bgNҡ4 %«܊܊a]~zSlZEA&g䧇Tk$S&5BTc2_(m.WVܕG8}"u-w6H9V%(Mўp59]L\T_P*Iy6UL{ ):TSt|U'wfokxRxK&R@/w ڌe "ZEMzP;n`z) ⥝xtIzQ)RNLݧsq4v'V*׬ſˬq%؀Ax0C%r)o%;}6.^[=qzs8ɤ%1Gw/K;> >&Br%ի۟&d4Q}J( RN20vȽc~Es2׃WP*<5~VNmUB'RA/)T#.vYBkc<Nh!nj"O&LSVswFjٮ?ϫݡms6,9PwȄ,ݖhI(I{דhU-wt'p*7y1]ȪeٖA a@>.}ʵ-_[Wi]ӗH:fwa?Ä:{HJμ:@2*pS1y9p.u12$!OKyەQ)vW."l Gx^h0wQ;:7%j6rR}t=ofUendstream endobj 352 0 obj 2111 endobj 374 0 obj <> stream xZێ`oУX1!xaB(1EʼxOUbSٵX,j.眪O+c+-Nw~cbJSV 4^Na+|/MWqWOݗxxezXJ97^~gx7nan:ODpop e0Q/Γ3Rk`U𐓌8Hˍh+:蠟h?g?~RЌe&>fRu"rÓCqCċ#9vrt7K9ܸz>_ ]pluϰ$ƩҍrlDZvPPdc$ixxjzQy{<hr+T!^l=EѲ)h+"$bc<0vߴ#$]YT2Y1F(Y;IҠGaE!c06WW̢S—@g! 3XHD G9 K2M&e;,S^T:cYM1l$- ΛFӌ }J9sL AKp\rXqq!;nڳ}Ir"L蕣o!KGr"M2N/)WjZ Ư Aqt.ʼGƤZ]]<Yv,=Р[&m0G2=Q%Pz b0)N9cE$l;r>^~mtgG8"޿FWo~SPW6B<ȕa%,cj1#Sof_s1BT4⨒~_TOz  |h00qhJLyr(#l%YAj԰>%MFEJG d/zɺ & aONR֔ ɺʢ2JH=6Md{7Xah{ g7b|F!r-ܳS|19Z Gi9{t㾈t'd*_(Aڹo(پqڸӝzP.VU_-kY{1ZAUpP f:Wy#'M6#g茓li{E1_cmz)2Z$.z}R9٬[ʖw#],lBE ߌ?M=po=\|U4/qX6saܿp 7oa֞ 1tkJ6]9 ז~P(^%j<(atcV66[\>ʂ]]leD;ߵ_Ff)v~PVQz7Lhbs+Аn9⑄`J9k;n꾐*sR닯>ݿ)Uzendstream endobj 375 0 obj 2778 endobj 386 0 obj <> stream xZs6&M$]_oT7}(9tH*"$Mg:.o(I?j?PDaDG03R-73D$1+Ih|xfyoľQK'bH%KRC˧ELHYuLy\|I,,|+> )^)9-~S-HrCP/$,1"R8.]tӟ~UVo1o:R̹;A5t8up'ypH˲b+,#qf'i4] |'q ޗu4 KH0wx^ ծjxdHĹ{[G.eWy[iw=p EHVas{b1e"`^F"M Z= cӝަZbgm hvj>~Jn#ܴ}1J\Z)E AeSZaEr3UmFKV\Vn7Fa#zI3'>lZQz'hǾ^5R&R;FJCkyПLc3GcݡR c'w06f^.--q(/hL1hd؍ 39{(qnPAvx[-SI@7_t@4(qx(L}ѵ4QUV*J}(K2W˕#`⃦osC.۴Z]HI2$`fB*CLdHFP$p p E&ѕI a>osLGWͤ^tF̹?OѶmQ[oFhKYPӢ{DO=4vdxbA'z-xˮSdapr4$NMTkTP"p<x@jBҏվiQi/a|V`|)j++xUHQmJ̳bG:ޜޮ^W٪ k\:-PP(ٳ>\oڨi܎K'-Qs:-Л}S?S8j!elCWiQq{TMJ7li4Po@SPOϪI8Ko[KiB/׷24g ۺWSj0' C"&bm6/02tz }~WUqUqz~y6 W= <4o+B&`L .J+SR"5D"~BNVa!w%y [KS  z*%萃&h*7YG_}Z(d$Q8+ ˀy"쩏F$);Rm0C|r+H4ЗGz;P K硸vNC!?'"QॄA'(/+9@jrwbG`ku[vĖv4-4N8ѕ& E zډ&PUZD`Iv):=RdIH BpBgyp oCa;Qt{ζ(:t j-;} ᶖTpuw '6$2U& :w}f|=j2wccP>wگ͍L;e۹otumq}ضW,Bf5OޮׯƣG6i]wpBWk4b誫ԞKCnRH8w$&#T $(%WcPiXچ+rqOdhϽiWW=endstream endobj 387 0 obj 2544 endobj 410 0 obj <> stream xY[6Q`=@̈u˶M;m]Ax tAȶRYrdi&i|oD{[Xt);E 7i?/;grAl , 6zuEJCeASfX~~sf`A(/b $OB\viJ(s/~4,%y3ѿp}6) de׵(Gs~oOIF Q}/;"wHYk)Zt*ljVg=k}Wrq+Ō0]/OgC!g!IGloV,d]Wޓn~XX OP*彍Wz(!91ZPt,NAs 5>k뺕PMպ$ъ)q$÷D>cy~Gx!`W 9hEBR mwݍYYG$U_ˠ19`9N\;01KVME<K\Sa2 aLE/ufەŹ[cNX54۹aaBJGsMWE]J JrlOxp0AO&0Cp+ìjy9Frݢ.ı S]$&D[5Cg#E4#4 QPZ4-ǭTjQm"@Q4Fԭ+QXHZqCa1@p;`J˝[̷8KHrI'DB Hd9{yE{譑Hx*1S$zgN>Ҧg8`UɊ@_֌1/s&ESofVGi|pg^UN6R &r,Ǡ Y1;VMWPMKj%J~ {]bW>xۦ @%N'|\`s'z%al<.gP.6.!F{ a6q,X]۞bhu3f8>V@'Q.;YNMצ|lTK2"Q;xӞzIDLCDq)AEb5X|&iu|< |6ߔR԰8Esi׈.%C%*`dre\tbhrx)軡\ȏ:BQD=IF; 5DV$*cLT%S?Q~Ot~ųn(L^Bs+Sq n))4)b~[jVZ9\5{ؿ,?H)/=4/i)KM,9Sd(¹v!_1ȷkqF6:O_fz]Zs[R1.L춺 j2cqmn^uW+4!Zݹf&\yHp!Gh5S3ɹ\W#`^[9GS@g#j3Hu8xnϱ8ir] W+X:ijz;NuUf^嶱Tv&{ /vF}yXt3FrY01iVOӚJgfh.ᑜ4S}Pi ۦ81Bu$N=H{3okMn2}7 irc ecejoTA{sSUԴdr[KO?7q4ECcY8J5C;**nON( 3,9j2 ]PE'G}|hAR*t4ٵC8vgCvgO3hF{C|endstream endobj 411 0 obj 2223 endobj 424 0 obj <> stream xXn6}_#q7HZ䥉@6ޢ(}.[ŗ;HZrA`gΜ~vAayO`DjS. [2FI,,݇Ooퟰ#e}buLA҈v׶hjLKSc9 |Gn8Z$NPVm}'+.Iz8=U[=\o&[XBm2팩`\mBn0!1G 6P3-T,ыP|7$1':`֍=q,,x:0P1QGkMˁrP7!V+]Ok6% MQe1C]־Y\} uCgy ҴhF eOU7[up1s? u8qLc|7Ə5\1˻iX]$ Ω5D^??nAt>EFQj+[[D7 )2 qmALv|j; qUyVI_b=E8[Ŵuevվ؃Ruw4/,(榯,_ʩF| 1ewf]AznAVF[duGOaϜunv0Cp`ԏqSD`m!["ȟ}kzi]] T8 f '&D)snܗ/^qendstream endobj 425 0 obj 1773 endobj 469 0 obj <> stream xYnF}WzjC.o}K h:*Z-l萔?R A 0ۜ9sfntw_<.w"Y߻ŻE&,͟~&\DB/]4MHY.*%I?]qsVT[LHMX=R)*Ou-HV}ulK!- ٕ&pִNշ-aGoBMrbH?o`J3z/Rj 򫧺=r%^YISR=UyJazOrecɈN֌U˔~vQ˰ͭSwtߪ)u55^zp#(dmp{ o`|n$`{`<J&'=S3eTӉpm'#IHHTa7li{EݘA}!J1IGd 2xB4{ʙtt,Ryވ鉗b`Ar30Yi6Q(DNL Ĭ+3욨u8C6E47c=d 5'-!ٽ9v=i"l:#זu`{hڿ|8'%ů٪u#- 6C"4>4AV ), 8?NxX\Yŋb=kd}gy8j.9K0RJ&)<Ҹ5͹B41O1'rQ岸0+b&([l…jdW8I(w(99hW1uUNN\baaD* Ts=(qOA!Ƞ > iKLPE.wǞ4Vv oڝYNCOYQ8~ 5گK|ְCϔ,VHYbjyoVW bWϠHEhb*ޔCD<-qQajc8jZ2ZI8\]ty$#3HKVqINt }hPV+ӡBZ5 c5Sԓfd3*Vn 5a)?S}JWvlAܨGIg[^NQ\.اEx$B< R鎵GL``-B4F4B>4&fM7H D(AMĒoPio7>x0ϿϯՉ`wFe˜Hq+🧛dBe@ϵw{HTh| ^}՛6%hØD$1yJ=h{7C1{5@@JO"a1]:!h_QllFMi=GqҴ3N|n5PpQs"E |L;$2N = u(A,itKw !׀du;'ҏVubmlwI |F7 ~wjĸZ_XAб~@E^nDpk: dUQ-xj}*S 99x2E8B˔/DZVCC`AP [_> stream xYI۶+:j*#ܲ8.U;p(JbE!)O& 4DjJ*rM |ߗǖExs /ܰ_EjXėBfK|/Mq,ijgl1u~}/(E|@KX JIS]6&B7BAiKU4u`zF#.59%d'KKB}ȝקR y_`@܁Ҧ8)-LGT2o ?pḌA}~jUԧ-!ԉe WOKzq xo6-BX<9l} 01FEͨVz*GD8SYR4AWUx+dFKrsR^ C.y{];3jul^*yiĸ:qbw8zs,QC<NJv&eE13 r [L1 Ѧnk%8Kq!#S7hR+ `̫v@"9m5 $̐Y@ )$N5BMT뢫O.u%.$*\Bz>TBaJcwpm' 3IM^ת#؝¨b#qr$)ş,:\YDAe"”%rv.USZRDǜ=ECC PLvM M3iT:`̧fRuupT31ؓD3UBV;'6-qUL 19 bz]dZ/ 4%.dzD1K!:Y5SYTyr(J5%oV*}Ai %8Qd a1'YbNMwi4YKhu_am#nu8+6bWrwRNhtntWK K"uZݛKts'-u'uCpv[ Rytj$MHc|inrd }ިgi,We=Q/322?t3zEsysT˽;ؤsO :(/Pzj&6bWL=AF|4+q?I`bvʄ'L]:+pZ3ye_~cd"!I5Pח=Ep&A0A Qҏ21W2}'YL!?USI3TD@diZqG$Og? ^+;mqOEgduAfˡ*d_HL^Z cӚ Nž|{ˏ@8u_qҟ |bav컺F%^f\p8jWՈ#BJ'Png!@n*:g\[j~ו~z}xymq%OcJt_֣*Ǿ*>(wewi_5}j\㮝1)^N/z[e'/g:X$k<8i fP\yY?:Ǭendstream endobj 479 0 obj 2253 endobj 495 0 obj <> stream xWn6}W苃Xo"v`mn}iBeG%e%;MC.ʋn"gf\8PwzEk?> 6(=ĂxjPu 8_߾.j"L(kWʭFv4%ZĐG@ V$w@h/v 4}Uy{L]rJfg>8SߥGI"!(e)AۏԪ8-bf*P-+@A "U5ё"2+e',|:Q #/]hqv@)܁+F *&( i4g?$dz㘁$LGRH#r i,?](mSSӖJkuĎff'+ᵏT)58Odkv UQލŏC1jb(97rF."ؤFñm-񋬄6 7(q3lJ}ZmRΐ4&?#}. ?QN{ziRtU7?{α"ibP/qP="ҦYIcrfrKIa)Ů^(yH,m=Z9*ewBv}`D73Fn#Ȑsfoq(a~Wgb>΋jwݭ|©u.Oe´؊=[8JeOṡ/8fJ^LF Bpy" ϳf0SeK+I.AP#Z\?$ QцEK"|97/7C]KPzP4rorBE [4'QgN4k8:,hx(dP1Z1s C(h#r\Be+p!4J b` X3 ,W:r"XH1N#tPlG:endstream endobj 496 0 obj 1073 endobj 513 0 obj <> stream xXKF:Uh2/`C!s ,W%->=/Dz,l홞_JX@Տ۬~aEwbzA`6 ,1J,HrFhlU݇כoؑi}r>rB.IPn U)a,ϭ.+!I]ØYBDLzT˒$s(,{SA2kNLIĹaFL2"I"SSb.dTGq7VbuCjhR13"wM*$_}?wշww2d~CCla81֫MSOЀ3"Rvݹ@Osj@g∥̱$F3W%gb."~g!==^ʕ~;voئdo k ,D۶kP8Bk 5utݛSp> stream xZYFS A^676Q>p$ą$I3>جb`fwu_}UqĦ?~ϦnOɻ r7aT}ħtΦQOӂEq>]&?7s_Hbb5Qpi?OO:֫aB(v f ,$,q(~_ZI(9l*+rz3g"`y#Fi$N=c<ôeWp"Ʈ|Pږy/$]Wb[]lv.֢ȗHS'! ˁZiׁn2iT"Hn&vjm}QnE@CayH+_"w(}w=9֏G٘cP̬s(; 8ڏ5B9+y_h"T#ٳӑ|2e1Xz I"T )9#9zu*(wqŌKN"a[:4&[s_+-*o2/lz2 D(Ab:HC 9r1\[># t.-}'Ru'"t϶C럒U>٠5\$2JqGˋ'A^:u-;uzzsz^k~+K  x R_}:b _J ^I-OwH6{sv"GVmXz~OamOIL+ZziyY Yu@̕M~ ))[u5Ul+{^+KePBS"Uw^̃E9F4 6S >ԷSf;^\TgR3حOHgPXҳKpi`TBd;.ӓaK.ϡ i#`6 CAmvh|ߺ4$^; 0L/3TtL üȳYٻ|O#pr/%M DB^+|rj4 L(_>gBAH݈La򺺑tU&zAu٭fg"Bq\:71{/,R gg DnX|-ZeKDԯW0,8ߗ@IH I=L<6׋/Kendstream endobj 527 0 obj 2633 endobj 541 0 obj <> stream x\]%7}_qߘEv )6(ǢsN Y!!hO?}vtO>on}fs ngftlr{7}H8nۙ=䗟WgR`2d)ӹ MO)'}7/i lR>s3%ߖyS.Sv+BC:|6o<(_OE9&fHn4a+F۴VhIεV\{vsy`e5k"p,G,dB㸌sM>wSˢ / . MhADq8E*ZacwC.e!!.J" Ȃt0GHK ~}̠]8S `huYXe[V’`}VO~hX:v8b.[ -'_Wi9Mw{hKV~r%[^gBy,V湜O3̄y>͇؊}:=ENQR9L-Hz*iά S~S/[>\ӣ,rC'bdzlUikz;}-ȒcUe۹>U /rAObL5[ ^^d{µqZb``"d>O' dI55Qé'3`td@t6-UIn_l0*K䈫l.3Z6?oFr#ӇY,0Ɓ8vUnuZOʹX({RIO;吔 A\Bþ1\'+˾SE 4RSh]˔CA1ɂpaҹmPZ9j;LgzXm ?O=i3'?΂tt@]fOSָ<+2aUw^23Z}kB`)1>%K3F' biY` XMB]VdԐ.Ulͳ˚Wgj6R}J>6A)1-ceCg|˂L{x;|9Z|R4T4B6mEkh"X2n{s HΈI Ȃt0ў>Hw{x-l˶۶u:$kM WDછ>|M K"\ }55{WwZpX Ynjf&nX a2v:x>Z,0*9JZ٘GZvom>AE'.ܤЏ}>x,`!@1c8 9H UaIH6!Hy48{C'BbA $etm$fv~Y`mЛC`e#tY.mzaA: 8R$|T9tTRb-lA!I1 C"Y.iJ?҆Clj'?+sx"f2]f i4ˠkYFQ)v+=$v,0BȨ!7";}xtd! eT$b1اț)LXz ӊx* rDG8g@ՙ4SN RS ⤙p-`U5-H#1BHҀ\!$[rʊLpˇ Z%8mޒmne|nFhvmkۀYz֗w,/O9“>= ē>z@>حѥG/#hW'^j.=i%(Ynty<\hDeQ3X' V|c/W[j+?RGkW2Q}+.'~ѺZ,YL6w/r &pytҀϝȝ'SdϵJy5h ^,Hs0`g*139pϹ~3d 촂vx8N.dAp l=S l%l ){`4qx`Ms? IBjE8Pl#d!N?d!PDD&}x*,țcٗG' ԉy.-ɖ(˳k:7!|(:xx:In< wxxt<q~b5]>XȂ01StM3uʳj܅@E59ŠgB,hADDB^脋:(*& pe3iz@j)  z aˇ)]R쐔؉Eߩ;dOJiRD`ч'%YȂ01!7;HBt RS,H]˂d 0+OmTKX-2lKc _G}ض({8G8:p˾4v $ǰy CWU T5Պ ǐCpu!Pn.Blvι,C 7yÛ<›ܹQ踓tt:w-Ȓc n:o`1}ɱ7Q 2 W9J1Ƀ&9q9`a kz5KqzmND// 2zp'΂dI1$$4H)N(p~'nO@Rr Z%8.T|AGH|pD))NqlLiAj_.xHҀ1/xH^" \?eE& Cщ-Ȓc々tɄ^S_C:wC5H!C X9(״ 5;7He^rD>6ƱfX.vmg.v#( ZPW6V ~zGEْEO_ǺM)TMoO+h+?5ъ-*bR&Z[Q3`1w2 P(rFOLbL"' Wե.M5&N|ʡh{JV[A*ntHHf~o#ru-Ga,봬!2VDL׉>&s?1~nI[PꝬ%/~sٶYV&s?mX^}ozoq ѭu{Y rgwI/W~kwhl7S ]ݿB}mendstream endobj 542 0 obj 4429 endobj 548 0 obj <> stream xZK6y }܊(G6p؇19ݚi:XR=o"Y$L;0`ɪ߭Hb=^}XW;ݕ0/w7R돒ݕt#VBQYJDq9^շy _TJx!֏IW48?MoUO;]c`R(O62\<*SXUGuJV?9;weyN3b czqܫ~g<Ŵjͪ\>wGS&wQ(@!8I|z|&2đK{4'62|?LZZ:NȝzDʔY?JkeÎNcJGocdy"2toSc/j-Li1QGw6NvcI; Xx j&Ffw'8+9BZQ)ѠH"I g ə SuzsIb +tU{zݮ eksȼ;VmuoAJN$Vq@.cM}mO /XmqL8BN>vߌ,ޮZUW6`8Y[ ^EDXbzQՇG<@No?XGͲIכ4(NM?1((-WƿroP=lIŽC:nYN+v*wD['LDNYuG+ 2m<"N繌 =H&O:dp]ulQ7} cɥ֟ ;q9?b $Gl#,Ʀ52A3sLAgi*+ʎ XPz8{x$14'ϒXrN1v͗-Ro(*@,DLtO+Ң*yBÈ@';o3/It[ā3ĔXԠctɪ&'4 o];!GdZ$CPKb.* ݹ FCh:`JߞL"ndPO1nSDZP.x'7AxEH{ZM>nyÐM2A(Qj6j9J FQwkH&AkLȱ(HluipLVS#¥h"IcϹoA 6d莁M֤MnԴ2Ѕ\>py^+ ~ώ:o[NecSON3oLUkԄ%cTLfT4KOhORj}7R^t,L>>5zS?@3-mFndGQzwG nԅW[$&*V$b՟ẦնlÚպ7#BX|Q^<=M@B*On`K'"yd\F|W.\P[ ?m"yv;JA('8ǹʭ gw"8@| ;2"$lΫCwP\`5o\WWm2ճ)Q޼g,gwsz}{Ƞh_2jzt;.m?_EYӏ)2|bl˦I_mRndRa7Ebؗ9mJr[=~6b86>TB%ti+ͷo9mBثUpaLބem>|v NmjKڳw2 mf}:bT6Ł̀3 E%܀!O:.t{һǥdszꫀi C}>CMS\ C҇t=QDYȯtpġ֏}3垟jz quw&Wic^24nc*;nP'O$8x]՘ԃAIA mS0Ғf{bNHe/ym/f!/iIL.d2RoJ9|rhDܚU2aX޹P5oŊҫ]|$>0aKx6eٸ Y ;{Snf^Z%+fE D'¢07`e$`م5}v z%AVP{*tW3xKA-^;ޮ.%KYS''EeK&?t̓h%xY!bb{\ dUendstream endobj 549 0 obj 2890 endobj 566 0 obj <> stream x[Yv^G.(1YXyhKe.pV7=ڬS>j·$Hܟerw߫1dARh2W$!$ϤLDE\& }uoG'ꍊ78Srb,C(*Su2OˌrO4݄TLp7zC¤,2aw(3(36)ͨ'~y:x~]m&d/?/Vq*b4y BP<?O uPB= Lde7yjGPutV7bB $H́~^ <'鋓GգFyf^¬ͬisVf,LN!f>1# dx&;РrE\ &Rˑ?',eU}cͯ3 ΍k*Jz]ڙ^'fFǴ 3T;Kߝ iU)DZ[ۉwv;)75O `:a.xƧɐiS^M6*b7G.pi--'2Yt"]4s39YC)/DjvSdZCr%tj#&J33~絯o!;2 %|l/ )@(sU8˝ Ph"\,bXBeH K@oO?iG0% T|iq0zE[;YQt|݌SICr_,F%@2ھD'x~5}-ձ4ާx"F(OtQR@h7@!amEX2ERs$q$VB< ݻ@nDШMI54q)f2"4_yLodzNg#Zao3]#BSұLR9bvnGJFhhn\zRtTP+?;>H͖JŴ]EVD †2N!8K x酶 E ƞHA]X" v̀+΀ , G:\Q<אC\Cu1*߲*ԓk sf?U U &H38!@Aq쾤D\f?N2520wVL iL9 e?6 |E0>rf+5z3 `#Ғ4u[/̈́Vd}5w:w)dfRpxWE9WP YX,Ví}0A R慯uI_̒+}|Я"Nb |kqUgJ*wiJipU;5{iye}Tһ^M?8?zY7+k%lLu&@tG{Q`>Dd}G[՗I0GC8ϐ@%؉T`Oߋ<'x|[ /44 ˩b2&8 : A€&ʱTTu [%w>ԥ37,30ޱNG| kJ\}k3EjS.!X-- Ts#S.a׿4VN沖ʊTT]#.WH (ѝM]XiWrzD5,c :}GlbsmC1kDts㺠GM@tqۢ Fmpv90nWͮ[o{VliH`2/S93h.PxBS\n$_n]lb(lN!VUgeMk *0'̸€XÆJTp7<p{.e./p0}SDSsZn-[F! CrOމVrYI>::> stream x[Mܶy*s㨲Ð!Q\ŎjR9H>p9JrMrҿOhݕIl8 t~`|8o7?e|Il7] ˲Mm߽(|o~/_U^9>R*=_ ExIcDQd4MrXErz46V߈c;?`0K~< u{T $.&_-/29WIKm "?va*0lV<ЊV '&QP/>#dpmH9Jn`^Ɵ;8"Ob"!POWt< 6l[oj;TE_IN88OCʱWɘ52\X? a̙8g|!_Oz)Bp;3vԐ }ʏaA / E6N&6 _hԥZgYX8WJ8bRV2u FsȄ4V6 duA vpִTWcU+M?ecL\E?H<6C`QHPԨp}H!E|]UgMZ1ɖ|O*ypEM*!#31So:e> l#BD`)h쎕MLf=}5\q 4ZK:fAreBDT_ ڈۯcj[ҁZ"H=x j ߬?((RN (7xЩ:Dž`kL ,zh*Ldb:I2;ES}8XJ>z{ qlC!I. K eOmY3ql?6 ~1Շ5VaٙB9(rYme,%.wC5b7܆F?͗EEp@ Tۍsz0 VIuPEmAgtܙ1nR}=$N8zprWk(3GmqKue`VK&uNwñz@4G0TE1O('z-@8?Qf"kX&JƺOwp )!gQ7*,pD?0,^"F!0^߉zXP1(] e`c 6$t~<8Ki!v;uJ$:KuAkUt2/tQ9/ ʬT!'R,&α:$RI)c5?>Ӥr22SU2o5:ʢO3/D+hs3j_gU+1pz՚.D2#ƣD@$MK[~ڌVDLZ4ZM9KA7&=J?bKS{q6%;+,'#y _o-/KɈt./Y#ŏkt?-XXݕT$.껣0$gV<ū!41hk1eSSQHLQ)F:|I u˹? \}q31DV:isMN~s %: ʰʰfʃ,x~I&!`Z:W'6V@+?ZqNg{{Y۬oX$y9,H"١A0mJOdCS0a=/w~dTMzą a4k>#װ؍/Nj~Ks'O⨏wI-" %>^`g"x׻舄9V)'u"AĈ\=uYr"? iq a5!"t[ 66V5M*1xA{sܗ+RKH#Vq*H{Yj^ m$jN] W5͙E)bp/xv9%;*%.{1D:}^e 2|K6U[q3{_dLFgUIʴ$ܗXn; 4̷]i(^J[:z F.?6!g-ddUPgTa~Ɣ5?^4ㅠs3NړHpKZ"e gQ^´YX3~JD[,Hǜ[bvӄCGIǒS5čWo0U_A,m~NO4a-X5U#xˉKv':]t](SXm2OڪLd|_|8=.;1t-"ҧ+ 5Fk46ZVWMwھ՚ީ܉\ I \z^RP\& fL?̍C|;ͬf򢄺1!A 3$/҉(D^<2~ٯ,*6MuͿZendstream endobj 594 0 obj 3197 endobj 607 0 obj <> stream xZK۸NT_QSk 'xl&UZra&Z4%rLRc;> QΣ\9 ϯn< <am:up}1`?և˕\%K|WlXd,<6J]QtXWz* ;oxQP1&1 čeD"gYهwG#KMUͣ(u||#azM G[,V]o7 #tDl\JJB|Qقp~GӗY U+!c{W SՑ\EۗXږRbsQx"ZH EL` E5ah. 1y)| HqJWp 8bk'Fq\< I*"v_zQwQ|]) Jb=z: 8/ lO"(Tf2،aw>eqB"Q6n'葤DLjzgtiTɔ&j ՛cgʶ٥ظ[&ٔ-64hbLBOQT*:D0fwWsƷ!tޗ)JI"H*SWih1Wv<؊;r*xmjeBl#2*CK^i3 vt]ICq/[ڃJۖB4.j(*m?k3 mhU-U )p%)4ncտuddrPˎZ෱Kup\)'yt4_(ƖOY%Bup9+JJYlr\O&ũ*aС3ӢMLyvHT7 {Z%ٌh2@saTCI{;CNs:SH:\'帊Vnd-EMr -mGa>:b 07880A)]WjRnKRޡZK[-mrC]v@-gVZӆLL"XgA/gTO6!?K&UKZ GT ɃjK5QO9qG6FS؀hɊЗoqH< θBXWX\4r.Ж&-.|0 œ0\Qj.t)s'Bbsg"7U0M  o\3' M:# {e+5|оhwo$>zw2$c~w|T8 -!S>DXye:9P<#p}m^19SWQlleB-{i {x`g0qnj=ȭ`6 |LPݏ三9E`)*Ky}Dt6+hZ e`N2 WC VeWw.lWϦ\轓3%BXMބ2E/O8"]e!8GRk't[Z6nXnAɹg :.̇_/^ _FwzrD*YeK)7>` 46f `gNHX$܁ṻOƓLnm>`d+k7~6A p/4DGO(L 0-1sDΧeEF!N5ߡCjendstream endobj 608 0 obj 2955 endobj 613 0 obj <> stream xMw䶭/̭޶֊DIish}H"gmoGN_@P5yیMF~]Wj]|Z[_ޮrJy5~OON">} Ruk;קW?=}q_@utU;T5By{hW)5 b:Խl8wOW__o+$Wv'''[7_>S8y-T)ZSڛO˛䄳jT 6ZdU˸m/q"F:ǯ&^[f,UQs2VBˇ9 ]I鶹tjKZ_\%uuKl']My@6p-mg [m5]5=ٽs];?u=VM9 Ǧvx pzO&9v]En?켘j w?Zn/2hDFGqlr>It\q{^U4ZUMq|ǥ)鿌[qGv1$@vA6ZO_7&;VOjD+ƪ5>q:o\u*i/A=1p.yl{ tsK OecpnrA O OZ r! ?6mj~r/4HU>v-%;l =RiU%#BIP‡ ">j<⛇vfGc՚t)4dr0IǤtVT4]Nٖ׻ﶛ\VSMI_A (g[YD>{4lΎƄ0;43x pbkĶ]71>hbճ.&|KBEoMzM׻|{nY'^-}'@V aBQޑ^@=ueJ{g'r w9fE<΀8nmRB2H=z]HB1a JNcU! ܵB˹+1B0By؅03̂>?Ò$ҩsиzCU3LmsS7.AHh >Ql+v[CF}26M) ;+dԹ_j@V>lKKP.ImAiL/i%:4[d'z>'E¥AUAe!^O 0-4Mޮѷ d;?B?ҹWBӮM8 "tjXòSNams.BhnL_C/!X!E `_pj2H>DaZA>@'^q |hFe4.Hp:4rZЭ65uH1u38  DyJ\luR0BXH&#RfRꫮO.d0A6 ¹+h;.H6gD͸ |#Y7E?NxLxֈHE Ζs.~:FW|DKD?h=C-DDau vH3An'4(y*'9vl|f9BJu^ [9 ;Uh[ո+G-n,f)!*j2œ\EMX7V!bC)ZDY !FVZf&ZJsHbqޯ9zWh֜uWN ͱu-YwV$ g;zK:5!%D!lv ID#!8`R,Nq~22ʅq k_$Y0,3$ #`rlFFM^mLQ!yLѭ<%3 yDD_yNf &hagAU.tY;f0A[t|KzH;XָYee_i 3A;ޡuLS!Ic6 eSQi>?t?ӱi>Z65ob; !Lk*')`*C1uNqThjm NJe-񘲙 ?ƎYT&>)0:t$dSlgiLMyS1KB\1]20DOvf1;YOȲx݂uS^p {ٝew}lR92Npvvm10&cV7w!Zpl̘ qE74 jnvTݳҘ9t* ԗ ,ȧ`ce`Sa\l45f0X6~,3H `Kk ,)]-<ᶿ\Mlq\{qiU DZ= 04@_۹Q#܃q#$aD!؞rWbϤg؃:{1!AXXA(m@M`jh@ՂI 3^@2HR-yv%r'|4P@FG0 W X0 YLcl0PH"(<,K:GmpOo{[ ʅk;cfLցн5ϑ40/ꌁ2 KZIfBNjI7ַlBe|g˅Dm A0[$|1" <kCӨpIA,%Rls}jFnb+wlh:d.a4*c`3ZARxDBD 7h`eL>[Hmr ! uZ8g>jM ZyG]J`@r53Z Xh7DNca@!d$a7?SՒ;;4  G&Zc`" f 0` ` R"i~v]=PJ随ܑG;1@] O Ll&DmJ,aD "=2=3Ւ-LY3i?OiGu%O121Z A<,aD Q"鯟bW2'ǣCA'J)@I10)^ف!gx2`|v`! fZQK Hw=(kgXtw1<<ߞGV1,#=O~+c)f}` xEY$ZoȂЅw _\<+@߸տ8V} A5akvD U놏;"A<W_(AH<_芄 oy}?ͯn‹ p#BHer7I?Zw\߆kψmu0pcendstream endobj 614 0 obj 4075 endobj 624 0 obj <> stream x]Ks$q37fdKk*CYZdϐRW7P|:Ydg%2|Ǫ,U'^g~X}?+Wu|jAX?W/姳yU?UE9.o}S'!?EQ궘oPT4 כ@*`=VE N5yo/oƺU]O~誢V۳b@ϫY糺ڢkWߪpR5Eկq/J?nƢ9rOS1Y^ iʢVJa0s\\B,٧_E3Uzbޜ]n,UU5oz^m<<ٍSz6/a*aP R8̡覲)Ɩ&ŦV琱j@1KR }E;6;XԝUME; mIٓQ1D@R8aT0 j0+ehz*2E9[vkVEkU77N]ѩHN 0s$#| e#/ 3'jr^٫hUUcg('(&%1'DX'sPx0aG"e=A-q1]:^fK]:CiBm _3ĢM?-L~tb -R($HthH r)9?]4}s̖&F,4cYte#URrj{TK*Tc;<ƍ]X A"9)H9 b˱X --+:YIW%Ni7!Fҗcg8n"h8\AITWyTb J 3(( Qʂ bB k^0oK:[uME姃*:ReaS.ImPyƦ%X(;= a7uo !ÜSX ƍTFrΡ3R<( F 8 XOVTH(:H!䂥&bHz T`PJ*})5;Lb瓓G-32eܻĐA  D R:s Ǔ1m*$Pah^ R`m1 -TZ:ʅ`Km=ua%8%@1NMˆҐ!eL$к,4k;8cV)ɵ,u]mo2mGMпC?)`L"pA p q;9E7~ gj@*}5M2R{P@4.1KRdً֫H)(BV@Y"&(Z D|$BXɸB ^Gp L 9#G/ C  v_ Dp=kIcAw=_.I!#o''\T:B7xѨt0+bفǔ st9]wrEwm}j-@Ӎmtˉ!tR~R0%(rć ''\TWķ<4X'fCHӪ^ܷP+%3S2orf/,Φ3 (hƓ@~%56{!6b_%LqivՑb(BGk\$U !#hMʛ}J (i),7r3NfSP;BzST޼2  ,c(JEIK2;, I'DK3kZEV^H7KAzW(MSKC4e. ( \~!w&,e%LM;͋HrznIoEZ2_+MZ!\ַRɬB#  \tc9VQf!NmIK Bv{BMltsL%D3` E>Y\b9X=kmi<|ٽ,u؃c0@t}em֗XI\ 2$ "[uQ DPhnU@$noVlӕCh(8 (KIo:W,? c9AdDZ)B;sHĀx(z@TZ Q,⤊N犍O/°"hX!P"Tc͌,%v;xvhD1I-eN:Szv@]yb]BGapn7 DV~`53^p,x3+DP37&13hHҐfk iOGhSMBRd\Qa4 B$78;l[0-MYbG!%boZK*CG6>~8?Jy @.8 kWfc٠*6/C6VҊ?gSk[B*YuÖ":q"2fA3eke791ZM4zjyVgۉzq\8urr4{dh :|lNAd.05s7Rv"ol]<Ձ99:~yW.D-g4A|Ҩ:7fXD+Ńl!.K/2 0%_[淿 U-wSquK`ﻂ'5ͅw]o._d7v7oѼƷk U׻^պȴoh6o"Ev|q7ꟍ-<%ٮ"'B^BPzky>ֲ]=@I.;^vwލ3sSg#RٞZӁpuzm! G],;O>e)mwR}PxM@~@*=vGj<=[Q=s/;T}//VV9v.wϫ]m~0`B>EEM8#p->A'NdR5+D@DuN݆n??-_nvlzty\_ f;8؇ekR]38>m O9?|漞&7ݢ&h_oc?.ċh}@4.ig6_"q u3<_R䇛efpDi}(m,k,~ًFkfD&oaL`MfKe,lֻj޻؍Uw,aV~+H?+fT?*vzrr\E6l{Q$rw4/ Y ;oM0>Kp]}Q W ac&uR?6a ٣|&~с=oHꡯBPx;ESL۝AJBFθ.XϢ#Cu?nBe&\a5sgx"`xG9Нsݽ;cF_oDƳvh]a|YqԔqC.uryϗOY.W_"Uk*O\jW]=ئCC~ud{(FVs ߧa-r5 Uvyqy~ 2."=oCcvG?ZZk{CKȌYee:}"MS-ʴLkfY@?/|;%<#">ښ^I9e6k&G^KuZQchOz1,RGE9|C<罤 dEba/i?%-mfek|iC&,VPέ&-T.;Y-|\%E~QoҽKIěEVN^kOu༕5? eV_o44yMz`h6I$n־ޚq1{Ŏ \?a:&f6]^Yn5+d&.u|)*=.-O:g^uTx/֢íuT4 u>,xtõ9Jշ$sOU(v](uv3uiI@^5 4w8p -|q',SXTRf%Q=_]j؇V:b/)j=ƼXe͋DYZ8Jw{z+֑#ʩvendstream endobj 625 0 obj 7083 endobj 629 0 obj <> stream xYێG7Gw67/! Q"yy=e<^._T{k D`SUTK(a UvF yH& gH#a e&%,ӵ[Dg f7z%9+=&Y7r<D{wm3tʌd'qtfHj?zyKf~M֋L᪪CǙ,_M6(BYpx~jC:YVeޛ{htA Uq){*J4d$a3DjT|uUkփ9E5Hc)s`ڭۺc]' dYN,=VmH j{./693Y' u'm,p6ͮZ=[~P%AX-ڪktyl uզS d<_ ҧԷ ۋ*p;Ir|狝bRt-&ǃnoo*4t44]MB /[ԭJէ<(Y̱9Q#R9z_4?mfiïrkGPܷͪYeUfV{ Qd"+{Jσ1Зe ᰾ @sgT+g" UC6{hԕ]c"Hq qvMT0$aB; QY: ;:ǠV.lvk\ ɛ tumsN;5`z&Өda'b2429t}}CǨmi';R7 e)l_;꒐=l$d!"+w *w0 Qo}ʋ;%!*3s\" o8N/6g7b `tF ΂Vߐib3HY$ϮcE*"T_I S_89I]T,*x+y'LiFڥax^ ܽj_ҙ å{a-=Id3ѭL /F~kEl sӌo8#r} ?«E׆|AE_lwó}"r'ī<g?;Rm%1%:_endstream endobj 630 0 obj 2029 endobj 642 0 obj <> stream x˲%˲fMw5fZ'ߑՓۓ>B]@ L '@<~7]7w1gY{={Z]v5332cd2/w\^~^Z??/?_}yE'//6\^Q߫n/zأϷwp[VudӎJY6՜}_w|lۧ՗_?ool??/o7ƿǿ??_g?'so?Wo 0݌O~ptsyOjϧx3y=*~hүƱ/zQ3ڮiS yM;%vksu;֜-eҵ(~Jvgmנm[fHײ,[[vKk|׮k7t_yү]zNǎ_RrZ-;~<䗻v%v-k[*fˠ֩dHצ7+[[\u޵kݑ]+oWշk}ؾ.;"+oYշlwmѮ7jy^RyT~B[]DEZ1n~wOw2xO??gI>1?x@uZ d.PuüugXjh/mRY^5naiun[ji&uyӴ#/_R0Rfm벜 +uեrjaq۴\^#5́4RӀ|{Jy]ek>9eXjooyaTl @jc|s˖ћ\y9[fXjooټ|ӲR)ہ2Rˀ|{˖N7VkW(e[ͽoYoS]ru_jS5R:7e *CfWhW/nXmo{l_˞fH6 mKֶU=yUym3k~_}kJki򶝕J7tmïжomɶѷv|ҵ Bүau6ϕkvu%96t2'$"DO z4D" }C!|P,D" qD!z> "C\zH=C=VzC!@RPO[N4s D""zH=z~M[ K̙,u3`w66ĴM<ȼKn۲Hh%=Ppxh; k3@jE)R`{SR.5zy܀`ljg@`EJ,t;t=`mgA̜b}3G #:J1v0vˮ dz2b(kG3nhOԖ{@M}DGwcn RqF;1ĸ̝@d烰Vq;c'C!|깓In1>s7F_هC 죾M ↌2n "zH=zn܍D!}>/hj47dpC2H=Rχ܍q7g "}>}t!DWcp?1H=Rχۺ܋q/ƽg "}>}n .uug* 5R{Lڱux[ȬeCnlujEcM;Bj;l\GN`F6LWy.Jis92Acȱ #͞H5wTKs!R-&/Z983;kSt0c'|7i0hgG{|2BXK%m*R!wc4`;֫ŕm+Ɗ>~m!lۯYVЕV]Έ.MZ5?BJ>]eR{5[~dx&&uh;4X*Foݓ%[VFw[c]ϩkf[d K=Vc XGB%wBlabC-sD3n3ģ5> #:=OTV ޣb$ DLѿ?DB"!HHߗ|"``E r9-3Ug /"zH=?<?yG 0"}>}nNx|8m3DB"!BRaxyϣ<^D">= /V?6U<?ËH=RO=b ~3^D!}>fy6]DB"! !be3g=³}3D"}NGg|yC~zH=B=_/ ?Oy"هȌ<>Ɓ>#HH$$қ!$_.|FtGx}FA䠏A#- K%Gƙ>HH$$қ!$uM<?A rЇqf}<ĨI:38OdGsϩWi8'LһqC.-ݍuʼnQa+HsO us++Hs7 M=sSϏN#>y 8gq` |%xtbv'"b!b Î(`_A. ^E>E̎Cϙ3-:u،b0 0ZU*rr=r@JR2o#$$ .fv3A A &AߓƁݫGR<ѕdt%I=Rχ3#\JW2C!|8nFv3Zђ|/ђ&WUEv f%(G(MB"! !jq݌dL%c*{L%A rq\>JFW2ݤRP dh%C+M!}>x`wa\7c%+X+ɸnr\Q\7úE(JFQ(JuHH$7CHXZ)͠JU2U2D"}Ov v3dl%úI=RGYY!\u3 dX7هCXaݭt ,`IK`IvUU_ .r%˹uF;rM29Vpns|uY9_;*z㹚'Qiijζ<>Eŋ[/ݝwXǨȺF?#Ο.wuocޠԽ9KǙ W1`]Y^z :> <l1gxL)jV>#:{u e1N [`K7lőHA RoLAL.ar K>1M$0ۍDB"!BaJf0ӄ&4a9D4vdXbNtq&0ߍC!#ˠٖA/u¬f|f s>daHG##a#a\Ez\8)o7|0D "}X f 3La&o"Ä)o$$ .v Sޘn#L7a SA rq[Pu^ƴ0oRPϝ¶'WE'$8.-=|wű'#Bxf WC;DB_<^ hzA[[W ͈  EkZԥ#~q$OSHb,d$@`Hʒ@U?.%9Qo<|,}O dD)Ć;|n}O5t{@>SXً S>@90z8Y,Ez,%%Sqe./sy׆T }>?6hDt\f2;ٹo6;J*r=pc%B!f2Y HAn3㘷˼]~bۥ DBz3%099 Aߓ:yd^zH=C=UK]&>@t)#@"K6KwiuRyD^}>d>4SE/ef{̥\Ez\XE-$^&vxKR)CSMbvˬO}Y !HHotT" ^f2{gRED"}O\k8ۓ62C\GeH=Rϻ%e~.s }T KRoĻwFLe"/y?v)#@!}~ x$03}/T WUGtLeN)*9{,b٭>Օt<@,}N9KN%0jȂm07͑HJ$%w'%_6p/Q'T>)D  PR':'j/HH$$/λ)T> O|B%r98h4KjE|B哗؄SKRG o4 M 4y&]"KRo\ B']  e"P/#r E*bvCWHx{'",E/"&3@Tr#ZOkAWi" 1qu7 [8I xU98b{0> ֝2胐F 6'QݓtᓄIȬ)&Zs 5BtF`:c c!^z,D" ~{Ұ.,&6 Mެ EU*r{"L` N(wNDR"))j: P(@PD "S P'='0HH$$@ś+L]a+o u vd)Ymm@3[f0,D" }Tm-̯c sV^rV_G"WW=ί+Lc& 3YɒdazIDRzSPr0-Lmav)D @+ wLfa2 Y>1M$0DB"!Bgb VavY,Ez,uĴ0i-L# Bߴ,^DŽ&0a$0\E"Wz\TǙ^Lf0Me0DR"))RRol0D "}8 "gvYd7: fɏvs} ]~ @|焱"pB1_Le,8GM3$!z@ k?vKv?0N)+lQޜ`+H;`O6@>u< !-l F${rq+g<r.MnUڡmcbC}!?1+ hψ#=`'&5<#{O; 颙E"rq=rļ0oy+̞# B|a-͈IFL2bMEL2DR"))R0eREQd 7)D p$&1 x+ L"Eo&! `HCD" >* ݕc c7$IH>@0T ~I @G<T_:hFic btGya#U>G &eqǛߏ"ba5F 1ƊG;F Ot8vh1  (oI_Zc 1* aer<@,r}6X3(3V{iNےCKKl-ӝF<)b #Dkx'[z.FoLa식c㪭ξK/oKGV[KyX_nuB]vFtb֫wkpF4qxD]8 hpL)rѧW5BtZF;o8G} zz|D>|ӧ٥.͔cow y,..oX^׍-Mt yExM,-컄Xa%>E41sh@d 9 ma@`BƊnqXcbϺ =`{?!6BA F:h%#jR{0]c9:|=GtFo 8a؍X@ '/ 8r9qm<,e'o wXK7p/ѵN9+t[S^W#vT;d}#ߌhm$uXVG;$6 mxhC6WGѩ9d ~>NE"qqձ pPfE^svwJqL21OPnB` ~)ϩm}r}X]-л،w&K Td~-f* 9tR԰.9a9MF wLB/'aRh)\uǣ%Cb1!FÐ@ Knqsp `|1 N|b/ KBl"j%+P#j>6A"6Ϣfg6SG 1`(@`L7$+9ɜdN2'0=J+x&8@t@,@WmqE#B@ UpV UG]G"-L)dptV_3ԾݰNI wyJ *? 9F`&gœz osug9gsb#?HTG~̰DQlM)[fK "kibZ٪%WdTdfZ^rƛHUJ]x'M'k:C 4p!DbcIejAF)st撳hA"ݬU`G0wxfqRXWӉQZE@D=2CD_hM_Ξop8{۸%ƶȱ19\=fD8akƏAE>=#:9&gONb$8BXÞ(Yk&Og_z:Hs=rv(;*_=aH Yd9!:g}#ENUng8摟.L&hډz'g9Βԫ.Lf{`~3 <n1heu?N駊,oEU;ur KM>3Z8kByGwh@~ܖc楣T b-͍쐳;@'|:||GfϺο:Y'5ĺjb}d@>E恖9!vcmi͖cd+R9N2x1ļ~JTi'kwt:5?łP47L#bg 1h ;Sx Nqe Ψx7wOė|F$u0#:BUfO5hЩo9s0kL^#`F1 l [ DF"#%Anќu^/ꢹy^E@CY[S!P joDDH"$95XZ_iwR=^tQ ENܦ5GYCP["Ծ|fWiHlvu"򤹰Ψum/:G9[3TJ,hQݐI~"GaP lշ䖖&\A}Y$J%D$]5F=5u_rm,ۙ>%tc֟˚]/܏KE`$ˡ82-F}[Fl1ta;ShUҟݖ^L[u;Z]Ul*]|/ "|998 =Elo<@.>)bW=0:4IqPtl};6{Y p*(ӂ{ `!/ug dD*W xҸqeDM2|5t͠Mh=`7^'3ĉ5B^@04) qr$aL7ٻ=ɥRr)\m\5Mָ@qp\"&xi 2$WxEIk ^sT<$pr٨}jC>Dz1p5JC5;L큟CaIh9,m@19W17#HCr"9HN7J3/Qҵ W$&k,ꊮ"y5:+.zL1U,05e5rou:MS:vӋKžCSEșY=[H6Wu}UAӸTrdu?ruUG~2]z%eѥStj5~GG UJRBu6ӤI$i4hr4mq&7w9XU~*PՎo+4Oj#~c-(J< r~*JQlF-6ĤG')qauZ 4n(NQf)5'#jHY,RGQ<$JrST0rl QwEE:a:9Ӌ]U^@{P!tZ+#VuSLkBrlSUCNٚ)B9e[0s%Qy0 k٤fR>[n/[+ Հ%juBM٦թm后#ueM\LAoTɪdU*Ygd;@V/g~=U۰IRRRe˖tjζGyR^<뾦 *xaZ,x$!aan1m}#@| d#وyt:^u#݈[!O eҬpxO*FpJH.E#(Aш?ziG#`oXأ~D= @<: ;V(mڐI҉ˁC۱y5g9>yE9ק*u5wpɣQ(y* @"dDP 5XC\ϑ٪xsvkysDFEDx K P ċxD jEq1 kųR]L *%R׽+4E}' CBlP9j萣2 qwӜŧuw*ҳPVm/o6+/mjӪo0Kۥȼh!G&YC\NrJ%I|*J T(r\n&p%S5^9Pk:lP*,3T_MhaMe-D4Ln.$ FKg[T̶ɣ`vФ7;ɝNr'q=!'B؏.T"օȬ~ۻdnuQjeQέ3 cy#{.1u6iG]^`hт#Y_s+Ԯs ~dL բR*WXlIljYl! y x>@+@5hXgX w| )I$e2RQ%ϨI삭k |gq! ؃$%-,q)7"c*-D4ʿr$ v#F9F0%Z^@MtPq G(< ,8/q,@ǂ@E !!؈V"z#,଎;XsDC1bSf}4y{ī;wJj%ZIjղ-V (S@\">2Ly>=\$Yo Ṥ(y]*UPP! )~TBPܬͼ ^Bll)s޹4QA@*)"\Xd![-䖟Wr1r+K/Wdڭ TS-?NKLݹLnS^+xeiF(>[meZOP7lJ` :+  etB/s({PYX{Bt97/ c  %;{qfF gpDr"9HN!Ns}iٴc n }*]`ڸ}E-YW¶o[=\`Ot-}mm{>۠;5S|wC~ol$gzRb>pߝ b[UMÞ9jFEEpb[G9ٻfY )q|Z݊|pkx}3 =]4:8x ](2b斮S 6V0Of#)!F  lbzOyC!#瀳B 4Z`-ՄsM9صW3tЋ8cR\K}hV]aI"UJWLTL4R7[Bɔ@˔VPYz^iʥPH$jAq--K h~zhp&4Re1, :HN)S?*1F #)'jӚmI$ 1HAZvϠ<$J4J ~A+J!fD^22h,EH rZQKF"ɂQEF=,E"A !N#iQQr `q/e~4ZȺT*CfJ#jDŃ+,U#kٸLEȊto,?ذČրLr&9IY [%/FJx,+𛩏!}BtsSK{{+TA܎p]pLG!DA+?v А-/YEAُ]t\_,RҠ[0m*+Mt]!lB+TUSMӅ@!S !PȔԶIJ!SJS*L9?C2 PG(e>SG#wh6h;~=!Q)"5d䔸Wأb=n6- E"St&hh˶Lъ'O*۩#S '2Q%T| KeG,v$d51E+SO'LB&!dO;H\uVwKɕĬ7bG\YKxK,M|U_6H-%R"S<˙E4R"hjj9ȓ9KeHETFXT$ye0vLZ.*'T"OY"',r"OYYIEKWϻ,:=%Hk>QJAUqնy=퇽q:4w.ͽvqqŹ7T87ZqХvqJ]];|2HqLE\C!\.8nQg7' sD?-\S+ pP^q,,@!`~3#+/)G`Gp:IWQ0w-Υ6ٙO粞ZNyل&T$`"S`Жe2r;{D}dM&\s0=jy;+UB@[ WY\ ϲ6B?6ϊ'u7ߎ"T2*&i{Db`ĈF*r9Q#Q䏓Wm=V)]x1u#sYx2 ?OpPK%r7r,7[mtI>"Ԏ*=VDMP%RT%LbngEI9V@WRx\/YmWRϝ3ʅ-v]y9\TrV'jǢ=qok $^&6ߖÔQּZrMn$zʂG[HzG%Wa W[SkS'=YjA0IE"EEI~XaFԳM/LWa:]%nRc+_}WMu?>G<o *H${mOHGA.HJrDvejGrJxrJ 憞[;u"ijS*r)UȩQ=[`HbNҼ)'{]}jzhy/2ĸ>QG!~H?9#oڣ,(FbĿ!i#y/z4?ثUw::6vW~ET\ؔWDѺq#C!;C\I""]aBإ¦F%q)cq>Y*~+NlȢn!lĵRĪl6)*HvڋHBrlICD)eZRvyѼu܊p4n}=J 7m_ŒW;2פ+ǭܿ?*-^LWq_pJzGh:sʍ8pJ#FXY]zܽrw+úZ?L%!5\rW*C] Q?-!f:h1g~9?߄~h_Ҿl/L2y-G{6H~M薣y#z 5B="t?[n9mBm&t<@蘣{ۆ[$AosD!֙CEW{cmXX{7{j=?3;PB~;b!#:Tra:Hުhsy3;^a爺M4mQF9Ӵ<@q0ͻ]F:/0-嵌aL. ~i ,<)Ce:g]b$&^WWxu.vι官kW]:LH}ސy9ǓGN:!;Nd&8dFPNf-\>Gg<:,=m?xl,m}y&d6m'<Gb<3l47i^fy.ei\ւUTf<}[}O <sl wnsp bp+.Gy)d>G1?*O7 X|F9u Ŀp*~x:XO$D _Rl0 šizkMiM&+=So]A.(uȉgCD g }*p=Dq 8Aǧ #>8O;S@<2 聄XA<݂2 CRU` 2 Dl^ [; 4~c뷰tbS, ?>Ș1˜(Ѽޤy= c1`'F?ވ1zFއ=Sx1xƨ޹݈0~i B{o& `_a4X R~T3# og >1H.A@ȝ~1@?2.hs+?@WM-"KMY((j~BPԜiEU>(ä *V7;}ԐxC>DmOf?0ʊ:61ܵ aN`;!^MG!oW\{k6K;nHdMmY+R"h]8~R^}T}Jem;llbXO7Pnszmv=[x7ic)PGJ]6 w&j]!x[X^[x-#䒉\Sir=r넙Kr)'x)V{5UY_nQcг8EuE "pG0J&)m=e xރ%:8!6з 6oV$(^ pPsL?ElnD[OJ> !>wY#f<:=oknG$R)F(I]n}-w"6ԮWmbuiPQصKdսICT=֙.a AEJd= v d?$N~"^UK]+K띩t מ]|kޥ`[s]  lό^).!nnK%i4wӶ߉v c1~磹 '8e땺3~,_mxiD' Taȶ"ZYM^?GMSU6ҍ"QElZ( OiDS.^u[6׽ٮx~yV]i ӥH,|($Cpod {N^+mfnT`߈2˲"T.Q 2Aږ|gD~ 4X*\z'#>+֞1I} r7VA0 0+SD xK@%KRdRwcƨˏM(S~ޚ3E\ FxJRp(Qk_>p ϹXh0bE5kP$F@ O!ӐѐQc#䐘a^9/TW }c mu%TW>q~k}u &М su~Pmn 5%,҈"ٞ)?LRZ#He6rb':iH,/VcEji"̒˙LA )B/n$$++J2ydE$YLY8e%H\d$`!ɘ4Iķ%S_jtg2bҎ\,M&3N~8 [||u]9Cν{KB<"{s9hkG;WMIi$W̛U*=2kDɷ Kv jƕ8(,=sRM/skT+֓8 ,]O릶KtY,d&F"~E5dԁ\njK^2nT3ES[ѣKͻ%r=φ_ԑzÿ:B=Orw2Һ4\ Cx}0b>W=Ef=,=gޱ)8t8`"b|hSPyA o޸G:qsI,]/!\↶:ԍX:dh Pe.ꙖPCԛk6Ԑ34u"G|_hM(gKQi/IFE%#„v1+^Evuod z%sbj-ݭ1@.YGEN5k. i.o0B@A=F< WF<:&MḦ@$3ts1Xj0[̟"69_gzF7Bl:N@0Z\A W|+n?,&_ -_:Gs jLt>BZf:>抧>qHkz:O4=DN؁dWd<?~?Sp8 ֝q탐M3biq- _HW%Ll"{6 :o* :#.\DbL " uͱ˧ і(]&;גDfWÒ|MBz%'=Ɍ |m וg&Yl%'dx4}j}&08:"yI8$+ɊdMMm,>mj3 FR'`=57N{v(&X]B|U-fwJ^ǒC6Bb:7Cj2jUwrZe.tõU2{֣ĵ pф# g{ɚbqۚ*l --Knf A'oV IW fIԿlKx Z,<)VwEjWJHfxRt͞J[2w8<-?/`aFVX@ ఴ)g+䁏 H^'@DsM 'A7;'̈.&Ir6;Ǫ;y 2kJ4fIpz);- hRtѳ큸y'%Γ] v.(PxoWkQRvYxp>/ׯ0x:[+\@If7ZIrz%K#:&X-'Zg\2V蓪RQ2 B.c&è&}/2+D%8T/"U`<J0tn8B$6}ʒ-9Ab%|mX<( ()}̧Ū$UA4sFՏJ +fQH -B.s}ZNլV jVPjV8mڜ:ޢ1R{MZ(CخYtS{Xj쵿dvq!*َ|)}A.o l vͱj=?nsզ^V"Ư+M^?gc+j֭`6坿)j]gv`ݪl͢ %W_Я;T*NM:vd|WJު^ 9n7UT yl0տUO+֕s:ۦAuimPV'٩$%r>S]H_`|2ftZ c!i4B!|;$cYY> /,_.ZI8՚۠;sDkPI Ybg#Qsd*>Pu%EBw|ΧI:𕕮Ñ DM58p@V]֗?6&I ].S,…&$t~QM9S@abo%b܄6<2%0]zs.0]zsZz.e~۫KôM6c*^bx=3Yݼ\ڶMMNꗐL¯~ IY\ɔ| 0鐻,zFfYm@!)tsPhЦD,-n,WWk;R?,D%Sv:yDjwkɓ+k:0itQٸBwglͅNK.d쵘>rC6\QXf۴rc/,v M>^jqaM:B4TXpWRDamK =*~; c}O4TnK8C@&[m[5HϢ-fe1R{ :Rbײ*L.4u.2*ȒãSHEB!PH(BGnbJF,iw爮#sk]sDe#smfotDAR&^ 9$e)ȥK{ݺIU4[1{>bGYflϼD'm.;@' `@ŝ䛤w0YS&MCOwS-2h鮭jTۚkT!TC}Xf -/OKG{DF~4XK෈s]/_cDbtY꾫ו=mLf!~wG/;S/V-t]H^hi/Y_ Yvz]<h#Kx\w}W[ a/} Q.YvrrH.!AvDAA .M]Ps}5Biʈ~O`\_~9ľQEW]iD]b듨 6}u5G&մ%Ut/q _AK</3G4y@PGwŵBrXJD{eb V4^D泹'Rd@SRW⋺t+GNuZbrmVR4Tjer5 ! c Ϣ༼.%/,hk`+WG*' p !lGj 5H =5)n`[O=E!K](t.IOIV⑖5wCԦ]64iM6h5skpҤuR%i%:V[ ]i.t['ՙ.*dhK߬7R+".J*C(ŪO!&TjoUj͜`>ܕwR?gS paGZl*jie4$0tDtwznrȺ+x\o5<&yYuRw½ນ MohRpMALVK5~ӨQ-p".ze\bmRe!N"ٖquRY*%4j)V;-[,y\`V7sp:0 0?8<;^trBld 6qɈ\}\5!j"OUњ{fbgfw 4Ɂ@r 9ܒ0S֧MP iDEd3^B.ÓG-U}Q$DN5%$aSKifYE/wR0o~#ᵊ{MOMԻ656͏ m]S1@mSںUt 8{?,8&~ݭ+5K+ts(: \펽9jq­"u(}cr {e{'i4c._DߖHlH;QАe 7Z(?,Z(?DU@,JKL E)@Jfrîȣo]ҴRC+(&!|ђNa1iT6i=?YhH+7MLT2÷]E<)e5L7߳|E%RkG*{ëq p5ް&.jᮁ~܋Y>Ӻv᧕wIB: "oŏVȇ\{%7Ue P$ڥÿ$#Ia^A J.2&$VfaՂn % oA%lkHt j[%?ɆjnmZڕRDYVr<4ER73A9}&Az EBextp,!Wd5 ;yȌ (WWRD.D}#a8a#D{+6)^OL)6 "#psD6&Sg8@|6EoyWd#M{D[z+6(<ֹwMjQ@8R}{*>,pET8B>7 iE>K>!bS3a'JD1I^Rviހfk`NCkx^.VK}VXgs8|KpA{ W#ȩuP֐Ld V%X$Dsl5c#OR) d= HrDB޳n±96esMB6QJ]Lܗ"&aGʧt!l|~84h^ R{fD"<Ć/]eV1As &1CF 7:UL#7kmmml qYWͯ &;n,"Qb$u/Y5ʦVцJkDUdJ, Xi뇤tl;+;$*I&U;Ԕ  ݊%&SRA6 y"NOSn8Dj5D<κ8捐6T)qr#9Bٲ27GK.C"_+!Gfժz i)>SDNw ]'{S?"t>&-T#ee)lVN8kHHq <N\h`mK>+r48"/Žz@\໺o'%mN&߆E@j;ڎ\j[XykU]k"16Bġ-j=,ķ+`&-GhoW`ϟ:9 $]|"u:-oNN=' ' 'ϛ0vd:neCzB+rʰQ,ޱU-bAY:q* TɯID Lł[]U$LnW 2THb\Z"2eTH֜z6PS6DGi NU8=!U !هqBV#ggǞ *HIB97%gs~qx?X܈kPGwߛ]G>ϢNߊOI +8,pEZ fuCɸ"m{5jej1(&io!i4e:[C|54VsRkAFiWW:UyҬYg{*#o+Oa!0-{,c;i/mM~)uUDhl1;_W:ɟ;pv=αu4B G:CvX% t)VÇ0\%[1 %[j8CSҕl**)zcMn%[r20Ba>#fSWB6_ ճjG,Jޢ{Tqkf T\Vd~Rt|p4>l+9uowRI=^t-֚__meIL.Njb'D[s\3237LjQI7Z5zHO_gR?s)q=JO׶-b}gR?0R.p.q=J2RL*=fz=zKGد$^` W/0=^M'0XzauIgJyY?RUҲ(G}*iCIZhjiYlV9i^յԿalVzY!F[<ǝ( \+ĭDVzXӻ]=Z4uMc>Y,JiU4/1fE#6m(h2{6ΥVJshj=g3cwlѺkt/|Swm{3-[K[ %KlqU}X_{{o~?A dmZl~t(eޮ4ۏD,4Qu^5EҴҍ97T|Q35Nտt5i⑥on@ֳ:)70vvqniXѻ:o_9d<nVh D6I w(%Q?-ʖWKl)GPՈ{_}_4%DUX#yrBo*Syz+`KXsSk٤ečܡu;LTZgxZ'=LVx ̶0=|Q8C.y)AhpI^^,&RsgMۅ`D6q4jb=lJ1⹵ד+e}?GxrUB2[{+I#U 2*V0@;ʸSIyUm5d[!Suk+jBRR{;3#ch2nśЊNc*[%mK7u;[R] \K XT+jrReU n-1V*굲XTm+H}x,*)5U+[UiEAIRY;;.USY?If+_edSъr@.*|O&=ʛ3ƾ|25?ZM o^͘6RW_5F|(ɫoy2Tg+R"EѤdL:fŇd UekB\+WC9&{WMa/`JW0&syJN=o ~͆ҔKxj"_;z(c_L)]cj#|EGSia*oc*'5S\&cS{ా1Y@1YLJ3zj1S_5/Hc?(%s:gYΟVo UY Nho>9N_/bJw]("ϡuzzG|WcIQgǯԗ<|^gbNW?Zgs}~oJzjNU?u]a~^{|/d|[5ܜϮg'sfZ籥IPy甩^Rj竎tSHZ3h2%ߚf3sUxnnV^`.J>S?n 9Śc^[qf]g5[$^5ked=,-~$ʜ"SĪzP,U/`j'MՍK;ݶ̇UGYU?' ^yӛWE):lOhz͔E(OS-{S\NkG'uMPԘOl(Iښ>_})BkOE/H_IeVGLy\Շ)̘+wR-;M6M(Z=v)ʼH ƕ'-#QJLrE0PZ%$J ZJnR!¸&$JygKotw)':Dmw[jM*P)!gz{'BlڽgR=ӯCq$;gUm)Rhکd {AU\91NN.j:^J"Z%j{w5|Jjʖs|q(#e?m\ROIY +//BuZ_kY«X jJPDob):QTK'΋lC?cTBY(+y7dO,PImA*vW ] ̂Jc(8W;@je9fcC۴ wTgZ.\0)*ڽv|/o2qɷ3)ْk0ek< &}7EPVP՜*UwZDT"3ߴ%m:?oM W=Uos;6U7J]7 g7k-5v[#+Bwhpo^^xyLǖ-)ד)ҙRe\CAC7S̟Rʫ Q{9(Yedr/;DPgUcCTcϩfN5{Ӟ! Grx?=s^9?tiNS akp K1QSuW[[++^ #V7~!UeƙÇwM4>tkP55ێOZl=)Xot =PanR|{^˚RNCV_;Pr u֧֧-)iNdH2U&37۽eHSBK:lVKZ$N2RkJ RmL_Xo]&5{|X;2TVm?wwV} ^#Y/ $RJiVl}O*^Z ,T~ޡ5`|MBG[gE:/\PtJ< ݭk) t儖=6,Z3X˚=Fs1JQUzG2Xv&)_W)^tNS磫A5t+fthJnevWΔZ]o]-N2lg[Ny_ Nq3zU=jX`\TCFNEq"JlU>IEjԄJ{{nJ rjݻ(ZrE?𙔥vР&OLg.8=a)9')_c_,7=j8I9м&d=MvJK"o<-5ӠK_("׌ '.k/SMI =(j坜2&m#FJ}jNf937)==M0X^l~Tl^)*v( le?R\g}ǜjJR˙3J]jJ+Mja)Q|1BI35RD®Bےjo7t}&{좴tm29unsG,v=zi&W͗^Cd rFlwr%*C:˗]9 G'W!z1o(<jBTUFW;/M2PR/TC9z#V\ME ğ㓜gԯ\SR*\ܪ0|x(b-ͻH0%HQI\j>#xoM~zN'2^<&zw|+rZJ{G[9(/0ۻ|4oFJ%N-%T :tm:_v7hں8uF<)od}r&o~iJWUHDGrSOi1UaPe*l^wfkׅ?zD3KS}2]i;QY7``+-c{S\8bG5dkxk &oUR~ҫSOsU?EHf==3V~APjFN2r\A874]N˚6tێ?X2oAO\~r>vVmZM'{";s;Զs^,S#a&@?+? Ww Z _3d_e͌:YZeQ;&j*Z}s9Y}JXۅ^\L=-1kRuoW\:W9ktU\WaJVJ4gq TkG3e;R;w!5*$QgڟB gJ%'΃vLv9m1}̸tV5tu[SD;ɹ V WXz`EーZzYZ:k}$.;R2p}~,\O{%%٢J`VO v>Pza/$Uc// SNT+i|\/oNͻr>N+ vD8JJW%LӔ ̜B]95i|4E+Q>sa; Dֹ]%|rNNiYV}43 y[S׌#Q,!np ,#Z[u%_)uo,=$="NK_/\S :9ekyCOe%4%ZU'UuTB WeCVb""i!f :yMV[.CQ_>9e\z][V" e(Rpw9wQ*GU㒙>N Ng OFԟr1).25&ujDz"EFbHQdB>XSOdX4E-t?rTJ~/W|}ԭn>ّWi;Mut;SVP]*cz&IIBMYQ~4:EQuQ.˿<_YB|巿FJyL_7whf$@mQhUO7!㜸U_A!c}}O&tw!]sXKߟwoOmNQ'ƹ%Yo*梔8|0s7md-IǷ5Z(8ZYًY;pz_Jkios'h uKc5go/%?%vWx\.yJ_IW*6Sqݣ%ߣ0@5~tR]m5IWs|`dIGU\{uʷTmbTL%.KytN'7z_{A@6^zmdoa؏R}Ư1di8[I,}Fz)<ݐ:[]_}R48O5gMb9%ƼCI7;i???ʔM*gEcMuyCjq&i>EښCxMH.Icq F9U*Ҕ7{^S2?W*:= ^x: JLٻ7H ؘJd 6~喨MeD3ns% "_yWc3B 9J3!~fNIyb=&=bGͷRo&=%pYo:/_O5Yl/4dpK9˾o2= ](I|U%u{'{䥳Z:Jĕ9Ta7{濦ҜH)[oMiJ]Ѻk6R&o+rKwjI 9ģZ^q|5vxHIZ?ZgR[ύkO,UNV-&#^oidf҇?'pI7y)jjrLBdG)MκKSҢ ?dJKnR(?d:Eu_5RYDx-y^m5J9%#Y}GH= ,ruqMP`A6,KA,Mi)K h,?~3.!UtbQSΗ˳EJEXQJ\`P`fΰƳoŚw^zG9%A~vR(m{3]͞.͑s}.wcN6zzHÎ#sܭn10C Ėd^\Rh#)%ue뛥e<\Pׯ^]S/VzǭJI>Gzo1@<7gu `tt7޺|xkz?4o,.`|ܸSp)o|q.(q#mɉ{#_z1'ђ*zo H̆ŞhAк撯1W(]p.t"FOQќ~ZFAЧ$"͞NԺ4fI ,(%7GcA/pAN#neaqs?6yܿj0?b>x8l+D N_k,5)m{2'5RJ=[|`P`fe•v-a/'&V:n4H_MP@~'AJ+K4,V˺nOTFJ`P[9~eX\J 0TYz8h!$.(ڍsb.4kt-\aO嫦WBNB˗5߉L=\6[ѧ4EܯD)$ ^^e<׵h 5*p\5COYee*Xjmkbw\I(q(f"jJݙiW'#^ { RA3ZʩoWNN{֞Ϳܷ@- f[W]la;i0[:y16qqfE^*)+YݚcWyt(SWd}2&vTR *Ϝ] 7Vd+8@"GJ7eM$5T^m X]=^Yjm Z{/P-A!ߞ;Ul A-*-ԟP*:7VĖ}|m^jQU7h װM~  a}hjם+7- _-|Ckꅡ'pqpJk5n$*(7c1϶f\P4۸c"qIKm0Sv`sս?۹4x y(7TWDi?ZBiMw4>:ŌEL,)gm'[K^Zg=k3kc*zƨaAP n79Kg܆0WQ(/+ vk_ k&k ]^[=-VrcsUGε%^`De'Vr=_T5JT@z6sNɀu|Ek(h ЕږTҷdv3ZCU?M!FEYewlH`P4n\r|#.H- a sAk W1 7qZ7s.:@+g6T|ِ4{Fy_qT#qT jL옿.,-HN׌ТhgpEӴmVLt4+%0(m~vMN.& k0(m׈"(֗1mʭos.WHnv̔g:~B K2$3c\ l$fmnnediֿlڬzc `;c-ݘv?dI\P{{ ;-o `LE}(zhδQT+C.=pq.aJ܉;֭[q2P'Ɵ{x1r =.Dۜx UnhW(e-9iKfʗjP[n@#3>(fyiybfg ~'HẌ5(ANWzGvؚLF:x" v#Y.|H;k$Rx0$h>:bw"{v/J b twt?۔dt- lpȠsp ʷe^2^C;i(ޤNrP/I[k,Ľpk_i)C\3K  >%B$={FϜ mlyP٧M􌳏J烎sq*s; d;8l CV_E5gi8Re,! } #RSftid IwQaG6%9yG; ^71׻K70(1*Ri\0ʺ0Iu)GZ&mTJnM)bsa-J`6딋 n8dJ,=p1XB$j *pkM˟ZKmM#_icXrrrP3v}zK 61f[= `WbIzQ T3Xڱ?tѣKi͵Q(1i6n=/{_ ~!S3/䤇L&穗+?v!pWnJP[+o6WWنZK9X<9y ֱNeZ<#.(},9(eT}JYQ@D\iLKVCB~Z-l Aĺ98hibE*(Y\H)_P0(gI[ڈm-0gf 'YTވL]׍:v)$ݚsHBZ|پ!%}k7,`}u3de{*+BZSu qh(ѣ2җOmr#v h9'h/j `Pìش4Ioo$eoDCdJ\PzJ[Z 0{%.(m;[b/Mh &iic1똺~6I o&/6Rj(]*1zK˾S6P$.`%>2i}5[0(mW2lcEɣU>pc< I,ufaO=?~Sش sGT#`*0QXTSM hQ \P[V¤&Fͺ8"u:$0(RFz͔BKvc>m$d ☽Krtz.Hҝ;;zcG..7YlcVrV@B=6~aG:bl?!hδq}S/~+E?jcFܩUFI>9G\Ƶ f{C v{r+a,'עO?/,: `M?S=2LT61!xsjS凉n9_KK7Fp$[&N|>cFWZ G4oSE`WU4:|{"6U<,aE;_5@G{PF§?@ n-PT?Mi4A!<H8@I*KeM'$0KNvzdn1$2*ζj1a3Ud^r]χ*I=)q=JyNr^y+i]AI4oN)=OJ(1(PK`P{E+d-4RZJ `P4[YY[JA@Q ֑MsnlPF e<:xlwAz@₢z_sQYvS<(Z:죆%xnʏTJv|$,(9JTNhAMهfIsPKeK&@"Al4^n3m[g,-%hr v̂kjB;!A:* v岤YjT-=rبn>~E,% heS8ٻgbH ˺>lal%8i2kVb`QApvI|@pL{ipw첶ywEٱGbKg`JNc>j8pJ\P;}tbϒڨsJZv[:ﹿJi!v_dֻ޳޳Wy$[t5-v̴P[0B)ƕh}Dui` L{c=? ޴ ܶ.Ft4uC vRXR1=UK_p\ suE; faT<}U-L \[KHo9RZ9RgGӛ:hƪ*4*{`ߵDRFfeF"Nh 6t: 5bBaBcl\m,GziO @ O{M|i.0Ohemm~.7Eqc ` cGrze Iwv<:4]^s6!WyWi tc~dr.y(K~kv y(Y]-0(ڭ~w ؎K R?YI\٢UqEok7,I}v"$4X1'q4B#$;iE .4Hqq)D]?u~q$ᶴTGCႢ/KF=To Olw o ?J\{Da@tXfa3)Ð24H0La֞/=*ͱSK! 0A([*wϖB^A%0(IDs-ehxv05>l#G[AZ:}pANKΟruhG׳48s?w:W.>X₢҅iI'9Hh[r}-I,k%.(}6.LJ\&1@tsθ|.=^99K`P;w4{DTK) p}v X'-YFs0gڞ(]Z$A `My(7ZopJIBmKϠo H\; \MotX"^?-}3/>2iuo+84ލ `3aIzf1RH9@L(ۧ 32:m qA Ɲ-m21oH+JW?#jA\pӞo#r B/|~/MK0ߣ!U3cU9ޫY5epa\ΥtC3xTt+}q/= `W}OJ1~'E₢ٞK5x0-i ݩ0QDE_59W:{G;5/Omb )g<}s/=icQ+_oO o vHXͥT*ȤbG㍣[J:[sv5KnH}^EC!yEvM^$@A :N=~e,c#6eMa7~n)Cxwq[#![{q)lɞ~n)GhB tuq `;RX*r{hq+-J'04]NWqg%Ɲ.(ipo^=.`|Kc}Jþ% v[rR+_xݝoKﻔ[ƫqħ4#rSIݯl-}#3z;WEu˻_iOグO*/' `P4۟d:]|ۃdi( 6bqAnLGZha *T}L7 q66hď3sN: Vir{I`P4%C#>F>B#8$.(ڝ3N/1-9ƽEqI`P4!|, J5i^ 0%&*~qhH Eo`BsMCמedK#RvrqANW*n<6߉ucv:eIU$MӒVRwU#:$=Ό#Y N{޸ROUI+=UU)aAn\*䢴,[S}T~_D$4-LA\8o|<ץEs]jF ^ø-.c\R!Ԟ<ؕX1(ݳHQn)n "IP &o WJ\z|^a-=숕M۱g_))$VVt J`P45|eF&2sfX;-[WЎhAmyM߱oRya9.坪+EsX_ i[z I[g܆t喧I[tqAN˴^{޸cRO1Y>z"wLϏi|ʇ/35rr_xG%0]˚_+Es_i%H4۫ZBG}Cq=K!)kCˀ?DaN.)QAntqZҌ bT)Jh ?Z)B<P"_i5L atMZ#~x~R v)*h]G1L1ZD5z]tubI6(G#~S fM.C)F~֗'P'>R!S74|  I+P|h`TpN뼠QG+bJ'0}( /J`P4ۿ|U =Tz$crJTP[?4{@`.1|q\$vyZ:&9;A@ڐ3R% Oh74CC0-K0=d%C$k=.H]>Rn Ţ0鳺N,*bؾjZy;MhbJ]Pw xGU̬%FL+I (j^o{JXzҍ]f{uxx{\M1:(L6X2+_3oꍫ ],gwQo d;xUD0,,,=N!yp IW!!2br`_A>*uHwJ\P4ً| .f5%gL6hJ;4*wv2c[K?++An\F,)}=Hw ?9rڕN_i2W$6Ҕ!i vQzc[ѱGzT FKPP4UQ!_)'0{Ў"gZ₢پi+m#A^?C3Eqб *Sc*t٫*h+u#XKjW{^UKW&R;yXj!'} 'ﮓ>2)ySKk4xa_iHsGtﶯmQ޸%.(کyeU# -+ְx[JThܴ{%.`JmhaqB= jՆp׽(9[[ E2QT-0!} ϽJ@Kxd2$yi~s v7Њfk )ZAn| v*VD\S*ʇ~Ko} bK#C^|poԻh Mu `#HS鉘T|vL\O.q1iĥ%]qeZ6Tn `G|nީT|dv^k]ݷ;%.=U>uy^祢hֵ<ګݷ.ԫʣIG<Dig#ӹ~XxNg f:KHw-r2u$ i\|yZFƗf^ǙYA uwGoO&A\tiMIP1}-lP#'袗hw.z+m5N`{z>ˊ8ڼ[@;έM,rз"r Tdr,ʍU@=NQFY-=)bRPe65r#_%0]Qv&qq*`P4|)I6^Nw.C[Q\+jyQ\K*v[S]ӧebo vods$=)~3P>֜Gzt>K`P4|6 -}mHwhoE<}k+\sufGuiVf09@Ҭ]7I>i_m`.NW|,5ih§ qAl_86aJ 9d3sjKU:o3qwSgޓ|wh].F[4Knc)z᜜/k}ͻ#֦Wx}LYeQ-~}.PAliPZQDyA:x m;BQmy_qw%0]"@)M@3+m$N`*[io2^G{}L=rp7!rۭvcA' `P`vvqJAzlRmC:NC04$0(n 8D4 M@zA&D~"KFG4Ӷ7q  v*V7JAi'1D>G%mCsOQ  v̰*@zgOax7aPIޛP'ANPDj*ā$0(i0þҗgr5u+gXt=0d?Kj~|HsixN1+'k`,#S|]u˕ x"!ARbC?g.(iRjh͗ccw#1:Qhvs<6n&55k W@F$+#e6Ј  Pc{0ʼn(`P`fe^0H=ihMY[ҹPF3+m0!ACևvAujdڅ2xfڅa}A$ `E\b2Biogd@p PڻnPFႢij0mDzjGQjiL/n ?RhLmAmaѢec AN24*>{Hy1ճq PPS3zش_A-Fl0(i03AwaW6T|af6֮^ئoHX,)ilٻamM !JqFb%9+QvԌܾM_]JǙyn9ӈ@h>ɑܜ__3+!)ecsr1?Php]i0 (cN5,(.(ibs,{. ٹ`,@3C{X#_sCջ}K_ߍOa jf!a vj^^ Jeyj QJXCjgMRgyQ(XPS>ښ`+~$A|P8B33)G=neHL("6NxB3쫥O@x{i|Pt# 4ݘb.NX| 67>Tʱ9ݝE; fWڪ*&t\c5Wx\+FNMZ+C2|f:mpi0]"1" 4>SaF<`Gjb^kcA vj^G|1Im%! tlCi[k qynXSʿPFL BQ" X?MS 4e6th96 `וm1:Q;_mxe3y83?5Ox)\Pefc8*H=605tD%@ $pANJ0Zuzl :RwIc2WR#h4ZWw<쪑@cX2R_򑹇YZ"!%RRu $&S 4%Qh J)M&UN/8~OO}Pډh>,Ȓ"+IwT3㬼Ca11 Xǁ[Mk v̰B\(^ےSxDș&Ò K>ЎHfvBEDU#,g{ڍ1zS$ v̰ K`ebv|?Pz2 ^Ē.`V&[tSB v̰§cB`f>>ͧo.(کyݘL4T^s½>O* xGP'HR$ T@zh4O+yF+K.&yFY>` Io P畭C1A!$4XAi+ `Xœ5X i !77תR t6mMaOl_ȍ IϙV0C:t fHrE; fWhQA)}kr"ޫMe| PEHQfFD)tl\2S&1KXrJO|ҶG4a_iۀO14xQUu>~'^$qANOv" a]o,<$AN`dGʚB_66m7[r#DJݭvj^uy1{}eu>>ԩ1Bqp71#y}S/"y~d[&C"y4a_iO옝^[ݛEK:4طG%.`=W6L.]Bq4 vj^GڀH^uȧU4%ɓhʑQڢq0 ͊Ӫ`< vlismMuJ>RR]zډ)Z(U,92C{4a_iDGbdFZKݣ!F vXF/On(I: VxK+%eEJ2YE; fWzK'0#]]mZSy-}$4x*Ɯ.IKwg'/YV@v_[.`T& 5&`jx4(pAN:AmBZD,XK^E.HilBm=6Lavc*/63Xa#FH|)T=1O `WU]/OPHS,[L {x|QQecFvQ'I}un0f ۡ`E; ^9fLC%IMCs,!Cϑž<(qVC>c6JXD2_%0=ҕ\Oo$ 'ҕ&7ӕ}k/?F+m[Ƌ4J`P`}->O{2HdL!(=">J`;lOrDE L`v%.`Q>(?t- I\PSBl) I\PS& _7OMAvL_|yjq%yqfVno@J\:.Ⱦ]d5;@̊ж MI`m ۣYgcDRyqzD"}s/BKgTĬI5>u+hed)*sv\^!Ku Nb[{v Syzxia#u??4S]EOU@89"R/1yD٩"ZHЋc HK ڰNkf3AL{ћҶ_ӛE; ^WZ-A:Peg'  Lkg:=L}Nl"84a_ TzT1DdPHvj^P$,p I6%HѾV:vdh-"?=cɜJk$0(i0h+Yl$.(8F-mcKUL%E4%xovK[֋ j̶_]4p(=ZRؚP$+2UO-F$0(i0\h1CNR=ul)1f4ܡ= tґ&M0`+3JNqANՍ=æ9fPEѴ]6Ev6PZiL^ I&Ńi˂SsJ3IE@E; Nfu1Zeyl ӿ^-*P:>HM'+,iD0 XDaHe{0K]{oKKԘ{tS4h-oK7% `OReW9.{MwU~a뤩r`νI* %u % `r0 H<C">F7 +C)4cnKS ̧<KuTd T@zr\NMt8, tjN7'GXA[SZ7(+Ch]pMU0E\Zq0%ANٍ A̠B}zIFDC8dqo"Y=.`4R>G.r>z pkEKq&׺EF&!RۊtAN깿cI` ű*#8ǒh̴|6=Y]&͗v3R#;1H)>̭ҍNz&DX?5"#pt7:C(igMRq! X偠BxFfjRvg" $쩥2|(Bq7(Jb `Le_NF₢/+d9o<6NKɦƢ. 彗{S\y+>N!qp^+~3T̊IkOxmGggx( E}~r9]"-4u\ii>g@_yT$6oQGNj\`}u4 F*EYԟJ0T!Nz FͽFI`F}rے h}msJ*B*Fާ{0T9k>6rN{ [CSAcL"~ZhK%Q&iܶ0ǧj[Y{0Uyqףu-h'Zh^į$0Fۜ ;E; fWZEN`}djSG4nXE; f:h1L cpJx@&9H@yAP*5NJ,@]FD :@j6>8;@k(ҵ" "pTcsҺ,?S1H Le= `WCe4xݨ0u1E`"Ԭ ߊi?~il4Xٙwz'y:,BjmީzM(j7"j#מ*$Q}HgH5^zm!1 `DžWc>)EE3+ҵ pK`P/Kqu? ?ksB+;~uJK5Y$snlxvΗp&zU'H#!"J]soJ bL~0g^t#"&h&u_D.}m:s0(i0þR*OW,̏tYЇO0;CV [z[q]:DjF OMKUS\z*#Cg>6@;#C+{0յ&%ˍi.NAH-Mo2@,D7% `W-Y`-ृD<oE^]{o^Λ%(qANA,T/]mB#:zi6UH 3pWr8o-OJ w%;1v% *ŞKH(I: NGZм5&Po,tuB?sM\3q'sE; fWZN`B>z c,"AN!}}4Xn{uC!sB$0(i0:%@ |!Rh}anbcpE;5+3ɡ#atsF}[pAm[6h JiF&;ezm,:-|\<EL50ͯ\_S8Rsj{v vjeӲ .#m@ `enA|*@*o>P@;@[([]P_3+8@ȹר@ԚԡGG#GkXz  cؚՌD*Hҩ*Ciͦ1 -^.Hi>ҶC9bh^YW^)Ro>=(6Dދ?2h>sz_3^WVr+ w d݁3G=ȑ眬aZ\*>,d-uf}v]C_]ecJ $a#Ȉ(qdfPR>+AWA!hXq71%CC0NO3=eߦ2!zq fJ;fx0}6xcv GoJzޣ7# ` 8 GJ|n%M#P!#g86tX ){nJbA XǕOD9ƒN/$vH0y~ M &;0>ƕ6b+=nؖXP 6_3wI,0q+y9Ep؉?Мq=%0(ڝJI2_w@2I1VX!NC*ф^%0}g5?7dΊ-MC ^%0Nk& 8KOڵeK*8<BH&ynwx"V,F=UBSo1eIrf}}羕3+lggV;8J j[v^{;W4yqJ'v1v۞$>0.@Α#?L:?eԼ}]<#vrms}o#n%ȻvpGzmsj[ $nu2\\ V9w]8δ潿nyvF: ])ݿzm TnqqwD?]̴pӳcͭB:Z_ M_t_R<]-tvF y6~s;Ii h)E}>/lę9_7oWpws[1,Ey{9qINC\9 6 簰F[xϡgZҹ\IZL,@#ѕz90Qjv&4^=(V+P۪v;Jf\Y|iҶ\_88w(S"#󳶯ǹjhx? 1@pg#s}ޡL0psY["';Ij<)0$.hb~(ĽkxJq w%lOgbINsiyc l'`{i/Mب\z/mT識œ: Osp8N޾ߥgd;;r],^.W:qqj}/պwui PAe:q'UęyMj̸4M *U/޵s7ݕ4M]8nyz#qpFehu5f6pk\'53t|L縰hpfpiQũ!:~DiFb18rK'/80@#iƛN[t>m鶫r! 6Q;)d\svmzL@9j}Y-ΛMN<nJ5QGN*k۴Ie.Mw @cϹl75lrIa-ڹ{pFFw+wNa۲ 0Q 8ͣfdBKFu_3TTҢ)?U<ދjSvz=}퉰 GNTfa+ΧQʙvV2kvg5P@#ٱl97Rtڎ%k9ݟKZδ)0p:I{Lmx-1..p1c\\kK;ew]8eδySz~ \ˇZuJqU.HwH@Ύ+]n`Pւ-Ϡ gWя_[묡m1\\P!=E3hę;O"lQ j96sITtv] l jx`\P6>K/hbQl=}p 4)NIs?݅3M=pX» k0ӢϭύoMMҎ4Xyk'G4#۰Bs *ixpfpniD/ jmƸXrj&phiqWyRy]HKm8i{ k0ӢLOqG 0C4*;\ۦ]Ωl9q&F e;XIңPM )uZ±&FVsEK4X{-'ݽڑK>"̴?m-S{O;"vV*f.;ݖQ:W˭]?q!vr T ㍤O'I)pUvϣNS<"TͥU:SE7ԿJ@x/ƸۂvTgӏ3-r=;۷Z}AԈR`\ -K;]8"i~kOs R`\lxP짹pPD1+jh߸Ή343N.Z6h+16w*Ƶ!,k7݅+L ]<,nu-qQIEbA8yjX„6Fy~<)d#:u,6d{ Ij9 nڪӍK:3N+Okό3gƠHnkM&V~x F)0g$ǶQQq3LSaq%\-Q<) hb^^iZ% myy&/ǛIE9tv]*E$̦dn3X}mva>NXUۼO*Fg~ Kx츹r~zmᲟ&.VG7h'NO;8vK'Pv];v`Qlb|_8W"Hcg{ACӏlY w[NZd9alb-sxHTaq&&H:>}s~C0G{_rl6}S7T9s\\qԕ&v0@W?8;N :ΊP(m4V6n>jAqqUItMwp 8"Wpw{j߷p4pQ|w׋'LmqimV}G E8.!vVGFp 3:Mx(jg6liT>Y>܎ F9v"<'0?-JQVnt_8!P#i;D3Gxwi+Mڨ: ۷}gK< vZIIGVEq/VX={VŇ4ީ'~ '4tXy%i$@#F90gѳ~>Jqu7-`w`@F|X=m<%Hz4U _xdV[s qFo )0q?GJv.J௷ !! &蠱:>r l''h?HqxNy^c}RX5V[k80#!Fhd#\ Q| N݌mv߿(_Íx`\gQ;t]9ڿ(q_9? OU3祣A34f6!I;çuL q3PwNt.t'?gU ZLcInL⧻rXqE.QpT$svFagJ1Ԁɴvy^Lc\'wR&K;ܪ}M<vv$vGN[t>i )]8ԂJp'gcCQ &F+AT ?h~.@0–$19GD8#[|& 9ov=OޫM>xOmA%@)l)41rnBy8@5u2\\ n>5t/gZ^'j9M3mSJeI[۾鷿=Sm!%{ Ogb`mZZMg7zJ8 Iy[? 8s~zylBiF6_"}?* a?wuz0h>[jxۤ-; y['3-NUGl5"8#[H3} {^|:iy~^'z{[P 0>ׇ[M UwD 8Co|⛨Ϧݐѽ:߾):>'VZT 0>-1.1hbѩu=zԊ?V PCF?~@GwkP4j 4ݣ炙@hb|pp * {p@J?;4[#fP|&ݑ)^̥}T#|Q jƶ^e?礰mbSQm鴻Stۧus{uhd;c0ZiwCYowo|9xR\|;Ad:Ek~q=&^N(R cLҬ躟k)A9Ļ k$w>ErB@rgd;!|e(jLl Z|mo3rx`|QblWX7M =j u=gg9װRav]!418מ[XmqRv]!41~x7;NwtOhv0VaNeJ''v`yBshbŚFuߥ)>Y?5(\?NgbaZm﬿ X#L4ńI*{(2:YA턀:_P\ ^Mտg%D@# PGJOErzַCc'vV %Y=@_k<^Ŵb˿>t]`3-r)ۭt{yw.BCMv׫31EIw~!"Hp{,T$Im/lg41RpcX]lݤYotȶ|[ߵ%lcOiwٔm Fd ^Crzp/]=o~ch$F?{F8ӂ,_c.gh_[xk3-/X9[@ P[pq&Z/Sz_wy]`}ni8#¾_M(˃P=t1sW'b]D ȶ΂s{yr8޷gZi-?+GxUJF%p9r\?eb.3Cco(Ë)J 4-3އyvn}{Q4-~}(Lۙe]H4'N1|۴J'GÄ>Gq$S]F%)% TqFJ(⾳-.zooM5kW}{a^/jx8#¾;豟lcۣb6LZ>.OvNVtyеk8#[HA|$/{yvՓ'l1TF}[}g[gjxLhdI0O)o0v'ہҺ]`m)Qhd[g't~Pl:(EaFlz)3icNЧR.f`9 xckL푴ljFpdf:9F3+2%Œ=O*8#98;FAs/l?~cmO1BchEM~.fj2M4emQ3<{/jTO(4UQpknhӛ? N9mG/u|Q7crgZluҿ_W9b+UΊy($AgA9M6`8iN׽k0SFs +T-Itv޵z`GA{;,phRX~،@Cw夻?&hd;x%q{xv=YYκ)ұaFNM.:m+1SIQF* ፡B8_>W3:ly=r~ Wۋ?R -`9G:M 5?^wU44۵Jy?=^{=-hd;+xîAHݟ m$EQ:[Dc\\ a*=t/,gZnEse7Q \\ 9t33.m<4SQk6i~ۋJ}a> ֐RtBH[ 0~c<]mhd[gq~~@C-=[B6昶. 0.d j^?Y= >hRMp6NVʠ<>sџ:*S3-Nn.˫G9 bkD)POjS+)m D)=j;{[xRy4ȺT&JoaK4jI~L@CdrtD$Uz) xOoFp.joܛ;=!JAO*g?WJ`eJsAlgů|o[{e3|TzB?N#`?-7dh[g?ӻl vthdµε}?ʪhdKc(ۺoopӔ~$+!ƔQT$ޅ;mxLMEM=./hbH}p{9}XT8.J Շ(Wp~8@C*sߟ%Ugd;̥82v.d0N:s0@#Ya.w[ :o琬IEcma:/SB&SsЎk^lK,./ hbi)W@: 2M6{-kq9m}[dRCmTsI1piNe>~]W4h|/DV(D-.*8ˑWU_\neB{gӲK\_Nδ8,ŵo>h59⊜03$s%K&ED4((#YQ0Ee]ɻzjyގJ IE`QƵ M 5/^|gVC,ƭNZ?kMaZ1Fd~.{%3aEp$Q'q=w~@#4ԞYgQJq3 JqdgJ-5|&%IuZˏPD-( b"JdŒrU^\g>vK lquӷI˪_bj>0¤AJ!M sR|#]yqO6de4fW@c, ڂH,{ Ƥ`;(-wG,hd (0dt(Ux.YGXA歛X9ͽF{4=:펲7SWBbm*QT__KNҪ5jUI$eC9]t.)?JL_gr_Ԋ3 G<)_\rz= ,ZSp3oA$@-GV*BsJx8#[XQNkNӰx_SJx@#[\< rP}N:م$q{(rTƣ]0I;;Stj@U{뾣-fh Kuj,4RDp/Z/vKpoqf *<%L{m>MmM`G[3U{ʕ41qpY^|B@#[\!TF^ Y"-S֙ލB5JW'I??X~OӠm <_2brg50Ipų~T @C22ICjFTJ0Pk&Kʗ~Si/V~qF%E}0WNʦ+eS*M,Gy!^ulK+ez =̴(2 㭫jNk αd΅|-TH:T!BdߖEq/0H[`Sf:Q(iSs^R@:q/%wu5=8r[ (i VFOZ-"WI!z Orq :"$MR%sn e6UR+<ݖ4>:)i۹Piabv\ϯZܟ^ >Ip']C9RR 1_+[ڭ2^T̠2>~ʷ3p9:p 4Hʤywik[2֣phd;+8U܋ٓʪ4J$Ud*0ӈ_s!#%uu{&B-lqVi^Ix=!>P%qQ~j@C͋ƏuZFq>zq$JNptvuV:3[0c\E/W~;*ƀ3-NV{<_j3m \eX-KKī{.KV!>4֮D\Iyavg?08#[Xq*k2v.dEJ5 n-%ZOsZ@cBC-۟6Rm ޹^FykAOTEmT^%a2>P \(Vnhd+(JmYBϊD2 Lj2df]#Iꆴ;,5V#d5SJiI`#Ĩy[%IV(Ƃn˹{PFkֻR`5 MqZ _s%y%ǻ5l'Utۺ&s!uE}R>݊dEjN ~E5@5uJqF8Ap(WTSL>s\j˝ 5i'f(ih]gnI|֖d34ũks>:HL|{j49um57,"Sk b94JT_(#P LΥ9ZFFdL^y|=zl'i:Jp%p% tZ#P+¯B|3k 9MtT!_^?-@0Cxf.\x>Q1<' 8ŒlK*|S 8MwQ@ Lzq&FMdY6jqfQ 0IP~t@Cb;Y/+QrB&FVW'gJb@#Y:Vs~]{g[Wc1&{PFcaz_[1,nJ޵^FiaRv[L|~ANaT{gK3)pmɟ&jkµ0Sn8s){WO V1@- 9X}<*UJÈ3ťaeg^HX">Wys˒Uhd(~]2a"5WzשZםҨR"FHږEq%G](g<0iY5Sw/'}6y-KaN:r[/̴(uu)TD 8CS\q.w$s.R)ߏD,fPj\_δ8}Fnkv~DlNn1a9P0MfRP/_0)/ؿ40ն6 0V~Mez9M N{XuޝGTgdVxRysɤa%q%UCk1$8)J%:U܎Rma_3%<͹7-+v>s|TȶδQndM7m￞^o_t65 '%z|8bUmVO 줴y""Pvކj̫sٖ66{-y>ϱk OT(]s~EE7{IucC2ؔ=|7͕>M \AkRz34-+iv}|+_0ZYΆ"J'r6eo'pJeǍ\ZtT>lKwHLK}Ea^"ې|@Ê|\gbtFĪށ3-/" 9ـJù4jש[}O#ȶQ۪ ?YW)4 qF%$$qdFO;ԃ|N&F qVr!UO$(Rվ~܏@C]Է~Hzc  o]p@Q6=819IY6$zߺĀ8EɫdD% <߮J\ ..סԇr %(5օęgrN[kuqF}I8;3$3}Q]@m i8UI+*+?%m-_L`@m i8u+ +އplb2ч4ٖK/_S]>hbTb!`[_>Lti \I8鶫;W8uu9_s}<-N Q,9"дL'EKSro ) -7prGan L z4mٱP>vKr$ 09;+ QDv/) @#8F1)'q0 APM˷#ws"B ȶ(iuԎI{~H>.nDR;+ M4W!w[M@m i( K#x2:^:!g$JJE@#MuYNd4m*o!si!`'Mr@m i8UI+]V>O)Et@m i8 $ Ȕ}z oOsKl qK2v.p=^ELp-X_^hr0nKV"} a&m~A|A7ý-I?hd[g(έdD\Vf+2@#8FQ˒y%WIaێ ENCY.@c"maIдFsj4"[ uglLڃ4@#8FqAh":vHpOf=JG?&%"fJV8C+;z~ew%TY6u]rP*O40Cx"&NLY'OUZy]ihd[gb%J'ӘOwϝSҀiG3= aGݧwE31TYWsXڽ|Qggd[_(b'5{tw[? n@F# X#=f@r6H(*J lKLŌ])Ž@/Rudj^o #4-3m*Mq.!IAma_ bmI)Q/^9J} -1NJ20օę'v.Y\-t~rDgZȱ(\860#®AIK<5w'AB 8Io":@/ e]40@#8 vÉ_dNs{fc:jBJq/gp8tAAacqBc%ƀ)/1 Z?AXh=Dy!P)9;ȶδQ{ LeMJQNgd[ |Ɠ$Q Aȩ3}_SH*ȶδQd>K}uIKgd[_(mAX~G3h{%8mELa841\ߣ%@#8FqmWJq/drlH=nٖ6HBﻊζf_jȶכB%J҈OԉkDpF%b$s/p/"U! '&a~E@;9?hRIGtX_QhbX?ȶ/i$e9[ɹS麢 ȶδQLIڪ(~CE?I|HIGDpX_hb(g^> &@Iڢ aqIDnX/E=̤ r;uy|\8T8#¾AIġ?)~o[89P˲|#믨иiԲ\,2/h41\ڽ(*l z:Â>D:k{I5Z8CbvBvuɦ( );L}YԲhd[g(&~U u8Q"4}[ܹPZͯyDvf},9eJ$5? Qzabod8\`Uo\ޞyޛchVIZj &rv&ܺ/9.n݈4kL L͎(=ĵ@+2ŭ!AfMw~AB)_`ͭS&\f׶, 0ވR5J rM Uq $V 簸$Ѭ)u/hQ3-L8st9oki2[[1HH(yδ dʹ('4F%p_;% $5\O4?퍷΃@#8FGi5m 1)C<ԮG4jt#֤z&*@o$ L M4v/SpL4-3msm  L4OP%4F[ܹB[H["f}NTvhd[g=GJ3F"2x wӹ/rs PPhH2/L41RBڡ!~UIM{s]нhb 9t4Q RH 0nxiCs]BRbʃ<#A0U4O M 5g sݡF ~]Sz&3]hbع$zy䧣~Hb4-3mv@A}*/ l z >>XǍ*qqJ8PV|jLˇcӈADu/Q3-.ŜU>=$@3-/m^SY}A6[pru3Y]0i \7Ϸjb2-HT_s_y;i{p{~] rPԘHUY Q&Iş{B0IqOT맺!ĸlw>?d3-# 'DSM{j8#¾A$S6AY~}_Z\Iq &FKAuxJ޾7Q 2 縰%$(ieaEYwMXך6!V˫1۞$ٖY*ՉVëAF C;Έ &겔5`+v_UC)N}> ӼͿGB VUްnX;dβ25F%pH =3mד3fPu q(UfQVd5 'X}J⤿oGgG}{Qjy쵣BݚF%p~έk1B/ (/ 9zαZv KM hd[g(@Z(B5,n?ǫstԨh4-3A\@#8F1%*s/;*/MN;QQXOUf`YGDْLb8U^V='A..n] ) -Lʳ! __@ℴƓ$+o]!Eiq}!S%gd[_(AdR)L푲!k$ MKIܣ9#1>{.Mhd[g(f@~M2}s;dzJs,"lK,Ii.41fRJ7k^o0^d-W̊&J?mwz.WeSPk/41PSQMn*mIA[x߇T<: 6Q^3%wzRThd[g($~Y2!?~`km ىy"Pӵ~lBV#pa?dS, w]gZЂ\|Sy9pF}IW(бܾ&Rs)F%plw)ou=<4i=b>Ʌ4b+TWo7dq$ugٖ6dVKS}8m~LQm  40kNĩtn>6c#lKL컹h41\&'L@#8F!kAh 5N4jD_hbHn_׫@ '݁3c~E,Qܭ2=дA~DpqS7Qq%p% B-B\ȣJ4v5gd (=δIF s>ͭxҫ?;rL q[@ 'c~E䬖q$ѾU23v4=o3a=lK,8TLy1[1" 9C8%By s9 i~M@*o`&)6'9qn5sq&>\WD-H|@F$~ 541p'}п0zQIZoAc"^.𵸭w N>۫|pcl+}*3-xf`Ygh6S'Z-si9@#8 6-x2b5Y#l>*TfG-. M=41NS+]^QD ?d s3Dz L :m>Vٖ26v-ȒKqS.S.$܄u{&u>JG߯ ȶ­00im8}imXbW lKଆwpUKPfB8cy\^53 pÌZzZhby QZHhd[g(&(ԹViE5F%pplحx2Z]--uMZJW MKJF 942cnF46t>edï[SSĎ :;ggbiJ}_GiQjUAm |Q;wyDž{z4beg!"Og&[D PaL\A+Au ȶQa {j(GgB>Ui)~UٖYp>I1O:xEN6Ѭp~Tp%pT2ȓN 5|*ŧdwl[|4ŽفZmzhb^¶_(z`-=3-*8d"z|37wpq;"~ =41n|uͿsܑr+uX\_PDHG6|xkcG" |pVߠϣ Ĉn }@31lbUfeG֝pq36qB7L ZƩ<~(m Ud;ujkJ׮YhILJ M$(-!#|?8J(I?xDQS~&J3Gu;XuO:0TWZahby+̭<]F%pstEe2Zckb_ lK,`̷&Ͽ&u`~q'~JJ3-mď{"V^yۊ$t"yJ7Յ>vMӁ~:IKĻL 2h/T/9. X+7t/4δ8+dھ6>Ӂ\%tVn 03-qɆ_{T@ٖS+}(hn1ܓjw-?e Hj Whhs_\F%pT04K#HAM]WAghZW &~I% 6t"uȶδQeKĸǯf̳w[{"Jp EC@#cV)oA/`nUh13-Q{L[k:R{ lKLEljEf=&yy޽jGMAi \IEHKdxnYsù/BNz:LzL 9mٯvr Cӂ~ᷩ q屛HcL Pa; x;Rhb㾔b^ȶ 2 'HpGy.\׻mĉj@)0lэs?p&ĩB>!&Z#~Q@ v\z M |kUyr_q]Ssm |a v]+3-Q VG$@#[z{^ItxLͅ4VP /ouI}4R8"D#z36TzG M;k_)NŠsyNOo_!m 0HEKRx"'i{xjJF~ž+r 8zhbHG+A~}D  [\C@CoyK-R,H4ݢD.JΚLr?L:mVٝwy.YpF}Iek4v֤S^gЩB@#8#&*`bJ''~YYFF9L~&q64'tٖ6霿Jc7AT5CAgd[_(fqmUr%L:B6uȶΐ} nsi5k iW~\K !m |iؽ ֐i~7 l! !4-3m3.{!\y'.YlK 9H4nvg*ZwlKLŬK^IwFsV֌ea CM8xiր~% 1B/h&ӵTyV}5;@i < ߆!u@ дg*J M {R0wl?̵BӾ24U=@@#8) FJ8/oNd|Ӗ fZmc [n| iq`P!-kK\/9. xE ǯVPghZW &I•myK#8C ]f4@"t^ȶΈnm}ҩ4"m"9fF~M@#8F1}뒹 Qy~P%'9.j xPԇYTQ`Y~LC8omZ@#[LZ0ϵZ^AP hd[g$6Lys_"1'J#`ػ0PfmƗ'ĠjH)0 XTN@*ӻQ&m ^n^ʗ)ʞ4-3m:I1SLzLI@#8 xLanh[i lKLׯJ^I吤W{~8@m%=RyPIͭX@KdusV*!ȶX}`5w}L%pvuGShd[gȳr(F46HM}}Ku [i$'>/(41T11ϧa(nQFP !ĀSkW5F%pT/;^puG\|<`u4(S.r41\[6::dKMCm !LEKxY.s} L@#8F1u뒸Wx0\2Zu#!{ᜡn$&AFϢj2%T[=Q}TghZW̳Rv4. au=nRA"5+ !M 5WǨ$M!Dm u&ĥF#̣ *mIB24Ի&sVH^bH}GHڪ$GVs]+hbHs@s]~&PCm W\VF*-7ć&JLbk@)P {"P)o-[0nT?yTQ&F 6 *8#ۂnZ30eiWh<|rne<~I2p%pY3/h-BIYDDM6}90nAg{ ""PSqwRv"JDD% "ZK;%JO4?^Phd[gA~\֥#5QN4~ Mkt|05Rh B!M -6 wank2BFsE eJH^嵏ڒ+c2-I|]@w;l i wh$DS]P hb@* Ys)/X_hb(íۧJTdm]` Rzd8j*N #ʔ8ٖY@dR 3it'T]s$!ȶȤf(nSit'\9QCm *|F#̣bL4-?L;]?&Ɯ tmM&08bHḲqL̵}Ai \'0q3JET"k>UKv1ٖ6L[Ž@2n|4F%ppüƯp2$!(yh$ "b7&Ng*/4ԀXؓ IDfRȹd؞ed8#F1r(u/0T7ֻ҆WRpF%G&2m4V$H\eEʥCٖ6 [yJ̀LE(/´h\CtHP141n:ޏQ7H`j2";WC*p>Or/* 0bFKfW7@r '7Q'=s~AR0k~}r?nQF8#[SauڟeUJEaF%pƚ|o{,~Ѝ,vp6iδ8Hl~nE߇؆hv3]P4gZԾȵ==B&3hO~" _ @Ca.} uO}(f7Y&ƍ."Vt!@#8F1?hJq/ jDϏR#dC9NJȊMtAiAggո4mF%p|W{-s/"lKD i8v4?nc~k 'IL.41pgxۂ% mƸ$ MtAfi1;>%4k "L3WW'҅qyEF%pF<'0iW)KcCso h<鋊ȂoYMDaX!k`!` mIIQTQEę6V>ߒ:M5JqRDX_Phb{)|l9@#8F1'qpTEܧ_S{""ȶΘf-~i ^,Kppq1TgUMę5*+}{پ-T %8Jb@#͕TҔ;ٖÌ]d=C1q-z:sXMEm X!= -PۇB6@ f@Cͤǚ՜vH4-3QrwF I|S'L {5~l=yXqF%bЮ^TGäi{4-3:99L IL#D(7n/ڪzvw"@161 s[0QO~ 'M xEzuUa+4Rs@GŻBlKLŤ]*Ž@H諞8Rw1D&Jblnw [.]b֑<8bfۙ|DŽĥƒ>&@Ϥ랈3-\߫N|c!ȶΘ|fU(Z8s?rj4-3m.{!*.DG4LAr5@'~QW\<6!qh֦D{ "P3rQԹ (S hd[gJ1LNq\_ QCm QWaZi8Ƒm<UV>zG`Ĥ$W$.H41pf{~` [0nv ɉ :$M սj{/kV+fGMuAiQ){*9!-7:̈Dpř{ lK,;)LHd+D}bhk|3-+m&{y|Wjm6$F'fDD,Z0qqMK3-`Jd¯y+p¼g[8gZl?"ĠQ/kq]IM&*ՉojFٖY@)R wsI×ϲm}<An$8)Jc҈@#u݋kau=ٖ_TJuǻZ3-Jd-H:e=}.Kq#9Gr [(jg?v"δSm= m@#8e{מɧ]\7U&C1?Gc,u ּ&GnR`1$@Gj1F!z! 5 14n+#M |m EF%pbR^ !6=6ȶ“bɴEJ'hX zyS5ٖSl-x.Q_˒*uaoqq#3\|3]{iASkxUN"*w~EhqI\V }8hcQJ' J#aq~EZuRx*h=дA4JDw=?2, z4-&1nƓi[}8=tǍDdZH (Euޯ41Tg~M ʸuO 5n #L8n3^*jz3-/mӨv'T:U4ٖBůp*amlT<\Tm iUQ4t}>}.Y+G!:xK*~%&%=tAQ{.g#+m4IF%p$+G0{RҨX**֩)5QF%p+0oq4L#A|WWIgd[WGnL[dH MU?]9,n"3T:9t`&EfELp0 k(P03]PhbPn!xy'7Z ' I"~AgD&Z[~AlDma_Sz8OΖ[rW&kpOumEnDm i8Ae+>-J/дj4ߩ!ǟ4ߟETh[_XgZ-)Fhd[grr F42tmZ(Q9ue [`8wjX´c8b7ApEjwT-~R;ٖ6YBJ{rtdbw;:Uig{sf?.h"İSqNRgd[_~{q0;ٖ6JH fT oO,`8#B#$Ѡ\.?5~K F%pF'0yikΥ1!*.mg^ww,Avpe &Fvv;԰YJ(zb?=&M`fi_hlKL]̽…RɬUSuu$3#0u+O%3*!ȶ/i$cBS~r; .-71J4(Fc1Q _s\بd(tq TFw^8irlK{/p.@:}=:j4NtApiAȂc{ Y8Cq]ԹSmoi*r%+lK૧-LV!mu`+d$.z41𑮷/pܞ.DCmaW es zg9MCm |"0e i8c65T5ٖ6IB[Ž8io0Q T=ٖYmR D4D&Rֹ[zw2lKw (JJ򙊵O4?M6T, Yگh*)Sn96L..jjL$5BG5o$]Cpa \gҵ=ęu.N|ӎ$!ȶ/I^$>i}]w-;|Iq/'~JuA^CIQqqe0{%Jq S\^纠!D24} F%p(\K…@#8F1̽@rmk6W"LBm IlSi4)׷\[~?gEBm 1H!&I.oDLhd[g(&5ͽJrAεRW{]((!ȶUH9ɍ[\S%9{BLQi \I>5 TاfdNtAoiA?aSzC[<} &w4}{hhAҭ90a*Dz.4߬4*BRyꂼ@JG5ٖWwR wƓiDQ R ;W`ِ4)xxPTAY5-@; rD 0naB2Vݺin41f_chOwMQbm 'qWkQ|,SSR4_ĹJ~0d8,*L4-3N)v[t.@zy7~[gU`|{U7Dɍ p)(\|?Roy%pG6c9u9Om <):6Ϛ :lKgp nmhó[}(g;f&hI;L9X_hbU}6Qm &0Wj8F|B/Uؒ wNZbW@#%Q1sIyo3@ '352@& =cKC*V#4\NT'*x~d"ph:{oq!L"0GhM% *&Sgt"ٖ6[̽Se~p/K !ȶθ_'0YhN1۠OU<Fgd[_(N~UJYѼb wB)5UϺt `ŜkU_Ѵ*ٖ׷>0Kqq qL'[!ĨsjR|n@#8C#K6IbEJTZS|VJ@#8#CҸ5ϥ#'<S80Cx1WGqT g*ɹquM Bm 11 'GN3Sq )ٖÌQ:F?RͬN="f4-3mg,{%׏}")ͺ\(#xJԡ},"Q!¤]l* :˫|&ghZW 'n5 UWA)QP d<ӂ}]Y4+^89&W  Fίu z}J\tyɂ,B ;YRX?Y <4?O0`.Y)>B$F$]+_F{˟۫Rvp,T- Ot{t4)1Y]Zntg$]*ki EڙږZ" ;S2ͨxN"yKR۔'@#(s L~8&Μ/#9]°oO9 c% 4SaP %DQ˭tK8ӌ;R518.#@#(ñJNrd^ɐW0-q4́2( ?=-k0C̚0H猡M{um<>3́&ò(y1fip9PE<png*[Hys.Ġ͵ dsg ZZEgO:1fQ%K]B&jO, Ơn[΀;-38~ʢn̴[]s H68$W4B|GU}G$ (~׬vYe*ۧh@lq /x{"^AiMol݂@#( 2C9AvNגٲﱾk]h H6ʂ!pVж(]LK10TťZFd΢36~@MM-5V EsJ:h/hi>u%%?,Wg$YWdNHARRnskA_vŒd3ℨۋLy[tȢw}e`&Ќ9 YHqKM`_DR#g֣޿Rcnsw\_۟{v/IП}?_^2nbŠ@ϿwwS߰;Qײ!١R#?|֨uHL=$u~jӤ US?k[CHؔ_E!{vӢ&@)vki)5ڗߝfadХrگhv>` d'ѕ(S~@-_E"ĕdsgV3u'|-}z0*բ iw ]/fJL J^4́2nR.9:]IJ(jH?F06{NaHZkr0rxyifcq'xf%Ԧu_nyiVBIy|{&j&n;9H3PB8yK+gŪ䖺EvS$Z2OxG0÷MJZQ[n+-hwSJ֘Sl2pObZLG7(mH6ʂ`b0 IR"Za uo;L3ͬ+ 9[I qyVug$YdJ 5AJpFuIqlgHP\r<_GSPjxhTq$!9]Ir DbP BDz0^>M4[<(t2~8#RU{gQ@lQrC8k讜ilق͚8=uM hjpY v#\g$]PNyJװ-3nPF9PF4]%sј7 >=J(%_h+f 5ZHh']G ]8#̺8H!=tdeۣ nn{ 3́4qGlt@Vr䧸:{@#(㸕c($-֒[Xʋ~{^ H6\Զ']F sy/.Uh}z4́2(GݶdDۧ14k]`h9߾i>7#3E|{~ $#Uux1 US2\怖s~%GiVNu}dAK6d1cgNYa3~ϞH6d~BgmbZ2|=@}b C͢ØF~G|{_'#Hr ǡL.]օNԬ TIq:hA{xvh* {WP@/'I$%RHnhwJ)OI/1ʀ3|2Fl)-BZNk9o _H͞s\%ؖS~%FiVgrUQ>)18# |Bn:Vӛ3 \^lɽY IIqo[tNq&Q~z+۞3bk"DS1HL+3aךE_-JqoCIN.04\?}R+h$ӕE)d;mRREW8$jk&˜: )L3۟\mcwyʛEtq)3KFw[a,g(T{߳lc^*PJ(Th6^yna.4owunrm-]. @d"D-n1\۴2B׶(M.sW"Dsnھ Ͻ0u4L] 37K1g?)o@#Y ߽Oc3x ^Z/yS,cU:b;Go(,tmg`Iav~ M4pu~z;%n3%R:I8NId6(d4x2)Aw" ߚ^B](m 9;VNDɠ 8CQ$Lձ* @#٘q1ŰkP?szlx-vav([Jubi9`گ; 5{`ֳ9{:;q0Cѐ+q8۷O҅@4֤xۮqs՜8i [ G@ GX.n mR<nȭu[\B_904N闺BxiV/Nwބ`_99n@I&ڍ~,wQt3% tIg'L\<hx/޽! s۠8``9$$_H'gx/޽Dm܀DߐP ~ TM4:#:Fq]taNY歺]wk?{bjM iWv yU׺P#DY_d^0,+h)<.!J] |k0JEl\;ءIWҼS^_IqV"Hqu4wzռܰ>a@"IgRd~ <M;%5GYT@#HK?.4K="JWxZTW׹ޕ3j*dqJn(Ű i*o2ХTsR`LJʪf҅&}V.i53KiYn`_3' E]=&ܑds+)0t.A'8ɽ׭מ3μkJ~u\B@#ٸ` aZD? mo9k%tbw~ (M4<Y7dʯ$Cǭ+I;/DXP4B{/!عV# Kg0&Suݺgg:scΉ¬u ](GgYwLlP9s`N2s^^w/&xn$!wn+1MZB OX' ,.DᾺoF;H1՞ Nt U[BU 8Ӭ|$0rNp 9 8'rB/u8Ӭ*[Ծꕊ F{>ENYK"gFTj}L}w9Pn^QI#l9˴4K]hiؔn+SsDl\9ǰul1͇TBi@#ٸ4`=Jג9Eq^r}B|Ӂm%QG<-PR*ThI#"c6)buӼ{Fe*d#>-?])zuS\YfHaCoW-J1]Ǯ3Zwhx^/Z6~U4)vki|Т|s/-'TW dbS9v+I<wU_V "H69?]\۞l[z?x/֑8DWI1q2Zdhx^.ZG:_֪RF,c~v$w_o]i[~3 u4Z/uTFvrSfX*#H6.]H1 i;[L ,i],U>ރX"H6K'm'mŴsvP)P4 쀫=R3m}| Ӓ'}xf9H{j/K-g{]XPW3cW'1=縘cǐn%i6-Zb|B(.0 4nw_TgRp=Jp1)݆T|{vhƃ~r~{凔;*d)RWS3joX> A3Øxu՘|oGoWdfO:yYꖺPDӲ^GW(e)dC1=[;KzS~Md@yYtt)-t8F0;,7Ac܀6D_V}Z8#ٸZwn9Őí kIΛϭ~x>4q1?G)'Bf~޷ ;pq \\?'8CQ-m|tsp/7sq1;GnA 3J f#?{q*g(yv7/_NQ@R~냨[mQ*g$Ln=JeM dc(k[9KVx,: P_ gePߌx}!nF' @Y43j>R>ɪqxr ;v4ψ^ڗS1/c^}yMkręhkMܤ1K m۝'L/4R+f?17p+g8ɉ0-@_BM@kjrɆ5y ܔj`Ɇ5pw2{z I<x7޾U3 +~wΏgv'[Gr?;1 5~ M4|]?~gMscڑ=UN.4'JU@ H6 zGcw|1͟#Yf.a5ݴoW[;lf]![ulL3-%=rpqq>ql)-ҭLbwEFqi޻þQS Hsj4{U?~ B(nnƜ$V^_ 4+r*M*V3kZܺs's`Y|v{9@lnmҵ4WIg_-d!7BjReet*`&sc9Fbv{vvS*}.4⧿z AZL۳~pX#H6L1ܪIb{Y1Wwo33#@43Ӫ|QZ:kt*GlGkEQ/xļk֗iՋ@#٨TfX|累Z j[ۭ*Oq9PT~%GiV{f9πDm0&)Mu_Jgyչ>_Ʈ)NUggP WWV&uv}[_뼗b k%dǙue]g(k`r^AKiУ67C,J1'\ h{wAt0բ ҃JݭW3d%.m&"ٵI19Ȟ3RW*uh7{o xE .Ś[u8{zmw`Lͱ_ kp֕&.Ts}؅jpFa9LwNW|P,J'zI je3+ޜ r/g`Fr'Aرɖ|\ >K$KhɆbz;)z3Ew }g$YWXɂrp'Y1僻˞߇l#mW܀,Dt^:zN@vfE49<]䔰raL8xo.r<ڞ$ y",A^DSrxSr9L8#?,oJ,w{;VH6 ؗիEQ/9ljG rqJrXK/ h=e}mJUR_<:eh$eBq9d_H =nGKi;oOk$RJs(|4T#P4 إs#(cVc+O;3)4v'm4߄^S>Cyv*9,aQ4́m+m]^H6};/(`ؽ[t+_FL9MY~3="@P~ׅF2,{O8/7JEL@#٠"Ġ![Oɥ}]n*pFDߞj9:*ʖ}}WY҄F:[F Cumu@8#ِ:d+I.OԪݵeL͚zk0ChJiUV\ʢ4Lxi$,*xG`6h$ 8Gn \kL[!&4 (m_B%.D*x= L*`FU >P3 (m;B0Hu"cA@#XTR|[JPF!u„& m{5/&i֤Er%ΕDr)=+/&3d3ȋOqu&Z2GyK'"f(1EIUXbnڦ~}r ,&x/}FhlS/}8 cEg@͛$RcR@ȿD#3£)9ބ,24#cUJsabծAS-,d',Gnw2oHa.=iۢRѡWFrM4d,g!LmM 9t[ @ ;^{޷;tj9JpRWYuFH.7gucoid990CE_$L3 *W_+ 2D}%%v$uɋr\VI!e+BuxivDGQssx(d9c>߷?^4"ϱ0Oq[`i,&8ۧv$a1-&R}W:R>| h$eV>[gYe$YCe Hg7%WaO\, WnՔB}~]ÞmJBvcRy3Xn$SKt 5i sh<֤hxRvn+s,i^$6rln+=JY^SC6ݣ1>9H6DQ9~ M4>%ΠhDqig*WEգ8LjYp0ODĩYIM 4ߵ_S\ 4g$ )}k=?Rָewqxvm H6"O+N'e3RQ\3g(ѾA䩺ItkN[zޔom 8)~"&j5A/X m7)ږ$^NZ DCFwQJ\#HAm?r'U\/}EOY J13] M45% Cg4F0?Őn'*]KE"WϱD-fPiLjxx h\^ EnJQ׭3NN _OtD)znGNp! 9f"(j@iV ~uMuTp.\ɭv >k #rh ̋6-6mF19H6b"k@ DSy Pu,S@lRGqL^ DH',okB H6J҃=Mȕ ȉuެZ ƔK])h)EX$$R3 )B$ۿDS#g$ :(2R+!+b }ܘAߙu3Q`k@U"DSxEX:F]~vrZbm~C?xd%DlGQTi!h"T~k>24L!x.rⰮH{)3 +ݦ$ʵi,0dpjɠm%@͗nj~>EeRWgRJX"H6",8t''S|R%v/ bS/~h$e1_ NhtLprW}9j7&- %M4οo#FjR {XB3BկtQEfӵS0%=?oia J~VEךt|n]}4Ŭrv^BKeYA(8= S j>5p*(& 8*VSnk8>C,JZJW@M?JO눽^f:QEsqS&{IP;΀[T\gSg9^vTXg+6FMUN^U2m/H;} <{g.nPEQHH{@-E}1=^"HQs-Qi',]O `tL}BmgPs1_`3h:ڐ$S^Ne"N}o7D, اDPXV"u@#ِC_9qfdsLd{r^h{N.ZӞyV,kvvBh9e2Vh+d1ǪIAEaХR43 Nħ~E}]颬6ey(}/ʕV +qOvԎĀؙtat%)DC#ޗ%^Wq+d5)ca5JXO tͯ5gHR0,:](2U_h)|_]H3QۙQ =V^S:wobL:jp;W8qh*LWTni3 lA*=b;K:Zt M$ԙ_-pR0Nnpmv6O-'1f 4L3R5MAmKqZĽ+Ǚlm\_.$@̓b @72m} Kvw'%F!=aT;v3S{6rM"zgdslG;WhnvwT׌ovb BJL;HqiP߿k6[ތR_bW8#J@RD'm2@ᦣw=g0)ܳ}zifj赾/mF<#HQm?ٝÁbyksBL:j7rjFLdV"ˋ@#ِ3©@;OZZ^\:G p::΀Za@Mx%@Fg$ yg (ʅhsu0ϫߒkF,暕(6%.t|΍Q_3(I18棽 ;M4س:$t 6M45`qۖcvęf'D/*nJHg(.kH! -es{5MYzEg@-4~jGGs?Au20~p?a}Qnb[9oI-|a1t&s^&q틦i d;ds,lR0팥ia5eR%8#ҎXJ^ 6#zjC{̑;~ ]ƣ{oP۞$ygfν ;M45ܫ‰_bg(U72nugP :xj&&ń\ܿ#ٷJq#Gӹqęh:^0Qt6Žh7evaYq. _H>/4 hn8W }}2蜑 @Yxܞ5  'ɘ/4Ҕ~}[6ݪQ4Դrj^tKt{/lEgqE\ =Mjo%.q4rgwf+> ^V R+`v9"m̷_Igg u/=xO6GŶA8).nj׭s3N.z[&.GlDGqnНTh2mî`8s^&J,T^O18%ƽ0#T9L44Z^%p=]9j8沽 |=M4X/A3ە10nTAyw\gO|6|l ymW`ܩٵ\`htє/3bUmPJ;u@ (u'xۥST]#; tCb!;~718Ci7&;z2B~/[z}ޕl wՒ 'Eܐz]h{|dsK;C]'z!ns{nSGLoO 3͞sFƳ/nSr@Ft[aN~@MTf'sJ;aT .kн@jiv g(UAS3i΂SX.O !@#(ӎR-tgQ*dދUhDAvMg$YW4/4RV,sh9.a1y[o? 4;'|Q`G~tGliGqTiEQ/(>:!ޮ޲u~9=tT!JzqY C$zSܳ\|hTIqu'\C^og{1!VR\+7SNMTu|q3)h$ettVD=fH~*@#( 8mP/tZ׏{SyWF9PۗT1Nyؾs ;Eҕd2[|9hcT ;W4Rj{Ǵ5mPiҡ=ZswbK EsJ:3j\6@YyP2́8Hattles[S! 7}N1=U^L49,Og(UA ۩R";]8ƻ"`glG`J w#JW4xMun@-.8W)4ԼU[ -)4́2\Qтl^7%}t;{p6z_h DKî 'E5;4d$QQX$NY:_I=uyo;]{p6e$QSpQ۔E z,[ iyߗxf3́&[>3l:SRߺns8Ӽ-tPKr+8]պ9P -};}`g0sLEz:~ hw jc}vh$ead[L8#Ҏx\/IܣK~{;NpC޹+u}ęfgX_ >8hTIq2NI\I,NFY}̧ەa9PCQؑD! }Wfd SbxAp HAVCZ=j;ai~$#Kݡ;Da {^AfS%O?~ۑ3`<ImxraI&5Kg$YtwwN vJ^m}߭DҚ=8-ƍ BpIo5T .ΘC0ChޝDH w)@t%<9Ț!u[i3F9PšےLӶr|Dmo- ]f#1E8Yã.Hb0#Lc8xv[qZL/ 78C]w@QJov@vnC2BzBΟ f%DmH;>A߿4 @,:SQW~[@-^!cl6_hW DSk.;PGkamﭛ*ʁF9Pru8 3x̘Yt[2~Gưprr%.>~{g02s L6ՍLDxceo/4j QVIqYOj8v59N "f'U(*^n EsJ:㔤ʅ%bX? eozFfUbڥ]h D񽆪vg{UQ H68w*U/ĬՒGM#۬:I?n`įvOeYX#_*=AlFM!xss8i5?h H6ʴ(T4ykcZGJbzwjQ^Yr\<)^W~W@-ݎZW }A(S++A nɢdmR H69qm*]P t1v0va\B4@dbO.-`X%h&cСƈ_Im $Ri_\n}Gavl9gxv /ShNk6zH8#T!pSPЅS}{D?%1ە3i J7&Zw>zݶ-8-3}R<-RC3ͬ+pAKI.@=GG1_g(U~}c8d~A jBt_hN}rc(Z$V1@#(ӎ;9z!ȺSkO|w{vd3+ޝDw"ퟩ<[{ Al4iGq0m;"W":W5`XgPqk CrgA=S0ߵeuGK}7@#(U^M45lZL#QFdsL;R$څ%6ՅJuh$eQt{i'vge|8)ІBVw}z &\S !yO4TG߿o82-9C0QB!Wm|! SUH>mJh:P4p9Qwb]Ch`SfI_h*h$eQ t%Sda:9ZYަ^h!H6l&Q6+]OJ{ (j[z Μ!)[LT+TpGAdA"트52\ң* u1)Wv eT=ZZ](#̚⼲^>3GD/&I"=[BpYu.65.g(UA͹r%eK~3ιA(΢WwNgrޫ*Fڞ$@-' j^7DF)Kŕc4:H3gx(׺LD,o+{3&@ۡsĭ-8Ӭ;<^,5f(Yr gu9S- jA9̡= 01ИG6g=a4́2(sv2{ܥ"U[9H6ʴ6y]}<)GltiGq2mL^̳};_ PbF9Př\Z)}vVO-=P~4=l"} F9P KRr9M=˹(U؆1<s5dsL;V*d0[B@#mؠN9ۣ1HAL~C9*>+?esL;jRG#^6ʔ w__ J-8q9P@g(̃{v|5I_K@Lr2(U[S{ ?wJ|; g(Uԋ[ LSJJ-]o p0e4_Ad!릣(ewrǗlSj}qE25:_dh$Q佺EYpkFhꉓEe[׼m"x=ݮ>kc3́G$ UA8u)9%^V. !H6* uq\((#S*䷏iH4́Zq\u36 j5h+'\Ol3 jqF9yE;&pQg9,orK]iV!sE˧)oe F9P9n;ebrœ&f<4C(=fΥ(f֤ ;)gTKIgX6U8#ҎtەLwHԈddg_蘣F|g$]Q-9.Ju/G) dsKᜩwki X>|t| J`Alf]Ap;OYxOuܣu@1929ZR%|7(A'xp;Jwhif|<:]n 蒬Fqr>Ez)@YHyoIS=u2;:Td3DۖDsf嘲׏JuI4q^4&Lݽg1ArDsS? U 9ДO_O δTwEۧ_@YpƶbTOYq]n}L`Z\}hڿ(o%?.*3ux M; 0 xRSY~# ôA``带is 4́xFk0@M r3[tے3`<εA>׺0@ χa-Spc0NAlf]AҷӔ떊41hʥZ d(eJG)" H6ʴpg\R0E8# oyc6Ӓph/'~آ3 PW!DC /]pArkZC}D7x"t +OXKQYȂ{:8jNy lq GfZKy&mf(MAQA&s\d)5S4]ɘio,0:NpZ#L[,L3<{8I-$(e¢qkm `5o؝LKl]61^Da7T_2};X31'8-G ?3`Fh%ӫ&єFog$Ytд-mgEP.eiRZ\} B2uIM^4|ν8CQT[F>Co?ȍ cg NY-[Biv];]>&njI'r} q&M77qp25%CX8M9_$%,@0>8Ӷ1 ,?.,;igxl2`Fj&hBy[g^;+)&dR MC9(q!¤Mtt/nc$wϏtsဎW!tCy־RJq!;O4 SzTIztO*eQ<w9P&szMAliGr-FI;(Keb:^} xd)L5U h02e ʌ E3kRA/oGZ<\"c |-d#63?5AuIMr(EZ5 h$\_M4\zW`άt F9Pg)lt;,νӥior<)2@vԤ>~iwu)aͱCpdsj1QR(mPWZ:'8CʄŒd3:bC+)iKI^}UɣQ6ʄ)k%ɝ)-@)Zde-E0Y?.OI4́2_ Ows ʢ>cLCh7{\4 p"1 ~f7ۍ#ؘ^0SqZiVR*mɜl\x8)1KGsJFsg5\2% q7  j0_l-dds,S g6s& *e%yW*4́AN8v|A-sGIɳC]h$1dQ%[kQzΊPvtELL GC>OGSf\0,V08#̺^JzWqMltiGMz/eQ>Ι^I'e*%IQmNơ $3 sg=2^FJSQ%jc$:*@#(ӎ⼩퉢^J–;WF'a׫sqa3Uqv0MI~!v`LY9 x}hKUTNΪtF9PUEwz2J h$!{Gef\]K|rqFlCO?I'աV>3U1p0$4_AɦrbgټcBK}h$S_;3Άlҝj0sMyi%d{ѷP~7f%4Sr'ULgʔ3x:R%9uN>0#Lc89JsyXATcZ_\r$b @#mlI^dL\Lk]AGS!fqd۩3`<.e~?{{aZF9P4_HaD7 ;Z1v(Ec\e}oęh(&楱dduΒ0(ˎklfUʰh&:U"9Tuh$exL#)֏14́2(ڵ#49+S^@du(eQ;+هsJnJҳ2wWrAU1uN1o IyK+1`1Ƅ qఈ-Ϙ D3Gk4?kOl~a&r7|J@#IUTSQ=QuL;jRnBN6ʔ夾n_@Ym12Oޘu;'Ƴޜœ4e.4 D󑆪e|ACeF9PxJ(%<>{oxRiG#;(Z,ۛj4d3U:8%oR'?]I9 Tk[eF9P,#hV, q *2ͤ(H<͹y x;Dl@l1B8sZZ IeaRڠle3O?mD@vUWZk{s.BlDWήWߟVycF8#YM_:Sxwl)ЈRAh^ es̟0"YSds,mه@0"Ѣ絾?ˆdsL;NM 96Q[$q(F9PF v6W܎mKq}nA+FE{&Mz4́2(NکQ Y#]t{/[[h$ ԿIY esLI䩬HuC}0s6jYAa_/sgxm)vci> Zm[É~آy{I+cO/rh|$3~"rE(Sm֚.dslIc)&lZ(e[y0an, Բ9Z esLo64́2!qg C@v)A߯KY-j,oRzg;>¥7g$Yt' {<9(xn,kh Òg@-8m,\K!DCFУ|u|DP48"(b^Tm> ‍8F# B]}GIO4́ϸBttT:-.~9@Y% tö[ Bi9PD.c<0Oq{4Q "z`' z_UF21gxqsN4QQ0'HErXJGb.9?}%ZPAq&r&G]ʀ=b&@hpR7ٴ@#I>om?(}b^0NNJ_yo[\Օ~dsLiF`o]K4́2r9zBBZ-T"}}ӅFqeԓ̡iޤ!PIX bkEG(ӎDlE)HBT/}oQ6ʴ&iv3e3jdH|\;F B|ósnGU8 B6L&aC\<Ĺ0pܱߩ\~:@vp-ResLh3DRH?\ڇ0%dqzǩA~r794oE(K=WI'ݻVds+H)S EIӒ,ޞg߯f8YGΎF8 Hc z8)$9~"xC G 98!c`<y4̱M$rE@́~RYI 5fdV±NVR;vJ%޴m MDf$B'zr 簏rh4dC2]!E-Z41/Q̳9DM-.zB g=PYRL6EӣwSߔ;8]A]q29P%tNXѺE3́0H&;wql' ]6AiC̺zq&nc^_XH6,5ӣ}msڢzL;JO"N&&hDivPnw8~Lw¢xҢtSX< zW,deNUzRSovgCkN!H6ʴ t>ѝ哃ϵiL\%IWP 0^Հu_aP<̜$1uHKNjwFNd3:n<,ds+gˌL;9]koO2Es6|!Z!6%rL8h:X iP3t҆d3jɞ&B,dsomߧd 6: 'wޚBIҦx5τ{w˄-c,̪^z[mb/F9P dnLq!V׭)~d7F˴q K(^/)*P$zMjn6z(YW6?||3YsR_iIDS׍[>16BE:WZ@fE^eqmLUh$Q1KRmAq tI1/DZܻ{u_ tNIP&S} @˴@~==цd º )(PciL1:><8#ـHz\ #0Z pF9") N27nͶJ7uyg$]a `89[Lј%|\-/UMNO'QY|/BS!́2Ό[2pnW0%an;k~#8mK7 ʩF́&NZٰ"9 oA.h% @Xv}>ZY^CIFBރ>tvGLSuęfgZ/BqF`*H I9Т*頣<8"t{̪\\^7KC:!.2,j_yz q' i!'(e\`{`#\8mnxzqxn=Jhv$c)Qh~@M&UsdsK;;3(]7cbjkq5{+g$)0.Q0.AZ(e|ׄ}nD0Ӗ$hyjQ&AwF2-{ H`h1NK>[B pYU}'K:7r`<[rïS3jgcURj[Cټ皩Y3ݶJ L@e)3LlΖUdenes,`܍\<%nyjcQXHf۪;c`<:1>m3.thݘO4L7B6)=1 ^W~Ɇ@-ŀ^* f%4Q89PYWҠ '6s6)~DiOGYLP/Bh>Rm3A ˎA0Sk}3H5M|4uqGB_f/hA,sL`q2c(ƚ_Bk &ڝvŹh-@YS Cy-J[fϯ۠@#( "VaO6l1msϕ Eqv[|@YR GE'ic$P?Jlȁl**nB@MA3Ù:̺^<O8-lN&⫪Ao+$~8pԬUИK]!Dfީ;uY@#(ӎw ];u2u)KJGyJ+c$8LRJ('y\@#(S,\ R<̤oMj;gqQAfqXp/JǭDe3&1Ӵ@' h9L:3s8'U{짣lt}N6'LCH.# !HJpPP+B)Nox1%ܶ鰇_´M;V-7dsTӵ,d~"|@#( 觭J9fEhEMa h:^޷Bif;KXz1yλ5~![8ӌW\ZwL֗7 .:@y/ݙ*,+}]•gg(U9х/] 4LBV.:Zv[<~bۡ?AvxP/u h0|;m l F9Pm3BS/ynڏ4́2(Nr~vjfb0iqng gb Z^(M4 s"b0uq2jSܘ/4hI xw8x?kW,-ö2+8 6!t,XTݧ 'tEd }ʗu;ߊprs^}/#ݒɗPi/3`z,^sH IK;%zG.V@3m2ӔXa.w&.dСգ;k#B$C1*TI%x*\z: 3L,TTw9;?Yg*t#'"G*W9PGȶKuOu3I6gR\OEݜ(V@ݤ #4% {Y4܂׵΁'[IReĪr#l0(v0oQ,2 sIq'rscoN.ԊN&mv^Տ3ףL)0KnGh+vww ;8{cwW9d:Ŧ#j=[7w O޿kCaLT`&\.\Pm^(c\Q/2b5;K??4"g+%ĝ}eh k6jABX oqFRbd^.p[g*tt  h,#?[53 5?" X3ʤi8:tS]X8bQ,6|k}뻱0U)s\4t?"m#Xi;`lެA(vU\{ ' Y:F1QML'3l~[7/_ 0ȴ qaG_׀[s`GJ! M,5h15cdZCL"E._3à'^=o%fސ8F ΣKglٷVc0t%"M<#kLy3a'ZuǗ`VM*6 C6׻%dng49Jg+쳂|e$- t` miP=_Oh$(jmIRzMݗUY>2 nFRi~~:z{d 8X aެ㘜.+=;7ĂYؼ?n>>8Xf)Gdl)?3v(W3\/hcxz#bbwtf,FAL&s($N0 S8Y3 dquWcrCܞLw}15zj/broHh'bg*A5IVr]6Ӌ+ D L8Ӫ^?ssz]t_5g߼sa0Svݑhۏ@~}~.k h(D~i@KS3 $߄x%B%zJ3'.V. mq*I@Ήx>j-I1oN'F1M\`(ܻ$-Y$W~/mb;d\%h*_d&ֽzYڣ̯ױ爛_sQ\ߟ5}"Awb2(Q࣓ Z5soo?։{@X ȴXԵoB/(kJ &*x =_h+Y!8?z'&2b% ӎztg**W~qϗo/+;΁LnL%; 4n;Su`0rvtNz?h. 4 E3D9?3 žpdB{m! "n/tSod!j1BK4lVE4(ZI6hbCC9yl-yx!8X տ4J@:r^}b1(V2(dn/Mx]tN:*Xo@.[v3NL}x2ٯ$74;,$ 󯙱0(Mٗt ԤAoJoϾyu(V+5Y25h+v\5pz΁'{b3ձ_qhb=uIhӶnBLL'D{-y&RzY1VKST*dp4Dow}F'3݇ܓIQ|e&I[/`$f GQ\srN2O$2/g5~v۟9}Qsvӭ9d$04/Le RQ.kOF#Hs \M,5;IVm'EJ@8ǰ0Y<1tsɀ"nLM,<ڼ08X Xֿ41M?̙4ZQ.0V.eD7ʄ C%bINҐ\ƞjZG ^$#3u㏚6L*UN&qXtq:£)X?Bc -kY*#4Lh,?ҼbX4$4=Ii#h*gkb% ?ȟM/4³xFÑ_iu@!]'4ӭ9P؈tal&l75ل6@X H4l0Þγ64@X ȼ~Og/0&A,782t w#E#["Aium1%iŒb\EXyWap`}3b̷<[gZ@FmkIJ@"0KȤIE7 L#\Ex$b6.3Mv߮XC״3#Wg4,{iRwY> X H˘]]wVo,VF U:^uAL-7 VbPMh+Â?-d:%frk$xe`Hua&4, b% ӎb Ԙ^у˞k^_l/K68P @ZǓfWgF_k{@j_Р.J&7,pGp## ˜ M,5h$=q sI6reȝ,ڽ}7)Z2l$hxx2l? aQFL!AX:&yH]l}5`<|˺!.f 󩈅=EJ@ƻc)Q;oi.M] {Wj 4 UK qԯ0${xb% SwnaTA,j "@@5kDi :#h-|JgbKxsk4 =Ï?kZ?x@X ߧ#ĺsDn%? C%?<,3ʲhi]sѤYԚ}9xDu+mAR]iUCdsWO68P Hf&$uʢkq,Kt8eg#fZ$Q+w̢Ŏ2FVgO˱DnkO#(V@"־$!&foN#(V2(d~NT lb% z!ޯ0BEN"LRV&f+L%Ē׭Ș:7(+ ﯿcʨ9S|TWgZ镶Wh+vԱǥ&u ^G' &WgCMJA,M,ݦF(ܪ4&9 sF3dgaܞhM0T)м I$b1Jj¬ydL]9\</q<L2Y8X>+'AQdQ,YQw]y~1}*@X Ȕ"HM,|40Dw408X P&dg6%xwIvg+vߚ(FcjX_za4pFp{)ZBdN~aZpFpiGNs^}K (V.(Rj=W}^U8~6ifZ_&t\+:4n$K%ncQQd̼ c x2>/δ2i'JvN≣(4o I&iIXIUi=s7/iY ;.ӅXu5mwa G5g CaJ.ZiUMy-(VKII~/fGRg+%$m>!c\ݮ-9 dxH02]FiUzQ~ Iۯ9. 1ϑ8 '3Nae'ym (3:!Ydm}0>ʳ[A d6h: 2]U{ًxb% S>*ɪ '<b% xy?Bd2I:S q[Ec7ea*։W;mX bXtf'~F +l~˗/M68Xa.'Iq4,#8P $hrq< v(LBGH<X*3?oh ce<&UNTbhbݭ b% ӎb}>czE,t"?mq'$աl L5q!3Hnua3tZчufRɘ}iR28P H/. QǠpiJ'Ǒ\ƱO BIdZ JFAg+Š?K\3i<qFp$M[42uRKAQdK0i,]3Mȳ_ltFiGȴϿ`Uz+Y GmE-zw+Puh%W0n~fWg*t~9DE(-z b% ӎ"d.(BW0} ʩՓcRaOuaz&}~~&L"giC0 MYd $29(8IRML$ LUYcex?ⲭFHMfz@P)*^82j~Eq<<r-JǝYј z\Dhb٘1߿i͉ (V2y9[چ41XF>C8M¸ LD \,$ϩy C%bNJNh?'vi: 摝Rkad\ԊOtaj&VM"ﻶMmFԖ(j .F1hbwc=$srGY !.>0jFCWc_Tr /t2ħ0@C0aQ,r~ Gk3 '3pa'x}hi,`0)C;I{6уw H#X)"[8 -VLmY>ׅ Xx/h`'w]=@QdQ$ v2 :áϭ` :㛸yaneR[ܲJG0|*}q&N$^ڴb% gaןa2Mfw{_ύb#(V@_)$!yOR$3"/Ș;:_ZN/4L;뤶 u"`=˴\B|jd>b% #U0'~iP$'|KtaL;ޜomU8X 9w'Q%4IBɧytq՜;|{;x4qF\ Y5J%ɟ}wf#(VE{f4D&#۳_phb(\~~C$0ԉz_0d>#Ēs{}_'h4{pPˎgVh*N D*:,xKs@LcڻDFՂL16LER_u6UoJ(A6sthC3F/GQdQӓ uo˯16S(ZAc\<,7] ~;LzWz c`0h\fJ0C>6LBK<ޟ?ny#(V)\cZLFe]Dfu#(V2(smA\yq]]* W\AxX1>@{rmGi#qFTL 8#˯p.4pϿv@ F 0cA ΫyDA&;|oӼ`"(V25)A$2H,ٿbXEQ0b6{K*bH#p'h+>Vvcj zxLFbD^Xubw64L;J-BdxϷ#>԰ENqJP|%SASЊGEQd$-R7Bi*}?GDO,h*b~-OHW$!5 d{W@FD,PJ hCa[G:CiJI<뜱Ȇ.L,}}lQgsP(j=)0 u{ @KM'x}ۯ9.}F.8}+ǙV5nm|w<(J@ 0 uxU @K]J2#{EK@X ѐbX gjL7,5a0Iqo! BBk{o+"Yg*t~IrAKwȮE{~6s w2~\اziUzkGo @tksH^^dD"=ȄbamowQdJ0SiJi'o X"uw8X AbHԂ\AESy{#G@M^#BQϬl)#*mQɠsp4p>c7Bsg+%D?M w*r^ln=2F"+Ő|j 撤IJ<}>q'/i'I]1 hb$/*f~aoЯg uHfGϿ7!b% ӎb +(Tk!(VuE a ӯ(H dzjvfe!(VtN`'$ܞ3/d9J@E'ElgI $.ZR=|g\1J@%ĺ-INh s?e6\A H/4TwĴ~Ogj52D}|=~DFr>:ܼ9fU8J@*!+ =(YJtk \:X8h*ɥNHMZh#s]hb(,vLJ&AЯD5~]pgZ͹QWb[=O8P gdenκv5 rxh&yrݹCRD]=f3E]OJkgיU8X j=s,RWMKgJ2<Ch%C_OHEHwgbѹU܎@LCQdQ`i9N;~Ws ǁH~fOy3hڞu3 P my\<(v<?&V g,`4ڥ_.N">w&UgFnCz5sg+̅&li+K$) ĩ:^]B4ƳK"BÈ@:߼,;j@ 0\b;>&rw;0MsC("E5)[@Kͼ-0v/瓼<JJ4&hOM=ժޯ~sqFpiGW%W zoئ &.4o9c\h+ò?kdFQyWEpz] dM_h5tI<„M3ţIa'7~zIER#v|it t\<>=] 'L+:wǽ6%FI!,)KsiJ$Th݈0Xa*<L>L."yom{ ZO B NMOVe Ӳ+b% Zfܟa2-W[՞:M,]9c\<\/X3kESFiGaCv'%!O{{홦g_aTܶ/ ܖ'ţAsKѧ`)"ĺIJTL@sBE9Pp/xx4[(nk8Xa@d)$e$œx{d.bB53LgJRno wjhbHd-<$xwo~q!h}1$b͓_0hbW4 FI,\yJSi*EeֻXƖ@8 pc.4lT<糇t3B%!!!3]hb٤x4^M-hk5-m@KMܼb}y<J@h?OdVCٳ|ܮ $xj(TFdD3H뛱MtcXKuiU$%l!f!(V2])L;ci&Mf^^hfb% ӎbE%ʊJ<- ^+Y!s]0hbᴗ=ak% m`<#} "M,N/43_P16'L,9YDBQlF3 Xv< v)CH\^y縟A bqOLٝKu&3X@!hmqpf(b:fIEi j!T\>gZ('aEKЦkA)P r]q>hb(0*d}C%P" 'CK$C<Ib,9V)EBC~qR?ir{L?_d~:LWlGXvf#M,Uoד=|0Zegwr(eׯ;G&Wc+ߚhG0o~oDt{@ hCX  &w-Kw+& C%" "Xl4Mje!~=j~{~T @(j:$u1}"D5l1`N z:g))Re M2ħ:Nh>b% ӎb΋@(*/UoCzNq 6s.3j,;dZhgzA/u2Mj`< LX42ߞmz/9d+ܷty.ؖ3dT2an'zR&E!!S_(hbcngXߣ$>b%bcH:ghKa1dzs%7f+DҤGJk܀KG^kbP'me,qfg܍B_ NRxs]hb'XGh b% ӎ"Ԙ]P;XFD"(V@Z)udl=|ϠlIJ@ƪ&ǐ^hK>3Y+nD&h+YR +Di2Mks$X3Ϛ_QIeU?Fs,h+v먶("Pڵ;MAK)(FmS]MhbݹG?o(DJ@ZC+~vV/h]9\0BYNLGXc$O:2dr߶Sx'ue+i"?W\|}Qm[g+W kR Di2MjuXK3F^ `Q 5KX(M4SMV③{;3%Lo{~͔ 1JaG'ϳ_ hbUn|}rBJER]b9oy003T0Ģ"(}բD)Vh.5pr XNd֤!Z2Xڢz߱kPʑ&#T02s]"hb$DC9zqXo3 V ` ӟa&Mxp' O3^U۷=?8FWt獸gvK3ě|w$$b%bqBHjJD7Y?78X bHEIsI$<닰^~}2Fb#ŰWhLSI7W .!(V2(2mYzAn[Ayl}A`'&V~C0T* V5B]ҮwrznvwW9*"} nT1jݺ6MCL($$xD)R%lz v'M,5svim]CQ\H1g4L#]KqnB"IJQf/h ED[)>XjnmK\< R"'4Y?:I=n[g* ¡_Q*MP;w% `l%@UǮg0"R5qgFJ@:cmųD( 5ƳDFr`0"±-V;8X X0 cyOQFL ,TGn[SOE[FI,j=B&M Ni "/RQs.{3fj-<-O#n};3]hbٹLW{mh!(VmnP}_~bf!(VnnF4YW? aFTA,ڊz)Q0X!*R $i)B]Dk4'/gdOg`!RSd]!(Vj׵"!7m]|ob!(V2j]ww_h$!(V2( $)xeN=AЗ5C2@r[`k!Q|P,$J@ ŝA*M ֒5dh0TN`'# h鴾`<UCWOǰ=-ꂥ8Ӫ 7|Z4L;C-BHa[monY2 FiG%ԐzviDB'32 cɳ_0hbmwwMhr gpX =C$ aFPJ"ŰDgLzn ~HQɿBQ\(mR>i"Icx2TB_D.O~Cc}Y5i@X !bH">}j9~b% Maү0PVl]e{S|A O,늕@ ϜJ嗜#J@?O EƾcS2e+Ĥj-EN;>qNpܳ[>ɑ3J@ŝB/3ml>ݧ&C>i+|#f)0>A25sf4xY>cdRth++RƝQ.MhP (ZQ {o]h+v7~]z>KQ_@X XU mdH,=ѷ~.XX4B{xV( ,肝@Mez<+DBQdq$f7' HjyboHBQ0˟- rckxkBQ0OI'^v-Sous)((jq\ kt{ qUI 5f&!(V2(V44 <_w g2&xIjTL6X -o cw^1h+v+vzEa[ߙ{}h[ `KqnU> &֜{]`V=م@X @b 4%BM =7j Fq[O!, EԈŵr?@X ȸ/ϪsgP 6R 0a%^> &֝^;W@X XV8i&Rn-lkjN7]8P ifn i5E벻?AQdQܐ۲(Bw̐=&!3+h){sDdZmYoͩ ۤC!rR\<5WQc@X ȶZWO`G#}9! s).RK~uΨ"!(V2?)d[Q&IL}|J@JQLm*zdNUN_9.S @[gZ^<֧ - urS'W_ *j9)(vA^Fg;_ Ld~yf3CZ"ֽ1s:(9Vd#gm3ęX1 >'I($x%my M,Uv4Ͼ;aTP,5ʦԧjíQS!(V@\VMnF4 j̧unjFsh+YfR +Hi2Mͷwu1@MH֞u{sk{;wѠgr2ֶO;c}+ǙV5Mw| Ͷ@c\8-xl$4Vd,YF3Ǧ8픥NX{-a0q{6 2i-;A~pwH3K;d[^h'*zQā +:ǝ[P/ɼ>+Lz[A.E FiGQ 5hy;lj}=m@X |J6ԯ0Pw;r8r5#Dm$TS$3n!+5HWlUuv4VOSDM}4iujVHnV sc^j4_oe Cgj[1ybY=|}埗?>@X bdgي@X ȴX++2#5^vo{ǚ (V29B[4:%co{$@XTPg:n/ Юsx̾qiCxr<}a,Z ޷1 zن>~Ǭo;)=gwoxo A|saߡL):^ߑ} omaRQd{\GQdQHq {%sF;Ű:iL0/==c쏞y^[dz/i8 senǞft?0P ka'Y/?S_O- (V2(JJ/)#(V+ `[,UM-w u$b-|J3@7K#d*5J>zs>Bs?z@X x߈l=QJ@uBRi]Z^Pw#[A 06ŹO/3lf=f$4>mηLB8P : #n δtU46áJ@"dhhFQG_bFWךR`<,5~6D<&Js^/Aئݲ L+o߿WASl3ž_qLV&ʊC+[N Ћ>p ̴q zx˓b% S\@ ߏIӍ{6ݯ_(vJ6" ."1z7іdcg K/`K!P[Y]3h+W 0 [h6yhn7;Mp:iI\ L$㽏ߎӌ ZO \X vuCMmKi1.0a]4|7CinN2? F80N\z# FiG%H]=&U&zW4 p3m<8ʝ=<_ICQ0t( y*UEԲ|g{]!(VHԪ|(5۱g+W2dZٗٯݺ8}R7끽q f=Ϣzh2^Rٖs\ܣ$@i'?γ_0hzy0G xe3Kv5]% F;pO?,dZOݲ}7fڣE F;pcn&Ӻ|b_E(X NgFݯ05jfD씧b% ;z n]i?\.?ÛP,J@E=pl%.5Սx~1ק}+hӚenD.Ya0jf BQdAWK1AJizHe?U_9(ms.m3hjhuDl4?fU yC'P= DRjQO*$3+n)C[4&F̿7E0jW9.:7>&MMfmIr D (V;in l}A`!l!pʼ,;Yg+Wl]TZoLȻym[90I@ű_Phbr_? G=qP#h')K R%)=|4,~dz<&nz[:^/]ih_d-%8s'd©Vmh* '~uكpW Xj?W󱅆?t4c܉O_41tW< 3r*Xk(VxaTqPܗک˲i=. jKVJ BM_Q&m-?KJ+C@l+Z<;~eRFiGq/$~}6f\JgbQoqz\o_~a;HTLX7hЮz6/3 1d_3ePa&&XM@X ȴH+eN>~6 Ws箉O&3hl;dmE/90tԺG8}^$)d܀{jTlX7 -v3ibYAWlJjaCmw^?Vcsĥδ}7kWߕاтe/$4Ԡ/Qis[ p, '@v0v鏍ҭ906FOu(AuSoyow/g]u5.\wkgb[})J@&Xu*Z&93 G`A>7Y&M݉fϦ43rlW :΀3د9,25>l ̴u 0د(0++U4edJydʐq߀{QJ@f~85vV4Rsm,/=~LݧՓc[Yn\"XL||qF\q3Oaܦ7J'uow|mtAQ0tP;>V]0S0+vz7f?kh g-F[MddY8 Ƕyc~-#5y nyLxEDZW)9IZq|&>BiU&oxݒ (V2YId <׍Y% CyvX7޾텒c8X X5ӣ $ij=lM@X ibX4tk4N)ɴo/5pPz#Cq׮%4ʹSu}ڳFKv pw=r.G3jl:#vnd[Bpͭ#u@ io{!1|n[Ӑ C% tqUMZO۴JFX(IԞ;}a9R4D8;b j }%W0vs\< \ 6Loe&g.g5v]O4L;V.SM+<4,9uEPÄHFΊ{ږ (V29y[4 $gO^?B%bB% 5&ԊPܖgV C%RdivSxAD3+v- \ÝS' SIfig&'f4ٺ-gaTP,eeDʉ:t᩽DZ/zƸp`[|nL8ӪIz`S{:/ `{ 7s]0hb10ya4L;uvw}o}%`lqTIlٮrl.Vg>Q%'Pf*̄";CwvFi$5U/cfZ[ưxftl|.V8J+di`s-}̩a&yGEj43-IF>OFg`!Rѧ>ШvZQ GE–"XdDK2g+b,KK b% -;=:aj,[kyt[8X 5Q~}y7ⱐ{uq& rCX8"$MB!@T4ɝS>Ps>XvtiE1>5=0Xa* R JsUBmqvf !(VD}e05mt>"Qyr 0+abg@ˎdw1O#!*%x##hxn$Bu&܆0vf0T* R\eoVELW g zF8X,`c5e8IO&f3̡K`{(P!(V*7)KwƩ$v2ql 4VTNJ>vGCc/$w&<\h;R{9N3cvSϧ!ĺ>ۅ|W؟qFL+>@-6k}v.bgnTe6ʽ^&s\8kN\ >L\+xiB<% Qq{Mk5iEH֖iv|Vo(Vvgv4N5`~c>s{Q0׉ȯZ4Hw;dm(V2(ݩI毹Z5{_/Z3K1_ƛOHQ\^lh,ͣiw Ȉd"4 \+M,<˧j߿ 4ZU;b! K}+ǙV`/m$=LI]8P Xt)#&-$ s'CieD錍w鹏C0 tﮠPX6r.M3jwc{],`D[x2I p&J.?_ts+ &9œ+.!'QLWU$7FudZ$,nu(]ҏ̀bhkOa".cboRC!Qqyx/w2z<[4Tl>0݈ 5n]FpF%nR:zO^n) ʄZP TBɁ.Mx/n]qJA0`8h U|F@O=Ʋ;FzK8Tކy4Ugiϰth%p%!t&Z[]q)J KCqr_#d=o{xK*~iɕX 캩F@KUM!y{t_.!=JJ]5Hj4nB^{>yѭ_ٿ#+pf%f&zgO7hb^s jWlĽyP@-m2ȡ2V^[19[f;;Y:R_9~"p,zU_uL`eA"#EG^iq jm`8at]hb嵓,M*Z^4L;{cwnRzц 7mLײR`8}|F@}m}`ɀ^ݞ| D+4\hbwi*1ۚPBW|/L,R_{KCn axΜ(VK_4/~D' FQO20&Y޿7E#.[Y d΅4`\W3X8uo\" p's%RG%bĪ%GmR\o!(VP0[UJ>M0`V[ri|*N&ZH/vtMiEK^Ƴ]mQ6Cqa2wv|9ooFNZIԐ|3XjU{g+I1h+vˉd6~[C۱1*[Y d*nTTS8ˆ~N1O5!(V.V9{wʆ4!YWɜi镟nDpg+vnM2v}tZ/.JaysLK{.<`gzvEDuBc_侟҂lm`<< &xA;w)u%xA3CxN`9.a!0|ݛBigFvjC?KFbXԓ (j;͟hK:',@4ʥ`Cδi+ i{҉oǥb!(VtN`NYICQOO[wE ~(.e4^k|}$O0ر%x΅nG\(XxjGU%2)n C% Oa5ѝa*Mة۱#AC1&x(&&Uy M,5zKe6xAQdQ꩑)NJ ?Fg*US5PY6I`O_2Us GX֗K;_3䰿o/V(o%ɧ3!S,y-Yg+vw\eJW%}J7AQTaMQܛ:F_߻>HGm{_0@i.^4fc, !__Q0T*)D&Ox7jb% ӎ"-ѯL.vNil<߀n JpFy%%XiC+xi0@_s\z+t< R"VȨQB^-m9ۘaHd-(CaEœ L,Tlv}NͳAQd:pX8kk~94,h)tɴ/{҃3y&ٯ(oq=Wu#v;G`Gj$x@"lohkxrAsW4~M[,>+9k8c\Qk%),4nJꏼI@˦޹a3p}-'ĭkՖw cL~lG}I`lsoSlm@KdZ}Vyv[iqB9J@I>7 &cClsS?j[0 /\7mgbx/nif@f '4X=l8*GQ>~Sq*wF8I?(Ϥ[J3[Մ{9߅nrןz9(V}WHv$oD%xs{i#Ym}e pFpiGNTJ/'=?(Z_ Exj@Ķwo .ƲO*M3 J:5Dw2rA.>\M2(VK:D[<#̨]4ͺ/j>ƒwX >os)% C%b!XDeIG7M< +hP\>LZK  pF\A,j y>1oM4Ůd:f(t %Xroͬu0X ibH4`1m= b% #"XEtK4NI^z_/*Jp'sAcSƑ_qshbp}C6,m:%J@z9n]`UQdLK-uߴ%i˔b% FwPnux)i ]E#ɴ܆sp4n$mN.miyX 3 f2 "7~_1(VJ4.Z3O cQS)O'NTE ~Gi@t1Hgea&Erk{g}N![|iOXH uD+}߽i93 JƲ^Ք:3 `,j:8j).4l̈́ۙ \8J@*ү?{|Q[ut HjOm"=Bg`"RvE|N' w[1.ap>n!δto3yg@#)OuB+³.aT64ҫ^J0P .¨}QMd5c?JW{bEr.O3f|WdZ? _|^V.RQdeY`kD; F ?h4&V2i4ϟRpg+v~QzEv&M']@Q,]ھ[9!t:qX 4SX3=$WqFp,DZABM`}E܏;5oFyUڪۛфU=#I}~Eג(QՀ᳝S† כEde1COg3)R #H^DQJJ@v{uꋤ/ĬRcX!ۃ@=8&yq@Z ȴHU] ׷;ソ,ؘs\eH;8fM44[?q(Lt/ s4 }I-8wᶑ:r @Z ȴGU蕆;ͯ_AQdQOQ,Zi;{'!(qMi37X? &mqNw9.ۄ]8)v v K%6:VNٴ[z vP:`l~į㗤&3,*l)oѴΏ tKs}h;s#`6KP%8ﰛGN l!~a%g.!ĩR|mfL?6"wgwcՆR?w &v~= L@S81w?n{.=`O/9Lqa>D7Lvsfڼ=9-"!&KϭJ3q&T!7J@fT,f4L*$dߨMwOJ@muHJ@&gZQޝhΰT@cE`LTAN& 0NaX?3 &ΛN.Ӫ3n^o^2;8dX*Q]_Y[iu^HmhT+Q/q(l?1. Bc:O>kO5Ύ 8CQd')n"{u/zۃxo0Pͺٌq~)d<8U,Z"_[[8Za.iDyႄ˓8کR\^_D~rAQd+\qaT'"q h*0Nk'~m,̰T$Ags\a'8HI6kSk_N؀Frدx,4q_ִ>Q9uԎӮ'FM2dY4zFsVmH5j=k)ai`Zk.s<ҵMh4Ž{>uo"~'4N[&N5l\v祏o" ,Б$ xW8yj`+f8lVjESton9#ΨV.m+>ú5i})W '6bC3'םę8Y}49 4O9O^p0 oΫ\U?oI8R|P؈j(Bb8]ViXJ@m'u&!m;u~IwAgT F} -S6, ߆?^igάtI:q[3mηfSo'_{|݅B3,*}~~)L3tq_h8c j˓c9g|gp{&Nu$jݏ׈QbDJmS$zmnc-ϑ"Шߟu!ߜ[0Ȁzk&<}'Κ<=Mj~3tcY v/p;Q`ܮcu~ghT;=ý-Q:;H%c;$*R 7hFnоܬ}{skKS͡nV#`{"zW]m8zAT ;1,hIl׌xXp;g u#T巨~m>vFu9km]q4Af][*?^C&4j%Laz q&N[~z|%s$uq&Γ5 S[06UnN@~<@S e'݀_4r;4,n9{neZ m=z#5hT+Bx AROlr4<km*G ަjA3-mΧS,J@mM-JFtxE'=+qRs=L3l܏;#͂0Zaign **acjIZ+m@v}{ێpU}tn wi3ϭdF+j% ӶNvUJ/u=su̇/sij% ͘@=k{b ШV@CmOiJ僅>Q~5ʼJ@mŽ٭JJ/4۲j_C 3-`n0/S DJmŒB/蛡l=zb ШV2m+%mE\pD'4"QANGO~A3͍Q/x&::d ΨVDd0Vۤ$Aa]8~&4j 7{j/ك@Z )b=5?`iz6kO?&N>Y6m?*6 jMX4&6jôa@q  U%D2C/_O{Q UA[2Xb$τ@'L+zO(7hT+RzAtt[mL mZ 0Fn+M8{=֖zG%7oSJqT}u#]hV▎w잳:qv#lu087o7rקJ@!C0h(I] Z?җj%:<Ǚ6Ouo׫  M79iE=zK}nD Fi[`hˢ v[HHGTJ@%mĊŭHF.qugjbM(ÝXNz0fIGxG+ë~ 8@˩Jg3sCi" *~) ߤ~}Mju]pgKl%Y?| j% cBH6JR>=O['~U2$}o$}pb^uW :8SjܷzI~1hmUƸKCWg<|ωuOrhmAI%l"uW'8ӠmMmȭ-vIl(6̆ZNr_7ԆBQ0uw3Q/pbx&Px(8yl 湾޸HJ'!ճ_hTsigy^.O4Lۊ۰9 %ln}n F#ߦ?ޔKJ@Œ&Ph{-ISݚR\(J@mJIBWzktPsל٤J$/b4qtqwIDFi[Pq&WTOԹzz߽T v61.NDݝM 8r,b9O`Ew0&YK T"_o%H%J@}tj%Ҷbev@gEv6\|J@r&ٜ%[8ޠn}Ț ΨV.m+V)ۚH uʾ[gOnnV#$7IwgIV)v[Hеu q&N3퉤堜>#(ܲqbf]phAZS*^c, * Qa%Pu̺0$AWF"vPϭ^3m}[jW) TJ 8R,xR~u)|7,Ij%5D9Kmqq4ݓ`HӭN!ΨVKڈ[\:Z_{\gT+%mB-IN.h A6-HZ~CS] ⦢ۅ@Z mbXǴ":l碾>/<(܄F8*rz MfkG8Za.i#m乼=m %<7 Q)۰pPj"jS,vYv5$yn3Jq'ldL?8U+f$--fw{gn_?l!̴)NRM% Fi[:Sc>)AdԋWgBeAPĉ ^~CSf|&tBmdC!g!ĩҁ2πq * P#׳_0hTCѲ▮~9#nmF8چD/YzX@8q:OVio*Hc\ 9yp33π!U4rrO|n ~ L9)G^J Ǒ@6?m'Ɍ8J@mź^aаv??Mi^T&YG~3=d&(gT+%mĪ헌< x{Z$BMsB`;ϓ_{i{}r}o-!!m2dUþy8hm 0A8IvփLkjMvj% Ӷb!B/ZZ*_'Ij% Ӷ"%%eUM뗕^@Z Sma Ж(LcV߻~ q+]4D8۴5A;pe^Zdz})-hב_1hLvy76u6^Nf;IPWLB?Ǚ6qj+d?n!sC[Auq&NT6E G@gT+WrI (ծt|\2hT+' O5kUCQdV[ںʜ6ҫ}WZ4gX* nECeַ5q^' %jU[3qѲ!5[$: Lf F^_8A?4ؖ%Hgדv Lhnn,G%s`"ΨVKڈʼn/ so{0̃ڤMi <,s4{M'g${mX*Ckj% cMcX,6LS^Yv+8B XMX+B NZ$u,eI7SQ-T8#wp㾾 f"36b "'S$&I* 6{ M)3#K}z}9 sȗ ƚpȭe:MhT+뒶*"r"/sjP[gxk`7op' p)V2u\HV j: n-N64rCpiuO6!@Z U=*<~':^VhC88ԋ{uOY|!ΨV]Xl;KPDpݭm-b3,)0y2:á4)ztӗCtd珠KI%8~u|2z 6!Mi=ԟ!ШV2m+R,nd8Za.i#R/mUr\3nY=(@ kE^Z?&N<8mK/xjJ#` yi=&Nlz~,0JmreDh܇Z°8Za.i#LnQrA}=oh61, I~ Dik{lm?>%dyP5ix B8y:ZXU j% ӶbvB//ɢۆ[*fj% V cj\MiC!g"ĩ*³>U>I !j%ҶbiB/,*c"!nJ#`)bE|7# O СYEALZT#`K ]|/:` G[DQ\A0=,-'zm1t&.83mtؼz? QV%H`Kד_p"hLC!t "Tne8_ r: L'f_Gĉ5I\7gD5ocZ4"g7CQ0W^2I'+={>l5n36VMA"ϻz$WkM-GLasshw9z`8&6ϳP4¶< .EM̹@g{볌ݔRFi[\*?월2MHFb}4[xCQdVSd ̣mvToZJhJpR 8zP A8oUSøXF[b]Ię6HGc@Z ȴ@th̝0\[~/ CJ@mŒ-@ܛ^ys4LۊT[]P\=87 ^hi j% V #ݲ-0HެGH#1$ nF#&\b;g`Y"ĩ]/{$P4"ڗP}0f=4 8NǒQ8Za.i#Q ,!M&` BF"]ϭ[3mpOf~/*nE΁q);lI8HlE*PܰǺ`Z"ĉg4';AaT&4?qn}k9$ۣ@Z bXTJZKnkk@Z ȴXu5X^L$ mRc\@ {KpIuE5 %PVcGCF6pb ΰT*i#V nIrE}$>U`0IVq5kĺ#DO9ء/F؄)"+X\Mԧ}@@q'ShU25g^qݥ^jm4Lۊ6 ^.t}mO?3P{RBJ@'-?ę8Ѩk9Mխ'5v͆mHę8\XI_h"ШV2m+jmO)\,m~ڇE F)^Zݫ9(@Z ȴn3и΍ʺz`|שs{ n.#Tb!yPՁj$}\k~1 =TeBAa|L%@[1. U wbi33 qbF0I ZG[k3i^x/M-MxQ$s|7pTM5ę6THևWj% Ӷb1TJ/(P ΚHQ`6GvXVh^_?&Nt̎Cy"(J@_|~ Msnm,bx K%b!X5IB 4_$y!j% ӶbAEQ2Vh87. EZ @gJϪ9K*-&Еu `MR2VcΰT*i#- (AZJa!ШV2m+VNmYzA"be_q&|7.Pܽn0ikӣϳ>k3Kۊ6^P:ϩȶʫ=>yk3Kۊ[=[hMƹj!ΨV.m+Dݒ\M Uˣ&ej6)7TQ&N>?76"LG6Yi ѣv kj̓CQdJa$^JdW!}.u'~BC]~DS՜{K jN$V#)M<:PG:hΨVKڈ[nB Mz%{(%(S ζ;gQoKg YN캎V6#eS^Wukd+PFL&NH3Q@Un j%Ҷb-$Mn[;J?Jm]B/HHS3:ݬFN!ؚد4q٭dG>]7J@młcF/[Ǜ﷧s%FIns΢ K%6v@.Tw陏1u3i?<6KC׻1VzaTF,@1[K/}/hI F`δS/X!ݓYi; ׫=6RҷZUfX*S(dRkuFhf#^Mώ 4p3ObA g`!ĩF b'G@S: $ }?ę8uoU#ϯy\4EV!X ns T>ג8Za.\)[@*B:M'ZH&sH6w dh= &4<n s}%v@9O;$C4W+@'|Ej4Mn LmJspO_o>j% Ӷb9-DhH^lKՋppOA>u q͓rgע@Z ȴX #+jzZeg#v:j}ٙ0?/'=@ę8ѨI.nq㇢*$8R6z n$Mjjn$K[߸;3 ly` v;is4Q;g{#`δy7zȀ߫4_ F&80t6RXe4Lۊ%[^;u]~?&z~{9$8ZaI/ y\S쇻`j"ĹKZy4Lۊe?zEM]K{{T&iOYqZD云t+`o*4:mkM$ou7q&Nn'PV H^j%Ҷ".Ȑݎ#P9Iqef2]phsK1SwBCQdV_%+bhUSs y~?[@Z Ndʾñvj70qW,~4rD3-DžYx'@Z ȴX´}%+zm=¦87 F6|_`g(j% ;bt}Qn'A*P5mư0"E(wtqM؊Xt!| [NX)s#Lg2Ճg7eDQ0 ШV2 [*z_phT+ىTOqj= =eDMY??40a]tJ@j= Gp,MRgcUci~PaJĂ׬ (|e}4'} jmu#a-TCz=!sN 4pjv>LZoD68Ck@Z bXj]7Omt4҈whSFi[j R?*~:+(Jҗ0x4DhT+ىIq,Zj-8Z?>3IFQd4RH4wDD7=P#u"O^ɰQk HQFL'~H.-~ܽ^'*g@H~,=8&65J4LO)S'q o|qa0JLgæSwo2L# , 04j=M*_FSn]F83 4qY/ޛ<0B=Dz~!R@J HthT+m ~%F&Š~h8J@Zx@8XͻGQ0k0y.wR~h^Fi[Lj [M?D'4j*%v{ =Mjf_țSRB[锳`f>L:u^ZI n8M^{G~!N87my~}6Es FIu7&N<~?YfT[1NteGbY8&De$7^m:W *% RAPF-̨^"{aTCPu3 kb{ e? @Z $zcݿǓF? @Z N$rkk۴+ܣ^ZQШV2mCQ-KJ/i0VOr4Ԑ}wԲc('{m{Yc][1.̋TTln(6isl{&hT+!7vrmylO/g)8[dF5wg9VfwW+9L*ZߨM˹]dpwKxХvw _hT/h|18\}7$\\;p*#'3 β6OIJ@m56w#,4zIaE a^xU>AN4U3bGj-R@Z ȴXfUI[LP K%Eb c Vj8PQVf'xfJ ШV2m+I]%}LQiAJ@%m¯HN~8ݦoН@[4ŷiėcm5tSV+O,J,APq$^V[NwgT+[G[ Ѥ 1J@^[(Ve)}_P_<7?svObWOGgDCrq:GVfC,PV?BS|%Z8NJ aFPi[AQrF= EgT+o* T2޴0nߩS=4D#8Rm$u+*uoG4<_70ιGJC=M*\ o<AEz9ԓ_H;!ęJgOBs0ma\:z '8@kqc(ܪ pf#F=1Bi/U!1s̉l 'Ǻ'A$"n.z*IgT+ ƒp: .Hh]': $؁0Z!*e֔`R $W,d mIJmsXkB`0Eo4j@TE~!W@ z=? .Jh5G;z 8U>XЄ0_ 2J@N.OhĵƴxAQdMa ;^>jpv>'+2@4q4;E}mI83Kۊ.nI؅)yP f)o!-DYyB :ۦj3=A-u);ɔQGf3ꡆǨLOGlgDɆz#b(2PS gASB6vѴtlhT+ kwIq;wկ3~NŃN֡ Q~ 81_-Q:L}!a@'hg{"(, pa=Ԩ0 Lgs; $ihT+Hf$4gr4CY ΨVKڈl+碘N)?C33uYa90Μ# :QOjͽzu|iCC'iXԋ>^MiTs`3mykn9>fhT+2zA!eFcQnnZ#`f.h(p<$AQdVi۶zA(Sژr(-@M z q&N4-jɝrj% ӶBa& ~=eeq~B`[E!ez y'84j5BQdVN,7ӟz^s>ZF&5qnRBpMsVNaLF,~(%$X*<:; -Ԧ0w=`I~!J@ H9%6#`)Mz 18A}j% ӶBBIeȬڌKkIz)m~bS ΨV+zCTgT+ ~/e o)gQ9X PoQ23qIZep6VAQTV(} BT l-O}B Fi[Ps+/ͤ^^MݱdRgT+ SPVIQ,jfA&Tmwe#M&δl{gZFXkRN1S=Bn|Za.\lI8P*D<`B34 'Ñ_M +_;jo7P=p=4qh}wŌo+ qr=K~!ڃ@: KY1=]1@Z Ȕ@˽FG@ j&ئ wEFM o9f5_?SXf-zqXLr$5{QJqƻhzS0v 5yPes\cS_ CF}WeۡL~%j@J?LCȯeɴ'J%ELUC}WʘШV2T)`")V( kR/pK'y j% ;)n"k< bK u Eþ?~75>@M{d_:+8U19O J@.ilg>;hT+YOO69Oñkk!qHl8qP eK6,)9qb.Ĥj% Ӷb5BQ7Fz#%MhT+* x6Ԯ$=hT+^,KFJ@Ƨި\ʵ&690<#YxS')_8I Ga_+YuӽCnwjvTz|c/3Kw}A1wDK Lgw{x6oWc{ :C-H< :G9 CR4q'~d:ZQǹ3B-яw!܁@'O풰B(:n['#Q9B&NHʬ 5QrSoϖsKQTT/(hTAkAK(ƑLFG~!8'3'$`g-z 8U)ɱ aTB^bxk祸 K% ~Ia([a3i)t3m^,%j^-JӜ)0#߂>G}0WJu~~dK@K~/]d ~ MÑԛyﹾGSk2šHsr|#iC+Ke J@%m"S2rE)݋ "@QdV,Ћ]9_幼&5zr=8/;?u%-@Z ȴH}  {{}U/Im: N6q\'W@3x ;I=n݌j% $YWSao)9P*bjy]{F]Ћ/GUdoC-f#ШV2#i;,hT+'삖m{CfF#ШV?ع L\@Z J av]:6.&&?s$PbֽgI_.{}h{FQdVڮ:f.Ӻ%?sPbk#~δyId.Q58%kNnuFumgۻ hTT_y\ HOL$Ӷ:.,jHJ@=Ig7 Jv2b*%5jj% ~ u9p:;R-ڪ$8/ #{roE醩1.!p+ƙ-$Ȟ@5DѷО^eΨ4`掿rӢ@Z ȴʘ^ [*A'w\8 Kc#"y>)^'m`z e[W{Ⱥhԣs9e:}lXu9>{}rt,ö/`Bb9b(eu<06OHq+z`4Lۊ;1 Ъzt>mvH-kیc$gp(( uɽ>u.?h@pjz|mw>%QdVdt?w*iP'S~a7*֭~- sIqߦ K|~:n5- SIqK:qv?k4jZ;u]h⬃>O;5)Е%@M!&NAFfiWeeImAqVq[gT+%m`.E^HD%F/Fp2LkbpkyڃS vڌƸ0+6H58&xB;E5L>lKqPIqsgL.ڇW'8R ~ȡV74~4C!zViy}n0Dž wOٿnV>a O;2IT>S /T^5nP[VL}@t 1q\[6f,Ѭj>3JCF@X ñD]vUebШV`M1,ۺiJzYm(i&ͭ#QdV$)uui͵lԉ֭U7}Tu˷uH ?`?j`5Kvj% ӶwΘ^ЙW^gT+qjI;Z<)\4t\Lߋׅ0R Xm%]삄eBFUThXU#ڋFEFi[j q;R$ڔ`fm4qlU#}VDsgT+32FCITkjl>B>Ĉ9NCܲF8vw(T@6eXKu8F0/ |!~NP|Igrf"{o$6F@W18z ÝspF\F$ل[W`U*m>GChT+Yt: ik:N6*n?PS510yr-e}4&B z&aIĈQJ@#l½XXP blz Yhw vhI6oVK[hKԢ"[$W; \ dǧ[gwST DBn+x4 VޗJ@ee>d=UF̟ΐ}HJmŊ &߶@}~z;}2$ B`Pj}xh+P I2?Pj۪ϩm'zidUP>0k$0 jb)~nhFШV2m+P;~E2L7O&kHyϟ>J:oa^sQ-h'ngm|1fѠ%Qd9gհ|wás\ tb8aL8,c}ێPk3i7znmBɳ~^:?` 8A /:P;yktbj}]vj% ӶN о1d惨) a'lJuW78UcaOJ&j% ӶvB/)8ow2sT'4/!ձ_qhT!)wADubDu<7I?7 Q0?_4󭗎K^?'$ҶXy "H\o}n݉ v$0_&N5:qBAvu56Z/iU4zaTF{E`F.h(Yk^shT++v^ R6ߗ%4(?$C:Ƒ 7@8cvx}uU^6eT+KozMl\mJ@5sJXd}{"k&yR rEx˝.@Jm}?>hs=3*>3/:4Lۊwe3zM:^eMZBQdѯ'ht(IW: @3O.| g`|!ĩr\d~mώ{(ZA&anmdĩNȬ}VjMX\e! hjo!2 QFLO͹E9D iq~AQ0Wt-4oC6cX*H'ѴC2\ WVG~AδyB 6 .wA/f!ШV2m+V]~AzM{>?{).wrDWuܺ0[7ԗo9!قZ`MͶ@o `$5SCQdV,I{X .{4T@`(JS.t)u쩞k{ T<qx$+mw@'~ K'Jm̝~أ}M?hT+Yp ?6#-.y\\w6ۓp&ϓfӬOJ@lxcaTYeկgKE@lHSDHl?Ժ8SlE41[O4aב-Jm-@ dScykXhT+`SFá4mnX%AT Fi[qk"+c~BBQdV$Rd?j'4 Fi[Q됰 };-ױksB(j%ڗFB/ے$8Ittj3x_{Calg}^5hT+K!$JM?.n36b)䯍䂪m!:nC*j% Ӷb!VEWT]oK3?0ఈL~ n M7y{ld BҖ(ƩPѐ׳_0hT4J +1jb(v{ 1A(;^,8pvO:nui ζ4sgej% ӶɄ^?nGS:nsywt[ `&ϙ Vm<)J@%m풌\|Lk3Z΋s8ڄ` {$J=? &NZrU {Uܵ:v?Pkqֳ_yd9+<+4hJtW͸d t61Li)6 T::J@m5VeHJ@Aę3kng߷u"CQ\qbXx8,ȭ.oe( sIwnEDR7S\ *AznzBi$%lmM1bg` :_>6+Fs,[PԺl8 vRϏR ШV2:)[Qá? QJ@m}]+ȼ}{׃@Z ȴX}U)C=zBS-&4Ijd'y5ǹBδ)YVo50W;K!ȁ'9 ӶԴH s ؾpGGTJHnh:YZ? ͠L7%qV;8zsKkYuj%ҶbB/-8n@H~B`a߭_8M{MϘ'qqHیR`Wa[PW,D8Խ8{@Z ȴXt9@?6v)Z4Lۊ_=Yq>?6L@TH{pF\(5G[-$͇#R4LۊD?`2vI`tWaKjXUsY'[偖.Ƹ8CݛTrt`9w6у[j% ӶQF/:f&_ϵ %@۞Z&N5oO=t:"jqOTZN۵X-Hm5陈,PmU\ vK=?t4Lۊ !;5f,ΨV.mo{QHJ@&yX7D7Fi[.jk"kp5`_'NH,=ΩP?Ýj"%Cv_G~i|&5pPIp$!W ?rޖ^U_še@Z Ȃ`z~B[@Z ȴ$+샲gtS>QD+MC6K>=,wڂ$`Mds6Lfj$ok. K%`6bwɘ\,%wv^;hԍ>9!POhlD(8̉Z8]rhT+cvA3`/މ ~!ÃMh9Qf?g`!ĩʂXmexӷUIq:' &>Urlv%9=3 4Ifh(I7ɝW>'&whT+w%Z|0uoFŒjbaXGd@Z,܂`h{)L;X4 5c.>O_;m?][ɟCQ0Vz̝_9o_E@ML~ !M8tC.FGn~8@6z .&M*iwJz pJnj5uMp.؈4qޙsK8FDQdI1^ 4YS}Ok~|gr{צ7]cbIԳ_7T ƮV2T\;8R 5FkGo6 }.uRMhD,;e7p͙N ={20J iAn–h!ШV2m+.Dk*}~Nň@Z Hd.mUҡ4tr{9?WxᑸhTwRqY߻"idV%CHK_ň˞uO}k叁U{9ΰT*M0wdz}T;pk% Ӷ{!{W+dh!l_84vt{r=98/ gzt"S}(۪$8WpECH7gkoG[Pw( %6!!xE]3@Z ȴP乮.ڞ [y%H&Wu7q&N~gP55q&.4q؅E=>3H Шv >A RztRc};ū]gs3,*8$†Dwϭ3m̈́{~7O8Z|3Ajթ7l $3<386=I'sm}b/J@&mJ&.d374,hL)f됶_dayeָ"!hTq-_uv֓9dVȂ}_+s<z(+e4,Kt\I9 Qݫw^uQdV#\AB/ ,}J%cUou<=ΰT7vnp MKy'G4sFIvS #"4pƿ~)08GKҩghTAs b`h,8{1)?$gL,Ct]CI-z>h̨V~g^D,|^7-߷9 nvjP3qy2s~NqXUJ7QcdBL[<3MyNa<ɘF"J=Mji$,z_ ШV2m+Pݾ+zl;xusGw}>|0ШV@BVgnߥOi!J@lA\_.>".4L=pOthFX֝V/\-M;ק:@Z >7C j% ӶbqW%Wb_Zn}cY`RqF\JbfqQ4Fa%/ci$,c;*ZzTJ@lGJ5_~<eSe8CdqgF Įݏ 'q҄?NqFX$j $+T`d _{/XUj &P&3m =b_TwxY_Hlc]z ĉu ,G/W/?}KV F?:7 8i2izq&N4gԪX~gg!Ӌ8Z &J$lsxC\hմj% 㽔IV^&2+JB65՜G;_^E;hT+[JsI ~GZ ШK e(Ճb~>_,S K.e_yGgK'djy|Ⲡ#eIs#\ ,Q]dIܦ/mh*;K*9J@8p,Mʼ\6StQs=h M*ŤWkkI!նɨgE@Z,|65[%SXɌjNlrβgL*dȩ}G<QX#dެh .F[}J@+)f"ɚt0LI;B&ҦmhT+_sYW.`S ZIqhШV2Mɓ2< 'pJ4{i#, i/˸6:OI[ ,!BV2% y$CrAQdS_ 9K]ϏG{Y4羗{ՓH)0S#rЏu//Z ֙yˑh9jEt>J6qɷ!|R[ڎu|xS+?J&ɺ.gTu%ekFo(%@Z vfBX{a8&p0GgOʒI4,h)/ Ӯ:8'O5}|[MJ@mu,w"q!nHd0d]ǁr$|OX+# 12([7HDQ!6ƑqX?,CNuѽbh܎/"eic~uOfL=* qZSGC^3qRwq^T!ΨVHuh* citau?$~Zƺt BQGͤPb6[,ogT+̥D?MBE5fЮƺĉfޏp$u6Uǝs`IEd~A}!SU[V'egϽ켝4DaI&ݬz=[[0 s΁'aHqcSm7P/gT+%m?^POy~I5Aد$@hT)Z5E3,*GETIP ijG]u[G]]gX,YT'5n}dVP827moB~'q1gX*ڷ;NzB$v]%P請.YJR,k%K} ?.@̯ U|֋$Wi**@+ѼO<1>BlsQC8op/\F9tgv qFu] rbv8(#h9d.7RwI B9LOltU<2xXeι18CDv=y9!6GYj橻/8PC(Ցc;IŏΤ#I V'ā}|? $3m.^1ʁ.J N![\RV8#j]jCIpQ%-B׺l YIwz:ИfS(d޸ 2&y#ӽE#h$eբrD:pt^WiV;(Bls)ծ|w̃B]!H9 IKbj!d^g$Xv@p-y74rg(UF[E߽G0@ssG8FT޸N!4#l''s8L!H9U1 h ;?B(`l-#:h/ qM%}^y6#u;ǸahQ & ͎_rArj83DҠZ'f^:sh>jR8HqM$̼={ȞT,&-phsTI8_$P.^1CUꕣaS#@95U Wn [0!h\-~%kIg};m0gsGm8԰NO4yλ, Pj(hJr9DH9U &R/dDS"7%<9\ f$U4"(3h$e1mYwW"o @#(VqrПJ^4.G~έ&!dk?Uu/ NR@t{.$"ve-@m?|oߗMP`nss'(tʨ[agi1X#9ù1[>:)8lvs)|?s;-©Dӌ4 L3}2iגҚo>fR,PnG7r _# ܿqm2bֿ6ũ]Mܥݱ8̓gkEO~7)f(Mn8ynZ"Fe? 7̞A}MIQ!Le&'g=>Ԥ? ?9~of4Ԑz-twdL[EYZ48L*~fP0G :ǹS(n\ٸʕ!4C,g5 qFѥ]Ejajx) F1 ]gǴ׸N!4S;xbO Vg+@Ooe4R'Z!GX2J-jlپ;:'e4mzr$ђը)6GO$a3-c@z-ޠs?}7:fgL%%>kč!H*u>>J'K6cG_`g$X" \m%e 1Kvr[qid4m8bs 7¿s=ijxٛtԢiov4TQ0dB4m8n} $ dbVwiL dL[Eq=q@Urs4MqSAQ F &J&IXq7w6 f2ŭyEӹ.aLL3عsi[T:v68-4͠8t-{,ٳwg_\Ƹe%-='hsTK;Դs> Ee!|{kPfy@y H9D+q~Z:Q~֣|4> `R- =154uBtI¼>)@-{آqlMozǏ/;#,}˰ pu<"ͽ@ПΟ{,D`G4nǔ%=?I!c@#(VQ>Smдǹ(-({/9:>'=te|?=NZPf"2Zu oFiH.?PRt~zBg$X&M;eE\]p/-1^,hwo,@PI4plw75 |C 'S^.@|Ϡ8 EBޟ6 ƀd K ah9&υ@Ђi<w#hH$oT?=,54m8nKn%T @Els{:XA?} %nJ~( V]N2@ +C8H#dm Llg$X#P(8Q'y:H,5ls9S!QBi-o~pHK% qFѥPZz%ѾU#6G#a*z%va;x@O (tָa!DCbtqF%<F H9ʴU{'.ӐH;=vkGdL[ő^ c?z|jO;oS"V7fu>J:\g$Xp !rH9X)6%-N#V.rAv`4`9ǹ# ^b`ԭ 3NU|< -k}rN4*ecI@Ϭ{F_2}.*G%:0ׄ EkrOܨ,aZv4ぉQo,mF7hjf̟B:e46FQ]A+0k"A8bk`uh!2_M7|L @#(su^(a3-Á}w9h`ޤ ?0YW[`yhu+YoL&80oigtr'ߠxg1_i]&wrӂϿ o(3KƢeEݻ25FQYpql(L紘*q(vqF`H"C@+tsCh j;hٽ PT1GPD]]#=.Q>w͞]`+~ݡ*z)? zFq v Rпok(? ] @#Ysى!cO\nEZԣ-^zDHvʹ/^)7Hvq 3JByDj9ihf-gN[*\BxmOP] b`(2%%=5O;(!w4Np%Ww7y|/@Fe~t hCSgVoW8Gv4ueLZi]ק?@#I'B'rY]eX%lDC }q}}aiv G'o4m2mg (tigyqb|rhij('47P~F&}YO ֒P:d~s]YũAHz%:~9G?dL[ξ?@90 >{fQ-h.RkfjkFQ:wJ_&P?6G6O{4mseǝv.z%Ž}˞sz4m2 1]~H{iyJ4^2y@#(Vqi^ b^~מ?Xܮ:ެ Ozj3@Fw4GyMj#H9NpQ#HwUg-"WF{L۟e_M > n%ohQw3^K!Mb@7mBiu~h$;siM}Wsq QF2m`gߟ6B̸lF w ]Snu @Y u"1 >̹%.UюF褥口ֺр3%\YI^.Z3JhA4;:0ʐ7 DN瓁쮽8ng䗗J߿LjP8a|F&ǹükzHz4dZk:ay$Dۮ]H׍Sy~5@M(Q1S{!ߟ9)ma]ifs',o_ @#VVQ hG-WuIHrZ|F&ڎ9,sRL{kt>C5h$;i{!#q,OrC-=EF쬇XP ɱ/~E'3=W Q޸Fv.Ky\}Z 'qhU#DSq2e{K@#I !#@\Z8)䠼Zl##HvLD[ޘDw/>aɡrmF&N1b[PM #vN8`t573\Әh9Ɯ}\&za.^gGڡw9)6֛o3|{~Y&Е >)~8wgP}!<$KiE t)bjqęlt=l՟bc0@cQU) [uY)XJwMo"D?q^N17)d~TYEڠi(׫Z֩h$ۏ sn'EoM|}H>`;AwJNj3-#=ޒsq]Gf٦nG.}V)¹\?:v 8,'o;Ds'nR q2 JfmS_YaF2ۨ:{DĒLXRt04kۙ[^wz4p*䒟ԟ]~bЊvъiV_A>B>(d}pV?)'6~;MGQ6z!RwG* kt;Giv]G>~M#8#UrȮ:ULohFz@i,Pcnks,0I1c!sw{3׸kBz4|8Ay,(^ڛàQ֮W3M7t5!dΜdEd:4EeGz z%wQqWzſa덹IqN+u,ǝN'Lיu&7Q5;h$۝3N 72 o?~?h$;*vw< ^V+O{;A)&' ӳ}^/"H/N3"}'X/"HUwڕ+A qP?7~Z|R}vviFU|Oj<N:y"GR]nE4H͹]ˍ'@#YWǑV֨ kAͤ"ܷ^=oDz#qPrC-t -BJD֥>Ego4Bh$GQ(PF(yC]p/ɗM}MQc{ns@=7Ssn}c8`%5FL3|t=u٭.|T8Fmqhx@KvCfLjM DSO]~ŃcO.:)j o4gqW%)y98CYKLAn|JFѮ5$+r<(v`iT>dg= R:4t6:W.gV#u9b F>xY; E>Fj.BK>dpv(5 }nSk HvWK$g˕(tRl p~|ְѰ@sJh?7ѭVB߶v}45?F7&4:p2ɹ1ޣN跶Q55A_vMZ/pJFӾ|`Rz! ״ޯ Κ"vPqn4U^f_OHW|ۘ8"@#(V{Fh_:=SIYo9]S:Zv7:Z3?3Zn 1v>8cij og}N;^Omq;/V-ntz v^6bpF2IDmÎ]p3-JH])˥ic]N*M{u[ SH`$@h$;mYQKS~ۊ 93v$FJU}%0zCq~|2t'8ӬčGŃ֙!RoHv&Hcg,>rz6?">h${ ?m9g Rwt @#YdjFs=\Zϻ=&nWh$e6Bݦo_CfrNɲSgdgMf~:]XqŬx҅%F0w-@'I}ҒamnLjŃ{͈;Y\gL vLƏM;tP:;khsT]7C=e] Ab7G^{q^Y*J㾩u}r1H9ʢ.Mݧ]642ti桻ѱv'tvɸ׍v M4kP!_*g${NC6k.MqNq=ܶ:٪l FQ68]i'Zx-0AN vL2Njmꁔ&h_ /% GH3m*Uo:[N0+%7bC 0ֵ}1Amjt_~hj!DS u>[]?ѬZ&44M80v킅iqlJϧbMRF3&I~onhZf$3Hݢ8upn=0ɷݝAF L3P*P)[~/ܵ0GdlsָAqC>:z?͓c; Rs|Ij H8Bd d~Dk\<R:4 ej]},ľKZ34.;Gz\$9PnQ ?ls '3jAjik[$vPh$;s BkyضE֬ƹ}[vZdMo 4˵ٜ$yiF*BǀjP9.9,P^# E' YG(Ei4lԝT=3 ˶ˮ>ېvAo`;pd.fZSbFӶxp;E]o?r|VE8#/Au%}WPv<8#O7^?|];g$;7uęhgoٕ (Clќx27 JOh$ejfF&/:G<>"v:g(:XGǶ%(WNl)[sl^3*6uR{ m4ek贶d~[qL;h7e}>V 3yWMj/H\wϴ+n9-%~wﵺSHvV;}GZ%'9ӣ< }WU ﲴi]dLLyw:M^(5~Cy#N*DP#US~J}֪zN;*`3waӖO{龂mD4U_ o;|2^*GK9n||v:!][5KPyb$MnWif,(0lw8M#?"ʚ_w=ʹ]OXZaFp.kU l:[YUxM76yy)IgM3) wyU>ʰ\cD˥i&Y g$skla;b]*W|Գ>N{#n6:zYO@Mu<-*㤃FMshW q;Fi}GrԣrwN8_ pYVY\~=&쬂&(ߵn9OҸ=&4ݨ*͚ MzE謖e'W/u+՝qPHvVܒpQ I֩%;^$yf5?z QX#4 I6wyfm#ӸJ";Wާ.eJM@#YMNRknR_kQ'VPHvҞVGhW9Ŭ0Scߑ]3*-Eyr ~M45!iǖkhjo}},ݱ\lluI, e^_0)}6z$m=N nЮwhɸG%_s|#/&==%i5V찟^Dbc}bs!]MJO[X ?F7qnwPLRN 'bӮ^WOd~_r5+C1`Ur&WHN{P@{'(xA\(DC4k?3`QŊvS|UR?oYs:l'/ 8< 7bS>˥vSuUH9jh*g~$i;۫&@j-)h$[ NU3rCͳW.$xPj"*މu J+nB45FU7)vLqF2wr #wןvRU~*0F쬠f۵ 7\';tC_ڣN])Fur=*j@k7}_ߣK:8T~NJ3ܩwy>ҩ߉.7;=I QX@z~2XD6=e[om 4;Un`Gb[^q׎{W:{э4q/;idP7`FpY5?J̾u57܎&yuL2<=_tJ@ͭ]q;ˁ8MwQ`*63hiu s챔~°NI6|~SR%/OJLi P~sTSoFI6Rf~w(aF”S!-EI?Z/S+Eg$sKQp j?$thsT9~^:-Cty=8zOpGze8t`cSؿv4 s ~;T(hw~ߖocwU!o#jqE<M4OZM^4N0 q&% B)s&|ԈcWn&]{x|f5 IA:;GN~_t,]7=Og^ AeiVhݤN/]L)<_Q=jX@*5|ҳtbZ8#i1\Ů]EOqcH36)̈́q+(ӌvEG=)SM!PF@M22:aK*dg*#Պv܁{O?w/:Tx6.a^ʽ2L2Q*MˤI)}צ4U<;>r^ meCm2h.{ sŪF2nv=bc/ӝkiSkijiSx{a@_R."wJghr\h,i's |\(OGIf;RH=,lgOZGqP~B|)dpj^p^xi܁o뭺4QJۍbp&Zrsu3vI@%ߝ&GO^AtG+4{z>nwihROK7 jNJj !!r1ILr輫䅗Nm9^3f(VΉ_ F2|Ay;pCc8?wyNJ/y⤕fUGB)g(:ͅ +W'Վks~sC, ~SuX q&깛~u:)I`HvF @~pw8q5*m#RUova&Y~m9ncSi'69(7Q]#DLAύ~9?.p9-jH?fT{YtSGMn4x*oO 5- Eh7Wkʏިh$;G*NAȞ=u~ޗO* ,Ԥfzu 0jƪ'I#fDb]P<3ޤ++ըGIeۍ&U~8孵46US K}EK߿s*+r N߸^7"D㺱jIOFu!^w7\TKkG>RpRK@R.x*hL>7hDhtbc*PsRuJ?wxkGΚ[",X屓"Se~3 \'UN @M ֩~3wk)Xh$;+X0n(a;ShW|qD\M0I^K` vW@dxM\C.P<Ja;+M4Qԝm ޝP3j5]o\XNHvVP;5boa#dg4C{jZ= i[oF]N6t(gx|>sM~$V97ijٝGb_Jס:V{.8eEAqYՊUQr1jEm*s+NKְ[̟z(g$;-014}gXNiNc"U(Xh~߁.VS'btF@MSH7X:s1}^|ᆚuߤ8్us;dbtԭ3N]ߕ~{N7XJY18v9r j]@ҽ_jo6((h*Ї[Y`s,[q5d$RyF@׊٪gZ(fh$;mw,T/xu?4^םbqFbp5*NrW|/1]>w͢kcשT^z8kggU(]%Q  `sptA:pF:q!}\JPsKWp[K3\WnN?LOoqKTcG V~w{hzfE׻vT7:(+}hXM剧MԱ3uE )=|o9k?jQZDݩGiv?G,'4=s '49p;hS1DSܐ?C~cJ)Wf$U=J1)LOX?W{L83 xrGJER$T+h$;+TXr"Q`_qt+j"(7mxF@m Մ{/vha@EF@M}{=0$onǒ.H|c8 hsTyNz)=}3|w{.Q~s\Owot)X.$cV2C{zm4Oei#J謩.bO;H] }|CUPdZ`M D̲uK䢞A15W7H9ʼvuAޥW f~Y,1x%9ie<+lEjb)Lr Dj|};Ho1<[&@蚂K̹]Srn߄v74voC;ކ%-f$;jأk+3ݢ7yS{mSG96Gq̯Yd;8ɥ}q}h;]^2iP0IT4m2RK>qjmZ),b7Ԣ#2:fVIӸ׍M4$;lCnt s[k^ǠZo$#.J_ۋ].)cjOS) c`H9~ I3jAd^,~ CqCG.S^U%FYt0s+bvW̨jsՏ9C(5Z*S>>}w3=(zPuz+lsh_ۥ$p|][!HvڼWq̬FhL1<[*o~#׽L ZtuFۨF&İW@@Np^ḋ+D)bx:gG; L.@6(5nߨUl"[JI $.p.oQ-D8wgZ0)z3}~6Ca^N8qhƗjRUN;n7:3sXu$}Kk"H7Uj̎:;&dnSXq<Yq$ST.f%d~RYő;P܈0?gLcoV]| h4;hQ?.vFg("wCc|mf`WBLQP:fzkq&^}MwDkvow!p;_iGt3KWXVZ34D9DE =)]n1 TGvMT͢h$; #Dh#DShQD/DG^Iō/G# A3*EGZq I2QgP4m2)(ە!o13m.m'Ʉ,B=+*G 8hg"(Yw#Ptҕ#qB;ʹĹobj{4=zev,z!z(Oqm<);.p'1E]w]0bi"a2!JBOTSuRH LL[b^-Ѿ6A]h;)ގF՚|ycpꬹ0N#RbT~@ #%qFѥ.]2l=}: x\{Q &1IC_>(9)@lc]" @(P1uVJLdqN%P.7|~ 6%-:'r|m*7NƔ/0Gu ͤkϮs0:vA4!Lח[ϵ@-wI.o4T8v!; ;v\$tNqYN'u_ E @lsi8$K%WGw$:ά+?zxfF7hhss/kw>Fv48(#V7fuHTC12 $HYYBwuU+ D=^S^S6GEuJu߶zr@enBQݾC*tF]'`bT~@FlǮc}NSr"ہ@#(Vq_@xIDvU3_y 5\&ؔq4 M41Ct'ug)Q DC#Fk.3mt+q S/S44l;`dzfTF7hB$=K.~$013m&7Q4 % ^T/%TΨ+U~hA@ƚnY3]혮qF2?p<1Jc :Ă h%*Mg{F !H.ij\NHW98#ƺ8pC6r;'?vpQ%-؝H\3Jn./\vu^qFu=DQnmD|KݬH H9NhZӮ8?1A{Qph$e>4jA"!DSx8bl~1M"nL{A`-0pwt-,Q > &_n=3MΟpv7,f'WAw- X^'g}3ifjQUbr1Bls$!Sj]o#wgQH3m&ig =( ~F ͠f9uL4kR4H H9D5ST~5h dřB)MJ: Z糍Pޜ (Ψ@M(i-oM@#(sEC^nR"B9FQ\3i, @ I ϯo0H4R+I򍽥DJh$e*NcQ 9V)Zg$]yMzIGL՝K$dL[EiK(8ȡ9K}LM!dĉ3 T4ҐzdP^lsi8N+'y 6%-K<KN6ւN (6{qRX>a70f) ,E]c`ԾC"Aqb&>jBifJRS+~ThcEn,@dkt1Df&?**XAlst L)کvAlsti8K$W/1>:40! ϋP_H!LO}eNL!@:(h^Pq)WXD;+?2f 6t Cfc1,*rz@!ʟlyQ &کNUO1#N3m.? a>tz?-Ҍy\kvϣ1Ύ@ ь#N2dѨZ'gZ!L9ǹs)^LѨ[gg4{iN2)Pg@^O#'ϑ f5ΝL0/pf: 8 QHUEi7e`sK8Cͥb%p/zu<7!H9ʼ\"FqPIN8bUYZo`4m2m ݹDꕼC~k)?sa3mMsB'0ݤ\LH=,d$ q@tgu`QgM`-jYOoc4T!/xY͒`l'sGIpKР87{ qGgT8)4A|!D;27UQ ׯ/0>3m./ӈQBtz;-!oa!H9ʴU0T#$J=i'I0Xwf]InkƽD A&%6j?az^#o.G79$!,؟¥b!!_3^uJލHN<]1$x^:8Vx晣q8#FiCrvR Bi9j.;Blsi8}%R/"ct%Œv68#ƺET$q6)EZު[?قBgПYqF7(3hV%Mkvld(WpV.J6H-bF=R2m'^q/u^^|[ g $-П'q%FtM4U$IۙM3mO"r]&jMtK yo@4Ѩ@MitE 8C樒q.\H4&n2* FQv68NúPˮ m٥yΥUyCN QFѤLZ7a)SlD f#YW@SwA!D)!r)i) ˫QB$g(U"JutٗD?o|5BlsW㌦TiT/wK!h$e*Ϋ I&;Ur)]0-jiOSoPq4TJvvcmOǏi r3)j<3+߃ !U!qDa tq&ZquUGye$PS]+2!'?'S8~d fNn8+ݸ &7LA,9 v~r.`0~6435n.)s/4nFQgG\ g$X_M`p۸a^ Bnd$%S&W f՜O۸sj;\܈3N'nO#)>Տ`@ny'}.؆s4xH' 7P>r"ğ(qդx2BTc4vC+ ףs6cl 'oP~bsB0~J!H9NA:&J aiB3g$]*\+h 3vanKU)g(U"Rڱʅr\*+{x fNnP~]є#sYwx;6G$9X26V%-1/lsi8&T/$7Ng rq$HU1PKINBnt4xHevȺT&AzPKR|"m~,D<]8t3mKZype. )떟?P0;+5h b&0+)ေQxg \SZ JTOTB՜p;"M4M3 n}L[d;+?ɈFu:g=q ҈5??W(2#P9ES$(3/(|odMW86DEvt@R21١NH9ʴUѴh#J|@Ǘƌv2$Gqp#43CftWx13m.m/E ɐH~ lc]"NV 8hϲSy]'lc]"T#Iy> RBFQ⬤^Hq y)zsƴ w28LG04R/WxƤ:z=4Y@;k?%Wo3Nx8`N 't @-PRM=7/gBn1(譱uuJ XN6~ud:ȋMo4ԐLJ@|$@#(a% ڕ 'K^Aߨ@MUĪ'('"H9ʴUt'Rd;c *m(qR r%>w8(A4;5.)*Y2 :6GvqJYD<<0K;Z@)0qN7HChSy.EG\?AṞS'8K\渝e"DI2@q8#9DwH5vo].y 1rAD bҽTch$e*NcKs^ɉ4q*7WJ{ߜ "H9ʼ$,Fqv*NKbU9 "dL[EMw,v!S|Kɢ\4FQf1vXZ9>+=gHS\TB?e*Duq&xa')a&ΝSD6tjq҈%EKK drWvnRFow"RaFUI8Z"arW7Jjz{ZR3s Q Z&ҊM fDRFQd1sv čEINKt&]%/Gbp~pD:#vӚ_LnxJch$e~R8۪LPK"45=ig0b77t%@M좢R0ojl6 \Q%An7IhzN#BDlsti8q6H,mWKmeDlsYO |;(+|/1|%dL[EB;Ayh e.Qj %dKv)B.?`"F7?h*#A$g!4Be>A7jAA"DS) iyѤzClsi8q.N^BmzSn/%y66Gj\H8f)cs?4ats܌غQ!4;5:m*Or:rtNClsi8OiGQ/$=ys6GsDꅄry5G9&L_Y!Пc\Hcn04x| Q0$A]ᤤ'G7Nh3&=kNk<#d$ qٴn$Ic tBqFuO̦]h7)IN4]ݩ<#HϐClc]"ݑD㰏JAf0N7[.@,{R,;({YL)H9Nbh؝ZIzI瑟bFQEgŊA9ʜԂi)}y$qPlsi8kFh!+Og$]n8z;-+x)5~}4m2m \Bv显+%\"@#(LwXidA`0` fPLAJ&EQG[c#g$]*LϹhf߈3m*ig3I _j]IqQ%-⼥;HaY:NXqQ%-⌥?@=/&YCTlc]n8im&%CQ6sD*t]OA p&~a&H1%/@nЭӍ3LH |G wrRnW~q){<=`4bpFuI8%iWFPg7Х\u%fFhsTI(%$gW6(A4;]]7D6GABO}`(_g fU`hV$똙86GBմk FQ "JI{1@=!4qtg 7lviv;0XEIy.U/6G5tk9݃ݱTws"Hvr1*Sw{"ӸU(jpYOgG9ګ!tSIFhLⴿޜڣ\gڶ.S}} dMɫѭY8̵;0'W=nwFG\u*w(\5dL[Ep]kvFj5.S|2Wdg$]~8l'PKSȷ[oK"qFEq T?˽Y$?$#r4m2/Quz7)?/)rY+HAΟrDf2G7Zli9=sLۢeL[ӓ>~Xes5BR\ǿ3ܤx~ WyKρFQR>A#JGlsN <]p?-)uћ2;8c:T >*I~ęh(VwKU_:?[,tf(rG-%OIoE5rIZ?dKϥ|{rjߒ.0mײW1o--WΑg$]'3 4HQ6)LO '0h$en_' P@7;@;k;ʵ7^PL3;hu:^. e H.iWEV.2o#r_cf0җ=OjTĴ(LqbYW@mJcƔM4jg, ǜ_1/Poj̭o%zWs~Bk[d_)Z[XhsTB";"(iWd^*%3mJZĩp\*0>䷹/s h$Cj&8ǿ#(v>r5χwlc]'36EyBSd7;رҼΨƠM4IDs|'c_S;x*Mg͟o`.&]yrdLR=$y=YAlsi8z!t#S>v\= }BLnUy':n}^q&I/9T%slŒdq]HyQă))1}4m2?3,}!)H9z2oL4; ]eiztRh>_ajWQ1@mDøa:8#ƺENh;ꔟH(q,d}eų#tţIMwsizCطm9LMb8ןs\<;w7z3MOU6==zqkNda\-LTٮoY ȴU q*w^]ק1e+=s"_cLS؈bǍ? HV2m`uy:4{8#Y L!Wz( s>GjLlkF;.xn},q&E`jW/Dd% Sբ_P'4*.+~ú'~ ff?+Sz8UkwxtapQZ 8#YӉJw#8Y uݍO(#63: 3؀1xw.Wh\7uS0@9ei9 s1ûqh/3K;#.wz!|^<gJzdQu{ A$=[~G1018)T'W:7&^g|ms fw,Xiv'@#Y Ȃvxb gLV`3f )QgǬ$%t }\< gס R+Dq Yvw J@&Ku>5˥٣ N쐵D&`F hX&bY\Z c}`G/9jm]ծP_?Rp9\@#Y Ȳ0A+ eqaX[T9d% ;I]R\_RҝQg8?5\#˝cF^,wgp‰u`ghA(>c[/Y Ȃ{ C:6G U9c3MOmfkY=4@#Y ȴچҡܤBn&] v%dQG({Mdfەgm:Wj.yy™NY:RzD@rgׂiGq^jwc80\ 9P3`ׇhAڶ[uou{s}{ܚTeP?J@& M̏- HV2(I襴RWs}, ipFi FGᠬ~zwӏҹGG r rhF™(gB;lIh`9Hq<'B0V c3Qlf>5|-HV2;nnQ2v}T&OmӿK~ᧁ~JP֟ ?[`DU!lizX!=9E;P(Q@,4%iiw6ˑ#"(60| " 4xb Q+*|K: o.| y򆮋rr_>&["izQ{4|ݮ\JLC 'J@A;]Rd@~Fx %s 4Ll&4]3-T"J@ƅ)c]/n Mu6{\~62}R`8Bd<H?ϐ^ĿJ@#5~0!8jqgPw0]!귾o) 14J44Ql^kOgkIJ@^^sT8DJ>Q_Z@|;TmkPzE,8үOx)*H`l\#n9Y ȴ84`fF~c8mX+P=Y8 MT]/׈B.Mj1ۤs`8v ,OD=^Ͽw?- oHV0ptuL? pT߷h~  5:L&<{ٍM!6GYa.a(ci aFiGqlJR;>3wj]i  :z,^bΩ>ylp3b(+v *O`°8Yɗtf>8S 'Œ;4Qdx %;3+ u:2]!EYa.Uj%PT&Ia>!ߩ(ID ]P?~OQ(΁}D4Q0XKȋ1JWp֞i ӧhd@ v LA1#컐-t Ǒ+N8C(S4TFbvĚ_<HV)P]tc_Bv$@#i'[j>qK>H d% 4_Tk[o_|ű8^sd{IC:4$0Nq]zAű+{q~̿)n 8] rDZ+O8B3MOCieu<I/3O@1 IWxL;Śy3A*99D)FPYJ@%A=-" riG @ODe% 㱞ŋۮdX+ (S4&wVE=+NHVc'Ÿӿh*3*IxfqB E%rSK F*?v3+p&$ey/]?ⴋmq5O=s7)Qe.Zh{2ELDUafvo_}$J@^`yTA4~!S:W0+/ \dY7JiDݓoon7l/ݧ@#YZ^]՟^7RmWSnD1&Ł&HIhd^w}/=WM?G ɼ3@uۦݼ8 gELsSh-wcD p&qxeyn:Hd6ς3 QV.ܟPT<GYcǘK_ $PV.ecjV5<g$+%L39i&jGA sE4r1SK87-|<g$+%8K@0D! JLp$ ɠ /pu3rNYv@-jPfOZ7fOhOpW}OtGnF0>u0̆;C_ҚTpd%R;Z$Φ28CQ 8ŚfrI3of/'#t9tkjec-/=B,0ָy1  d;A hC.ΌX`I;tzc.s`<E8paWg;`Ex4zAo ! DMBv8CQ (Ȣ-Kˣ7NL'Oy#==y{/}N7d% 4Px˥PUo~|MJ;4,0@Vz ŝd% g3=^;MT5ﵷfxfj Op(uKNBܜь ~ImQ4c,JZwIr+Hg_ױ`Q HvZ4eBYfo>C:<Ņ&~}q}n K@#Y ȂV5FXwK&pK>$^}˥5-Ί0cyo:8o5ֳzjeڿkwwnwkdql-V}|O AdATCiE2W(34,hqP m F{ֈi3>OTJTL<{ MTNTv;}΀K!jKx9h E%`..g(*tz}i~~I|jȥ5N+՗{yF40CQ L簲/h]5oY] HV&aW\4,؞WW"lC۽t 0AGN(AI cmjQ1P쳆_7|] sBh< PVɼy= rb*x3 cN7LT4tSx#ZBaf0 /{.TBKka64> d% ӎ:ۥ#sK ɴ~Zq转dJOi7NÔbS FiGqx kPw}K2Iiav!5H- J@7dCxmgKqq-}gY7_8CQ 8o''WBd˅~oU%g(*l~҂M΂(6$vjm$ǐ}^{uxQ.ZФKۻ^>dE}vvh &J@u\u_ADWX/2vlc|>}.$B?J}t4Q!]Qvuw?(bG؊/sҍA6Q(zƢ#ѐizbP-š~yy'aFBTZ΍vQ?J@=B!>)d,J!N LT ԲyMO HV2|3X}1<_vxUbs 'ęg^˫OTvOQ<2/8fZU4(1uQ c7L4L;#5N.镰TOZIOtaA) 0~+.bs 7&5ܨgLuG/tg$+%EvB=/{]C0ԑo$Dڙ-J{`a^xəXީYiZjW;Ӛm4=waBt1ͿgNfc6k/߶'mh9LSu솝'|ͧS9- ,_BEe% & !\4L;3dqԔhzQV`w@^_@?\ĵ:6_H (Y{cXh{:ijy9 \Gt3{ \I DEQl=# P =@ jVBY +WD+hoOvsMOhgRaAv_-Gd.)NDiU<4عdQti3Ncl&ɴؾ{7I,xr8*I*^V2jDTu[rI70DOL}嬮绾FFa}1 X\jv|Ioq(4=)vԷf>:U}),{r8*zXB/+YPon0*Kr <#&LT<_jl#(+YP߃ xssdO*N/&j m~yJ',Dz{wPnǸX;S_bj[I vs5oJ2\o~L'~d5yBBefow\Rg$;)Hw(T}G*'퇈JE5vwe|q~9&oThhtI|ޒUe!*i$֏_A&GSl)F ''"C͹Иo1I/NŶ<y-u8Ӵ[ ՛ͣ&IFiGzo_|d\hI!oPV27Lf$/W& h5dP a!ot<gyLcl[k6 HV@%=_m< P0r tpZ(A-t}O+#HVK)O{E~8 џ3Xz*3y3QgZ7ߓ:}>nm'' oQUrE!4,y0xCIo,L= HV2(ruΞ\ ny6Ɏ=\!zq(J@̑@dQ\+.4oL0v4.1PaiSHXJR坉., 038#Yaथ1m`E;>Hqۥ0̷ ҶFI&/Wۼ>pXGdQ [~ +XK@v B`T@Xgы@b/ 8=Gjuh$+YpR_˿Oֶ]y3G>,j;,P/qIq޽BYFiGIaX@4"EauϤYqJFiGqTજJU?Z\R\\.nqxbm 5̻'ϝ%ݓwPqb=JAC t[s'€{ 6q S Ϛ GLP+s \<]0J߄$'h$+ has4fd%¸Ջ.10F0.=F/N̥W@ ehv2 PN%=V;۰$;LS=rb "7%i25 |eC# U}p 3Me{uoB5-t'(iZRJFCH>&dWͱ^ÿ' R0e'a9FYa.OC3S?wS)3"~^6:R(;:_UTJ4EU(v ]Y $ô]3Ux0N%}\jgt}`bQǝ>B{Wi"#{ww`\G8}X{n&'zYa.-A{HZ.>APH%xJ:P/u@N[w/{$g$++S{$)0n/{j( >! 3%T^\zrzM{qk\C2H O΋ef]VF,.s+Ga@B{XXImzIout0OYw_ia5d=($J2ImA), M}prPh#̾uZ<ԹF73C Õ~@UM-O{V'Ns퐻N90k^'q:>LPGR?ރTA!g]*: Eg N4 D!WVsyDڨj3]V]ָ~5m5"%w0#ى;NSNOΝ_Dprc_j]?4(Qֺ__!ƅ}$ מ\^#DE}z?au}vptz Ӝ"O^V;}3i>2vK4֋pM>ݓ1;K:pYg! wPq (DgOF!PJ[#D58֧;bFږo US)py9mDT>74QSd ?ƺk초eY mD{ ]q;΢vo֬B7j4Q K^cc}e8gJFff܂ģ,.-CutO-;ֵϜOau뢞Y"$%.:־+a]sm;2\X %*zn48k̈́ n<@#Y\DZhi]I0v`+կL"sbƨd|A_TSOc%=*]EZSh\]׸oԸh[c_G|0l5. K*:%egVm6nsg(\x[q-lͭ/g$;f~$]CƲ/0)`^xVQ{ROnMwS;yrzrn8M͸~Gt5ESE@#٩IZ/y?!SɴQ N1]r\8DWLZTr a&I.o3vT\e/ߖd0DH")? &sJzbF*i~ub.مꤙwٲ̫,Rt׿*uSѥ8;Z\zq鉮/>5IM9B*U'[=v)VN`%녞Y."$%ڧhcR#`ۍWnTh$;G^0yEpY5=[/h$ii ֚g(4]UCc}@#i]3=SB%l#ٔ^hf)09ud]IW &ԠTJpRd?K B7̴I0kfO~*q *ZSiZ.q$4T7ʐ4QU2\yl){9`dgU4r=(Ka؋ip܋ºs\܊!B7N4QktFT5y/{AO܂@#Y\I*$?1U:h$;tG}n^0y㽽t9M;N XCpMRFXVO[Fp/ JT58Ԟ4jdgՆsۿ]XD%kmZ$b8#ٿ[W>ڼZFA;s7$o$i7y5O>*w"^ dF3P:R<rTUf?+S[1(S}m 'vA90 nIF &;~Oٳ~w*Z@5U.fOwRqFӊ]jŵ@%( zBQ6vUKv4%;ΟXY ']YYBizLw<\'}[O@?eeqՓj{tz"=} 8(5H\lbɄ#<>ǣåy".>$&Bwj4QM=n["a;k 0\*\i7j4Qլnv=(!HvU:* :_+C4{. 1Zip0$Ķ 䊝xnwtRY6󹾜M\qőߨszjm,NƜ]k"1m.2e2֍2MTG'ιr\QJ{B] {Y-=fDrr%a"ݾ}*H--try=cR̓Bę(znAc}^ժb3RKe&eq Ja퀟\yGvW#5-~@U͋a>#AUh$;Gq.^ĩ^?'5vljKZoT@,,uO5`ؒYՙ~VI~5jaEdQE$x-̈2M՚ӿ Ԕ: hZdpf\r7^3MO [~b@Y 80pDe*JڕN)oNr5,^_;v_8Zv%'f.yA*^2 W5ҋ{\͚C,6{.e#3ȮqIXzq&x_=\j<3@ңV6}HOiGGHdEg* EqG8 y/C+w3v/* 3(kUh$+ Bk 6V4dgU > y~.,}O'-~b(-Km p#鬀 feH .ߒIJ /~6Xkc}zD=JZ8yx5jj)*f75(+#P>T4ZS³({ DUsZ!F,|x(. hçL~?۫^ b3꥿͙k1Oaӱ{Hv'^~+ѐVl396])˕ݛ:)m"~MTNRlB l%{=VQI-qa/4L{n8ěnz{;H[dgU +H{ie P&\x|ZU>EDo:~$Xa,xj8$#OY0*61ENhZWbB 8#9HۭyE.)vG;e8 =0p\ƏyK7HPi[r;EG]wh3YOJ@Kp:޳%f4řrGbv蕰.OݬT<]i#Mh$g\sȧ='Yg=o߯g||4hGlI$4QUxVǰ8Gt#Iq8y!MT5ˆ}ڋ1 aFӼ̟&gI^?žخ6(FsCP35߯,{mAOb@#Yb/½4'Q:1t(8KrK(Œdq÷n2/s:w;ַmo)rɤ`Yb|5.N,sa#4=Ӝ`Xc"i-'@,'pmXSY1Cߍһ%-CLY c^A2 WĶG)N*0̓5hy7 t4w!HGyG-zG%NT(Ưu#ACw? HvVG)!+W=נ 9R#t>./t#@Z_WsL)0X4K+xtamC3Ac7$|sᦱcdi7MT,/ٮ}%=FFSW⦄F/\ՂetA E~4;/'pAyF}5n- Hvңh74ԡe[0CFFs3m"Y?39(&] %X?Jk;SB{[2ϭ[@ęgno^E{@#ٙȏ߻^18WrnR~Fݽ@6mrgKmIo?~ DUr= .^4]\y ߸vR`|׺qG!DӋyuz[Wh$/fڤÿ~SIXL:z(oROh$6{I4_G֦R Pqn~<tUǼHN HDq^nͩYyFsx 0 <*VHV2[qyu>d"F)HV.49fs}ϴAs})TwsS(J@\G<[u1n_`LtsW֗ލ:it;Sg(*\o޾zu2HV. G~izBQ=O=T15?3dwT8Y\h$+YpO۱B›~{S&mEQ&`)>==7Џw dQ wRz/+Ypˎ)|"[D) @~"4s;gq:?cwh$;F)/M#a-jǓ~gl4q&Y:iyx!giM<үKę{=듅~/YYk4>s,HV2{nxO8 WL})gܶt^}Wo0}Ø^_ȗ鐬 ]tGWдI&^VhCnv@LEԜ;K^KϷfۢh$+Yp ?'Ys]:(Bgo:3MI^ݟ Qv\838"DgiyGHv!GtkǞzM'Q.Ñ߉hi; dqnf'΋׊Bd% Sb:Gk9N H,A|{*H╅tXa(+i"<5!D%1nZ03O1Ά;m5$̎.d pEIsG]U g(:[8𽹝|)>ǘ^ʋ`ށfS %qTyՀQhHμ~fǽApEHp]~!=DJVqCw÷ȶ=)δۍ.OeX|t14Jڵ.~%MZ'ޟj E׸0 -vJz8Ӵ ͽ9g湽e9HV2 })x+݈:h(t[XU>ˏ}!Hv~ ;t-vLe\މCh$Pr CmŴ2Mc_P6K|l ibVOb=BN(ۦ(5wxmc[Iqz^,n4Q͡4!rq|}Xwm :Z8~K6ft*6M4@ןxS%*4FPhH9N+ݔIq^8{7MTn>p'$ޣm_`L ~!=FJS͡k}?Nd1HvGMΑnY\_6r @#iwȦF/np>3Ӽ?=ř+^Mk\M!?n7LӚZZnMxҽYn;18MTpc%fmO h$;sn,]I3sH杧4XFXi)Ib I>^]vy'2<2v7E|gp=J'4ݑBֺDůCW?#sHCuDPMQa,<_AqE#HG`rIZL҃<dg{~m_$zJ33>v;WhQ}ZtD,>5[s RcQWQs D8(:NuӝF󰾷:9I;Sbm2os ;dgyt~ۏ+b*)J TJq]{YMTP l~ GuSڦ$8 n;<4&A>g 4\ݱK Vh>L_S>1C)1^mWvsđg+ DU`xaoC}`F=?ovrz^w}r>8^Mqo4QU9gtH F7w)1?SZQAɔ|YbmR#Hv=JlPKi 3^q$)tiݑHSgW P ԌIFx)MTէT/]\pDJ08Cy( `aNRf$جğdϞx7"FSg$ R,KwR@~ dyzݶmW$ʲNo+ d(g۞(SokTF8Uk"Ȏl+I6)KZ%-4I )o۶Eb ֫6,}>%xl8R*JJZ78hpstK 0NvL,ԍ && I|ok䉉dq"m}6;Ya.2@mGt ,>`)JB<&f/sk dqB&'Ű-4 <0oVx(ed#m4'es}w+dՖ(6emSz.̳>ؾf ͛k d(#mWz(QYcm|^E14M`˶铯$I5?sA[O;)ZE!)Kn;MT@^oPC#ҶP"{㾑W4=W;3ހ~GqY]_x'B쬲cUBW흷BǪ MxR6ʶ<&'sSb2@#Ym%?vrzRegv-=sʛ2XsC%m,iJbK\:,ۻ(7HSݥqfo$I3MOHImXf}wgۏ+T\sl:f=r SDq/d Hvt$Ndp(+b_f- ~~3 l*N=!4=lO}Вr +BQsLӓnM=DF5Yۖ\š iMę4E[/qOmb #Ikr}<Ml8_ʮg(:-:eh! 'O>ӫF2@#i)=F-`ҌnYv1FNz[- `zȪ k4paY(>`yf5Di:Bj>D$0m3\\?\F@5MsWrb@#iY)=Uj2z k*sde(Wm_z4^STu&)v$ssz 0DjW.m5[qA:; MT-s{ؿq-E+hr3V'N[)dq 0w}!i9 lƦP @#y>7MJ lY&kif ¼~+fXÀf$ H{hyԷy"Hg<6|휥KiV4B>˟d,qFW~~Szrf-'wNa a3Of2)<'ױ =C<'Ei'4ݕrp ' #DM#-%T=Ipq)O z)1M͂پ=rV,x!ir kYl|/È3Mi)[Houb@#y88i,]KIy"X_V78Z&@#Y*?-ɦD<תN8CYI*=-I'UJseJs2!HvZJbvElQp.kmVZ?fw#D.FB/XDHגV"ڋM BCɡ#T4=!|e8\[v$%Pfo4QSJ'ihےVh{0#z&8{hbmI+F١$гhy/G,# E 2wnuРlv] o^ f,6}0l_z>!ic˜\Ιfg(:{eQ7$! dߵ}~Ah$;{c>ppUwRcC#~8M:OSzoHh$Sags۷vҕ4c'YM.m7{}61JRSFJ 0CI2; ~Ԃeс` 6om4[ΰFD5Jq-2M({*Z~8JTC%7ץZ@ eut6Q j~oHVra^&5uaqa2;v~Zu^c傟%^Ýd% SJKf~Q>}R0Cis ;:ȫB*NYFZe~~SzPgGHkh˚:WD**xZ S5fhP?^8~ 6@~vۅ  ";\OI9,W9L2qq(45wXMZې\IGoKdlcwy~ԷRX0FK8nehX0mtY5(8#Y8?v$z%PdߣE`4dMKdG„֫03II__U~D ֣m5L2`qEqߨo45Nc^0CiiÛ ՟PV.oøs̸k'5pX*_J DO-d}:8~qa2EmKwzu.F):V|zd|_nH]"@#yESGRJKtRr#Ҫt4ߵmQdh$wQ}a<ۖ0#YXDDW! n+Iۍ曞(N}U'=&MTʚO6u]ЃQQUU$fT(joX>xdaם˥4O.i?ӰQɑ}MS(v\i}/Xg~yz<3-ts= H/r < zr8XlС4[r}\ 7*4QSt m>j]k ~۔7"A5[O~؋@5nW0?Kj<æ\d_F&*Mg߾1%~h$7 {cN+H~wgʖ|1>cj8n$x{j9PT&eW{Xyxv̛6:4Wx*À3a $乃;\\Pw 4%a(mWz}1o}QnǼ{ثt|3y+.6o+vJ @#Y\Vb_JF/8Vru~'s<ذ_TJ'XrX [N& N|C|>W;:ǝ4N#ONLӓoŋ>_Gdybz|l%HVgW/MdpŇ209u,p Ν}2E]?oz7eRI8\zwwj4QռHSQZ%,+Gq8П^-2״F[J IyQ;;j^_4[zJ1ZKŧ %sⒹry) {E 7-4{jN,o4 h5`zGq=d% ӎbӟ^W(Xis|LS)4#EE|~]@UEWcӕe ߗ d:gѩ@fmZg[|oAj HV=c aR>c~}dp/69*;ja0;;G u>6IPBD!JOq/)_w}(Q}ܦM }XgG۶$bZ74QS˟ç'#HV2(yJ W,jw2/(pٶⰽ+^H++DrtMKX*goM=+({I*RTdݩ\Hrݾ)0)s6~ij͇)+5h$+va k<4doy?Kstq`f^s-ǭw<fIagKnd%`Ҏ⨣?! $-¯>*-DJqO^ ݱ3Pv\ `ot[hVB{6d% @%` NRPi}-|=o7~n'I6Hx]i_IKp@#Y ȴ&WpgƩ_4\kһ3Mi z%9msP O.ͧՕFtW8!HV2(TڮJԃ]y^3w {.Z<MTӧKP88Q¶-.nxnׅ8%P4i(Ώ{[3MO64 ,/' 9I! vZ({:׸xʄ85ݨm喺iZcYzԺQt ]ɓ(ޕgBbP'3jEGO5,<"ùengyl'_^ @#Y ȴ8&OQB8 >Fqi0pS(j@ܙ7:q4Qմ˴|G}W.d% ӎx?7 \PnsO÷A ] >y6jIz.7[LGMQk$PT*v)Nбȟ[{T a0_'jN8xm-;`W&D{r'DȃR ;E~%Ä8N;L k ~FMIL3I:vrr%KRqL4L;=p- )k8g-3rJ TJ sluuf_ t=J@ƭ.~Յ@U:θ{f@6/UW- ..W{Cjg]6Wth$+v*Ywq-LϞAktbo4hygiajn2YB0tyluv8~΃@,kr AAZo"!45B18_i8#Y 8i'Eqe_ev%k HV2(vd;Gcxݔ9BdS;M#a-̓ژ?_H z^s\<zp8,'#W's`b FTmQnazAR͌DBdA b(>r-)ց0fVfQ04jJv7Zk4QU# ZpSr`w ۶\yë_NLS| |{Ap\N&Lȱͷ~73Mg(>NjpFpz;73MOZiT}6hjQ%i?9l=/i d^P pxt2Z%O}I\g(*t$`=T޿Wx2vCDtsKD1jy\ԗ3O: -JZ<7vLTT.m,K4L;Bdy8Cc{&ezVwC17}aLL?p[Qhg45!:u=1qn#Qg^ܹjzH7ѻUO~xw2z[ qg S}n~*-%J@E޿?C I?|ӾS B׸xCQ/gyk'_|;.d'\pYkY>=QК\4L;~^!Ҷ־g|]ɺZ3J:n%N\&ׯ<]57S/YFiGo"+DҘҘAdQoMIuVshOڦ5.67pLCd>5 ݔ:nK.pG丹_ogPUYk4mKVfgѐBb/h|8Ma'(,xr!8M:@˭>OM:BqFpiGNDDIg_5%Jŧ51v*DJ1Gzz%IBcMPj dw@BQF0iGqvDW`c_jZI@\QMI؅/&{3hm$8O~@5M.;I}o<e J@>?5 @P˅9,kD  sјH`PJ͗}4l8#Ya. A-&#5|dz^s\8zq鉽u;ۿtm?P\D跩yL˟ڜ@'v8%[o 4=6N2c4[ HV2(I 1o6FfJ 0=}6J< MT񎙗mpnl/xopįt@F+X\ӲM!8#Y 8B17Ŵ@0s?C z.$F'&˵i̿ޑC0(h2'_\_M_L_s;_bkrX"w\2 kOzˏ?cxIép Su!琌J$;'~vl!sA_hb(*tG,ȅnrjlKMo{1 TAt[ Pq~qsX-C4,R QmŴ_2=_KZ qFpiGqoHF/DAijIſ&8d%&Epز#,@lğbM`+t E8JjBuvOXPCdQ! FP[֚jmFC FɎ̯J I .!{7ܢ m!t0j-wܶόD:AF pүav|84 ÈA.W҂ l(-̏y㋲4.it z5?%6s覛F 0`O%ꥸn`gtKtzG 0]>S6 LTTh{Ծ\jFiG[ޔ^-3=vD{xTAHN>> 1Ϗë:Q8سҝ MTs _]&K[tGKB}~@UCKMq#wqN8=ǙjyG?Jx0r vFryC*U0^d- SIw#!ϽvϨRLgHV2(v7PSecg!5 :~Nc&j*UOs{ XdS{vҥ4׍އgO֗4L;xZ`)ǰm{QKÝ^իu\Nx3b9_bU PTI9lԊ&/ ,d8Ǝ e&)khloc͘^ϣD_2mW` |C VMTokcWW5o{8dt1]< sZFߕkriQ ~_YT`>).v+@whY|[*HV201U~K+cM)>aM(S>L:Cqwh4wBaV C 뫿[z5Ixƻz?$pCG9apќ3stS/3Nڴ @͉'2*2^Y_ib01'2̑2/+_)zdRp&s q:Rp!t!}Z q: qf&R {"ZK`x> y~j\pt2GN̚tu CKG'J5D|7F9F^pX)js_;@YO--}x:RTH jqT  eb* @G-0 ˮ1?g@XIV_^LEHE,;ˁGl"oGHKv?Zx}&`T\7T۸[)-qNn41+B%sʀF*(c߶%t@(LI=嫮/ym8<- 0v[J&F$R9wg"Ҽ#,w`xM303g04ٲx癖pV*~phzTŞHԺ_>N;5sl 'gݬ?>@8gʒG2d}8VMR{.tfwx$ Tzܪ)V~<)*eO{ }펏L1I]q҈@Gj s=pr@ksݲ:\$mg-&l0D\RL>Gǵ| h ̯k}|%w ׵Pft@(y]D:~pM]s@ӛ(LV,D62gru-1!@\\fWWZ|&:5BAwc,tw.B wpT"fqCZ-bdKk#ē86hu@]t@kvvxgb$(\Ty![خM3->:}^fdR)w;d,"6ObEQ,t]u-\&)[t%2q&d2^O7%q"BTlɓPxz `Sb(_hK#E" @4ˌWN$2@C 8'IzT}LZ6\WК*IEd\\}~:*{@~-H1f g1 j -asԲjⱌTJcubk k_}L~)Dt@4ʌDBgV<>SN"E/lٚ:R:l Cu1g里Z6iś 4{gK_cV%[GaFIBgғܱAroGޟqM t@kw6cc dsQ) ZЮ .E1YGZs\@Gzy0}dJdFaz)`*}9.';瀦UNeusg(qhj'9/-Ξ cpܕU(qhjIT}DIѳ]BJ??Qf,OԉŚ^:RTh\.ifw\HbxkڧHQeߞSɘb#55A@O~o*nYb$UX\Mh5 t35P(L?Q$ЂL:$I[003Tx^~yS)hz<`$I?_܏/`Is@{( Y% {"/HOcųȻx#(ahzGQTŞH -={Hk/zpVGPК2\4cxi8Q=>I+?C/J]Qr1~/5aA?~(lz&KQ $т`ɫdM%/'y 5;aNPnCkŜ|oߐUdd+乃«޵_hL 4zq[X^H5$quOkaql `bN &oT{hfK8.֫MŠ7#0I B豅O~x4$ݜ+1 ySQY ^3L<L?Y]bJP)3~k\tշ@4onjpd۩C]-pziKaZ(HM=Br~Oon ]ͣʃpƄPWq曔8!!-9AYq boYsmY'14 v|OJqv]sͺ.'+R:t@uu7ΓױaNԎ="z^\&{ ;W$5{s '6,vja]&cxB#LF3 3Z ÞHF,Wxy<͘9 0fF(Ǟ 9OcDq\Teo(`R#҇س<Y!q_hY/$Б^ׁYMUskHZYc5BgbhǺK=}C _"ahjDŽ3)aNDaٳcp4;&怦vLACMs8)dYo}qSų,aT"QGЃfл8 - !N-]["f8 !Y!St#:9 S\iNKi56ˆK͜o'I#c{d?7E.i©ovso.I㤶: \_G}sr3'h`oOڼ׺:*e01f̹-xp;֍2zCy{@G .? >W9-c\6 jfMw$qRB•B+A$ d.F]z m tvf ozš&9I[02Z py`y~–s@1qL s2..Au1e󕾜$pT4Q[45kE#ah6384%M`E?FHZ3l` aODFQCga7{rfm%!hͦDM ׬"s.*T. 6+.:}N"|'Dr;^j\[0"L1ؖ5Hu&$ٙ n+n$2z_U HU_hFH#Ef{zUƐVՀ~:RTa}p)[КZsFrq,D(ku jZ0fl=~t@kot=nB"s-h]9 CXcOCb4\i Zgˆ°'4@7fC+ph9 EV Þ>>68OXt@kQ4{"fqwЕDm\} ̯k,°W7_: Zf€ׄaOD?bإs;lٳaJ!۱OeqhU'"E6zuv+l.%БR[4ewE@׉`8E[p+ j3 ^wɸHr5܆@-l~o< @6&$ 1rbOו!Nt,; a-_s @G 6 eGCZ@%$ t7YC :hOOX[We)y+e:}f G&^s@k(d7{je ay՜$6&u0o*G?5@-:=1pCÅSEgW$$%uu8'I]9l2ۍ͛0opXPyʒ?DS8-o"\h> dZ[E5 :RRY6x2}E5Ń1Y'PJ+B͗$1D$  |ZKwd@fg• °'̨H˘x~EcI)u1ٰfgCsqɷ!C JY8i8_㼄9NJ;&955@1F> 5pr) ]!aox ,5IR3;Ys˜GP+QY# {–6 9at n o(zc, q'-}oV`$Q=TkkV}wޥ%Q=e\ϜtdH@VzGŧ!);& <}!:mWZZ1:OBPQrMi/5 J3cPiz5n2?coB֌($\"3Ip $΃!]t+H@f3G&8JOSށQ$ǞX;b.eP?~Ł1$\8p</C=1n,V(u%X7g :3V+88C_D2jC_] t\P%ڣF WJ>wL];/:5sC^]:;R!+Ar5AV .huaS9u[9 W.aȲw=ԗ)m[B=NNtLnО!B|iÏ1JY}džAV`О%'H5mx|h2!&t@{VUv͡v/ oFKk^ fQfb B A0'I![2mʺdq:=+ci1M[–~>N/J_ƢJ1U'0Q-t5KՂ:5 Qsu!f W Z3䒉m(Ħx6]@ϮNКisd Þ0p0]źؑ,솬jfg Bѕ`yX]ȐK"R"Rxm~{=]#JVIf(״V]gcֺɱI27RMj[{v"Ʀ]6ʇF|zIFBi-pԤt( %+"f WSG|-qhz 2 ̹ܲHڞ⧻bu>.VIК$Y;0EqnnDsW!$I߅H]jǮld@nˣ=D^Oua"')ZrPUlNXq" L@⨧%jiJ-y+9IjV#I`OQQmbK+1>Nj[9NNZYOBO 7s d#7X3~f"0dC@,yqR\e_јR<7zt&!Ŧ^Xc^Gy^/$БJ[۬.11,$%YHnw=%3ޜ 'Z ӧTN2VI=KBM-hTU% ZskbB#HBp d*V֊\øV_Ә6E6s@#6_Ev'#2pi IL))xS;niȐ~hK*^¶9B<0 Ә`$!}'\\.@Ԫfj${B)~aj}#\}V-OtԌ-9^.}0o̗Ud0ZCˇ_bG(n !qhͱ5 KKM0W"D=JY97v t@{V;rϨuc>x,@+ T[,@XهpmHCx ZǩJZW89eSx& # d9T*3[ #E}mGo+. ]f2/ة#[kXZ5ˋ\̩Jw9lܤf️bA._"80`taIIټ G rdF\qe8bx^Ht&@4&:Ó:)H ^7.BE P)v3̙kd*|2+T>!|?S{`\ÖoE 0lGrή_CH#%\$9ŅaPIZn*;|vtJ.؝+@Vmld2pǒuBxe+i%Uڣ3r#3nw_b 7||?dL^Jfj=W39sAA>aEk…x sr;(cV}5o8 [> sf@}w.2ԪT\ tܠ$bw~C-?XUNݻIVD]OG=DtaIS13'Yi?ُi!X WۅWgDq<Y3fr5,3)1 jaOݪʕ@48,$5G%f0 K<#6a*\'h͜9JDf o¹|ZӐ܀PeDjV*jH!cmJ )hwjRmǧ"1S%h| tBse]I:j$-GbVNPxtqNr-hkݛ$YƵ4ui60XNT5z:Bҍc~ɏ*jfyd  m[pm`+gxTET8]F՟%+U Z7Guaۆx/w3_r?Q`w@vB1c(jlI&Qs_6vc2KZ;Nb"5rᗙJ+$3%n$MvA[.$GaȶCg]9⍽/}LZU= 5y=§=w,AS&P$>ih5)ܓ&EST&5]JtJ5# cֈ:i^UnxR72fpAM0u#8j͙.U%z6!cO<*kӨ6lJ8fXf]Kk*ʹ5U|v-1Gu+vRN$\m ĺijZQ,> #pF,w. b{0m}o&D.9ݠlfP #5~6D/&}^k2cZPp ҰK.Nk',)+*5]YH pUL2:f~@KڥuwAJZYhVk/U+rH 8l9,nx!ۖWw"70Mh}ekWDК;d~Lpp%KZsom& ' "+ ܖ耦gxSB֏9S9!}noɔ+hd5M=`?!}S`ƍ3ƾL|51/%> t@k(I=s1Tn\:&'oӉYG>N/̚JIRgU֨ ҪOꙒ<&QHz_M HiSw{1]QDil`vBIM" s]Hhx̴wbR?H)5[s%DFq(ޘ+-5S4n1z-4&@)Joz/}4> bu )Ofzq.K0o7-@rfΗF='ٽ^IgK7_I|G(7sxG2ϱrO.3bL>WqNZi S*$!̚E˼#Y)ӂgp _>IRda$՚LJb&qhb°oY$MoX-F'lOqet@f6Gscs !,5}Մfֻ?u{<͘X%i2i'/mWj sZ0'(De~QO<p*hz8vbB/$q8€=k2 Z3PI=v`(eȿdc:鱴6q Dl TF0QPhL% Y=\䲢}I:ohM߷BZ;NҘqI+d\´nj\^Wt倦]kDֆp- /݅@[\MhGk3=ɘ]}c9#$M`,P@f2GEtmqǴ&y)aN 75dI"Ed5 |#EL:{`L)>JQhym]WQ'MǕLZ3hPI=\2q QX倦D.TvƚX3#2&[29}n,C_t,@f,3G$!8Quh_,[z" J3cp:l֜%a$Zq2BM!`&Fj; DLE.mOr t@ke{j< 'n C"^+!hMK6G#&!8W<Bt!z{w_~O)W}˛~ U/?}|Wj G}ݫ/ r݇@&_*ǑAx1 ?^4?iBh)~0~)R@ y?'\}w>כz̾~axЩ/?Ea!E0Ssu>5xιf+7vTG2o@NSPMb9ώo""q& /7E;dji_aax|W>b񦄿Ec4ĽPҸJz3nbtY/4up03y+f +u_ptD*8뾟#됆m>/|/뗏?=^~o^ի_~f#Ov7Ü )Hmbe<-sz7D1k& 1Y]Ms,Y'ɤK6E.17:}_F]EQ~-(!r(52(ڒY"rX9WKeEh()VQ_%opl~GQE*ڨc1סp1-+|>Ɲ#a^_ b?a˝D a9^?ԅ fT׷[l94b/oCzŨߤWb]R2mjCxt?(Qb ?xnqC~whÐ w[} }VN/?>}ԱT?~ûX.e(|><?}̿)(黧$Q_/kqhc8?4o?m2(Ey7c?~*'!LWjz{=@[ǺLe zSdX޾<}&αӷl?O'3 6 *; ~q[|}uß:8ϖ7@% c҃xaoCLS=?> xQ/JX oʢkXI/Faܿ6I_ǩm"DUnWxn=0!uٗߍ]7 JG|)hKoknTt}c2eR[y~L8l΢G5-r/b }rq,c̗$Q>*c`]@kL :f~'mZpSX?# 5v%]zSmԱ˗~fOɈnV#7xs-ˏoDo2~x9+Ut3Le, )KLCO)Mˡn=~|X>y}IeY''i.sDʛpFHef+ LBG;&UbF0B@Dzq)KO/gI.gh?}GM_% :ORUÀ'y|yx0_u?;o8:^znsr|?SŒP4>m7~eþ{[m5?.9ƸGةQO?fǗO)3|D~endstream endobj 643 0 obj 265385 endobj 662 0 obj <> stream x[[o7QoO wt 4h] Ƀ֑Hv:KU}NpayB܄*|\-HhM*B0jJjpSMo/._|3} fubYhVě<1cfs^zQL~\u"I$<ؑؑY#\z86i,.V=DB*>HLub8G̗^GRH~Ubv̲:~{Z<}&cז#!F+ζum#ړݨZ_KOx r_ՈHRcuED"#4 7eHڵs9),c]A ";dKӷzM jiUSоm{Dkhm=ψOD3Z4s8m͠M&<@sL riYXskD)k1gjLA!Xhv5V(.eCKLU5m7u/nk hq 0_v70'Sy/z1eVPae*kg}FH, $R.ij!CoXM$ƈfwMnB昋;/wŭsRSxA7tup ]a^`lў]9 5R7swj{7[]u{WVs9FҬ}7c4ҽr`}y3nк\b^mKe'9o; A%^ ><1>b`d=Wdǚt1^ug7ޗWYYaI;:N@7߆-Z  ͧ>&Oo=<4g63FO|[V˔39{\zzYeO77᳠mAXpylk_n:vi͘-DE=(4Q|YDGO]Y(!Ӂ]dç.1MxmG WqP ]Y. ,> stream xYKs7 yޒL|3^ĩ:9ٵ,ws)/ZOL&  @OݟsN?CGkw߁զ?[Qn]z=%_l.>] wX;G-0B*_ڸj: % NsFA"h"5IvǷu[7n (?RQPivYI Bԃfy*I:z[< /n{]nn')=/7ۇ8`[L-iDZNcW^%$I6{ {_ta; 8Ew_zܑTX~}\w_zN?>`hr02aG2B" +O(D;^kiJث1lI9ư"H5F[e4&T-U0/{9h|pq"&oV,zJ:eÇ/2s893Ơ8d*af§ΔOsIHl]"E8qK9.mct0jK[T/(|Epk|"h>/ eʋ||~J/Y-HJP #Y.R ./f0F(V-2L[) Ū΀:-"cSDq[@j\ TmV&LC)bfBbzVH (+[!XqV!s)-=[ !I=ƨ0,Q?bTi(qꗁ]<"n쉩8Q$ &?IiISL۵aR'x :T,Xe&`Ogf7& fT=Z6UJhԵ69iyVcM> stream xˮ,Mo%6?Om-2-4/_ <.V3fG_8uM:.ү:,w_~O״URW7~l}_ ,@|FWjIPizm Kn.^yFo8>Uiݪ!WEg>ϰq>fȵ=5˪$+G_CnF5Ǘg_e5.>K_ˬ.ҕ54YRmq_{,ӵz.c-_l{,ݷjo+] cݦ󵫣zrq{kk_GK_ia8e _tSs=kتr*c]43O.23鿆m^ ֡[ZHW]ǭ*Rj˼~6@uul׺Tf &y\:c5`ݕYGtXGqh"OѩiX<瘫11 ]tBVZkdǾ:lnd :@oQ0.:Lqq#b떫5UcYuYl~d UF]8S[TcȢwQ9%m.|q^!Ra\~)yN뤎6̇7{ 63ޖc6Vօo@C>.wnBgu\nI!tz;}>)tj =Nw1xҧw~~ن)!I[| :-2yϳre*4q+5\MC ]6[2A5MxPܩb%lcr4LZ6wӇvߓZ'z'Mvx๛:9}:#atP'ɵa^tݒ(a&ghV_~b(MLGo:H}gO4ʁB|kȻ_.CЦ9ڠxj7AWJs}[pBWײV8|R(v_6%ʖk?6>RmvPnAoJp33x ˺2L6pcʠVKy m:Qo9% YW8M {jҺKM.Q @A-D{{ƀA]{m9HM#Jg]%c{W{)Z8(TWC'жc_mqBjjr,nYl_m ^O ژ8!qQ & 4|wPXUy0x:o' Mѵsz|`SJ;-^/㨇 -7kRԬڦC5 f-Q}J)bӀҴcO S]}C aM(n3*W0VV)H @; `SYJn7]2gHkFtp gkߴ0tvM lr2)y _ _ h(^kե+u8qm%~TGrR¡p}_v M.6z o@nV5g`ecXM9vypz&A׺7 tP&&~+fYiΫug;(Yh _hB,'wF"lkmX!>'жc_a:( ύDS AIan2l\|(@!Uu#UϜ7x.D,']rjp6mAܖbLݤs?U(vMbtO,]0a˳="Au^? XO s`/%U~50d8jC^dK}QfVsy,fc~B9.̴ Ѩ뛎b'l}΢c HU;ItX 8v3hb[D5ҫ4ɡ2&e:"Z'h&.tϸQj9k&lYOT(MV !Zv0Bemw1*@[f4ܰ6M0n_7^Xo*lS(jTS xx/uvoP (vx&ui,ѩfpmq 9cҐ{[Q|8 rP-;G."Dq[΍Ѣ_zЫIS)Id0fvIT5ɗyR+ h ˉ_na~/EOr9ω1{J0$ѹ^\aXs.@ RˬQZ0|&Lͻm';cR#BgbohՠH9mw{+n6.T`{jMDh_EkJp31I}?ڏ{ S8MzM!`lxrIetZ n9.vI!"Q"]5&2a@] ES랱<Dz9eE:,#piMș\Ȑ8Y|@tӀϻ[&h rOADQѝo}! ;?vX B/DP'l@w)sR)B WԹ%USL B5R`H ;PhU}4/~ʼnN'.9x,RӤ 5X֗<7X}l-&PĆ1G~31ATJ!#3xЪb_#(b]Bf85l*h{<(EAk(]r\kƔXS(H` * VK4/] ! Q ,IA]{ @!UM3(\:h3(hP_i䬟o y4k5˗(._ N1uGzt8YmǾ h^Z)ljoq!f̐0u-Jqk2Dk>9D.d$T<ˠe"y#2( ˠ*ǠUy#&j4s}-/b'lߦ6&).d~pg 'Vm̴iբXdn @wsr #2״IΙt %@!jBM&AW?5@v:1tz 8T4i\3wC_)p5[5L8-}M=vaC*BqBy4?7V`ƚ693D2d,Tu&uuoǗ~EjC-0@>tDB*siԒj5S*(M7L[6CDׄ%صsi+عO GjpB*YQ?E vjS&Yډj aTv uW7N>o*tnk &VoktWl~Q¨&];F4Q{@]N M =c|QgUS)]`T*Tm]7ݸ*+AmYuo6e0pZbȮ'0mR NK˶8X] P63fNUq6Ѳ-Oz'0|ԙJ)0"y9MNHEƧ?-^+y獊I >4P)%q3'ְ0bV@yCg#c;~‰ u+JR|zG81<=@!u;$em&$(R9bf2"s4%AY۩}u!@ 1H , ;c%elr \@<ڌ6"T,5 Ӽ6,,줄@Yi-G!#(vCKB{etO(K]u(vK|\'qC0(|tKYz]W~oXc:̪C>4юd߉Y ymW_Wޑ4; VO dsR4'/kX6=Lh_ uA`Fu]N iR0Q iRq?m}]F2p`mR`H=.,Eyi]On Whm)k؋bS0xMµo?0t)a(/@ނI!y?qxB*~>Ki4oQ݁ض@! eJR{4) R(5ǠqQ"qikq^p`ܚJ90$OCK 띧R(1-4Ӕ)bLqQ`u 'fU'/<EܒbBoV&ƙ̌ިdIoP޸fl7=Y}[fJ@;7{@Fc,2uOoP~.Qk[YR|t|8)9m5Dcg*-'p wX[R>X(vNJBoBu8}r{7`6r`~&;#U(TzgJ3ڲmhT@E M=52~l8FI(hQ 6D(΁3LNz4if0nQ L,@8Y<@!O2t-4Q@[̨8Y#qśiT{+1 ֮C;0D;!YJ?ۑ$Y(vK\fƹdPɱ|Bx@-bs#Bk}qZژge(2?N8==SKq+C9mt 91׾yٿn֜ I IJTUT RquO0&}ua xO[dWp_]Ol@!YND`];`(vKƈy3id ݱ۰PCd|,.R{җKHO>tj_4X;vxhۃR:I8 7[{yږnBᝒQ LjS-6ڹ6>90,F3!$j_glZH)e8솬ٵs&8ϿWgT뾟6N:u1-?IIvD=[믿׆_ݬ>u?WoJU]M}yc_>P"4y_{oўd`O>]9}KQΖGTdzؓ<֤u[NRSs>}eǥ 7*k}\<~1'鞧|:6w.jHTi%烺.tKozR\gzR.㊄7kPLkĈipBm2hQ ) m1v%-36G ]8u(Y҃MVeTSRw48ngnh cUypvMqXv,q_]% 35Ҩy5A(xoÓ(oNϾPH=4;ZCt0E|N-$I":g\IFMqڢeH(vOM8S]旣;,߶c_$+H 7ۜ$oZ|ۤU6t(7#8Մ3f0#&P`rB Pm1Jgg6(*&ڤ[Ox|́#'vK/@ Aa#l5[d@:)0҆9w~e_wP-]̯ƩU5{j!Xj[j5:Mj/ʹ}I - jtBhp)1{SZ5G3{he..+`Tbq-hZGJdM :G h8zzV؂d=Pq|.r 26Q0.*j͞kp2lCiT88ū uEߵ7u><(A`#YUJzjnT7ew\k n Q Ruv:c\>9 L'ҭ:[-Hv9IBzzoE2.^Fl*bOO@! }EkGL(vO`Y܍> Am= FqrڸZWKqsqmwcdFcK\ukq V?.YK6S`\BNOgPHSv%o3ǽw$]qSCЪ٤8 ͨG?eފB.E T7N8=Sntse@q&\1 bjZ?$= Qz]r*7M# 4g( :mLˠ% @-j Y(Bg/-r}hnpmѓ!5QTңcYua@=CuA!q>9qR~d#nmK=4 *:MLzMG2ىif uzQZTX9oӺNMNHSZWr0 {Eɵ~&'r}.b9IP)nTO՛bcMԼm՛N"= u2kn?BhI]<6H,:;8kGiV`-S)^ _IZT[Z{O}k!kZjH=ꙡBzQ^`.(e)AmH{F=7(0Q~uSi5ZVt6a.=$NpZt2D,N&~b#4IY[f[+~gX[ ݱ"`b㓋"E2P骤m1|-> ]lQ\QVۥg5h pms ,3'Dq!_Ei%xr9Bq< O {K n''('td=jaq R Km'(X}{͇ 2$!'NvPHS9U;3%@p S`X Юwr^l`oMucD@;QpQ2,)$t;amj÷f:rNk?a>:SD;xz,siPz=Ph~5B9RSƹ8.XK[CnA^}s]Q]楽mtŃC650Ωetn7d]5ZpI2 rK^jݏM*duwbtpԄM3u2\\FA'Ηu3ԍ{LiTB|x\;גUY }mwu<N|-} ESEʤ|C'~lE .Hl݊ZrL\=RCTY=e٨af}L@#t'(ڧ+soqT6Z9#d a=^k{3 @{f9O̾q(ʅLjXۙj[O+zښB).,NR'J(c-uJXs6׆(<0)s$-T19k{m pϮsRL0oJeXL2ndQ^D1¸PZRfsCigIb9n W_k#jA$h5_ҏwHHܭ%0Oq7AOpE_dÒKܚO ~}!3{<|k; a=㜟^2Z^6(.E>=}C&!Rw+~ixvXn`B*}-{ fF'_4JKsB^8?W+vzj#Z'Zvh:p).ϯs78MM}7}w*4qM{j/[.*++88Atp)P d9⃓(ΣiL,U nݴd xSǶʲlz;bу@4AܿsRF{UR?r?Y2Pm:ڒ`daF”r޷PLk #(жqax|ںMK\P@H ˷AgYidvebN#h}O>Ḍ8\ M.cյb=F:&Z3 -FXQvò t *r랮abuSl]#A*)0xd tATۅ̽Tͱ _?j1a GXrL?Y&y.6M(ж;zZr| ;'vv9'\5n{ÉwbX)UP0: Y@= !!Ғ\1֯xYJrhۃacƑL|VuuulTă..1R\|%N:+R 5z[ ۸@&ŧm fb*Wa|a8ךj5x9O$9Y| B*RzݗAsK@=,. ]ar 3k %ӷSIPBzcV ;D%1 \4՜eNGo hjM91|}B"F?nCp\P@46`Փ(жQHonEȣ""֯ (]](BU'ж}?"dqAVpWp@t"RW!&  iΓ\z3EJ2u 5!Dm|rQ?NK/vj/hۃ '0豌*"qziԳF ؍8t[6Z@^m2| L d|Šc&ν.+=3,j@_VF Ɂ,::s{@!NA}ƀY1m{DR7BRŠzMK:bIN,0Lmy\z= $T pm;^S6B(*WG^dk 9+kSÞUv.:L cgNwŪ^O-Q@t$`a3FǣM#Ɠrk$ݖ08)Nˆ('ee,(@!j :z74w @=QF ЯT$`/@cnkx|i CJEN_*{ߖFm\ަfƊ ?(f |Uq <Ҳb^?& hۃ01Pmaw 4/[ ۸™^?_RH ds4)yP{"jC~Kv ߽UAL!hbm5tT(ж#2 !RbRǽ̧} א#`,a & s{Gv{H} ݐs6T8.*I:-GQh!/F8†D$~r[SveoG,MRE_b.gO֔]◟ ~Ւᄌʔlx:V4@=茨CߒۡXW@= t6s0.&xw@'TWv#Pm:*T 3k;z3b&E5,ߙ?z106e)0oۃ {v@!C~mF7wHlv aeR.srT*q 1q\3jz0T>axjGbGhAN']V :)]}P3@!U(gz;z 8Ԇ('0ǜ>(Ny; vl.Vb&cu hۃ8+* (O]x*Κ?`*ElU!Rq`(~8'AE($Ho"UE*R &MZl .ײJ t\Q* :Rd^\_tm:Ӕ#ΒU"Stn]ZڻO5mL؂m{Y^csOO'Hn-Pm:s?X! \ɯg8D*UQ n^Y*ypJ?/־݂]x34vؤ MeE'/PHCT,tU(ж 70jLj·_M*\a 4 u#xojc';5GS NQ&<ţ]Sb=( i2^ hE|7AW賬_5珩öAJ191|Bꜞ 验3!hۃθ_a5-{˺eh^xaO^@=,@g¸7_"q-qΥp*c mqbhѽ)eZn@81)(A|5 u vzbQc ³=Åchj^EMN2jۆiRhjL#@F)ORë4nq)]^WȏyBwiC(N_7zvlԧ0Mհ \X}gg\|BjzlG_Gq?mI$T?d)5Kӎ=K|^(wwp$ S\x=l䵺2)F(ǫЋG6F).<󂾍* :q|aBN;jOk B\am{YsJABw) Lepnj|u̴[-pU.K92@jj軴y,\Pθ_ɰktv.ٖϽ~n8 g YZt" Tz¦:* $ [RrT;LLZbGـ?qJ1++91|Y BLTKW^uЗޠ%hۃT3'}x&ǹ6ᓜJ Z`J #+A>&^iÓϦ1['m{*pn'Vd5Q < ߔvCw|8~ȉ *U_sT>-guzOJ|I9 m{!0ma`oK]GkZ]:Uhmb}*x IgKmخiJk7ޡU@ێ}9@s.Db/Cwqp;S'Ågx 1+m]%ѕ-N[H9k;?Ai% U*j]Ah9<$4[W[:?tb)dz|gP }} ,1D kH@_놺Fe*Tѣ7Q⃩eK|m{ŧ?ʦj>\ۙg%˴㋢ 0ag](%l2Zy@#bW{q3EƘB)0F'k|t2zN`TkP!tr(S: xzdfNk4c.=EGf|TC$ 8~F/V->1ݤQc4Wpt#;/vVsՈ m{Y@f FFKzK?Z=[Fs&b%c{g!Ș:.< uAS+'u2!Z@!U^˨25"zWޔ?QCIֿ9`=6(/5N.ƧJ0Kr8dY.vSk`~7%anЏ)UA@my B>9F.X˱?xk$;'?Jr|}!^hI$/. PHk̍jtX W(:P%xIlqiY.Mo2F<6DQp# jĕ[%f})ךlxSg= vA9fЏ5{ ,WjAZ@k7N-E4G;ƦWUE~''m J]ש5]n`JuhuIN|{yntT mq!RbsZV >KV29U C@m52Un7|DIaxB;}Bz=%4f{Iࢣw*ꀏ)\"Npy ! 0ҨxEZ)0:K$DҋRwx9lscO6^TpʥrkMɨ\ aہ=X޹ϛ:`TβrD(Fatx!  %^ҖN ND7yYt B*BVhP!NB:gMY.ry/Il|+2Պem~Ƽ,6@!Q-j?ys+FlR`t.(ruYˢkdRqLjb1F2 /QT=+K еWAY mqIı9:J;^1'N_3WdY*vS"j@uUt*J@\X AWuIЧۚG )su\T\lOS[6{, P]WH%XtOu+?u6tm6&Dt^" ,碸u*OlWr>춗,qҕ01{9QĔU,T@!"vޮ)v0ıJѱ(^b*v^]C絩PNҔo Ek/UL nj/* ͉!Ws|qR~ٔOry}C{gg _UW1jt7>u F+wmG+rQ?ϿE 9^C e(v]VpTbqzdҁ(61#\Hy-mZUf^>&.F` PyYt B*TjO^ǭ q)PN|]yz9"ˆ¦.E'J Zj3BGi .y/]X. uRv9*mä@g~TXl;>*y?}+ }J40eV A_ A^j蕑uB#wJ[A)Pm:wO`uk5i~~Y3Wl9޵AgDAtND]ȅ>qYJmR`t* qRE(LΊ]m1ϛH(ж00plEhUq.J뜩!NmǾ0O!hmrQUlhm1}Ve (X, Ag1k~-5٧3lR`\Bn$8QtpBrBw &  Vy" t^L}z9.hۃlNp&ۥE@,a|y}s0Q @դ>Iy?˿e/c+9Jq[RPJ+-N_iz畖m-}Ph۱/!y4h[JwǤq!p`/v`:,NA`n]9#6cH拄 |̦\SwfJvz-5aO_BbtVj\|Bnj!Qև:Η>,>aOadk=)K] 7yMi]ɒÉoڃJ!|Eq\^YkUo֌("`XA"w89sTpm{ЗEFRjȪQAՁ2qM{QrQg0sOYUJ.hۃҊZs`(Q@ێ]9\wvOCd6Y$MLt:띟V;|p Ag\ q5B7n*^[ n{͟kpA35'N8**j6Eh<^BM1D, Р| ]+ȣR8 A}2X ۷ NB`ƽ˟]zNB޴8:[렅3LKOz$%|~{"q{WxuΟ`К^j WgAF Koa-1, 2'ޭ?fEUp65.<8{vFK֩E{tU<@klJ%p'AƲt7,AMTJKKA]Ɖ5R39 RȃYo!(Ņ'@йS'PHӊZlݑ.PPm:{]L.f.}}F#{H`\SR\۷'z_G5UPyz MGz` Ē=q8oꏾLؔئ u+vKcS\n2XI-Cy7_8L"ϗ"'ibz7mF֟;{oR̂- jBM' ybhZކl+Pm:*0.x޽Tyѓ6vO[@pX ~+ |V6Zjpo+zVg/7 \fn"+RuH+ 0ؘ/02"ؚ#IekL۰Mr1bҘU5#g3xr՗O31mTR\xuGk1m:#}<@!ҝetf]rRsڷEQ,қJ ,|Eh^U& v@ dN/۪W+WE{&` >x\?[[smo~6an`͂ UJp;9, 0TΪ3\u&xn߶cW)߾Ԅl o@=I{j&dQ5}{h\7A8kS*ƅ|i kRw5eToD!W@t(w"O-c,8tأ][ȴ_w{ڂ\UpQ kCO՝( )@ p %E3L-ozAk P&Wvy\P/θ_到k %{Uv67 ^1eRA M gzZq :=,kES, jhۃ A/lSF\z^YUcآ'.O-x=(|?ap`)ib)Q:Y@t>csa\1'}=I_y_@[̯>,6حz>Pm:[Cpm%dq ]#)0ɲ "^^-Chc_î<‹-&`82g>zL+YnKyrl[Yj諺eQ<8%TP5GF 0t`_[jhbw~y= yR\J|׀6T) Os|k_~" >0R`X 7Ct;q4 8!UOel4dqL78W4%J!pV_x^p's^k$ͩRC'E} v.G'PN5C'eCE<+;W׳"RB/b+1\sRw2p&@u۬x;-(rtK_Rm81VlR`x*=(/ȝ#:S|b,|h E3B񛳺 =ZZwq&nWԴnk}Еq%, ȡm1\ܵp]S-}+ ; *[L)0,bxjT Ig r/V?+/#ͲM[ rRm V.Ix6ͧ7`h!xa8Gjqts\㼴CHc&RvrHbPBjʳ0>kY욑sl8n)KDxBW(h Dq*Ttp|˕Vrn^L219=[\-z7 @[N5֟kRQY?).dTaDFuSRWkC #G4yk/\RFe).،thp)0}mz%d7Z@E.{;/s6*ϏGB3RkK1MV"D_#d}5UR`XuŒyimwy)AW 99WXOmK"Z"DqfeўI5mރHɦljQ{}68m7!Vz%1B R"qO鸺+G8M,*"fcda9bP^'@"R mR ?eD'g(8N^%qrΪ5a=F|3D`e~ BzʨUj ȷR4`g4!K*N~Vq uԳSRkTѠɵpljoaTյ&.DžךXCYqoJ!k= !4pa<1ou\lG{*W@ ܣ)0,}6%U,Ua8N 8u ˷W)9e 90}lj> Fll0h!Y` yj<82CzT;=Ta#m 1 EA0NTN85%kad Y8!tU|\E`V5QeU7?8[~='WAɤQ“rh{C=5!CPy3%* |_M!,K\ GS+~P/I\C ]M[ ˑWRf9 {l}e.y'vG| f,Dތ@(E~@(zUeU5|B P@}Fy>>((\Pb#NF*G?GeS7\F{IpDV)pJ|Vi[U^H /"RQsNm emku5I"!&r ~&ĘcR+ˬo^OAch!N¿86q@Π_JyŶWrv*#ҧ7@H~7C +^{o@ Ct=S髦A x?~g8Y֫d0J<ĐUMgùJO8_^i"b<0Y)$$:ъ0( mg1iCv@ٜ]3XR)B!#9vpmwe68 /e^ϫa(vâIOY70Fh=˵ F&\pZgtf~҉6?BX)=LE @{B lqC>iĸL}.0-m|R`X \oF/:Q<@!vtu#uf,ysf*fT6EhM/^O'n R5i NRkG$Ttpũ u7nV_KS`H)](vz۬Qǰ)FcyԷyjVSXH]@WȡCɟM_j ԷZ̡^W%sLp!o˄ NeGNzvI?S0]b&9taR"L(,p }~N& l|#Gbv Gx\CHmO,w&J]A?Y}zimmD4P&s0c l$YߏAan>{*Mп|BT/ m{Oܮ-Nu1nkbDyF}:`2Q@mr Yp=2Ax ,Fg࢔Lt[՜ h'^Bنن40Ex) =P>@OzJ":}v(q-;eFtѳ{(`m7+wU랚Dw8Ep啞׏#;{צ(Å\`*78m>D=N&}jnt_p\ `mQcz`̟VyZXkPf A&{WQ${(iGrɞ '{iAdFۓVT|2<~Zc-A|:Q| @!vf)Z*]x˦mcu*I No&v<}Tg\8FDLXg.YXZW<~C@5R`H?IJ$:)Z_8/,i7tʁ\RAw>f߸Q? dc[+|6K ٮJˤ*^7T lh2\D;-MН$:Ei7N}[աF^0Č@gd8jZ[HLmw9F&Y(" kkZ mxP]r)`5BM_Na-E Hԁ1C.\idIT]6QxЙ_PInw2f$-%FXiӶ͑]dG م`;fiŧ=R ̈́\,VrO0l8QN$ ݠA@$injh,Bw;身ة)8ZUx@YH4B7|mS.Fk.b'LP`bNPh!GUC2ťdhO^`3J)0$ːNPHa-:5OۂkJ77% 'x;_GۆG~c rI)acoM׻pW43򳝶@sI%G~3;f|T"cP*XpuQ_Zμ݂/ #k;}nL;7d$3I$32b@+[ 1(Ɩ-EI$`XAÆDYTVЄ1nT25lItpTBhp ʘ? ֕Є1n ݜCM6ct/V61CmŊ*V7!ʧ$heF0aJ"[qHJJuKSă4\lWrZ-tFpJ M=7eVׅ!e,OON{ )%Y oHQv3UrŪѻKmYU@hŪP_/+z9Uf S\egSye;RpE.V3dKI0<򑉌|ښYRzJRwq5v)qbD3[J>d2Eҗ1(ǹm㔙$Ti[I-g@'iO;|EH* x$>]@ۥ0"lvP" Ԍ&cgFlR%Af}xGw5blx|V >M"Z%\vjï鹯~*xI5"9xVG<tb6 fqWo"p5B[)]@j,\壿_|/ʿ665 ls߾ZT˫G4\id\x?^m8F;K띷=|3gܭnOo[-\%oa7L +/hpV mfP)U_h%}ERlrC+1oj0Bۭ&#t4UNba' O[;5 Mp zIIW/U£2nO.c-<[v#2e;cb ׀1(G4S_@$̨Klfח}1(EE?t7С"[h%5L#|A'5ic-3V7᪬sd2<>=b ַH$3@L[ ` DE0E 3\a5ٖEF.(E-Ơytl%F\'!?,7- U%mo,xF0! !93 Q$cbr#\ZJC|$%i Bm(N[C["eP -b1(nј'hFк/zbDF3&1ƠgX_O'gzws!],Md.1 :9%F"0v-Ol"şt!O%B8;b-]PhMgiڂ8MHfd E4ң1>LzxbZC ZH =_P _vOzI _NVF6:(Y?M(c 4>։9[^7+4цpBۍ7i iM(gMOՇ 8nDjY7J*cyHtjɽ 3Ĕ3Bۍ4HsAIƺĂ~Wl:r>7uQAҒ{9,8l˒UZvF!;OɛޗפH7 $3r4ѐ2Bpy}!>Q@h(9[;\CU=NIi*:n2rc~(%y8tJut GV*5$4tv,ܖ%.mFoI$C\<x%uA)6֑h ;;(_a̼ڵKt2^v3 3R+ 㖶Qv.Qnzyt2B ԑ'f 6H2#D9C?xuA)Rq; LAbP c 4aM$nn)\Dѥ͖) b ~D>]U}1_I-B v`?K'i Ϙd0;I"`# &VR J\nOO#i$dF6 GKGω0dTK. j0B5{ڮۻΤ:.]޽O<z@p'Lh=jF>|FFqj}Qn~}}{~ۇGq1t7e qzT\/X̵4ouW4QjzHiKfˇ$GM5ZҷjiF6`j^~uvS[/燻oJW߼}(PI/p&gOgYj7LA7y겹GŧDʈrӤ)6yQi*˘/OֵٙuVGeF͘}lr-6!]F57\D+|f3O8sN+bF:6k›6ь/[6zv.۱6TG_ѩ*P *'}2cET)VXx{#rI*??dD_<,\UuDZ XYu7uND(9t5o9۵5HУ8/iKVqfƦ cӺD0aX7{uGjq4qxLЌr>(ڍՇDVTNE竇}IW߰T_7jDMs3q6"1Ҷ8=O6[&sp|ƚtcL5R HS c޽.3-> stream x$Mr%M˖Ah'~,n= 9#n"dѨ.8~1ON{ǏG~?ж(h~/ᄋknw @w#/p^[o׿M^߽[L3ìo?j߯Lk=~=0y}JÉxˏSy}^˛=__Eek}ϖqNm^Z^2e^X6^_uS}/}ݗ|/Kyj۾Dy9UM'%{{]??(|9߾T@P洟u)s{(S{Y{Yøv(OCiy*v\e:ݹ0P{Yw~K<{tma5YӸ|Oq.=CR(+Z+#ʺVvU8ZA"k/zZYGE27s$?oZE^_竬~AvM͍+ڷm.Ʃu]dkvO+t3ۮ-Bi>ڠV n{_sWiWlT"/6_0kRq Z+;oܵ;>PTT?D ? .Ei>uoﱷ {u0KEcYK=kj.^걦z\:5cYhk%0uf+y*]=z}q|v9 %gɼ%Z Xm.KԫW+OeItN|v9$JLXgKr_$q|yڳuXW_lq&._&k0ۂ|˽a%\sqGK7KeYX:'nڴ0™ady*>o?Y(ns#`>LOL*"l7o3xPr]qi?(C^wWs1"m@_D]4Amל7izyW24M Zhqöqn~V־ޱemՁ h{Ny.\(9PMR+Bz,st#9lu A' uv78ަN?6 gghlG_n`ێ>ȽEҶy륫06`\_ ƹ^n qn[Pyd+~{Dwm@LҴ-ߛF\Y)G__5ʁ 21'NH3I6M7N-*& >mƈNشuP6n*~Sad8f͗R\Bz,rP0U9hRd;ٴz*30j\S~QH:/;(r TU,m1Ptm.#(bGt&=Xo S'Å;W]:210nb!\6Epbg`S*OQb!]9ך1FL_rfWEMr0R`Nk+/aPHM}(5XPGnVoƪt)N|#{V64xpzU'Aϟ>mHRpk/8"]]CU(Q$.6Ƞ胈/~ VƠ/ ȭǷ?j۠8#BRo/+v?80 ׃M%Y\~ȇwq'g3sڞ8ڭzC$W P hqoe gFtCML'aÉo #҇#'Գyㄷm@_㮿~>ZTePNk7t0ӂP6 c Qo p7ؤ©.>kPXà&\(vOQa3?O=3ꎟ۸UӯBS$ i;c'AGOh{<-/kA`[=1-qیE`Vd'nKpuQR4I_07 pڌq>\t"DP&"`ˆlN/ӇFyf1:Ov利(rX pB*bu'~!Iaam6i 8zuQA 1Cp}qo!LFj]SA.@[ְA!3̥%4 ӔyΉb; gL`7d+39khb,5N pOAx INONX:|:î~!  InMƥ==\8% 6 %X~%RHNSPqz7뉏$(i$D DzQI$ @HxT 잋߶=ai,9*vkZX`ma,'nzǙ[e@M&\jIcJ *؛'7=-qJ%9Q :tB6SIH`TR\[.s۞PmiekDmR Q0(튏>=NH֚&Mzk\mR i 'Liu(0_6 )0Npq _jI_Ufhݶ>@8tlGOsQjGh>>w0!g9nt âPEZ) =Yq u8p35vvw vI rfln 2[L'pxT<ȕ9P6DF(vOFޛ7%?끌]_2Nnݮ 8jr+4ƇVgh7_)&Iʻ6\Vg>2@3 7 %y^R=<y=P.ϟ}bBg6&g]u!vg l픪QIuoR<~$9nCph8p$Q♝TO'v}OVQsB~%yBph ^~Q.8m#DZZe>=P> ?G{qPg|(.'xٹƈ茳.79zM/&qhƬ*DtEE /}lBqm7 AZ2F8amk~F[N]m @mݿ^w\:֞ 왍N 8~aO\zqmғ4i6BDW}tf2"! icR!F?ȗ}Ldq%*e!p|=qP1֘j@nDŽΧNZUH?~ ]+|@8oa*Ϭ^f1]#[/#6 mS9l6(F{"ǩ6E@}>2|mȅ" ڌ}qokcCRl{L0uXHV(MךdRES~S`~Tmr gIs3 j)駾yi#y@]b?v&iO>/Ji/P

rIfv> HB?pUX=zmKmں--}Gmi{m8ٕ*YTCVSW%3 XqݣSm(4bGY2+2w{PT=gvÍ@k.9l}˪z@t<@vǿ¥v^GȸUɈ<2YQ+*9g}q734#xk3-G dWnx+m)+#أ<58 t}WZ@cj^O_ M<.GlPlyq{ DZ'0s0B_A*!3)X=zS ߫t>*H)I3ʱx xL;_4]8j j֡H~kK3V5$yR3h 2[ލ[r[ݚTr, kZT|ϭv&VI-@<P&R~G-a&u0Y\^yNˁ|Gܛ}iqUxtӁ{;Svt&֜C}D2YP!̚ 4sk7$GH_ :.!j#4lJbyUnx`җƊ̣Ao:բ (+IrV{E bH֥+L.hbqD۳ dW>g1p%@u=@Cog:.R-D4]Z;K8=@v5_usZ.<|J@䳕'@@w+=xЖ:j¥gpj0g*LZHVn)ka{Uek`˽x}66uMV7Ղ˻aB{<Թ|<Ǫzh tL nj#I=@ve5 l.|qL8<@'  8슺e7)N6B_h+fPqA@ GV@ᰭ&4:\¦C3VIjsfcS+  @{eqzվL WVh XZO7̎|-ϹjNul3he ajF_ sM8[ޡ1~I.NV>Fol ؞tL7vs,rxP1ШU qM^ MdaZ븴3]0~BN[Bq|T i;q< h 㣾l8$ɑ_53ѹ#*ZS$&-[Hq4' m Gĉ.F2.<¤%ޞSV04zk2hZ{ҝJ;~rBc&$k;4zͲaʷEg-/녽苪NӾ￝ÙVO6X-bߋJb qcS6;Xu#ƹNGEoR![l~c@F8;#GKo@Ս4!N7t?u[ǙXOW%(V8t||nد< [PtϯLm82{|VyP+!|֥l=z߶뱔k';#q~$w]we?&Ǜvx~뮕 -evv;XUa| >~AMᨙ&zvqՓNhciuzF9Ű= 5|qqt8UoY!Hqa"-*}%ںaEt$Slxmd #:~uSX]i@.-GCZP7I̡_ve>bv W; $|qT$i>et$L:ihba-U;^&GqѐL@vL6Zz}*.Bm~" Hm: jE0- #q$Z3i5k(asM=ͧ۸5JߛG0jD8fѩ˿-oG};PZm}2]ǝv}UÎ"(]l2A?ky,9,8h CYGZ#4qĖP54א$7FȮfE+4z_c>n^׶JkȮLP*u6|E<._Pv^ iu۝2y40ۄ„Fs'H@ TBStUZj JAh=8l mμHn徻G(Jk@gx p2ix=姿g򻟆 ?GUxW_?M>ז~o0, ?閚wY6,#ORN<nϦ7Y!?z?J>s!OO+fY>jR_W_f|%q\O__OyYrSWKLkSjTo6YYT%3P?uE<֯??gzo"endstream endobj 697 0 obj 391125 endobj 701 0 obj <> stream xZKoF680^F@Hd֎WV5b[$(1!92coH%y09Uq>DiBT[64:V D㼍â\M4:\1IIF!`di{wGV&ǻ*§led~!d $MM3 =8 :߇旺J[\|za` $&T"^aUAl{՚IMZoE_>3{P|`E!!䔙ra?\տtb+p,MXJt2q.$27#W`׺0dar)mRG{~&ENhn7'{lsf"1Yϭ/Z'UH3(.==fV۔ߦ.4DġɁ|,0iG U'ywU2l2;n-F6rav\( ̕c ބ3) yd'S)?tcI R"i,RGs^Ж]lZu=]bHaߌmKے^K@O08dDBF|sd&-nBfϐadẹsLAGj(]壐#:ރ%G~dINu3 GѸp2lvCܨ^ ;Z?8a._XrlTs*vf3 % %qW6r'vB@: 2 X]ۜ5ekF.E=sa;5WU0LL`a OxB/SR4HLr1=ȩ`-ˉF A!zV͸Nf 91!:s@f0VSb򭾺>YUCԍi*ɑ]{#,gKxYatjΉ`@SVZ)VhJ7ԑ*뼯aI;/uk+ugf̌zTW G_F7>!ܮD'*WJwPe1BSoGx.VHf}n1pG*Q7jʌ솹2a0jp0'Ay2 iD}) W}%>Z}՘I'gsN:5j3\ R`'ڭMnL,""urЭzcF`ScVtЯAjTr)DCК&Dl =|7/z}Sv ?@rDxtI&t72[D0 jH;WQ$w'f 4a@yd9)נz4B'RH@GUlb@qޟ|+{ Ŷ]DH+C' S6:q^7U[0z!*`\o{kB 뵔]a[' WJ8#Vl0\ظܺ'f|hVgtn _DbӑN $Bv 6&% `JA|ZLrY}qxKU\ka"~ڸWQb4]/)@Vk,L"Vr> stream xYr3@U^8`}hEm?!.4zaPkr,rg'׋{wTNG^{gDbQmjz$I(OMX>_o^m +R: &bfX~ /_14Mšj? 9A"&XypV %p&ffvW؞cb.C5 NDIc|vj[g ~ICeD!n$>CZRF[_)IGPqDq\! ?*|M"bL#H ĶgiL",A(E4].N/;O]}X/KQcŒC̼0Ցm$!k4pPC\>1sob=m'a )\6Eh0cxb%bʗD!+NK-Cgpt8RCSA0"0iˆ sG\u4!ł&]p br Z6S̝aӿ0 ET~sx*==seM:Jh褓*EIjfW{}k0TjYgu!,%r] !<>.~LXƘaNڤpj,^;ppGEIhLsoQ!UB@2P]mvE/:CZOMU6.T' ֧hP.CPbO.UEB C_luOgZdJ lLi-顧T4^50 '-o;U'AK?}l۬lAk=wvbHBqPcq*CɍՊ>ɲN]Z;pKģf|;32.ΈC8򛋔z6&/zt8o2^b-U0b/v8pyщn/Kf٠n[d2PcL#F [d&y"Ax;rS]>ʐ SA'k--=PbЍ܂5Hfڿ*A{C;B}(}U6:~uvS)Q^1*'Yn02c=e%{T(Fc–`–)VD7mak=/lymt),&$c^&u jކςPIA}NE# gj|(++F3k;pmTuFwj׺=2EaUke͈:v)镉nk0q^J;-ANdo~I@TrpC)禖FOk]oA$X2TTO٣RE_{l\tmCG$8Let}ar X0j'F̆^ߩ.l5j2۲˽HNZ꨿ƕLϋlqW>tEt,J,_K>.Ͼjendstream endobj 722 0 obj 2186 endobj 728 0 obj <> stream xYKs8{GJ{nuLjʓ-7|hH'dC٪-eF_?uĕ?w]&ĝ\&LϺY8dpل1׉I0Ǎ'dztjOXnW[mNq;Ir؈ZFcIl#~71sBDN{w:1՞t{M:-纮&ӪnWW'DJ}0'&7Jb%1Ur(ppkGM񻁅?v\XauQGʅcFҵeҋ\ Qgjk7͏Xf!O۬ROMA/dBkOnߓdh"8!ɯTk6ۧ[a+USzy^'J<+ENϫZuJLi7:]J;wX8g$Ia1U!S~ >b ֥뱀j$yA;XM/(W?5'ǽ~ޤj+PYD=C1Q.i Tp`}tBWiShG;C5 |RCb+m$5U—\"{!U6+oDtUO&ծ b0])[Fwӎzx*F1lOuD\".:<܉ʟsT`4婁AV7R^6%;K?Nv:W#Mm41w:ߠqUU=Eh;6lú=ȄF@AN]ul5lgeZ?i1 b3`Rp\SX"^>Cz:prH#.tZ84&bjMVn R;X©mhv6ڪy;LT nOLt~kmx á&^:U93_qL)a`i7[9*>ϚNSc$葄mlK,4ŠV]<&"nH|#"-Ψ^0I^ËֱG}1ӆ%AE0']WmWX*`ZYO=A0{Z߳U">@p#ZZH˽엊|*tk^\4:!6qFxOV‹ַa:Ե8i-ie>Ҁb{S--t`Fkv bpTgeU@%x{"V(1"CBIRi|7R~+ {> stream xUn0+t&-$hQ,+ZKt,&Ca؂3Ùy_cP =&:xE0Qu!Gėrq)8@M\gW$"#(QP(.A߻jg $Ue!b@F1٦eDPT,}9k_a> d[uN!ޞBp 7"z#FI Rnߊ>QY]ݿ4g&G.8" xTYINXg<)զ DTxг˾Hfmy(7rHFYRdct|vقa͛n űbe9ғ!Y惍37$}_:fA4@R~VE*ڕbτׇ~_`2#QR\o;뛁[]߮5kR4⟄,8[ٌܑ`="㬁TJvXbz`xu~ZzMC?VS~ԁp0/Mm:%8\ x0%5$bJ%H^.'S!DȈ*бCMTrʌR4V){ %خݚ O!cX-;76P >s,+S| EDtl;ޕMetB,ǐBwpk _ 6 7v~uX][uyqsv I8QV6bjZhqik6pQH\GZ0]<>Bendstream endobj 751 0 obj 836 endobj 4 0 obj <> /Contents 5 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 202 0 obj <> /Contents 203 0 R >> endobj 224 0 obj <> /Contents 225 0 R >> endobj 323 0 obj <> /Contents 324 0 R >> endobj 350 0 obj <> /Contents 351 0 R >> endobj 373 0 obj <> /Contents 374 0 R >> endobj 385 0 obj <> /Contents 386 0 R >> endobj 409 0 obj <> /Contents 410 0 R >> endobj 423 0 obj <> /Contents 424 0 R >> endobj 468 0 obj <> /Contents 469 0 R >> endobj 477 0 obj <> /Contents 478 0 R >> endobj 494 0 obj <> /Contents 495 0 R >> endobj 512 0 obj <> /Contents 513 0 R >> endobj 525 0 obj <> /Contents 526 0 R >> endobj 540 0 obj <> /Contents 541 0 R >> endobj 547 0 obj <> /Contents 548 0 R >> endobj 565 0 obj <> /Contents 566 0 R >> endobj 592 0 obj <> /Contents 593 0 R >> endobj 606 0 obj <> /Contents 607 0 R >> endobj 612 0 obj <> /Contents 613 0 R >> endobj 623 0 obj <> /Contents 624 0 R >> endobj 628 0 obj <> /Contents 629 0 R >> endobj 641 0 obj <> /Contents 642 0 R >> endobj 661 0 obj <> /Contents 662 0 R >> endobj 674 0 obj <> /Contents 675 0 R >> endobj 679 0 obj <> /Contents 680 0 R >> endobj 686 0 obj <> /Contents 687 0 R >> endobj 695 0 obj <> /Contents 696 0 R >> endobj 700 0 obj <> /Contents 701 0 R >> endobj 720 0 obj <> /Contents 721 0 R >> endobj 727 0 obj <> /Contents 728 0 R >> endobj 749 0 obj <> /Contents 750 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 77 0 R 202 0 R 224 0 R 323 0 R 350 0 R 373 0 R 385 0 R 409 0 R 423 0 R 468 0 R 477 0 R 494 0 R 512 0 R 525 0 R 540 0 R 547 0 R 565 0 R 592 0 R 606 0 R 612 0 R 623 0 R 628 0 R 641 0 R 661 0 R 674 0 R 679 0 R 686 0 R 695 0 R 700 0 R 720 0 R 727 0 R 749 0 R ] /Count 33 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 75 0 obj <> endobj 76 0 obj <> endobj 200 0 obj <> endobj 201 0 obj <> endobj 222 0 obj <> endobj 223 0 obj <> endobj 321 0 obj <> endobj 322 0 obj <> endobj 348 0 obj <> endobj 349 0 obj <> endobj 371 0 obj <> endobj 372 0 obj <> endobj 383 0 obj <> endobj 384 0 obj <> endobj 407 0 obj <> endobj 408 0 obj <> endobj 421 0 obj <> endobj 422 0 obj <> endobj 466 0 obj <> endobj 467 0 obj <> endobj 475 0 obj <> endobj 476 0 obj <> endobj 492 0 obj <> endobj 493 0 obj <> endobj 510 0 obj <> endobj 511 0 obj <> endobj 523 0 obj <> endobj 524 0 obj <> endobj 538 0 obj <> endobj 539 0 obj <> endobj 545 0 obj <> endobj 546 0 obj <> endobj 563 0 obj <> endobj 564 0 obj <> endobj 590 0 obj <> endobj 591 0 obj <> endobj 604 0 obj <> endobj 605 0 obj <> endobj 610 0 obj <> endobj 611 0 obj <> endobj 621 0 obj <> endobj 622 0 obj <> endobj 626 0 obj <> endobj 627 0 obj <> endobj 639 0 obj <> endobj 640 0 obj <> endobj 644 0 obj [/Indexed /DeviceRGB 63 (\000\000\217\000\000\237\000\000\257\000\000\277\000\000\317\000\000\337\000\000\357\000\000\377\000\017\377\000\037\377\000/\377\000?\377\000O\377\000_\377\000o\377\000\177\377\000\217\377\000\237\377\000\257\377\000\277\377\000\317\377\000\337\377\000\357\377\000\377\377\017\377\377\037\377\357/\377\337?\377\317O\377\277_\377\257o\377\237\177\377\217\217\377\177\237\377o\257\377_\277\377O\317\377?\337\377/\357\377\037\377\377\017\377\377\000\377\357\000\377\337\000\377\317\000\377\277\000\377\257\000\377\237\000\377\217\000\377\177\000\377o\000\377_\000\377O\000\377?\000\377/\000\377\037\000\377\017\000\377\000\000\357\000\000\337\000\000\317\000\000\277\000\000\257\000\000\237\000\000\217\000\000)]endobj 658 0 obj <> endobj 659 0 obj <> endobj 660 0 obj <> endobj 672 0 obj <> endobj 673 0 obj <> endobj 677 0 obj <> endobj 678 0 obj <> endobj 684 0 obj <> endobj 685 0 obj <> endobj 693 0 obj <> endobj 694 0 obj <> endobj 698 0 obj <> endobj 699 0 obj <> endobj 718 0 obj <> endobj 719 0 obj <> endobj 725 0 obj <> endobj 726 0 obj <> endobj 747 0 obj <> endobj 748 0 obj <> endobj 752 0 obj <> endobj 753 0 obj <> endobj 724 0 obj <>stream x37S0P0bsC3 CB3s 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠r8I f讈~җޗ>L_ $֪U)X#woP{s_.xS! fY endstream endobj 472 0 obj <>stream x=@@Dw/6YGb BT(ڟc54X:j$frVl_MEJuQiE!ᱟ HM ۂ )K^Ͽ;ʳ  P endstream endobj 418 0 obj <>stream x33R0P0S5T05U0TH1*T0 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[A%Asuu]L&Ԫ_oݿϯf5_bZ' nN0H:??'&*'9'}Ƽz6^:"ӱeɎP01S! *R endstream endobj 368 0 obj <>stream x3T0P0Q5T0P01UH1*T05(($dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠q^NC{L/8nTR˯?Lskˮގmӻ&M`G$WrL endstream endobj 365 0 obj <>stream x35T0P0V5T05P01QH1*T01(+$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠 ƒl;Os(zW:W__?A@mznI{pD8X6mX\=rM endstream endobj 361 0 obj <>stream x33R0P0bS scCBSS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠BYDN8;?l$Y1,aI*\Ϣ8YK?02pz*r\M[ endstream endobj 358 0 obj <>stream x33R0P0bS3scCBS53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠ǢUOI߿?|/~Mo٣ȵ7 FS! T endstream endobj 355 0 obj <>stream x37T0P0S5R0T0PH1*T03 (e r@"9ɓKW4K?KK)YK%ڐ KM V8qy(-)~bMSU~ׯnK_eVM}ulHY_zmɯ5y3=WhsD$:08pz*rU& endstream endobj 345 0 obj <>stream x33R0P0V5T05W01UH1*T05(($dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠Hńk‡c|=]wC}+v魘̜{ Prqi8\=I endstream endobj 342 0 obj <>stream x37V0P0bs3 CBm*XBr.'BIQi*~8P t pV0w62wwvvrllt29y@vv\. j;ø'$يG`ݵ;.7K.}nUt6T`^r/&W5_roKs}_^}MG0LB y"Y> endstream endobj 339 0 obj <>stream x0T0P0S5T07Q0TH1*T0 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[pŃw&Ϧ MhpI(ے6DK[%_7{_WTjOHk_w˶Kcl1&a0DĮmb:r+,8\=HQ endstream endobj 336 0 obj <>stream x0S0P0bsK3 CBsS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠8-E'ܯpuoA5_>a҇,{E08pz*rOO endstream endobj 327 0 obj <>stream x342Q0P0S5R044WPH1*  @I=C4HrU()*M)w pV\ b݀}o]s~Nin^1HC?8[>O"zo-dw\ݭ_H\MFABM6Ďl E>MS\=l6 endstream endobj 220 0 obj <>stream x37S0P0U5T07CB3S k`gɹ\N\ %E\@E\@5\N @%ڐ KM w)+jtQP[8-@-QKNp99 @*ߗ_W#{#D&} /3_+?]npѷ>k.;rծo18a6aOxb F߷o߾bK;aa'v~Hr֏`hrT;Tu endstream endobj 210 0 obj <>stream x3T0P0Q5R01Q03SH1*T01PA3 =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j vgQ6˔W{o_nj_{+Ùema>stream x3T0P0b3CCCBS3ogkg`  ɹ\N\ %E\@\ \N @%ڐ KM V8qy(-\8KC[BYMTKo]ʾm`O%CBZǠTXC endstream endobj 715 0 obj <>stream x32W0P0V5T02Q06UH1*T02  r@"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]Ԗ|3/M|~/_{Wo׹z6j`hrT&5 endstream endobj 683 0 obj <>stream x31R0P0R544U02T0QH1*T0(i#=C,JrU()*M)w pV0w62wwvvrllp;qy(|ʒO,xAS! G' endstream endobj 537 0 obj <>stream x36U0P0aCCB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H KM=?luܖ-.(K/Uk_7S! < endstream endobj 534 0 obj <>stream x35U0P0Q0W05P02SH1*T01(Z**Y*$r9yr{*rp{p;8+rDrr;;66 @ܼb;;.O'WDB#S! endstream endobj 508 0 obj <>stream x35T0P0Q5T01S03RH1*T01 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠A[,{mɖ]V]_ B׮`hrTq>stream x35T0P0B abU`b z &z ɹ\N\ %E\@5\@%\N @%ڐ KM V8qy(-\aW֖ 93tTlhtۛCWGa 5\m݇÷1f&>MN59&.WO@.l:h endstream endobj 502 0 obj <>stream x35T0P0U5T01U03RH1*T01PA3cS=CHrU()*M*w pV0w62wwvvrllsJsZ<]n"`"'scU|X_G}őǜ9[h\r}Y{-cwQݶGuct4w6CB FDa endstream endobj 499 0 obj <>stream x35T0P0U5T01U03RH1*T01PA3cS=CHrU()*M*w pV0w62wwvvrllsJsZ<]!o&ϒĽ߾߯-mi5& H:DKAS! &J endstream endobj 405 0 obj <>stream x32P0P0bC33CBC(kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAmY˗]f';pעS! : 2 endstream endobj 402 0 obj <>stream x33P0P0U5R03R07PH1*T05W )Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[p%m㇞#[[33 __~l_OjNLHMN0cOU ?j~_k믿^+>*e˦g,9#"& bT endstream endobj 396 0 obj <>stream x31W0P0Q5T01U01QH1*T01 E r@"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]9((C/ԯ}Yeo~lU֯}YuYk33tl;۲MaC&.WO@.io= endstream endobj 393 0 obj <>stream x36V0P0V5T0P03SH1*T02 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠pm[7"sD_k}PΪ@x}kK_?Vbih04ppz*r ? endstream endobj 389 0 obj <>stream x36U0P0b#KCB#c 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠t':n_?8\=JP3S endstream endobj 73 0 obj <>stream xP0P0b c SCBsK 53T53 79ɓKW4K?KK)YK%ڐ KM V8qy(-\`K7__?%Ǘ_ܐQk/~?JB L\ \a endstream endobj 70 0 obj <>stream x3T0P0U5R05V0TH1*T0 (X*Dr.'BIQi*~8PP Sr62wwvvrllt29y@-vv\. j dp*[𡗵E{ӗ{/78'/,YزH__euf߿mK}>vm3sn&a$&pЁS! .KX endstream endobj 67 0 obj <>stream x3T0P0V52U05S05VH1*@hn`gɹ\N\ %E\@U\@E\N \.ц\\nn@n.P9?47ΎEAm6nWFy zI^p\ɗ_u?->vmn.]p(ʐ#N"`~wAYa4)Uo/r5{m\-.H183""IGn#B ` endstream endobj 64 0 obj <>stream x3T0P0bS#sKCB53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Ezi"{/̾rUW~/pZzaQ[m}eˮK.@ŽzK_^ڳzl.WO@.lPc endstream endobj 61 0 obj <>stream x0V0P0bs3 #CBsr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy((:,4z;o[WP\Ӈn ~`t~c)~~C>B\"+\=R^ endstream endobj 58 0 obj <>stream x0S0P0U5R0U0RH1*T0PA S=CHrU()*M*w pV0w62wwvvrllt29y@-vv\. kX oqtn￿?[*n҇OۏWgb#wo X!aJS֥l\=` endstream endobj 55 0 obj <>stream xT0P0bK3S#CBK# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠hfpSS~C6@ìɕvjKf{߳+>W[/8ģpO%?02pz*r;[ endstream endobj 52 0 obj <>stream x33R0P0R5T0T05TH1*T05 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠S Cy~uW;os|۟?o \=TDW endstream endobj 712 0 obj <>stream x36P0P0R54T02W02RH1*T02U+$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠堮/M_)%;{`%}kf- `hrTl7 endstream endobj 709 0 obj <>stream x35Q0P0V5T05P02RH1*T01  z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(bja+> W|i"iiۿꡖgKLQi_ֿicf.&.WO@.G8 endstream endobj 706 0 obj <>stream x36W0P0V5T06Q06PH1*T06 (c=CHrU()*Mr{Ig me˥{us;qy(-ho>pT/}2W)+~!qt[Se< 8\=8 endstream endobj 703 0 obj <>stream x340U0P0bC #CBK3kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEA!qi+n',y1G`aP? q~02pz*rnX endstream endobj 532 0 obj <>stream x31V0P0Q5T01V07TH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠 'D;/8|%~+[Yܛ"\7*nҗ_2_۔Y_.w+:3w6$1 .WO@.YP endstream endobj 529 0 obj <>stream x37T0P0V5T03W05VH1*T03 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠r\f9o7Ŀ]zo ~*ߥD]C endstream endobj 465 0 obj <>stream x32W0PP5T0P01VH1*T04PA3# =C$LrU()*M*w pV0w62wwvvrllڹsJsZ<]6(ӟG?>4"_m}ҥW L\ \2 endstream endobj 399 0 obj <>stream x3T0P5V5T01W01QH1*T05PA3%HVP!9ɓKW4K?KK)YK%ڐ KM jw)+jtQP[H#_5{ `_ٯ/}]}վWoum_7u/\Ci~-{b+ʿoJzX\=R endstream endobj 320 0 obj <>stream x3T0P0V0 f )\  hd`g`lgɥPRTʥTĥTå`ȥme˥{+esJsZ<]6n8à7OYyk_V $.y{Z^R2 endstream endobj 318 0 obj <>stream x35V0P0bS#SCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠CbG%mo_}׿]__/٫'u懞ߏ7oU_{/٣i B ? endstream endobj 315 0 obj <>stream x37Q0P0Q5R07V0PH1*T0 (e r@"9ɓKW4K?KK)YK%ڐ KM V8qy(-)f|BܒW]V}XM/8j_ 񯇥_{zusW2ۜ+465p04pz*rzX endstream endobj 312 0 obj <>stream x0T0P0bsssCBsS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠 悄 9,i>L4_Ң}VUV$)Ook~p;AS! f endstream endobj 309 0 obj <>stream x31U0PP5T01W01QH1*T0 (*XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠H1Mګ_Y7uQ_=e{ܥmI:08pz*r@ endstream endobj 306 0 obj <>stream x3T0P0Q5T06S01VH1*T06 ML r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[1E!cn]֥@nz/V7fe^oi{ON,;ĝtS! >4 endstream endobj 303 0 obj <>stream x32U0P0R5T02V01RH1*T02 (+Dr.'BIQi*~8PP Sme˥{us;qy(-<#j9>n _}}ew҆C  \ \ 75 endstream endobj 300 0 obj <>stream x33Q0P0bsC3 CB3S 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`OVvŅ/7u_ۯpn_cZz!ҳ֖ %_ L08pz*r(J endstream endobj 297 0 obj <>stream x33U0PP5T03W01QH1*T0 (*XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠HfELUJ{ՎW7ſ Wk/L!^mKդE$Z9$\= P endstream endobj 294 0 obj <>stream x31P0P0U5T01U01QH1*T0 DL r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[p1l M/]|#%v]B G_M_+nRGi[X7RVVF.WO@.x_Gj endstream endobj 291 0 obj <>stream x31P0P0S5T01P01QH1*T06Q *Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p͇, WuWs3= %~W?=r][Z{˶K9s  lHXĠajB endstream endobj 288 0 obj <>stream x31U0P04P5T01V0TH1*T06( @"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[xb{['/~__ S֗Uފ^m-$1F.WO@.NJ endstream endobj 285 0 obj <>stream x35P0P04P5T05Q0TH1*T01Q @"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[zB埼_J(ߣp~מlկm٫kWz>stream xT0P0b c3 CBs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg`ڴtS<2vqwO%΍z~Ym01(pz*rCo endstream endobj 194 0 obj <>stream x37R0P0Q5R07T0PH1*T03 (e r@"9ɓKW4K?KK)YK%ڐ KM V8qy((5\rֱ4tic_}/{Ys賈 q7H]w "^SIH&eքC  \ \uUX endstream endobj 191 0 obj <>stream x3P0P0U52U02W07UH1*T02( A@29ɓKW4K?KK)YK%ڐ KM V8qy(In߾޽o_} x__`xmo/3M e`rTL endstream endobj 188 0 obj <>stream x32W0PP01P0T0TH1*T04 (Y*X*[Y*$r9yr{*rq{p;8+9.ц\\nn@n.P9?47ΎEAmv{f1UזlٲS! ) endstream endobj 185 0 obj <>stream x32W0P04P52U02Q07UH1*T04 $@X$ $s<=}JJSÁ=@ʸ ] b݀}o]s~Nin^1PDX.WO@.N4 endstream endobj 182 0 obj <>stream x37W0P0U5R07T07PH1*T03 ()Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[8#E\u|BvK~1 K/9?-{Pw߮ߎݒd͜vFyj gt04ppz*rrXB endstream endobj 179 0 obj <>stream x3T0P0Q5R01Q03SH1*T01PA3 =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j vgȾ³}}%&׿ov/ Vwάw+zi"rY7Hap`rTlI endstream endobj 176 0 obj <>stream x37W0P0bs3 CB3kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEA1qΪ6j =0??nYvzXbp?Z B JM endstream endobj 173 0 obj <>stream x35T0PaKcCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠CTb>w;3ˣ3.t}k_^jKM $mo#S! o= endstream endobj 170 0 obj <>stream x3T0P0Q5R01Q03SH1*T01PA3 =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j 7\Pp|(üIK/K2cG/3|__.woYK7nmnE)&08pz*rf5Px endstream endobj 167 0 obj <>stream x37P0P0b333 CB353T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠#?&~i,`y3SF.WO@.(Ir endstream endobj 49 0 obj <>stream x33U0P0S5R0P0QH1*T05 (X)Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[h!{Pꠅu%M_(zi%_˯ ~}O?^3ة ՘moؘopO¼ wˉ4wWݿ:UM58ȴh@bbB n]q endstream endobj 46 0 obj <>stream x33U0P0b3# cCBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H9䠇#ŗ8Шkʿx  *sLAS! sV endstream endobj 43 0 obj <>stream xP0P0b #J1*T07"z z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<].)Kq}솄nwm5>stream x31S0P0Q5T01T05VH1*T06 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠Ӊz-i _8=_~rM'ĝ0&wFE>{]xc#ۿߺ|deg  \ \H endstream endobj 37 0 obj <>stream x36V0P0bc cCB#3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Hɕ ͝\=E endstream endobj 34 0 obj <>stream x4R0P0S5R0U0QH1*T0 (X)Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[,[au{8HDzzpXjj=֪_ehmI*; ߟ;z7ʏCm\;ۄi) /a endstream endobj 30 0 obj <>stream x33P0P0U5R05R0RH1*T01W [(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[Y;` u~]mu곃n]v6 f$1c&.WO@.LDL/ endstream endobj 27 0 obj <>stream x342U0PP5V044W042TH1*T04L, @"9ɓKW4K?KK)YK%ڐ KM V84qy(-8̶1E'Cv$Qn0ĻNq,^/B_eo_~/ CiTL__P߶<￁Ͽ [o؝;N"GGl<N48qox"*"Y endstream endobj 24 0 obj <>stream x31V0P04F :Ő *\.'O.}O_T.pt pV0w62wwvvrllt29y@vv\. jr/_.)kڵk \ \[! endstream endobj 21 0 obj <>stream x3T0P0U5T07V07SH1*T0 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p&6g5>T/͗ܛ\˯{_m_?mnom[^u;WۥmB[61Hh:,!a.WO@.)Z' endstream endobj 18 0 obj <>stream x33T0P0bSssSCBSkgkg`  ɹ\N\ %E\@\@\N @K!A,`cﭠ q)+jtQP[0LBSgd쏽woUu px,AS! CG endstream endobj 13 0 obj <>stream xT0P0b CSCB M t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(me_!fH03kmb4[_wa+#B hT endstream endobj 10 0 obj <>stream xT0P0Q5RP040UH1*T0 &z@Y ɥPRTʥTťRĥ`ȥme˥{+esJsz<]6jRh\Of÷o8p??_>AsVϲcݮ#? Y^;캟=CVߺa&t endstream endobj 744 0 obj <>stream x33S0Pas#3 CB353T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`OVvōk_W |_0]_/@8 ^/v]zQ_fzČ]+#B IO endstream endobj 741 0 obj <>stream x37R0P0b C3 CBsS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`vHum1Wn=~뿱Q|o#>_5/77N=F.WO@.bB endstream endobj 738 0 obj <>stream x35P0P04Q5R03P03SH1*T01SY @"9ɓKW4K?KK)YK%ڐ KM V8qy(-`B֐]\9^z0WWzk˖q4[T2S?ta<릿7ofmҭ \ \8JH! endstream endobj 735 0 obj <>stream x4W0P02P5R04P0PH1*T ( @"9ɓKW4K?KK)YK%ڐ KM V8qy((2MH_mI)FG>z+_ׇޗ٫[뽽eޥ{$˖K!ih? _ZĠ*j endstream endobj 732 0 obj <>stream x35P0P04P5R05V03SH1*T01VY @"9ɓKW4K?KK)YK%ڐ KM V8qy(-?ڗqVM7}׿_/t{v/~wk!â V]_υiRQQ/C8|nmmfe`rTaN endstream endobj 664 0 obj <>stream x36T0PP06U02U0TH1*T04 ((X)=K\.'O.}O_T.p".}$S!K!A,`cﭠ q)+jtQP[VP|r=־z|/]2t&.WO@.}.N endstream endobj 649 0 obj <>stream x-KN@ eD Ol5MD;TEjJE!j!0|@ JC*C[2tE" Ƨgmزj9.v;m fYngA8^܃CD b0917q-va1{|^||Ŗ>stream x4V0P0S5T0S0TH1*T0PA 3=C$LrU()*M*w pV0w62wwvvrllڹsJsZ<]1fY6և֯!¾t?ɳNq o~O$eVZk@ * Š^ endstream endobj 617 0 obj <>stream x32U0P5"C#CcCB##%HVP!9ɓKW4K?KK)YK%ڐ KM jw)+jtQP[87?qV88z!|/16oI$\=5 endstream endobj 603 0 obj <>stream x36U0P0V5T06T01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠q9/MUK_ֿ4}8@4&ޣ_r-m\-,`bPrT< endstream endobj 600 0 obj <>stream x37T0P0b3 ScCB33 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠b 'yp6^emsul~wkߺu}_|W^ڗ@|Ka_f_gHAS! fI endstream endobj 597 0 obj <>stream x37U0P0b3K CB33 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠J d'.D- *kU2w= P8I3e08pz*rFmY endstream endobj 581 0 obj <>stream x31R0P0V5R0P05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[ƇWxU2Z~'W~׿[ľގ;YpD`G=+eU霺͜9NDX\=^I endstream endobj 578 0 obj <>stream x31R0P0U5R0 )\ Ʀ@A RT($s<=}JJSÁ=j ] b݀}o]s~Nin^1P΂;s@"VWKQNz[/տd[o01(pz*r^9Y endstream endobj 575 0 obj <>stream x3P0P04Q52T03R07TH1*T0 (X A@29ɓKW4K?KK)YK%ڐ KM V8qy(-X˺锠j+X\=J endstream endobj 572 0 obj <>stream x31R0P0V5R0P05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[Жዜ/}]/uץz[8tZ'\]}\"4߰,nEmLHL8F endstream endobj 568 0 obj <>stream x31R0P0bcSS3CB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Q{8k̛6K7p04pz*rʒ8" endstream endobj 561 0 obj <>stream x36U0P0R5T06R03RH1*T06PA3c#=CHrU()*M*w pV0w62wwvvrllsJsZ<]9a+"O_[ӎ,`bPrTB endstream endobj 558 0 obj <>stream x35T0P0Q5T05P0TH1*T01 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[~B埼_J(.#RqEt [4*HmW_ˇʥ>nޓC㯖ٖM۽-u7>stream x3T0PP05W01P03SH1*T06 (X*X*Y*$r9yr{*rp{(Xr;8+rDrr;;66 @ܼb;;.OEs2/dfl)p4mQs+D#B J#> endstream endobj 552 0 obj <>stream x31V0P0R5T0T06PH1*T06 (*Dr.'BIQi*~8PP Sr62wwvvrllsJsZ<]Ԗh>0CgI᫇8]_~WL֖^k{zk/[8u`aprT>stream x35T0P0U5T01U03TH1*T01PA3#S=CHrU()*M*w pV0w62wwvvrllsJsZ<]Ԗ͵SB# ~W~خ_+MC]03'ԍ \ \&E endstream endobj 486 0 obj <>stream x35T0P0W5T01S03TH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠a_NH|MY39sy[Y\=Ѣ? endstream endobj 483 0 obj <>stream x35T0P0T5T0T03TH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠SuٜYK]Ho6o׃:/U߲Y_㣁U_w%ľ]AS! A\ endstream endobj 480 0 obj <>stream xP0P0S5T0R0TH1*T07 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[pŃuilv$2e+,T Wb'FG9W{B]O:DDF(7S! W endstream endobj 462 0 obj <>stream x37V0P0bsC3 CBsr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(hi*yA$cӯ{bwGgVv0sܥ.6}ݪ[@˜8\=pM endstream endobj 459 0 obj <>stream x35T0P0Q5T01S03RH1*T01 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠!CN/(ܛo+~}2{ yn2K+$J}}/V[>3waΜ6k׶mHL8X JD endstream endobj 456 0 obj <>stream x35T0P0Q0T01S01RH1*@hd`g`hgɥPRTʥTĥTå`ȥme˥{+esJsZ<]V:ž9@.WO@.P$ endstream endobj 453 0 obj <>stream x35T0P0WT01V05RH1*T06D ,,s<=}JJSÁj=J ] b݀}o]s~Nin^1Pڂӑ+*>,^cЭ<: /Q&vOL6OLfҭ}@}[\=9 endstream endobj 450 0 obj <>stream x35T0P0Q5T01W03RH1*T01 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠sևx /| u_~W_%|>w[oINnouŀAS! L1 endstream endobj 447 0 obj <>stream x35T0PPеP06V0TH1*T02 (+XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[q#Cݓ{̷Wu­l} :KECVh04ppz*r@ endstream endobj 444 0 obj <>stream x35T0P0V5T0T03TH1*T01 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠 am}'^ 0ᨍ?/^,!h~\ogz ݇.o&aƠcH endstream endobj 441 0 obj <>stream x35T0P0P54Q06V04TH1*T04 ( A@29ɓKW4K?KK)YK%ڐ KM jw)+jtQP[Vֶ«+BUi B S'j endstream endobj 438 0 obj <>stream x35T0P0W5T01Q01UH1*T06 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`B˗mX>/}Y[rm__?^.Ͽu{ևK7$ig620rz*rx@9 endstream endobj 435 0 obj <>stream x35T0CSCB\=C]=K 0UHrU()*M*w pV0w62wwvvrllt29y@-vv\. j v>XtjcLؼEY}k~o<T8J+ ,\ \TM[ endstream endobj 432 0 obj <>stream x35T0Pb3#CBc3 ĵ3T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`gC@[$&\rO NAYSX\=';k endstream endobj 429 0 obj <>stream x35T0P0bsCBm1Q03T53 S\.'O.}O_T.p.}0`ȥme˥{+esJs󊁊<]\(Z"o/G±^P, \ \7^ endstream endobj 426 0 obj <>stream x35T0P0W5T01V01UH1*T06 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠Г- {Յ8Xf;7\aԓ;ClmBͬ]+le AS! > endstream endobj 382 0 obj <>stream x0W0P0bK33 CBKr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-عF ' 2ں鿼 {_M2( DkS{е붾ܛh(RAS! 4qj` endstream endobj 379 0 obj <>stream x3P0P0V5T05U01QH1*T05 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠hl39l.QBKv忶oiv=_ ~uuܡV7=nWc^_hC  \ \CK endstream endobj 376 0 obj <>stream x0U0P0b C3 CBs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠]ί{ov^] y-\ #Xo߾}YrR7H\wo{k G^IB KWI endstream endobj 282 0 obj <>stream x36P0P0S5T02T04PH1*T04UY*$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠n_>Q/35S! ) endstream endobj 279 0 obj <>stream x32Q0P0R5T02P01UH1*T0 f Fz@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-h|;:'-r=^_f>jq㦯 _toElGDB 3| endstream endobj 276 0 obj <>stream x37S0P0U04V07P06WH1*T03 ((*Y*$r9yr{*rq{p;8+rDrr;;66 @ܼb;;.O'WE)j+X\=#` endstream endobj 271 0 obj <>stream x33T0P0bs3 CBm*XBr.'BIQi*~8P t pV0w62wwvvrllt29y@vv\. j+Lp !3Umsw ^KZe91֛;}o{@n{=?|ʻOoPB z endstream endobj 265 0 obj <>stream x31U0P04T5T01U01QH1*T06D @@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[ǃC6x}٫.WKV_Pتl/sa4 V҇i pmNap`rTr:< endstream endobj 260 0 obj <>stream x3T0P0R0V04W06WH1*T04((Br.'BIQi*~8P P S!K!A,`cﭠ q)+jtQP[ĺK_Yu}_ap`rTͶ*Y endstream endobj 257 0 obj <>stream x35R0P0R5T01Q07SH1*T0 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠[ouu]:  ~Bz{mƴmC B uH endstream endobj 254 0 obj <>stream x33P0P0Q5T05CBSC!PH$r9yr{*rq{p;8+9.ц\\nn@n7P7s~Nin^1Pڂ/q T;;4QYu_OV$u]ߖ{n&c0MbC'4\=a@ endstream endobj 251 0 obj <>stream x344R0P0bC SCB (b*XBr.'BIQi*~8H-P)S!K!A,`cﭠ q)+鱳tQP[yqJr͇m%'|0kd{rec, /kly>}N=M&F6:&.WO@.nZ endstream endobj 248 0 obj <>stream x37U0P0U5T07P0VH1*T0 & z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-<R)+?roRf瘓A!#eWwoon]z{cX6ŒC/ "U\= XI endstream endobj 245 0 obj <>stream x4R0P0b  #CB rM t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(h+d+((W[ ?u_oK_[45qzXv WOt.WO@.S endstream endobj 241 0 obj <>stream x35Q0P0bSsCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`9&c ~pSq/OǠS endstream endobj 237 0 obj <>stream x37Q0Pa3K CB3S 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠#~r#˃@mennnrc^o]^K endstream endobj 234 0 obj <>stream x37Q0P0V5R07VPH1*T07PAK!PH$r9yr{*rq{p;8+rDrr;;66 @ܼb;;.O¼Z >stream x31Q0P0bcKCCCBcogkg`  ɹ\N\ %E\@\ \N @%ڐ KM V8qy(-<ߦȾEN":"1?Y5QF.WO@./LT endstream endobj 164 0 obj <>stream x36P0P0bcSsCBcc(kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAm႟-͗9=K/uD0hJB&.WO@.WDc endstream endobj 161 0 obj <>stream x @D-|ܽP cR;693RKϻ2X)_& lȞpWH/1C]ˁiأi:lbxo endstream endobj 158 0 obj <>stream x36R0P0b#K3KCB#S 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠HSV>stream x0T0P0bs CBs3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠(&+ ;[Ľ[z[cugrK^5]oܭw9[30rz*r$L endstream endobj 152 0 obj <>stream x33R0P0bSK3KCBSS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Hm'Wv\,- (?T}ׯtFĠL endstream endobj 149 0 obj <>stream x3T0P0U5R01W03WH1*T01 (Y*Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQPp叼*/lȌ[YoNkKv]^[;nߪ__[eo5p04pz*rB endstream endobj 146 0 obj <>stream x37P0P0U5R03Q07PH1*T0T )Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[8#%{y#M[(4g{,˼ɗ|}i'W?߿{߮-흷z00L6:ĠRI endstream endobj 143 0 obj <>stream x35Q0P0V5T05P01QH1*T01  z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-<ߓb7SVOp^lݫaî{X\=OC endstream endobj 140 0 obj <>stream x340P0P0R5R4W0PH1*T4U e r@"9ɓKW4K?KK)YK%ڐ KM V8qy(h1r5ę鉁wA3nl_{u_^mge.Ywe)koMb.WO@.@o endstream endobj 137 0 obj <>stream x31Q0P0Q5T0T01SH1*T06 L r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[[zq_Z׽Hjk8p̉uÏj|޷?+F=<<߽p?K 1B B= endstream endobj 134 0 obj <>stream x35Q0P0bSCBs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠NqACi/y~SM~7oM^.^9L \ \8C endstream endobj 131 0 obj <>stream x31V0P0V5T0T01UH1*T06 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠 69Ç8̗[ˮ_ⷮHY/tۦI$ D$mHXĠ; endstream endobj 128 0 obj <>stream x0R0P0bs CBsS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠N̦,< 7sijŹEzKQ_;v?C/[=QO&.WO@.P endstream endobj 125 0 obj <>stream x35Q0P0V5T05P0TH1*T01 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[lǛ)V'`qkr֚_߇y}_o}Uk7&x ^vD420rz*rC O endstream endobj 122 0 obj <>stream x33S0P0b3 PH1*T0&z z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<]8j-`boc_o/+qS,9c(Tf\|S! F endstream endobj 119 0 obj <>stream x36R0P0b# sCB#53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H]cOF?)?*㛸S! [= endstream endobj 691 0 obj <>stream x34P0P0bC#c #CBCCKogkg`  ɹ\N\ %E\ \@\N \.ц\\nn@n.P9?47ΎEA!!2֧,)f]?WKBݲKoBSHp!w&.WO@. endstream endobj 670 0 obj <>stream x0P0P0bsc3 CB3K(kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEA1qêf'41? }';̰`fo>Pݿ_}VBUk&.WO@.PG endstream endobj 667 0 obj <>stream xP0P0b c3 CBsK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠0BkΜ1@H  \ \EN endstream endobj 655 0 obj <>stream x36W0P04Q56P06Q4PH1*T02PAC#!HH&r9yr{*rq{q;8+rDrr;;66 @ܼb;;.O5q%, \ \68% endstream endobj 652 0 obj <>stream x33S0P0U5R0Җ )\ @A3CS=CHrU()*M*w pVR.ц\\nn@n.P9?47ΎEAm6i &9A*_پ̾R~_GO-`bPrTX8>stream x31T0PaKSCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠ŏst?\[nTi[HĺS08pz*rF;- endstream endobj 633 0 obj <>stream x4P0P0U5T0Q040PH1*T0T*eDr.'BIQi*~8PHSr62wwvvrllڹsJsz<]4XW[$&@bFEGC s_k0- ${-'\HԛL±DH܌ %^H8N8l h endstream endobj 587 0 obj <>stream x36P0P0b#ccCBC (kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAm ق*M#?{ L\ \U-8 endstream endobj 584 0 obj <>stream x31V0Pa 3 CBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠kDiKĿ|y= endstream endobj 522 0 obj <>stream x4P0P0b CCCB C0ogkg`  ɹ\N\ %E\@\ \N @%ڐ KM V8qy(-I*rz?GǗl&9{M &_U2]}۞@𧭵Ps g~O  \ \vjv endstream endobj 519 0 obj <>stream x344W0P0V5T044V03QH1* @TX( $s<=}JJSA= ] b݀}ov.}ܼb;;.O%bew8_ƣ{o߿wB-;[mk^^?v/__ח=;{mV޺?r۷ov9AS! ndh endstream endobj 516 0 obj <>stream x342R0P0bCC3CCB (d03T53 S\.'O.}O_T.pb.}Z.}g %ڐ KM V84qy(-7_B_U>˯F_~__ݏ]xǯ~_׵vۯ/!/# .WO@.Bi endstream endobj 416 0 obj <>stream x35S0P0U5T05P03UH1*T01 f z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-X0ǦC!~ ~8MU2=~s_!v 2w,_]dunݲPhۆCx8\=i/O endstream endobj 228 0 obj <>stream x33P0P0bSSK CBSC(kgkg`  ɹ\N\ %E\@\@\N @K!A,`cﭠ q)+jtQ3I#W.WO@. KF endstream endobj 116 0 obj <>stream x33R0P0Q5T0P0TH1*T05 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[&Ò?yC A kdĿ/wnU(-0pPrmG" .WO@.>(Pj endstream endobj 113 0 obj <>stream x31Q0P0R5T06W03VH1*T06 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠9a[zaES clt㛘VF.WO@.I]A endstream endobj 109 0 obj <>stream x35S0Pbs3SCBc ĵ3T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠΍;B?OjS! > endstream endobj 106 0 obj <>stream x33V0P0V5T05V4TH1*T05PAK#c=CHrU()*M*w pV0w62wwvvrllsJsZ<]n__1e !_-_w=oۥe<:N)1(0qz*r}R endstream endobj 102 0 obj <>stream x344W0PT5R040bCBK o`gɹ\N\ %E\@U\ E\N \.ц\\nn@n.P9?47ΎEAml, W#6-m:ȶm(E1FqmHn|ieKU=__뗯i]>]/޹[]O\MFfbЍD6 $=8$ZytVsr1nCB  k endstream endobj 98 0 obj <>stream x3P0P0b#s3sCB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠!5)7' [t B N;$ endstream endobj 95 0 obj <>stream x3P0P0bCCBckgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAm։m~qϊeo]U_}N? \ \r8 endstream endobj 92 0 obj <>stream x37V0P04U5R0P0PH1*T03( @"9ɓKW4K?KK)YK%ڐ KM V8qy(h2v8dCveǯn^~٫m]<8;"S808pz*r; P endstream endobj 88 0 obj <>stream x3T0P0aC33CB3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠 C /Ծ̾Wח/_k룾.] K.]eKGFʖK_Mԛޢ[B E endstream endobj 84 0 obj <>stream x35T0P0Q5T01S03RH1*T01 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p;ר_xtA˼Z[_;$+w߯^ۥ7̑Nڶmál\ L\ \p1A endstream endobj 81 0 obj <>stream x35T0Pbc3CCBcS ĵ3T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]vDeM6'fҭ \ \>stream x37P0P0b33 CB3kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEN?^|c+\q9s~(02C?#B 6Ki endstream endobj 413 0 obj <>stream x31P0P0T52U06S07UH1*T06UXH&r9yr{*rq{Tq;8+rDrr;;66 @ܼb;;.O ;}_AZ[u}^ǂޖ^{Cb B J endstream endobj 369 0 obj <>stream x35S0B#SSS#KCB$h`g`dgɥPRTʥTå`¥`ȥme˥{+esJs:<]>02pz*rK endstream endobj 366 0 obj <>stream x35T0P0bs3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v]I wHNd0}?XtS! 3B endstream endobj 362 0 obj <>stream x33R0P0U5T05S07QH1*T05 (*Dr.'BIQi*~8PP Sme˥{us;qy(-XpA6ql/VV//_zRm^=Zowݎݲ2 ]GslHXĠuOb endstream endobj 359 0 obj <>stream x33R0P04F )\ & A@PA@,Ls<=}JJSÁj=J ] b݀}o]s~Nin^1PڎJSl#/>S! B endstream endobj 356 0 obj <>stream x36P0P5V52P01V07PH1*T01SIX,Az ɹ\N\ %E\@e\@U\N \.ц\\nn@n.P9?47ΎEAmኂ-{վ47m߰qV_ 42.s!{:ZK\5p4AS! oS endstream endobj 353 0 obj <>stream x37Q0P0bsS3 CB3K 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠` :Iwook_ǯ+]`kK-]7믫z z0EQבUAS! V N endstream endobj 334 0 obj <>stream x37T0P0b3  cCB353T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`@0?<8{5}٫Y}?웿~ow}_XLd4 B X endstream endobj 331 0 obj <>stream x37U0PasC cCB33 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`DpGȃ__e~_oc?&=p.WO@.]X endstream endobj 328 0 obj <>stream x0T0P0Q56P0P03SH1*T07(X)$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[%̈́E٩FE-Z/p8`|}KGx)A.eۥ,[KOjf}75 Ɋ~&ϟ,v;y!8i|\6މ-6q8Xp`Ӊ   \ \*p} endstream endobj 218 0 obj <>stream x3T0P0U52U01V07UH1*T0( A@29ɓKW4K?KK)YK%ڐ KM V8qy(-\0>?EY!Um B CNU endstream endobj 214 0 obj <>stream x35P0P0BJ1*T0T)S=C=K\.'O.}O_T.p$t pV0w62wwvvrllt29y@vv\. j (||__meۺosss[08pz*rDE/* endstream endobj 211 0 obj <>stream x3T0P0Q5R01Q03SH1*T01PA3 =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j vgQ~Ծsگ/u]z;mĥyL)}'FER#ۗW̗ܛPn"{Zn{޹[IxH)&620rz*rQ endstream endobj 208 0 obj <>stream x3P0P0Q5T07W03SH1*T07 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠5 ̇_ɾQceoo[V$V'ƘCsYwF~pwأeחomaN vUd>lQVc:XV endstream endobj 205 0 obj <>stream x344P0P0bCK CBK0kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEZ9&|ά I?/k~M_PC_qpG8IԔDX\=uY endstream endobj 509 0 obj <>stream x35T0P0Q5T01S03RH1*T01 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`> ?—/_/8e~e˯Nl&᝴a͇]Qp8|)ߑWPe[r5{ݱ[v$]amá[65p04pz*rYS endstream endobj 506 0 obj <>stream x35T0P0bs3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]>stream x35T0P0UеT0F )\ & h`gɹ\N\ %E\@5\ \N \.ц\\nn@n.P9?47ΎEAmeMo.WO@.` endstream endobj 500 0 obj <>stream x35T0P0b cCB3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠sBT'WN+{}?{o=[o -/?" endstream endobj 497 0 obj <>stream x35T0P0bs3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]Vt2_i P?]\`hrT)D; endstream endobj 473 0 obj <>stream x35W0P0b3#sCB3r t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-##c@#r *&Ut{Kg5s/~p?NrI?02pz*r[ endstream endobj 394 0 obj <>stream x31W0P0R52P01S01QH1*@hf`gɹ\N\ %E\@U\@E\N \.ц\\nn@n.P9?47ΎEAmA ͉/U]e~Wֿ߾׽GuзCGy_~YDצm2e2Cn6.&.WO@.VO' endstream endobj 390 0 obj <>stream x36U0P0V5T06T01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠?C%&M]AϬ}={۴Ü, \ \Ml8r endstream endobj 346 0 obj <>stream x3T0P0R52P05S01QH1*T05(($dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQb̓] %_[z[[׃Q57v.X>ePPB=mbP`rT)I endstream endobj 343 0 obj <>stream x3T0P0bS3CBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠ڢ&ܥ3vg^VtfNܷo͛_eW^/Ue|Ͻq*Z$?`bPrTm> endstream endobj 340 0 obj <>stream x36T0Pb#cCSCBm@BPAH$r9yr{*re=S!K!A,`cﭠ q)+*tQP[V}r< \ \n X endstream endobj 337 0 obj <>stream x0Q0P0V5T0V0PH1*T0PA3Kc=CHrU()*M*w pV0w62wwvvrllsJsZ<]\ cQ%D@o_Qأ=q A"Wz[i&4e]AS! GX endstream endobj 221 0 obj <>stream x37V0Pa3KsCCB33 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]\Z%_?K뿬W $R>X_/ or%47{s' L7U endstream endobj 74 0 obj <>stream x3T0P04 )\ A0PPA@,Ls<=}JJSÁj=J ] b݀}o]s~Nin^1P v=,=XQDlS30rz*rF endstream endobj 71 0 obj <>stream x3T0P0U5R05V0TH1*T0 (X*Dr.'BIQi*~8PP Sr62wwvvrllt29y@-vv\. j 1>|Lf~NU5kѯ\_{ӣzdwm B+s1S ͊7}gܥnHLlmfe`rT̸W endstream endobj 68 0 obj <>stream x36V0P04P52V"C#CBC)PN$ $s<=}JJSÁʸ= ] b݀}o]s~Nin^1Pښ߫HSz_] \ \3 -2 endstream endobj 716 0 obj <>stream x36Q0P0R5T0T02RH1*T02  r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[ڔV+m6)x/uwyQi{ȶC[i',`bPrT/- endstream endobj 713 0 obj <>stream x32P0P0V5T04U06UH1*T04R )Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠_'zֿ\[t+#B . endstream endobj 710 0 obj <>stream x32R0P0V5T0P06QH1*T04 M r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[t߮?|I GeއK&h.&.WO@./Q endstream endobj 707 0 obj <>stream x0P0P04Q54Q03U0QH1*T05TIYZ% @*9ɓKW4K?KK)Ys62wwvvrllt29y@=vv\. j ֶe]"6 GE,]+~鯯_X+@(*6{),0or7A D,AZk߾~ $>|xĠ endstream endobj 704 0 obj <>stream x36Q0P0R54Q06R06PH1* hb`gɹ\N\ %E\@U\@E\N \.ц\\nn@n7P;s~Nin^1Pڂ[ nG^_=~0{|쥷evַ&[Ѣk8|ZDX\=]; endstream endobj 535 0 obj <>stream x32P0P0S54V04UPH1*TT*dr.'BIQi*~%P Sr62wwvvrllsJs,<]vZ{r5G Q/33K\=r# endstream endobj 530 0 obj <>stream x3P0P0b S3 CB C 53T53\.'O.}O_T.pR.}J.}g %ڐ KM V8qy(-'A/k%v[۱zu^/?6x_~uTWF.WO@. b endstream endobj 406 0 obj <>stream x3T0P0bc3cCBc 53T5ɹ\N\ %E\@E\@5\N \.ц\\nn@n.P9?47ΎEAmYA㋃j/?7P#=~CB  4 endstream endobj 403 0 obj <>stream x31R0P0Q5T0"CBcs PTD($s<=}JJSÁ=j ] b݀}on.}ܼb;;.OD(T 8ܛ\h7%SiT__3_?ؖ%Wleۡq620rz*r8d endstream endobj 400 0 obj <>stream x31U0P0Q5T0"CBcs PTD($s<=}JJSÁ=j ] b݀}on.}ܼb;;.OD(|p?&הϡe>g*ﵥv^2e@D#ʌ=gnns5fpCa1 .WO@.Mw< endstream endobj 397 0 obj <>stream x3P0P04R52U04S07UH1*T0 @rz Y ɥPRTʥ`¥Rť`ȥme˥{+esJsL<]VG'W02pz*rj)_ endstream endobj 316 0 obj <>stream x31P0P0R5T06S06PH1*T06Q *Dr.'BIQi*~8PP Sr62wwvvrllsJsZ<]sQp s˺鎙Ƕ^g}&mmu]o5giՍ>N9 01(pz*r5 endstream endobj 313 0 obj <>stream x37Q0Pasc3 CB3K 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`'sښ߲}__~X^tUC},>ł*V/䷯~_z/ӗ[Y2eci" 1:n TT endstream endobj 310 0 obj <>stream x0P0PP5T0T01QH1*T07V *XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠؂{>S@B3\r;YS~؅}[_~ui}W[7)*n:׭5׶[Y>Vڰ}{_Vz}+6X`Å L \ \86T endstream endobj 307 0 obj <>stream x31T0PP5T01S01QH1*T0 (*XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠؂慁×j8wr,eڔK^xU? {둈kR  \ \Y< endstream endobj 304 0 obj <>stream x36U0P0Q0R06P06TH1*T02(Y**Y*$r9yr{*rp{p;8+rDrr;;66 @ܼb;;.Oۗ?CG4u|WGC9l>~e#1ij׹`drT@6R endstream endobj 301 0 obj <>stream x36Q0P0V5T06R06PH1*T0 z@9 ɥPRTʥTĥTå\ b݀}on.}ܼb;;.O͇2w4oYWחٯ^_+^mKMڦc2 endstream endobj 198 0 obj <>stream x33Q0PaSK3 CBSS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg)˨!@߯8ox-&$N}ĠZ L endstream endobj 195 0 obj <>stream x36V0P0T0P02W02QH1*T02 (),s<=}JJSÁj=S!K!A,`\ \Jw(G endstream endobj 192 0 obj <>stream x37V0P0b3 J1*T0"&z z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<]TW[PpG?&xYE,@a)!3?#B yO endstream endobj 189 0 obj <>stream x3P0P04P52U06R07UH1*T02 $@X$ $s<=}JJSÁ=@ʸ ] b݀}o]s~Nin^1PQ 2nf/>eoWw۷A#B lL endstream endobj 186 0 obj <>stream x32W0P0R52U04S07UH1*T04( A@29ɓKW4K?KK)YK%ڐ KM V8qy(|O30rz*ren>0 endstream endobj 183 0 obj <>stream x31V0Pc cCBcS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Y~%KGE}We/{{_2N  B 7$ endstream endobj 65 0 obj <>stream x3T0P0U5R05V0TH1*T0 (X*Dr.'BIQi*~8PP Sr62wwvvrllt29y@-vv\. j 1>|B|Ͻ,җ_~}Wm/G@(P[Kۦ݊]!aDk B  {V endstream endobj 62 0 obj <>stream x33R0P0b3SCCBSK 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]Vb ̦{bVwݲKoul_L~\rսUKWWD"̱&.WO@.H endstream endobj 59 0 obj <>stream x33U0P0b3C CBSK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠[*}R}ɮUM<rEqFΏA)5?02pz*r d[] endstream endobj 56 0 obj <>stream x36S0P0b# CBcK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠 ǃƇ6FU6*sUM[g >3ŘwLP?&.WO@.ƘI endstream endobj 53 0 obj <>stream xT0P0b #J1*T07"z z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<].2kX M~uw=w Y_7}* P3K *E H+CB  XQ endstream endobj 50 0 obj <>stream x35R0P0V5T0P05VH1*T01 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p qk>5 {U2ٗѯl*d 7kw^vIJKyY7$LhmsNU`bPrT!yB endstream endobj 47 0 obj <>stream x0U0P0S5R0P0QH1*T07 (X)Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[,iK !F/,Q.7K[K~R?eC׾z[ݟeۥ< ĹLm NĠZ endstream endobj 44 0 obj <>stream x31S0P0b#S#CBcK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠hf3c_RԱ}nZ6ǯ}h1a=#B $< endstream endobj 41 0 obj <>stream x33R0P0bSK cCBS3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠hێ~>I#=֗Uqӗe>뗿.i~>r-wo]{S $Y| endstream endobj 38 0 obj <>stream x3T0P0Q5T05Q05VH1*T05PA!PH$r9yr{*rq{p;8+rDrr;;66@\9y@-vv\. j 1qd>q&C-ǽj_f_2~  Yko[l콹KM"v+GM1'GGS! C endstream endobj 35 0 obj <>stream x3T0P0U5T05W05VH1*T05 ML r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP["գC!c[v~G/n_$bDxgu -- {__ڪ[6Və9mk fD,Ht`aprTN endstream endobj 31 0 obj <>stream x36V0P04FF F )\ $ tADr.'BIQi*~8PKL:8+rDrry(3?? " endstream endobj 28 0 obj <>stream xP0P0S5T0V07UH1*T07 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`rA9:i*Ƣ[zF/.}};*D֛mE+&20rz*r]r endstream endobj 25 0 obj <>stream x3T0P0S5V07R044QH1*T03 fz@Y ɥPRTʥTťRĥ`ȥme˥{+esJsz<]z!{KFCc O Q|ɽ_\u__ri d#Hw.o;3?vݭܥۦ6m08pz*rsY endstream endobj 22 0 obj <>stream xP0P0b csSCBss 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠!r6ʏ8>a`̊weM>4sXLeB V_l endstream endobj 19 0 obj <>stream x33R0P0Q5T05W07SH1*T05 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠pN_&ނ^4 T_~i_o;")NH'>lo>\iƔ"%d=l~Ư~VxݼZIx59_qZp$f.WO@.Z\0 endstream endobj 745 0 obj <>stream x35P0P04T5R05V03SH1*T01RY@@"9ɓKW4K?KK)YK%ڐ KM V8qy(-RO|Kڗj__mˮ3_2V}붷V?~MY[_}7en˶K9t yDX\=O- endstream endobj 665 0 obj <>stream x36T0PP5T02Q04UH1*T04((X$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠`!O\ſ]ז۲azl B .,> endstream endobj 650 0 obj <>stream x36U0P0bc#SCBcr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-\p. ^?nK_}Y*))EFmZ%08pz*rg#;x endstream endobj 647 0 obj <>stream x36T0P04T52U0P07UH1*T04 % @z`i ɥPRTʥTǥRƥ`ȥme˥{+esJsz<]| MS! $I5A endstream endobj 601 0 obj <>stream x32T0P0V5T04W01SH1*T04 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠(u__JHxG[}oh6CB z3 endstream endobj 598 0 obj <>stream x33W0P0W5T0T0PH1*T05 "z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-I09#}\G@zgs&e:?fvPr_]}}_~V^ -n&ͣ!a 640(0qz*rGX: endstream endobj 595 0 obj <>stream x33W0P0b3#sKCBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Vҿ׿^+__"ޯ/}o~<$(ퟯ  \ \8-M endstream endobj 582 0 obj <>stream x35P0P0U52U01Q07UH1*T0T A@29ɓKW4K?KK)YK%ڐ KM V8qy(ؑŽ7|} 79h\|rW02pz*r}V endstream endobj 579 0 obj <>stream x31R0P0V5R0P05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[Ƈ;4W}7n:V4ޥ9NWQG^KjW^ɡnv=WMFBa61.WO@.(-K endstream endobj 576 0 obj <>stream x35P0P0QеP01U07WH1*T01T [*Dr.'BIQi*~8PP Sme˥{+esJsZ<]\_uB\w|KA҆&%—Vy~}m6?K}?jǶ-u?M+>nu+׍K3u/ջEO0`hrTf endstream endobj 573 0 obj <>stream x31R0PacKSsCBcs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠pJBv__V7}u0W|ܾ`fGlϏ 7p04pz*rTFE. endstream endobj 569 0 obj <>stream x32V0P0bC3c3CBK 33T53 S\.'O.}O_T.pK.}B.}gC.}hC.X.}7}gg7 7F[A(㜟SW`ig颠AGџYK/U, \ \ w' endstream endobj 463 0 obj <>stream x33W0P0S5T03T0PH1*T05 ([*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p iq&. /5対~޶Ko/233CW{Â9gso߾>Os_EY[/ ]M*mڹ&Cl Z&.WO@.zU endstream endobj 460 0 obj <>stream x35W0P5V52P03T07PH1*T03 (X,Az ɹ\N\ %E\@e\@U\N \.ц\\nn@n.P9?47ΎEAm ?~N65 [L2kKg=5_ߚunZ߮G.uWo/}%m:mku>stream x35T0P04& fF )\  @PA@,Ls<=}JJSÁj=J ] b݀}o]s~Nin^1P/[kuj+cύ߿ne`rT>H endstream endobj 454 0 obj <>stream x35T0P0bs3#CB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠 挭m׽{__٫_CٱNmOSos߶-`bPrT8F' endstream endobj 451 0 obj <>stream x35T0P0b33CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v;<4W~훾~գ׹[?l kf- Q,D( endstream endobj 448 0 obj <>stream x35T0P0T52R01W01QH1*T01()%dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[%C9_X:}a}o_zWzÜ1oc`{.w?S! P endstream endobj 445 0 obj <>stream x35T0P0bScCB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠6 /}\L&՛r&.WO@.1h endstream endobj 442 0 obj <>stream x35T0P0U5T05P01UH1*@hb`gɹ\N\ %E\@E\@5\N \.ц\\nn@n7P7s~Nin^1PB/F/_~w+@Y1$`K‹ꚾ_o8iW+ڶ|8Ķ!!S! h? endstream endobj 439 0 obj <>stream x35T0P04WеP01R0TH1*T02( @"9ɓKW4K?KK)YK%ڐ KM V8qy(-\humڴK :nq[_{rA}뾁ܽyX\= G endstream endobj 436 0 obj <>stream x35T0P0V52V0P01VH1*T01()$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[qE@c[YCfo]fm^7כ] Z}[7l8O endstream endobj 433 0 obj <>stream x35T0PaKCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`9 ͗9,U\%+/<&oPv .WO@.m!A endstream endobj 380 0 obj <>stream x31U0P0Q5T0T01QH1*T0 (=CHrU()*Mr{IgC.}hC.X.}7}gg7 7FK9?47ΎEAmY$ nܲn׽4[&Ŷn8[/_7+۔+veM l#:\ L\ \/E endstream endobj 377 0 obj <>stream xP0P0b c3 CBsK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Ÿ=mk_ g} @+:>ZmS! h endstream endobj 298 0 obj <>stream x35T0P0R52T05V01QH1*T0(*$dr.'BIQi*~8PPSme˥{+esJsZ<]6?aaVT]&f{ײzi[rL_:o_]e@? ,\ \@I endstream endobj 295 0 obj <>stream x35P0P04T5T0P01QH1*T06W@@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[B{C*νK_M_Q_)}*kSf]*:Qw oM  \ \k;T endstream endobj 292 0 obj <>stream x31U0P04T5T01U01QH1*T06D @@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[ǃC6Y5{~zu%MW?kjzf9 )&65p04pz*rS;? endstream endobj 289 0 obj <>stream x36P0PP5T06T03SH1*T02V +XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠6Z" kMkpu@}w _ltMS! A endstream endobj 286 0 obj <>stream x3P0P0U5  )\ & QK!HH&r9yr{*rUq{q;8+rDrr;;66 @ܼb;;.O*ܛ\X2ua{Np?n?yuן ;G}tzre:!7CB P endstream endobj 283 0 obj <>stream x35P0P04P5T05T01QH1*T01T @"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]avo˗__ʎTV?~u_~4ګk$66E6mC  \ \D endstream endobj 280 0 obj <>stream x37W0PP54U0P03VH1*T03PAs  =C$LrU()*M*w pV0w62wwvvrllڹsJsZ<]l"&ȊD)lh:͡&PMN1p t{@wD endstream endobj 277 0 obj <>stream x35P0P0W52U01R07UH1*T06U A@29ɓKW4K?KK)YK%ڐ KM V8qy(-9A-CLҥ_G_{6q)e%>8|j}Na$9AS! T endstream endobj 273 0 obj <>stream x35S0P0b3 ebU` sM t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-H8L۹_ofGW_zu0׭׭%Uj?P85G7p04pz*rL endstream endobj 269 0 obj <>stream x31T0P0Q5T0T0TH1*T06 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[xSU_ B<}Ⱦ]~Gq֗[[:>׵]u˒/[]1oaĎD.WO@.2M endstream endobj 266 0 obj <>stream x36R0PP5T06U03RH1*T02 (+XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`__S||丿Aoָ__[{nGD B ;@ endstream endobj 262 0 obj <>stream x31Q0P0S52U06V07UH1*T02( A@29ɓKW4K?KK)YK%ڐ KM V8qy(qZ ~߾}}wu@_BK^[e% e`rTR5 endstream endobj 258 0 obj <>stream x37U0PasCSCB33 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠0+や8 /jKdYM}ѯ?V "CB fG endstream endobj 255 0 obj <>stream x36W0P0bc# CB#kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAm*330rz*r#A endstream endobj 252 0 obj <>stream x37U0P0Q5T0T0VH1*T0 (X(Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`Nۊͨ'4OK>hoq]#scv/}?VgunmƠQyЛp==ǝB L \ \F^ endstream endobj 249 0 obj <>stream x36W0P0bcc cCB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Y<`aprT =EM endstream endobj 180 0 obj <>stream x33T0P0bS33 CBS# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠䊓 yKc~үo_?[N.q ^E endstream endobj 177 0 obj <>stream x33R0P0V5T05W0TH1*T05 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[$Ŷ+CONŏ)p7կTɯ_z[Yf}$T/ kHkp`hrT)N) endstream endobj 174 0 obj <>stream x35S0P0bS#3SCBK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠pI]^.]q/}Y HD_ _R15 OHb?ap`rTE endstream endobj 171 0 obj <>stream x3T0P0U5R01V03SH1*T0 (Y(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[#^a!Z[z=?sQ~U\Y?{oٴ3snvELbAD&.WO@.LJ endstream endobj 168 0 obj <>stream x37S0P0U5R07CB3S k`gɹ\N\ %E\@E\@5\N \.ц\\nn@n.P9?47ΎEAm".DyÇ8 >4ت}})s/bUW-U_߭K}vܥGg&nͣv!"EL1#g B ^W endstream endobj 165 0 obj <>stream x35T0P0R52P0P01VH1*T01(+$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQPb,[vǾw[ۥ[ Nm/|ٔB6eMQ&& KH endstream endobj 162 0 obj <>stream x37U0P0b3K3 CB3kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAU!aZہ'WR.b}#poۿ@~0җޗ>4]Q]l4iB ӅS endstream endobj 159 0 obj <>stream x4Q0PaKCSCB s 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H],͗9~p?E8Cɕڎq_6W։ռ@ B R/ endstream endobj 156 0 obj <>stream x36Q0P0b#sCBcK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠  WC\/v}m~}}@cC+2. -D endstream endobj 153 0 obj <>stream x3T0P0bS3CBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠+;{zc_oJ쿞| .WO@.)T>stream x35S0P0U5T05P03UH1*T01 f z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-ة Ѥ̨"saFZ~[VgY'o&Q߾~w8~oܒKv}fv)Z`5MJ L\ \ׇJ endstream endobj 147 0 obj <>stream x3T0P0Q5R01Q03SH1*T01PA3 =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j 8leeהeG_{emV>stream x35T0P0b 3KCBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠؎Wp0k į__W_߿wz, \ \GZP? endstream endobj 141 0 obj <>stream x35Q0P0bS3KCBs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠؎70SN& K& q-n/(N} endstream endobj 138 0 obj <>stream x35S0P0V52T05V01UH1*T05PA33c=C$LrU()*M*w pV0w62wwvvrllt29y@-vv\. j v:XKp(zȽqn-Z[n<7?|mn$r≠#>qqO0WJ|#ϟü^tGni6j޹,x l8t.WO@.U5 endstream endobj 135 0 obj <>stream x35S0P0a3SCB53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`D9*[&/U{k{wg[o >**~].]vHzY1lҗU%ӝ/]-fAS! *B endstream endobj 15 0 obj <>stream x34T0P0R5V044b CB (n`hd`gɹ\N\ %E\ e\ U\N @%ڐ KM V84qy((-XS&ks32 gmA S! x endstream endobj 11 0 obj <>stream xT0P0b CSCB M t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(m?}}᧬~5Igo?f}|9)7[s+ӬW%\O;d endstream endobj 8 0 obj <>stream xT0P0b CCSCBssogkg`  ɹ\N\ %E\@\ \N \.ц\\nn@n.P9?47ΎEAm W#dOWpǾz_eo{_e>C}ͪZzap`rTg endstream endobj 742 0 obj <>stream x37U0P04Q5R07W07PH1*T03( @"9ɓKW4K?KK)YK%ڐ KM V8qy(-\Djk5Ak #ٮ;h7e׮^[~}ץ =__[щ23+[xm8~ AS! CvUH endstream endobj 739 0 obj <>stream x35P0P0T52U0T07UH1*T0PXH&r9yr{*rq{Tq;8+rDrr;;66 @ܼb;;.Okk/խN]_HzrUS! Mx endstream endobj 736 0 obj <>stream x37P0P04Q5R0P07PH1*T03Q @"9ɓKW4K?KK)YK%ڐ KM V8qy(-\"*BᚠEo"u~;vM~eu痽ZVko?nU@u__ߊV]љeBy[sH(l8cI%#B BS endstream endobj 733 0 obj <>stream x3T0B#3 # CB,`g`dgɥPRTʥTå`ĥ`ȥme pz*ryf endstream endobj 730 0 obj <>stream x33S0Pas ebU`f䃹fz z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<]o~DD-W_[k,kܮKVE-}Y"@Ӄ3_ܹ B xL endstream endobj 692 0 obj <>stream x0U0P0bs  CCBs53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]X-h[-m _q>stream x5K1KPv+nr))5P*4BNJn֠KƟx8D?dɐ!4^{6tkѵ-{=CϤ5fkݭeܝewf/LY2>3!9 9]?p1}a(=alc;2CR?cS1@GU# $F1+Kf:PsZP*BcU^帯<ȃDI%%iXa/$Ÿ*INOٕ 7 endstream endobj 656 0 obj <>stream x36W0P0R5  )\ F@QC#!HH&r9yr{*rq{Tq;8+y.ц\\nn@n.P9?47ΎE៯.WO@.q0E endstream endobj 653 0 obj <>stream x35U0P0R5T05Q01VH1*T05 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠եrq?_+dWkӿzK}po׿{][e}48\=s?e endstream endobj 619 0 obj <>stream x3P0P0bSSSCBSC 53T53 S\.'O.}O_T.pR.}J.}g %ڐ KM V8qy(-sWp_3~?y+/ٷ5{^݀\\ L\ \: endstream endobj 615 0 obj <>stream x0T0P0bsK3 CBsS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`AMcsX_ȿr__o_k/GqUokK_z/uUC݀8 )AA../g.WO@.H/Q endstream endobj 585 0 obj <>stream x36U0P0V5T06T01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠#{KA/}6_ff&t9~_e5M*"ELMS! ,E< endstream endobj 562 0 obj <>stream x35S0P0V5T05R01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠m ܖ/_e uloSQ^. KzCݛ'X`B seJ endstream endobj 559 0 obj <>stream x35U0B]#S3KCB$hn`gɹ\N\ %E\@E\@5\N @%ڐ KM V8qy(a֧-v鿯ȌHջUoo{dX?j`hrTW endstream endobj 556 0 obj <>stream x0V0P0b 33 CB # 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`f k5K/q_"dzUY_fMwd}YcUܴz/`|ŷ2گ/f}W[߯=js<$?`bPrTGY? endstream endobj 553 0 obj <>stream x37R0P0b33sCCB3C 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]Io}믯Z!z|K__YW,_skp dO endstream endobj 550 0 obj <>stream x37T0P0V52Q03W05VH1*T03(+$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQPc?9#q_uc_oL-{}=ooUo]_!; $@ڪkk3u]uݔYK{ ;t8"aB S- endstream endobj 520 0 obj <>stream x31Q0P0bCCBcogkg`  ɹ\N\ %E\@\ \N \.ц\\nn@n.P9?47ΎEAmAKC'W~'YAS! '3Ng endstream endobj 517 0 obj <>stream x4P0P0b 3CCB C0ogkg`  ɹ\N\ %E\@\ \N @K!A,`cﭠ q)+걳tQP[Ҡ!_mFJ f?ux//7Wo\!NJX\=$e endstream endobj 490 0 obj <>stream x35T0P0bS3#CBrM t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-x`B 5W_ȏ_[KGEEExCc.(I~^zЭ \ \UT? endstream endobj 487 0 obj <>stream x35T0P0b 3CCB3 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]VLM?9 Eq'TeUS׾~_wۿ"xUl~}PF.WO@.-IK endstream endobj 484 0 obj <>stream x35T0P0b cCB3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠⊬V6H:}?W[՟֭@ۛ_~GS! 5H endstream endobj 481 0 obj <>stream x35P0P0&& ff )\ &  @PA@,Ls<=}JJSÁj=J ] b݀}o]s~Nin^1Pڂff=Kfq1?AS! '< endstream endobj 430 0 obj <>stream x35T0P0S5T01Q01UH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠 wd2%~]3vg.p(Zt֭mb<" ,\ \3> endstream endobj 427 0 obj <>stream x35T0P0T5T0T01VH1*T0 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠SA`ɡ~2ݰǠ]:b E?? endstream endobj 246 0 obj <>stream x35U0P0bSCSCBs 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠HD$En^'-X'7}׿u{rK]wdp B =Z endstream endobj 242 0 obj <>stream x33W0P04  )\ & A@PA@,Ls<=}JJSÁj=J ] b݀}o]s~Nin^1PڂYO4-t}O\=nE endstream endobj 239 0 obj <>stream x35T0P0U02W01U06QH1*T01PAsS=C#3=K\.'O.}O_T.p.}s.}gC.}hC.X.}7}gg7 7F[A(㜟SW ag颠&7CB u endstream endobj 235 0 obj <>stream x37Q0P0bs CB3s 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠۪d&[/ br<>8w"P~4u`aprTOV endstream endobj 232 0 obj <>stream x37Q0P0b3  CB33 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Sgj}>Ż'W(b p߿ ?믯/}>KD=Wqnғt`bPrT&_ endstream endobj 229 0 obj <>stream x4P0P0U5T0Q040PH1*T0T*eDr.'BIQi*~8PHSr62wwvvrllڹsJsz<]lTXO,S3b _\pkUT_W~ގzL?׶Mpj6W6łC[HeWlb`hrT!g) endstream endobj 132 0 obj <>stream x35Q0P0V5T05P01QH1*T01(+$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠NsACi*'W}}}e;'18} sN}ĠyP= endstream endobj 129 0 obj <>stream x35Q0P0V5T05P0TH1*T01 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[pH2T0MA6/ _{߭w.|\ĦCfV;F.WO@.8P4 endstream endobj 126 0 obj <>stream x3P0P0b#3KCB#C 53T53 S\.'O.}O_T.pR.}J.}g %ڐ KM V8qy(-33k~|ˣR \ \I?I endstream endobj 123 0 obj <>stream x3P0P0aSCBc# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠LBm_RԽ>>rc#/>6 ,\ \}J7 endstream endobj 120 0 obj <>stream x3T0Pb33CBc# ̵3T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠îM6W[0?.p)? ,\ \|@} endstream endobj 117 0 obj <>stream x33R0P0Q5T0T01UH1*T05 L r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[$vر cVuK}c vd708pz*r^@ endstream endobj 114 0 obj <>stream x31S0P0b#SCBcK 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H&Cns%3Mb_~z}# \ \5 endstream endobj 111 0 obj <>stream x31R0P0a 3 CBcS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bgӔ˙?(B y: endstream endobj 107 0 obj <>stream x37Q0P0Q5T0T03SH1*T03 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠pF SBC95-{վ̾Tڗ_W7Nyߴۦ6V4i Nd:,&&as7AS! L endstream endobj 103 0 obj <>stream x0T0P0Q5T07S03SH1*T07 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠pV MWs\Qp8|qڗٗ=}7?R_fYkά߭љۦ݊]mD"놄imb<@liO endstream endobj 99 0 obj <>stream x35Q0P0S5T05Q0TH1*T0 (e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[p{¥ל~ JkyhҴe˯QZmV4q/-ݒXvm(Dևq<01(pz*rQS endstream endobj 96 0 obj <>stream x37W0P04P5R07S07PH1*T03( @"9ɓKW4K?KK)YK%ڐ KM V8qy(-\ǒ"ٛcBv F,ұ,i{_Ueז_~ٛ>~}_{g_ٕ_u߱nnI~aPmPA5|N L \ \S endstream endobj 93 0 obj <>stream x3P0P0V5T0T01UH1*T06 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠q'UleT̏ߺ'~0uPG5'2?+~;PZߥ_o.umY&L1 S! qCb endstream endobj 89 0 obj <>stream x32W0PbCKCCB @RPAH$r9yr{*re=S!K!A,}C0P`,6 endstream endobj 85 0 obj <>stream x35T0P0b 3CCB3 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v]㨱Cm<|mB =t>stream x35T0P0R5T05P03TH1*T0 F Fz@9 ɥPRTʥTĥTå`ȥme˥{us;qy(XVUV|_Q}n}5,_wZb[Cf1XĠP endstream endobj 689 0 obj <>stream x37W0P0U54S07T05PH1*T03(S=C$LrU()*MJs{IgC.}hC.X.}7}gg7 7FK9?47ΎEAmUl#S7Z:!s?[  \ \@m endstream endobj 638 0 obj <>stream x0Q0P0S5T0P0TH1*T07(XE A@29ɓKW4K?KK)YK%ڐ KM jw)+jtQP[8˙顁ÇCVr Y$8̗ܛ\Dտ4k OY[]z'PmVmy[suwt6 I)&LU$pe;vmkbP`rTiD endstream endobj 634 0 obj <>stream x31T0P0bS CB3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠py5/ye[B>?M&A)X\=u8J endstream endobj 631 0 obj <>stream x0T0P0bs3KCBs# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`Yl}lǖ-K_{eZ}o (G'6\1(0qz*reV1 endstream endobj 589 0 obj <>stream x36P0P0b#3ccCB##(kgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAmB {8{rU.vd]z3*}M8#B 0a endstream endobj 417 0 obj <>stream x37P0P04 f )\ f a \PA@,Ls<=}JJSÁj=JhC.X.}7}gg7 7F[A(㜟SW bg颠m +9~YYz}oT/˧-`bPrTTJ endstream endobj 414 0 obj <>stream x35U0P0W5R03T07PH1*T05  r@"9ɓKW4K?KK)YK%ڐ KM V8qy(-"umKMFl-[f|})[_>.>j7*y~ }ü~nK,ۻtUsz3YElS H cP`rTU endstream endobj 370 0 obj <>stream x0Q0P0S5T07W0TH1*T07 (e r@"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]rC!+9ćLlr8̗ܛ\D__?4z[{ߖv-.ݲM;e& 6l: U endstream endobj 335 0 obj <>stream x33W0P0Q52U03Q05QH1*T03PAsK=C$LrU()*M*w pV0w62wwvvrllt29y@-vv\. j /T8|h^$9—|eA[vwЅ2%QK>ObŔ%4X^_HӨklNli ^8l:t"ßAS! }a` endstream endobj 332 0 obj <>stream x33U0P0Q5T03Q05UH1*T03PAS3=CHrU()*M*w pV0w62wwvvrllsJsZ<]b"!'P%}Ľ?s&ĄAA&#/[/M_*nmLۜ v|p7 B K endstream endobj 329 0 obj <>stream x33W0PaSKs CBS# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠òF!ƽLlrM/Ծ̾Tʚ;`GbUlu鵷Z]֥K95KĽLeU\S _^-CB +N endstream endobj 326 0 obj <>stream x0T0Pbs#KCB3 ĵ3T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠` "C shSb}!﹗*ߗ'}ן\lG]ڴQQ@zҥ QQQ._^Le/חzӗT]]Q@|F.WO@.L[ endstream endobj 216 0 obj <>stream x36U0P0aC3 CB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bgJöm~*  \ \1> endstream endobj 212 0 obj <>stream x37V0P0R5R07P0PH1*@13\.'O.}O_T.p".}.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠ŬTI"S"`[Fb/A0ޖv?*c߮ .WO@.qRA endstream endobj 209 0 obj <>stream x37R0P0U5T03W03SH1*T0 DL r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[8#IED !~·R84PY˪UMuMo?;ynޥ{s݊Q6M"Qw"Cnf g.1(0qz*rqI endstream endobj 206 0 obj <>stream x33S0P0b3C3SCBSkgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAmIƓx*_|qeάn%s_1/g^hQ[.WO@.[G endstream endobj 723 0 obj <>stream x342P0P0S5R04TPH1*@@I=C4HrU()*M)w pV0w62wwvvrllt29y Mvv\. j knᓑU-M~˾ޗ>Lo٣aӃz;j60w AD=p~w l v\!:%#B uV endstream endobj 507 0 obj <>stream x35T0P0U5T01U03RH1*T01PA3cS=CHrU()*M*w pV0w62wwvvrllsJsZ<]6p|akюnB^e_毿ݿ~wmڭ=䛣'͵'ǯ7˥ }٫}Dw61 .WO@.%I endstream endobj 474 0 obj <>stream x35V0P0bSsCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`7/kit7/R>stream x35S0P0S52U0T07UH1*T01( A@29ɓKW4K?KK)YK%ڐ KM V8qy(-\U T 0J.WO@.GNe endstream endobj 420 0 obj <>stream x31W0PP52P0T01QH1*T01((X$dr.'BIQi*~8PPSme˥{+esJsZ<]ppS`.k-}оU8릿_=8~?ֻes3s›Yۛvs"C6xzZzdcVF.WO@.]N endstream endobj 395 0 obj <>stream x3T0P0Q5T02U0TH1*T02 (e r@"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]B$V Z7yHӨn^`B moCx endstream endobj 392 0 obj <>stream x0U0P0V5T0R01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠ha6 8l%fs T.—//XZݮ_/<:kvumYmߖ]K^?6l˪]QߦH1`hrTW endstream endobj 388 0 obj <>stream x37W0PP02V0 )\ f h`g`dgɥPRTʥTå`¥`ȥme˥{+esJs:<]V\  endstream endobj 367 0 obj <>stream x35T0P0U5T01U03RH1*T01PA3cS=CHrU()*M*w pV0w62wwvvrllsJsZ<]zlp| u=DzUmugpMmb<" ,\ \?BC endstream endobj 363 0 obj <>stream x33R0P0bS scCBSS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠YKL8hk .WO@.OD endstream endobj 360 0 obj <>stream x33R0P0V5T03T07VH1*T0 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠-\mbY߿ ~Zx8 cKo^'߿OvoO']mv_g&Ih04ppz*rR endstream endobj 357 0 obj <>stream x4W0P0W5TT0VH1*T0 (X(Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p])$lYf[[pM@>K̛|ڗM 9YX+ov]vwnH\M0ng:F1V6::![}k L\ \ `v endstream endobj 354 0 obj <>stream x3P0P0b 3 CBc 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠>]fb[Qp+&.WO@.= endstream endobj 347 0 obj <>stream x3T0P0bS33KCBS53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠Hm'Wv $[K;VMo٫}?/~~b梐B „M endstream endobj 344 0 obj <>stream x37S0PP5V03W05VH1*T0 ()XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[q@U69ć@lP>?./a@c"k@†C: >Df-XĠ= endstream endobj 341 0 obj <>stream x35P0P0bJ1*T01T0*XBr.'BIQi*~8P)P%Sme˥{+esJsZ<]Զ¤ǩoKݠ_M^Z]]KM4eKvy/'!񿁃S! '7 endstream endobj 338 0 obj <>stream x37Q0P0bs3 CB3s 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠{r+_Cg_ 1X\=R endstream endobj 219 0 obj <>stream x37V0P0Q5R0CB39PF($s<=}JJSÁ=j ] b݀}o]s~Nin^1Pʁ'WRΪX$2[?Xwy_殻۲mĖ y$"yn908pz*rDS endstream endobj 714 0 obj <>stream x36T0P0R5T02W02RH1*T02  r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[x~@; //}Ye%צ\;tWҍDݎF.WO@.(.V endstream endobj 711 0 obj <>stream x3P0P0V5T06Q02RH1*T06 (+Dr.'BIQi*~8PP Sme˥{us;qy(e!~W^?-տ.}o\[< \ \2 endstream endobj 708 0 obj <>stream x36Q0P0Q54Q06W01WH1*T06(*$dr.'BIQi*~8PPSr62wwvvrllڹsJsZ<]$ TK/gsĂ__(E/^ p `hrT(= endstream endobj 705 0 obj <>stream x36P0P0V5T0P01SH1*T02U +Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠hrGr~rWֿZeڪɡ/v]GS! U; endstream endobj 682 0 obj <>stream xuL; @\D3^z};0;TLW\َjXѮE!q;@V̿=HQ*(\$deH8tM#|m=1\u^8 endstream endobj 671 0 obj <>stream x37W0P04Q0T03R0TH1*T0 (C=C=K 0RHrU()*M*N \.ц\\nn@n.P9?47ΎEAmŎ\AYn{nv m~ɗ=} ^BmB zH endstream endobj 536 0 obj <>stream x32P0P0bC CB P03T53\.'O.}O_T.p .}`ȥme`Sl\=1 endstream endobj 533 0 obj <>stream x37P0P0V5T03S01QH1*T03V *Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠F|Fܖ =nz߯Mzlkh᯶vo/{U߼m3̈́n$*qJڐŠ`N& endstream endobj 531 0 obj <>stream x37W0P0bsC33CBm@TPA@,Ls<=}JJSÁj=S!K!A,`cﭠ q)+*tQP[p%Fj/lғ:;(Os5p04pz*r B endstream endobj 528 0 obj <>stream x340V0P0bKS #CBKC 53T53 S\.'O.}O_T.pR.}J.}g %ڐ KM V8qy(h;.9l"#cibX-ow}@ "_5|?~/}eo^}K/}YPP hZ \ \K[9 endstream endobj 504 0 obj <>stream x35T0P0b33CCB53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]V`(x  [-=~Dw(˪_qSEVh04ppz*rPI endstream endobj 501 0 obj <>stream x35T0PaK3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v:sZliuۛܺ_C&o wp#`kjf5p04pz*r^ endstream endobj 498 0 obj <>stream x35T0P0R5T0P03TH1*T01 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠ߢ':`V{w&__:08pz*rMK; endstream endobj 404 0 obj <>stream x33P0P0bSscCBSS(kgk$s<=}JJSÁ=j ] b݀}o]s~Nin^1Pڲ I%\`./_,Uars}CB lF? endstream endobj 401 0 obj <>stream x31Q0P0V5T0"CBc !PH$r9yr{*rq{p;8+rDrr;;66@\9y@-vv\. j4NwAuku{MUֿL$`hrT[<, endstream endobj 398 0 obj <>stream x37S0PP5V03W05VH1*T0 ()XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[aj@c"k†C~7 qzrMN"a;1p0?lK-`bPrT>stream x3T0P04U01P01U0TH1*T06PA#KBr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[4Mli>stream x31W0P0S5U01P0PH1*T06 (+Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[Ă(nuӣ~~bF EY}޽{oT9}P ~3 endstream endobj 199 0 obj <>stream x37V0P0b3 J1*T0"&z z@`aɥPRTʥTʥTɥ`ȥme˥{+esJsZ<]Lb߫-:6q\|&8\=%Uj endstream endobj 72 0 obj <>stream x ;0Db.@k(",T)# >>byfB{OySJǚZ* H9^gdȁ5$ ] M#G}]{-J߆[ GF endstream endobj 69 0 obj <>stream x3T0P0S5R05S0TH1*T05PA c3=CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j7ډK7*/кdu/[_m?n@m8M, endstream endobj 66 0 obj <>stream x3T0P0S5R05R0TH1*T01 (X*Dr.'BIQi*~8PP Sr62wwvvrllt29y@-vv\. jKbWa -=`gJ$V羾E~cCK ~ooOsͳ:Fkr[oz1`mmb<" ,\ \R endstream endobj 63 0 obj <>stream x3T0P0U5R05V0TH1*T0 (X*Dr.'BIQi*~8PP Sr62wwvvrllt29y@-vv\. j 1>|%M!˽ /ԯ[woo?\mɶ׉Kox'.v61ۇ9l/rr{=*~Vkrwݎݲ;Ww4Df15cP`rTaX endstream endobj 60 0 obj <>stream x33U0P0Q5T03R05RH1*T0 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠HؐYYSڎ$~+.+|C<ӓv$Ik 08pz*r1H endstream endobj 57 0 obj <>stream x35R0P0Q5T0P05VH1*T01 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p!Bṅ8~.h|ziou^WOV!wۦn۝eۡ# 65602pz*rVC endstream endobj 54 0 obj <>stream x33U0P0V52V03P05RH1*T05(*$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[$nXjG wfMe9|xɽk/r ]n23qcGB_Gn\=WV endstream endobj 51 0 obj <>stream xP0P0U5RCBss!PH$r9yr{*rq{p;8+rDrr;;66 @ܼb;;.O2{*kl}Ā_ldۥ9zs y$T[Ĝ}>02pz*r/^W endstream endobj 48 0 obj <>stream x36V0P0b#K CB#S 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H[sc͝~\=? endstream endobj 45 0 obj <>stream x31S0P0R5T0T07QH1*T06 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠q_ovnR$VqCUs]ݲMGG"AS! E endstream endobj 42 0 obj <>stream x33R0P0R52Q0T05TH1*T05(*$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQb)GļCow%ߖ{{{^op[]oV1mٞNl٦͛UA endstream endobj 39 0 obj <>stream x33U0P0b3#S#CBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠hf[c{\\SWS>wǿ ~8xR9\S! |cH endstream endobj 36 0 obj <>stream x33U0P0V5T03P0VH1*T05 & z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-lN?9H@哨= 0&}/_CٽmӷMmٻeWAևlb X\=q] endstream endobj 717 0 obj <>stream x- @1OCۡt!BĩYŏoW0C $ Gǜ3hƥW]G9\=Ij wФ uo/D3=~" endstream endobj 666 0 obj <>stream x35S0P0S5T05V03WH1*T01 - r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP۸!۞im^NǪ,7%3(6[m-[{m@m۶L \ \D endstream endobj 602 0 obj <>stream x36T0P0V5T06CB#s 3\.'O.}O_T.p".}.}g me˥{us;qy(-l>"'xNh._~9_ޗns5Hٝ$󣀑AS! a/ endstream endobj 599 0 obj <>stream xP0P0b c CCBsK 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]OpHW? ~o߾}?pss?џ`B Y endstream endobj 596 0 obj <>stream x340T0P0W5T4V0VH1*T0 (X(Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠pE '[S-h|(ǖEW^/{_~WmU@Yk.u콹KM xTx")&66NAS! ^ endstream endobj 464 0 obj <>stream x37U0P0W5T03W0VH1*T03PA s=CHrU()*M*w pV0w62wwvvrllsJsZ<].hd=C!.ނFl|8$Ԫ[_}|5->3f+;Njķ@p=:m rkCgK pmɂCdE[-H duS! &A] endstream endobj 461 0 obj <>stream x35U0P5V52P05W07PH1*T03PAK%HVP!9ɓKW4K?KK)YK%ڐ KM V8qy(-!ӶC 枙C_[z`4!f$_׸_u_{ǭc'g7 ͏{:*VDD#B =rbX endstream endobj 458 0 obj <>stream x35T0P02Ɔ )\ $ tADr.'BIQi*~8PKL:8+)hC.X.Oy`y.WO@. endstream endobj 455 0 obj <>stream x35T0P0U5T01U03RH1*T01PA3cS=CHrU()*M*w pV0w62wwvvrllsJsZ<]육a2پ~e`_>zv_YmzyTM;&IxJk endstream endobj 452 0 obj <>stream x35T0PaK3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v*<~rAĖ@8Y /_$>stream x35T0P0bs3CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]Vq,\&ž_`4˂TTiգ+M=W04ppz*r[ endstream endobj 314 0 obj <>stream x37W0PP5Q0P05QH1*T03PAS  =CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j SDu2d(l"6mKfuU]~=8|"?4<~L \ \b; endstream endobj 311 0 obj <>stream x32U0PP5T0T0TH1*T02 (e r@"9ɓKW4K?KK)Yq62wwvvrllsJsZ<]B$VT}u<^U믽-&#B/ endstream endobj 308 0 obj <>stream x31U0P0U52P01W01QH1*T01(($dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[񡌙AS)%.?t3v ^޶GumB1܇6~?gǏKM 497.WO@.Oa endstream endobj 305 0 obj <>stream x37S0P0U5W0 )\ f@A3S=CHrU()*M*w pV0w62wwvvrllt29y@-vv\. j HeGO\Od*zS! ,> endstream endobj 302 0 obj <>stream x36S0P5R54V0"CBcS1PB$gɥPRTʥTƥTť`ȥme˥{s;qy(-a+q؍ץUGkk2~W۴YMZB/;]_:\=T=V endstream endobj 299 0 obj <>stream x36P0P0F`:Ős tADr.'BIQi*~8PKL:8+rDrry(3P`E%) endstream endobj 296 0 obj <>stream x35R0PP5T05V01QH1*T01 ( =CHrU()*Mr{IgC.}hC.X.}7}gg7 7FK9?47ΎEAm 7 5_Kǿ~5__z0v^j~bk[z," J endstream endobj 293 0 obj <>stream x35P0P0S5T05T0TH1*T01U e r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[CR ߯3X`uVF.WO@.R^ endstream endobj 290 0 obj <>stream x35P0P0T5T0P01QH1*T01W+%dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠9yn4ək~}sߢ^ߎ~o5:nk/=(ʙu+>CY`V_oR)^.WO@.N endstream endobj 287 0 obj <>stream x340P0P0U5T4Q05TH1*TT )Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠"/Ǭ=} 4uLgElL_zmo`aprTk8 endstream endobj 284 0 obj <>stream x35U0PP5T05S01QH1*T0 (*XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠؂{>˂싅9/Ź76nW|T_K.[z~ֹF?VVz28\=;nG endstream endobj 281 0 obj <>stream x35P0P0W52U01R07UH1*T06U A@29ɓKW4K?KK)YK%ڐ KM V8qy(I2̚QaM޽k߾}Ǡ"qKZAcޖhltB"i  \ \T' endstream endobj 278 0 obj <>stream x35U0P0R5T05P01QH1*T0  Fz@9 ɥPRTʥTĥTå`ȥme˥{us;qy(- -9rYKf{誯Rت<UK}ߪW>~zm}~r˒%9̈́nёple`rT%HI endstream endobj 275 0 obj <>stream x37P0P0b3SsCB3C(kgkg`  ɹ\N\ %E\@\@\N @K!A,`cﭠ q)+jtQP[#C%M¡E !DC5U/~H?[.Q׳e9vK^olq30rz*r2] endstream endobj 270 0 obj <>stream x33S0PP5Q05W05QH1*T0 (Z(XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[0GLn Q@}m_cZ'k}Ç7T:T20rz*r': endstream endobj 267 0 obj <>stream x35T0P0Q5T0P01QH1* aS=CHrU()*M*w pV0w62wwvvrllsJsZ<]. "'8e1ڡ*M_׵/YzWׇ[Xoպ-;MC$_ۖ:]9 01(pz*r1D endstream endobj 196 0 obj <>stream x37P0P0R5T03W01VH1*T03U (Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠#_mGC6Du/v]?{U.}iK~+nn;->#B N endstream endobj 193 0 obj <>stream x3T0P0b3c3 CBSkgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAUq̬&mu_}e>g81Ƭ o)\>>(3€AS! Py endstream endobj 190 0 obj <>stream x32W0PP5T!CBCC!HH&r9yr{*rUq{q;8+9.ц\\nn@n7P;s~Nin^1PZc\gok-ٲeWCB ?) endstream endobj 187 0 obj <>stream x35P0P0U5R01Q0PH1*T0T e r@"9ɓKW4K?KK)YK%ڐ KM V8qy(-ˏnљ )&t`aprT?UED endstream endobj 184 0 obj <>stream x0T0P0U5T07U0TH1*T07PA S=C$LrU()*M*w pV0w62wwvvrllڹsJsZ<].1k=NN̬[$έ?õVpI?n|9AS! ^t endstream endobj 181 0 obj <>stream x37S0P0U5T07T07PH1*T0(XX*$dr.'BIQi*~8PPS!K!A,`c ΥSW bg颠pZ$.DyÇ8 >Lwd2R^{վ̾6/?߰[UoevȖ^r˶~7ﻦou #r&g&LHɳE>>ַeq_gp0B cm1 endstream endobj 178 0 obj <>stream x35S0P0Q5T05T03UH1*T01 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠AV½&ޗk_8av_o;v˶K[ilbQbP`rTwGQ endstream endobj 175 0 obj <>stream x3P0P0bsc3sCB3K 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠#6gs$&$?tjYm)mc08pz*ruKK endstream endobj 172 0 obj <>stream x33S0P0b3#3 CBS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠J*ⶎÿ_o>3_[Jg`rT4O endstream endobj 169 0 obj <>stream x35Q0P0bSsCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`&&c ƽj_D_27}<ꪑ?.l^`Q \ \{R endstream endobj 166 0 obj <>stream x3T0P0bS3sCB# 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠B`أ?nK_}Y y=~+Fæ?#B |2H endstream endobj 163 0 obj <>stream x35T0P0R5T0P01VH1*T01 ((Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠_mY-׷[z\߱n.џ?o \=><- endstream endobj 160 0 obj <>stream x33R0PaS sCBS3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠pMrl̛eݼo}O*j>M&.WO@.Rl endstream endobj 157 0 obj <>stream x35Q0P0V5T05V01SH1*T05PAsc=CHrU()*M*w pV0w62wwvvrllsJsZ<]69hLXd|߭{:N"zEsPo_W}:;1)yM"i7ッgL\=E @ endstream endobj 154 0 obj <>stream x35T0P0V5T01W01SH1*T01 D r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[x,勇{|_/}u?n׿ߩWai'yۮn&pP0"1u9.WO@.Vj; endstream endobj 151 0 obj <>stream x0U0P0b 3KCBs3 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠pYɿ/7L}_Gomk~7?psx_~][o޶\=SY endstream endobj 33 0 obj <>stream x340W0P0bC #CBKkgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEA,zT_vM߭xTߙ>stream xP0P0S5T0R042PH1*T07 fz@Y ɥPRTʥTťRĥ\ b݀}ov.}ܼb;;.Oa6z;y7  s~>a/%&M׾髿[[Ϭ׽[fo۾m6mMmb71HhzcgC  \ \r~ endstream endobj 26 0 obj <>stream x34T0PP5V044b CBC#8PPB($s<=}JJSAʸ=@K!A,`cﭠ q)+itQPUS@k‚̬[\o__w}݊tm^.p6gmމM]yt$tv)01(pz*r6Ci endstream endobj 23 0 obj <>stream x3T0P0aCCCCB3ogkg`  ɹ\N\ %E\@\ \N \.ц\\nn@n.P9?47ΎEAmAc3̇ l_ؾ^K%&W}jk?˸]v']'e^YM6mzAKޗȘ})VakjkX\=&Zc endstream endobj 20 0 obj <>stream x31R0P0bc3CCCBc t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-mSd_|#c)_~?!F.WO@.P endstream endobj 17 0 obj <>stream x37P0P0U5T03S07SH1*T03T +Dr.'BIQi*~8PP Sme˥{us;qy(-"sBFf~×=} U)~د~5XW[}۾eneۥމ-nED2)&:6AS! S endstream endobj 12 0 obj <>stream xT0P0W5R0T040WH1*T07 z@Y ɥPRTʥTťRĥ`ȥme˥{+esJsz<]. f:ay5vQ-V |i7oڒ?޷:3k___}]߲ߥ۱ޖ]}+Guáh#oHMlmfV\]Ya endstream endobj 9 0 obj <>stream xT0P04&  )\ Q0TPA@,Ls<=}JJSÁ=@j ] b݀}o]s~Nin^1PG|s+'4hiͣ)O endstream endobj 746 0 obj <>stream x35T0P0W5R0T0PH1*T05 H($s<=}JJSÁ=j ] b݀}o]s~Nin^1P'\[kĵ {rP^]ou741ap`rT=B endstream endobj 743 0 obj <>stream x35P0PP5R05V03SH1*T01U Y(XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[8%MF| //˾N׿Q_kZ۞eZۄ"-.]emt(*ʅK/æ/٫~tE;W/n3pȡ, \ \SU endstream endobj 740 0 obj <>stream x37R0P0T5R0T0PH1*T0( @"9ɓKW4K?KK)YK%ڐ KM V8qy(m DDqQƫ룮f_֯襷@(QwCӍimb<" ,\ \vO endstream endobj 737 0 obj <>stream x37U0P04Q5R07S07PH1*T03( @"9ɓKW4K?KK)YK%ڐ KM V8qy(-\ar&!C{MKM}iB_Vemlկ/RQ]jKV.+휹K5m:#c'ĠQ} endstream endobj 734 0 obj <>stream x35P0PT5R05Q03SH1*T01U Y(XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[8-MCN`{ y /(><_vk}|ʴ#]CLbtWW׾mtz+)>v[MIl\ L\ \kMR endstream endobj 731 0 obj <>stream x36P0P02T01P06U0TH1*T04Q[ -,s<=}JJSÁ= ] b݀}o]s~Nin^1Pڢ֖//zK^  \ \* endstream endobj 669 0 obj <>stream xUJ`\ŹK(Z PqpvQ7k`s/B,B8dɐ!!KM |:ywb}Lxtj3[&6{Ϗ[|L,,nz15v1 ;ܻc8EZe, ,lRU[疪*ȥ(Tj(H2(cTȆGWG5%K+$E嫈3ȿC^|q8éuַ? endstream endobj 648 0 obj <>stream x36T0P0R52U0T07UH1*T04( A@29ɓKW4K?KK)YK%ڐ KM V8qy(S B>A endstream endobj 620 0 obj <>stream x340P0P0U5T4Q01QH1*TT *Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠1#u>̲pd"`6F[/./Tvin7W>k_uU(9;nߥ/oiw-u|L];z۳3Ǡ'L"%`"ۆClb>stream x33V0P0bsc3 CB3K 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`O bk/?~_=e׫zg CGg`rT`M endstream endobj 609 0 obj <>stream x33V0P0bsc3 CB3K 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠` __^ef_zWwc!wӳۏLp] I endstream endobj 583 0 obj <>stream x31R0P0V5R0P05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[Ƈr_پ̾e_}u_݊]maĎF.WO@.aG endstream endobj 580 0 obj <>stream x0T0P0bs3sCCBs# 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<].1yo>Udqx/M|/#/U/Ơ+X endstream endobj 577 0 obj <>stream x31R0P0V5R0P05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[8cCŏ+8&Uy/u,ǹ8dBژr_zoKn&t#`B "F endstream endobj 574 0 obj <>stream x31R0P0Q5R06W05SH1*T06 (Z(Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[c ǯ׉ų>O?hP_6C \mM/ݶwK7Y۴yt \=QD endstream endobj 571 0 obj <>stream x31R0P0bcsS3CBcc 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠AƇ싛9}})}دGm0wU^mӣ3Kvy{m٫/F.WO@.= endstream endobj 560 0 obj <>stream x4Q0P0b  CCB c 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]vs{V^ֶ_j'WLHs,S! cS endstream endobj 557 0 obj <>stream x3T0P5"#sSCB# %HVP!9ɓKW4K?KK)YK%ڐ KM jw)+jtQP[y7?͒MU {_ڷ7|/ _A؄D}]JAS! ';1 endstream endobj 554 0 obj <>stream x31P0P5T52P0P03SH1*T0TIX)Yd s<=}JJSÁʸ= ] b݀}o\9y@-vv\. j lan+oh>d7*n^}e0_C#\K]VNMӀiGt$48\=J endstream endobj 551 0 obj <>stream x33R0P0R5T0T06PH1*T05 (*Dr.'BIQi*~8PP Sr62wwvvrllsJsZ<]ԖX~p>&&^i,YfFq}zj_ǯW[4tzz eUsM8\=Ek endstream endobj 521 0 obj <>stream x346U0PaCcC3SCBC#3ogkg`  ɹ\N\ %E\ \@\N \.ц\\nn@n.P9?47ΎEAmAKBs@B!//ZsɁj|M^{ZzQ/3qٯC@082Yչ \ \ge endstream endobj 491 0 obj <>stream x35T0P02Ɔ & )\ A@PA@,Ls<=}JJSÁj=JhC.X.}7}gg7 7F[A(㜟SW bg颠Ab 0ˣ?n * endstream endobj 488 0 obj <>stream x35T0P0bs3#CB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠p·/6@V@K @q/SWگ4\=FL endstream endobj 485 0 obj <>stream x35T0P0SеP01Q0TH1*T0 (+Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[pm_{ٿHxyU.WO@.fsC endstream endobj 482 0 obj <>stream x35T0P02RеP0T0TH1*T0 (e r@"9ɓKW4K?\KK)YK%ڐ KM V8+qy(?M01(pz*rG& endstream endobj 446 0 obj <>stream x35T0P0QT01S05RH1*T01EL ,,s<=}JJSÁj=J ] b݀}o]s~Nin^1P9>eM3 endstream endobj 443 0 obj <>stream x35T0P0V52Q0T01QH1*T01(Y($dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[l`ACUQ-5*|/݊]w0*tXfݯYfC_~h½5lzE+DnmHLWbP`rT+U endstream endobj 440 0 obj <>stream x35T0P0bscCB 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠sE–OmubϏinݲun-]m{mK*̿}ioa_f_YubV20rz*r4Cx endstream endobj 437 0 obj <>stream x35T0P0bc3#CBr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-Qaɱ+Q?M9-`bPrT?* endstream endobj 434 0 obj <>stream x35T0P0U5T01Q01UH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`/b""}V}׿SK.Ͽu;Fn׭[yt$48\=\;> endstream endobj 431 0 obj <>stream x35T0P0R5T01V05UH1*T0 ()Dr.'BIQi*~8PP Sme˥{us;qy(-xvն?XS2?d|^evvv6A#B .; endstream endobj 428 0 obj <>stream x35T0P0T5T01W03TH1*T01 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠SAjO'6pcͫ8C~篿 ]=e>stream xM=@@ } -+J!* Og)& SͨgF0a)F9E~.} 5HіTfD?QvxS# endstream endobj 378 0 obj <>stream x33W0P0b3C3 CBSkgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAi?ZۦG {5bJ01(pz*rXA endstream endobj 263 0 obj <>stream x33T0P0bSK3 CBSc 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠`kQA,ԛ?zk}kWӽ__)P>AS! Cl endstream endobj 259 0 obj <>stream x31Q0P04P52U06W07UH1*T02 $@X$ $s<=}JJSÁ=@ʸ ] b݀}o]s~Nin^1Pڂ %/O v۷.WO@.K endstream endobj 256 0 obj <>stream x37U0P0U52V02LR @ z I ɥPRTʥTťTĥ`ȥme˥{+esJsZ<]rĸ`BC'Wr81re_!o-Hd=!#ЇF* Ř`aprToEW endstream endobj 253 0 obj <>stream x35V0P0Q5T0P05UH1*T01 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠๣N؂֋~/~_~yOR[+i ƶ}mIW 笵G}jﵿ֮pMeYF¡`hrTeH{ endstream endobj 250 0 obj <>stream x33T0P0Q5T05S05UH1*T05 DL r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[pg2@C,U/͗}]}[pUO|3s݊N1aep4uB  B PB endstream endobj 247 0 obj <>stream x33W0P0Q5T03R05UH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠`.㎃̇94XxM}i~u@:޲ǮmڭܥE$M8:!S! FK endstream endobj 243 0 obj <>stream x36W0P04F )\ $ tADr.'BIQi*~8PKL:8+rDrr;;66 @ܼbb;;.Oe5/?ߠ[@% endstream endobj 240 0 obj <>stream x35T0P0bS3CCBcK 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]v O?\rm \=V>stream x37Q0P0S5R03W4PH1*T03 (X r@"9ɓKW4K?KK)Yq62wwvvrllt29y@-vv\. j gg*h~a+y U/U{_Tn׾~^tǯf'̯_^_o߮ݲߥ۱[vd;̙#᝴m۶ ffbP`rT7V endstream endobj 233 0 obj <>stream x37Q0P04fF  )\  *XBr.'BIQi*~8P-P)S!K!A,`cﭠ q)+jtQPUXtD9OYӮ08pz*rG endstream endobj 230 0 obj <>stream x4P0P0U5T0S03UH1*T0T )Dr.'BIQi*~8PP Sme˥{us;qy(-h1Rly?_ w7D0c[HĴmrP`hrT}T endstream endobj 227 0 obj <>stream x0T0P04f & )\ @khgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAmCKdcI=alS! \O? endstream endobj 148 0 obj <>stream x35Q0P0U5R0P07PH1*T01 ()Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[P"RpݑNq__gTO- $*>II py٥ٙ~j{5l hmjlj`hrTPG endstream endobj 145 0 obj <>stream x3T0P0V52T01W01UH1*T01()$dr.'BIQi*~8PPS!K!A,`cﭠ q)+jtQP[[EC]4Ǯ(_[9U˯W-_e@"$+Ipgh_aBK?ur(Pm\6< 6q8H`hrT4U endstream endobj 142 0 obj <>stream x3T0P0Q5T01W01UH1*T01 L r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[ָCN`{ ٗ~=Od\Vl~XEE|˪'W[.< 65GS! FH endstream endobj 139 0 obj <>stream x3T0P0bc33CBc 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠YcBC9*ޗ f_ʿ}i?R}gn__/]zmofffҥKlu eזK~04ppz*rrI endstream endobj 136 0 obj <>stream x0S0P0Q5T0T0PH1*T07 (Y*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠8+>stream x3P0P0R5T06R03TH1*T06PA3##=CHrU()*M*w pV0w62wwvvrllsJsZ<]׿^n }JpLޭzvۥâm" ,\ \Ay endstream endobj 130 0 obj <>stream x3P0P0V5T06Q01UH1*T06 ()Dr.'BIQi*~8PP Sme˥{us;qy(-ef-z!`n򫿅ooߨg>B퍺\pY`CB >stream x31V0P0V5T0T01UH1*T06 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠C@ٗ/GeYHr~Cn٥޼-$6$Ih04ppz*r]< endstream endobj 124 0 obj <>stream x3T0P0V5T01CB#!PH$r9yr{*rq{p;8+rDrr;;66@\9y@-vv\. j 0d!Q|ɽU_u??u_}>vmnEg&n;$yS! AI endstream endobj 121 0 obj <>stream x32W0PbC CCB @BPAH$r9yr{*re=S!K!A,C}C}b1pz*r*2 endstream endobj 118 0 obj <>stream x35P0P0Q5T01CB#!PH$r9yr{*rq{p;8+rDrr;;66@\9y@-vv\. j l%t*_,PPx߶f^CXw޲ݙK7\:#tcC':8\=< endstream endobj 115 0 obj <>stream x35S0P0V5T05R01SH1*T0 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p i|_(۾k?em_oάp(:3Ehbk3s \ \@B& endstream endobj 112 0 obj <>stream x33R0P0bSKSCBSS 53T53 S\.'O.}O_T.pR.}J.}gC.}hC.X.}7}gg7 7F[A(㜟SW bg颠H]9OU,Bfh S! KAm endstream endobj 108 0 obj <>stream x33Q0P0U5T0P03SH1*T05 (+Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠v.lp՚ԲYs)A 'RW082B&w[4Q#QM ߀D'6ƹ \ \7N2 endstream endobj 104 0 obj <>stream x4P0P0b 33SCB C(kgkg`  ɹ\N\ %E\@\@\N @K!A,`cﭠ q)+jtQP[Ҡ;!EEnwfu;o޿__oj7p04pz*r.Q3 endstream endobj 100 0 obj <>stream x3P0P0b#3sCB#C 53T53 S\.'O.}O_T.pR.}J.}g %ڐ KM V8qy(-6_w|?ʪ \: endstream endobj 690 0 obj <>stream x36U0P0V5T06T01QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠f<ᣥ׹[OS[w8_׼O/YXj[t۴[< ,`bPrTj; endstream endobj 657 0 obj <>stream x3T0P04P05W0P03WH1*T0 L,s<=}JJSÁ=* ] b݀}o]s~Nin^1P beMle`rTd! endstream endobj 654 0 obj <>stream x3T0P0V5T03P0RH1*T05  z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-8-_?nt#tCn3!7&K L\ \K endstream endobj 651 0 obj <>stream x5KNP6\ \n/@(@݀.&EwҁС) 7ñ;k蠇zx=)xAS5z5Um@=.A>3 dgJro6e7,7i ŬweZ,Ml3YDbWDQa2ڐ[2QLla+=!t2R+#Gu>c_s$ɇBԾgx7) endstream endobj 635 0 obj <>stream x341Q0P0U54T04rR Lc @$lgRɹ\N\ %E\ \ u\N \.ц\\nn@n7.}ܼb&;;.O(OJm'xXn+TdOwߵ~woo{@~>ηmvz^z ȜX]Lե/.٫75SoR,bvyf^bʽ"Jl&r Z-L] endstream endobj 632 0 obj <>stream x344R0P0bCSKsCBKKkgkg`  ɹ\N\ %E\@\@\N \.ц\\nn@n.P9?47ΎEAmx?pSq>nubkq@?䊴4oX\=_^ endstream endobj 586 0 obj <>stream x36T0P0acSCBcr t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(-s?WlD'B m1 endstream endobj 518 0 obj <>stream x0U0P0V5T0T03QH1*T0 (*Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠Yl޶q[zu׫sDoA.WO@.gN endstream endobj 515 0 obj <>stream x0T0P0W5R07V4QH1*T03 (X)Dr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[sE2HJ!A5por^/}]6G~z[`CӉ4 6} oj~Xunvhĥ.D \1"1[qnk#B  i endstream endobj 415 0 obj <>stream x35S0P0U5T05P03UH1*T01 f z@9 ɥPRTʥTĥTå`ȥme˥{us;qy(-KaݮvkPPSKo0//V_ ZSߥ9&xnm8tYB FI endstream endobj 412 0 obj <>stream x31P0P04Q52U05P07UH1*T06SK$ A@29ɓKW4K?KK)YK%ڐ KM V8qy(-Zl}kWߪ֯ H]4}?.WO@.hN endstream endobj 333 0 obj <>stream x37U0P0U5T07T05QH1*T03 ML r@"9ɓKW4K?KK)YK%ڐ KM w)+jtQP[Ŭ pBfMi-x֯.ըNa10K(04ppz*rlL endstream endobj 330 0 obj <>stream x34T0P0V5T046U0RH1*  z@Y ɥPRTʥRťTĥ`ȥme˥{s;qy((=a,+i *9n^uz寷^cl{߿zz ȏ/ c a808pz*r\| endstream endobj 217 0 obj <>stream x32W0PbC cCBCr- t ,T!9ɓKW4K?KK)YK%ڐ KM V8qy(mQ?9d?N0}f, \ \*^ endstream endobj 213 0 obj <>stream x36P0P5U52P"3sCB#S%HVP!9ɓKW4K?KK)YK%ڐ KM V8qy(-pQ?áW8Dm }.[7ehN-,`bPrTUD] endstream endobj 97 0 obj <>stream x35Q0PT5T05T01QH1*T01 (*XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠h>km'yO,Xjz= UeoU۷Cmͬv \ \tBc endstream endobj 94 0 obj <>stream x31V0P0S5T01Q01UH1*T0 ()Dr.'BIQi*~8PP S!K!A,`c ͥSW bg颠p  GU//ү׿~j?_ֻ饻޶lcp`+#B ?m endstream endobj 90 0 obj <>stream x3T0PP5R05T03SH1*T01 (Y(XDr.'BIQi*~8PP S!K!A,`cﭠ q)+jtQP[9{+>stream x35T0PT5T05U01VH1*T01 ((XDr.'BIQi*~8PP S!K!A,`c ͥSW bg颠_mÜo׾z^K}}7ֿ,&.WO@.< endstream endobj 83 0 obj <>stream x35T0P0b 3CCB3 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]vZ4d?dOS?yvm V0gɡ[\=CC endstream endobj 80 0 obj <>stream x35T0P0b33CCB 53T53 S\.'O.}O_T.pR.}J.}g me˥{+esJsZ<]vq_({rv />owu{}Z} oyM]+Ms48\=I endstream endobj 588 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 49/LastChar 50/Widths[ 30 30] /Subtype/Type3>> endobj 754 0 obj <> endobj 91 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 46/LastChar 118/Widths[ 27 0 49 0 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 0 0 0 0 0 0 0 0 0 0 0 0 0 73 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 43 0 0 0 28 0 0 0 0 0 0 0 0 38 38 0 54 51] /Subtype/Type3>> endobj 755 0 obj <> endobj 570 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 48/LastChar 58/Widths[ 42 42 42 42 42 42 42 42 42 42 23] /Subtype/Type3>> endobj 756 0 obj <> endobj 543 0 obj <> endobj 757 0 obj <>stream x]O10 )T]Se!ipw'e_zv =z|RD`ѱ`BvW^@5]MO$.j 745$V?i vsmRh.\b$Nii 83/BSg endstream endobj 86 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 35/LastChar 124/Widths[ 51 0 0 0 0 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 0 51 51 0 0 0 51 51 51 51 51 51 51 0 51 51 0 51 51 51 51 51 0 51 51 51 0 51 51 0 0 0 0 0 0 0 51 0 51 51 51 51 51 51 51 51 51 0 51 51 51 51 51 51 0 51 51 51 51 51 51 51 51 51 0 51] /Subtype/Type3>> endobj 758 0 obj <> endobj 391 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 48/LastChar 110/Widths[ 35 35 35 35 35 35 35 0 0 0 0 0 0 55 0 0 0 53 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 0 0 0 0 0 0 0 20 0 0 0 60 39] /Subtype/Type3>> endobj 759 0 obj <> endobj 760 0 obj <>stream x]O10 XЪj8(Nߗ,N>ˮGֱ4%"@cQ8L;+'n:?`5]O$ZUFGRmcm+͟;s[2(9K7SiZL!`>SSa endstream endobj 32 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 12/LastChar 121/Widths[ 65 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 33 39 33 0 59 59 59 0 0 59 59 59 59 59 0 0 0 0 0 0 0 88 83 85 89 0 0 92 0 0 60 0 0 107 88 0 0 0 86 65 0 88 0 0 0 0 0 0 0 0 0 0 0 59 65 52 0 52 36 59 65 33 0 62 33 99 65 59 65 0 46 46 46 65 62 0 62 62] /Subtype/Type3>> endobj 761 0 obj <> endobj 364 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 67/LastChar 84/Widths[ 62 62 62 0 0 0 62 0 0 0 0 0 0 0 0 62 0 62] /Subtype/Type3>> endobj 762 0 obj <> endobj 16 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 46/LastChar 117/Widths[ 43 0 79 0 79 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 125 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 88 70 0 0 0 42 0 0 0 0 88 79 0 0 61 62 0 88] /Subtype/Type3>> endobj 763 0 obj <> endobj 14 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 67/LastChar 84/Widths[ 89 89 89 0 0 0 89 0 0 0 0 0 0 0 0 89 0 89] /Subtype/Type3>> endobj 764 0 obj <> endobj 544 0 obj <> endobj 765 0 obj <>stream x]O10 )T]BRǩ2ԉt4ipw'ew\%E cisDǢ:q6V&:txb I>54R>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 58/LastChar 120/Widths[ 20 20 0 0 0 0 0 0 53 0 58 0 0 0 0 31 0 0 0 0 56 0 0 0 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0 37 30 31 0 0 34 34 0 24 29 0 21 62 43 34 36 0 0 0 25 0 0 0 40] /Subtype/Type3>> endobj 766 0 obj <> endobj 272 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 82/LastChar 82/Widths[ 61] /Subtype/Type3>> endobj 767 0 obj <> endobj 768 0 obj <>stream x]10 E7HZPe)K.$JӁ$[̇<:ߢ%0H_#h5-hە @fcw*kZBMz!dodߪٝ$vA !t|)3kR/`:|)>MW endstream endobj 268 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 13/LastChar 120/Widths[ 51 43 39 0 0 0 0 0 0 0 0 0 55 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 27 27 76 49 76 0 0 0 74 0 81 0 63 0 0 43 0 83 0 0 78 0 63 0 74 60 0 0 0 0 0 0 0 0 0 0 0 0 0 51 41 42 51 45 48 47 0 33 40 0 29 85 58 47 49 0 44 0 35 56 0 70 55] /Subtype/Type3>> endobj 769 0 obj <> endobj 770 0 obj <>stream x]O10 ʂXЪj8(Nߗ,N>ˮGֱ4%"@cQ8L;+'n:?`5]O$uʪB A#E#FOݝs[2(9K7SiZL!`>Sb endstream endobj 264 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 12/LastChar 122/Widths[ 55 57 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 30 40 40 0 0 30 35 30 50 50 50 50 50 0 0 0 50 0 50 0 0 0 0 0 0 0 72 0 70 74 66 64 75 0 38 51 0 61 87 72 75 66 0 71 55 70 72 0 97 0 0 0 0 0 0 0 0 0 50 45 45 50 45 30 45 50 30 0 0 25 80 55 50 50 0 41 40 32 52 45 65 45 47 40] /Subtype/Type3>> endobj 771 0 obj <> endobj 261 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 0/LastChar 106/Widths[ 55 0 0 35 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 0 0 0 0 0 0 0 0 0 0 0 0 19 0 47 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20] /Subtype/Type3>> endobj 772 0 obj <> endobj 773 0 obj <>stream x]1 EwN I,KdhU1!Co`%[ϬGtůQaT5Vêfo2?fS=۶QUBkXTtAU]ٝg-PuOtF81_LUk#X~rn"_V endstream endobj 244 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 12/LastChar 121/Widths[ 75 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 0 37 0 0 67 67 67 67 67 0 0 0 0 0 0 0 0 0 0 0 0 0 97 103 88 85 0 0 0 69 0 0 128 105 101 92 0 0 75 94 0 0 139 0 0 0 37 0 37 0 0 0 65 75 60 75 61 41 67 75 37 0 71 37 112 75 67 75 0 55 53 52 75 71 0 71 71] /Subtype/Type3>> endobj 774 0 obj <> endobj 238 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 67/LastChar 84/Widths[ 74 74 74 0 0 0 74 0 0 0 0 0 0 0 0 74 0 74] /Subtype/Type3>> endobj 775 0 obj <> endobj 215 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 0/LastChar 110/Widths[ 77 0 77 0 0 0 77 77 0 0 0 0 0 0 0 50 0 0 0 0 77 0 0 0 0 0 77 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 66 0 0 0 0 0 55 0 0 50 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 66 0 0 0 0 0 0 0 0 0 50 50 0 0 28 0 0 0 50] /Subtype/Type3>> endobj 776 0 obj <> endobj 645 0 obj <> endobj 777 0 obj <> endobj 778 0 obj <>stream x]= wNO:D,钡UL@ }I:txlg}mwM@ѫ&0鈓Bq UiJU 7ޟЬ]Hu})#80J7 i1j fs(8; Ҝ1K|7KiG5Lj.yoE ,V endstream endobj 110 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 12/LastChar 123/Widths[ 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 93 0 0 0 31 44 44 0 0 31 37 31 56 56 56 56 56 56 56 56 56 0 0 0 0 0 0 0 0 0 85 80 81 86 74 70 88 88 42 0 0 67 0 88 84 77 84 84 62 78 86 0 0 85 0 0 31 0 31 0 0 0 54 62 50 62 51 34 56 62 32 0 59 32 94 62 56 62 59 46 44 44 62 59 81 59 59 50 56] /Subtype/Type3>> endobj 779 0 obj <> endobj 636 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 2/LastChar 88/Widths[ 42 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 73 0 0 0 0 0 0 0 0 0 0 0 0 79 79 0 0 0 0 0 0 80 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 144] /Subtype/Type3>> endobj 780 0 obj <> endobj 781 0 obj <>stream x]O10 )HPu)K>:NNI[t;,ڱK X&= Eu0mLu@vw=|/UYUk)hy Q+6I[tl Rw%Gs&#q*MK\1 >,_@/Sd endstream endobj 105 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 12/LastChar 119/Widths[ 90 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 0 0 0 0 81 81 81 81 0 0 0 0 0 0 0 0 0 0 0 0 122 0 117 0 0 0 0 0 60 0 0 0 0 0 0 110 0 120 0 112 124 0 0 0 0 0 0 0 0 0 0 0 78 90 72 90 74 49 81 90 44 0 0 44 135 90 81 0 0 66 64 63 90 85 117] /Subtype/Type3>> endobj 782 0 obj <> endobj 618 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 97/LastChar 111/Widths[ 34 27 0 0 0 0 30 0 22 25 0 20 54 38 31] /Subtype/Type3>> endobj 783 0 obj <> endobj 784 0 obj <>stream x]= {N c 6)t E!c,,>fo-9њ=8* O0+#WW.#r z{t7yzVjNꅄ hZsVX5Lz^h`ɘI/ eIv^HUUcxX*sZcww>p}!]~ endstream endobj 101 0 obj <>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 1/LastChar 127/Widths[ 81 0 0 0 0 0 0 0 0 70 57 54 54 81 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49 81 0 0 0 27 38 38 0 76 27 33 27 49 49 49 49 49 49 49 49 49 49 49 27 27 0 76 0 0 76 73 69 70 75 66 64 77 73 35 50 76 61 89 73 76 66 76 72 54 70 73 73 100 73 73 0 27 49 27 0 0 0 49 54 43 54 43 30 49 54 28 30 51 28 82 54 49 54 51 38 38 38 54 51 70 51 51 43 49 0 0 49 49] /Subtype/Type3>> endobj 785 0 obj <> endobj 786 0 obj <>stream GPL Ghostscript 8.54 PDF Writer userguide.dvi endstream endobj 2 0 obj <>endobj xref 0 787 0000000000 65535 f 0000838520 00000 n 0001011426 00000 n 0000838205 00000 n 0000832595 00000 n 0000000015 00000 n 0000000570 00000 n 0000838586 00000 n 0000925142 00000 n 0000967872 00000 n 0000866116 00000 n 0000924876 00000 n 0000967541 00000 n 0000865880 00000 n 0000995821 00000 n 0000924633 00000 n 0000995187 00000 n 0000967242 00000 n 0000865629 00000 n 0000909427 00000 n 0000967004 00000 n 0000865322 00000 n 0000909161 00000 n 0000966680 00000 n 0000865124 00000 n 0000908844 00000 n 0000966400 00000 n 0000864740 00000 n 0000908576 00000 n 0000966068 00000 n 0000864497 00000 n 0000908406 00000 n 0000993611 00000 n 0000965799 00000 n 0000864172 00000 n 0000908108 00000 n 0000954312 00000 n 0000863960 00000 n 0000907838 00000 n 0000954067 00000 n 0000863680 00000 n 0000907556 00000 n 0000953785 00000 n 0000863422 00000 n 0000907318 00000 n 0000953540 00000 n 0000863171 00000 n 0000907001 00000 n 0000953309 00000 n 0000862844 00000 n 0000906728 00000 n 0000953057 00000 n 0000854181 00000 n 0000906448 00000 n 0000952772 00000 n 0000853911 00000 n 0000906206 00000 n 0000952500 00000 n 0000853611 00000 n 0000905943 00000 n 0000952253 00000 n 0000853314 00000 n 0000905674 00000 n 0000951923 00000 n 0000853023 00000 n 0000905397 00000 n 0000951627 00000 n 0000852695 00000 n 0000899553 00000 n 0000951362 00000 n 0000852385 00000 n 0000899245 00000 n 0000951173 00000 n 0000852108 00000 n 0000899018 00000 n 0000838627 00000 n 0000838657 00000 n 0000832755 00000 n 0000000589 00000 n 0000002433 00000 n 0000989369 00000 n 0000891262 00000 n 0000937194 00000 n 0000989126 00000 n 0000890992 00000 n 0000936973 00000 n 0000991253 00000 n 0000988877 00000 n 0000890711 00000 n 0000936808 00000 n 0000988596 00000 n 0000989911 00000 n 0000890449 00000 n 0000936538 00000 n 0000988333 00000 n 0000890208 00000 n 0000936227 00000 n 0000988083 00000 n 0000889974 00000 n 0000935938 00000 n 0000983853 00000 n 0001008160 00000 n 0000889622 00000 n 0000935647 00000 n 0000983598 00000 n 0001006457 00000 n 0000889367 00000 n 0000935352 00000 n 0000983291 00000 n 0000889145 00000 n 0001004121 00000 n 0000935145 00000 n 0000983053 00000 n 0000888903 00000 n 0000934912 00000 n 0000982787 00000 n 0000888627 00000 n 0000934673 00000 n 0000982531 00000 n 0000884837 00000 n 0000934453 00000 n 0000982365 00000 n 0000884583 00000 n 0000934222 00000 n 0000982103 00000 n 0000884313 00000 n 0000934011 00000 n 0000981844 00000 n 0000884053 00000 n 0000933737 00000 n 0000981579 00000 n 0000883793 00000 n 0000933465 00000 n 0000981342 00000 n 0000883555 00000 n 0000924356 00000 n 0000981099 00000 n 0000883287 00000 n 0000924050 00000 n 0000980820 00000 n 0000882989 00000 n 0000923806 00000 n 0000980539 00000 n 0000882752 00000 n 0000923539 00000 n 0000980231 00000 n 0000882460 00000 n 0000923245 00000 n 0000979925 00000 n 0000882202 00000 n 0000922958 00000 n 0000965526 00000 n 0000881957 00000 n 0000922719 00000 n 0000965265 00000 n 0000881678 00000 n 0000922474 00000 n 0000964986 00000 n 0000881467 00000 n 0000922217 00000 n 0000964731 00000 n 0000881275 00000 n 0000921943 00000 n 0000964484 00000 n 0000881036 00000 n 0000921669 00000 n 0000964239 00000 n 0000862605 00000 n 0000921374 00000 n 0000963989 00000 n 0000862310 00000 n 0000921092 00000 n 0000963712 00000 n 0000862047 00000 n 0000920836 00000 n 0000963468 00000 n 0000861793 00000 n 0000920567 00000 n 0000963198 00000 n 0000861525 00000 n 0000920331 00000 n 0000962855 00000 n 0000861216 00000 n 0000905149 00000 n 0000962603 00000 n 0000861014 00000 n 0000904947 00000 n 0000962370 00000 n 0000860792 00000 n 0000904694 00000 n 0000962152 00000 n 0000860535 00000 n 0000904468 00000 n 0000961869 00000 n 0000860244 00000 n 0000904302 00000 n 0000961590 00000 n 0000859995 00000 n 0000904046 00000 n 0000950936 00000 n 0000838711 00000 n 0000838742 00000 n 0000832919 00000 n 0000002454 00000 n 0000004177 00000 n 0000895443 00000 n 0000941588 00000 n 0000848617 00000 n 0000895126 00000 n 0000941301 00000 n 0000848326 00000 n 0000894820 00000 n 0000941055 00000 n 0000987838 00000 n 0000894596 00000 n 0001002939 00000 n 0000940844 00000 n 0000987617 00000 n 0000894373 00000 n 0000946302 00000 n 0000847967 00000 n 0000898744 00000 n 0000838825 00000 n 0000838856 00000 n 0000833093 00000 n 0000004199 00000 n 0000007015 00000 n 0000979693 00000 n 0000888418 00000 n 0000933157 00000 n 0000979440 00000 n 0000880795 00000 n 0000932860 00000 n 0000979219 00000 n 0000880497 00000 n 0000932604 00000 n 0000978914 00000 n 0000880268 00000 n 0001002553 00000 n 0000932403 00000 n 0000978697 00000 n 0000880026 00000 n 0000932174 00000 n 0000978497 00000 n 0001001333 00000 n 0000879756 00000 n 0000931933 00000 n 0000978221 00000 n 0000879473 00000 n 0000920117 00000 n 0000977947 00000 n 0000879198 00000 n 0000919824 00000 n 0000977658 00000 n 0000878931 00000 n 0000919593 00000 n 0000977372 00000 n 0000878684 00000 n 0000919347 00000 n 0000977111 00000 n 0000878465 00000 n 0001000542 00000 n 0000919085 00000 n 0000976864 00000 n 0000999119 00000 n 0000878199 00000 n 0000918840 00000 n 0000961318 00000 n 0000997763 00000 n 0000918565 00000 n 0000961063 00000 n 0000877864 00000 n 0000997261 00000 n 0000918309 00000 n 0000996497 00000 n 0000960771 00000 n 0000877653 00000 n 0000918053 00000 n 0000960488 00000 n 0000877413 00000 n 0000917796 00000 n 0000960235 00000 n 0000877192 00000 n 0000917526 00000 n 0000959958 00000 n 0000859710 00000 n 0000917262 00000 n 0000959716 00000 n 0000859436 00000 n 0000917003 00000 n 0000959430 00000 n 0000859166 00000 n 0000916746 00000 n 0000959155 00000 n 0000858908 00000 n 0000916488 00000 n 0000958886 00000 n 0000858617 00000 n 0000916217 00000 n 0000958724 00000 n 0000858345 00000 n 0000903807 00000 n 0000958462 00000 n 0000858108 00000 n 0000903553 00000 n 0000958248 00000 n 0000857860 00000 n 0000903310 00000 n 0000957959 00000 n 0000857597 00000 n 0000903002 00000 n 0000957730 00000 n 0000857320 00000 n 0000902700 00000 n 0000957475 00000 n 0000857015 00000 n 0000902444 00000 n 0000950692 00000 n 0000856748 00000 n 0000950454 00000 n 0000856511 00000 n 0000838939 00000 n 0000838970 00000 n 0000833259 00000 n 0000007037 00000 n 0000008915 00000 n 0000940527 00000 n 0000847703 00000 n 0000894013 00000 n 0000940233 00000 n 0000987310 00000 n 0000893757 00000 n 0000939938 00000 n 0000987063 00000 n 0000893473 00000 n 0000939610 00000 n 0000847435 00000 n 0000898462 00000 n 0000946025 00000 n 0000847132 00000 n 0000898261 00000 n 0000945777 00000 n 0000846847 00000 n 0000897998 00000 n 0000945513 00000 n 0000846579 00000 n 0000897734 00000 n 0000945249 00000 n 0000839157 00000 n 0000839188 00000 n 0000833433 00000 n 0000008937 00000 n 0000011122 00000 n 0000893187 00000 n 0000945028 00000 n 0000846278 00000 n 0000892925 00000 n 0000944702 00000 n 0000846004 00000 n 0000892706 00000 n 0000944420 00000 n 0000845751 00000 n 0000892418 00000 n 0000944194 00000 n 0000994801 00000 n 0000845476 00000 n 0000892180 00000 n 0000943947 00000 n 0000845204 00000 n 0000891988 00000 n 0000939313 00000 n 0000839323 00000 n 0000839354 00000 n 0000833607 00000 n 0000011144 00000 n 0000013996 00000 n 0000876908 00000 n 0000915972 00000 n 0000976630 00000 n 0000876628 00000 n 0000915697 00000 n 0000976464 00000 n 0000876344 00000 n 0000839489 00000 n 0000839520 00000 n 0000833773 00000 n 0000014018 00000 n 0000016636 00000 n 0000943748 00000 n 0000851893 00000 n 0000897489 00000 n 0000992802 00000 n 0000943436 00000 n 0000851631 00000 n 0000897203 00000 n 0000943206 00000 n 0000851373 00000 n 0000902241 00000 n 0000950192 00000 n 0000856216 00000 n 0000901975 00000 n 0000949950 00000 n 0000851062 00000 n 0000901719 00000 n 0000949711 00000 n 0000850841 00000 n 0000901496 00000 n 0000839629 00000 n 0000839660 00000 n 0000833947 00000 n 0000016658 00000 n 0000018955 00000 n 0000986806 00000 n 0000891733 00000 n 0000939009 00000 n 0000986518 00000 n 0000888127 00000 n 0000938758 00000 n 0000844894 00000 n 0000891475 00000 n 0000942921 00000 n 0000839782 00000 n 0000839813 00000 n 0000834121 00000 n 0000018977 00000 n 0000020824 00000 n 0000876073 00000 n 0000931697 00000 n 0000976196 00000 n 0000875837 00000 n 0000931445 00000 n 0000975960 00000 n 0000875608 00000 n 0000915453 00000 n 0000975700 00000 n 0000875361 00000 n 0000915177 00000 n 0000975463 00000 n 0000875107 00000 n 0000914930 00000 n 0000975197 00000 n 0000874885 00000 n 0000914660 00000 n 0000974890 00000 n 0000874613 00000 n 0000914429 00000 n 0000974675 00000 n 0000874363 00000 n 0000914156 00000 n 0000957217 00000 n 0000874083 00000 n 0000913901 00000 n 0000956969 00000 n 0000873823 00000 n 0000913648 00000 n 0000956704 00000 n 0000873613 00000 n 0000913416 00000 n 0000956535 00000 n 0000873328 00000 n 0000913088 00000 n 0000956219 00000 n 0000873064 00000 n 0000912774 00000 n 0000955886 00000 n 0000855984 00000 n 0000839922 00000 n 0000839953 00000 n 0000834287 00000 n 0000020846 00000 n 0000022859 00000 n 0000942698 00000 n 0000844729 00000 n 0000896940 00000 n 0000942450 00000 n 0000840049 00000 n 0000840080 00000 n 0000834453 00000 n 0000022881 00000 n 0000025208 00000 n 0000872758 00000 n 0000931212 00000 n 0000974470 00000 n 0000872485 00000 n 0000930947 00000 n 0000974247 00000 n 0000872256 00000 n 0000930684 00000 n 0000973988 00000 n 0000871991 00000 n 0000930419 00000 n 0000973768 00000 n 0000840176 00000 n 0000840207 00000 n 0000834619 00000 n 0000025230 00000 n 0000026377 00000 n 0000896720 00000 n 0000949464 00000 n 0000850552 00000 n 0000896476 00000 n 0000949190 00000 n 0000850269 00000 n 0000896279 00000 n 0000948924 00000 n 0000850017 00000 n 0000896025 00000 n 0000942166 00000 n 0000849771 00000 n 0000895727 00000 n 0000840290 00000 n 0000840321 00000 n 0000834785 00000 n 0000026399 00000 n 0000028122 00000 n 0000986177 00000 n 0000887836 00000 n 0000930154 00000 n 0000985925 00000 n 0000887530 00000 n 0000929941 00000 n 0000973486 00000 n 0000887256 00000 n 0000840391 00000 n 0000840422 00000 n 0000834951 00000 n 0000028144 00000 n 0000030851 00000 n 0000948630 00000 n 0000855737 00000 n 0000901220 00000 n 0000948410 00000 n 0000855448 00000 n 0000948119 00000 n 0000849566 00000 n 0000901010 00000 n 0000947957 00000 n 0000849316 00000 n 0000840531 00000 n 0000840562 00000 n 0000835117 00000 n 0000030873 00000 n 0000035376 00000 n 0000990953 00000 n 0000996198 00000 n 0000840697 00000 n 0000840728 00000 n 0000835283 00000 n 0000035398 00000 n 0000038362 00000 n 0000929663 00000 n 0000973212 00000 n 0000871738 00000 n 0000929399 00000 n 0000972946 00000 n 0000871515 00000 n 0000929089 00000 n 0000972699 00000 n 0000871230 00000 n 0000928850 00000 n 0000972452 00000 n 0000870988 00000 n 0000928574 00000 n 0000840811 00000 n 0000840842 00000 n 0000835449 00000 n 0000038384 00000 n 0000041288 00000 n 0000870770 00000 n 0000912554 00000 n 0000990510 00000 n 0000972187 00000 n 0000870491 00000 n 0000912304 00000 n 0000971917 00000 n 0000870281 00000 n 0000911996 00000 n 0000971639 00000 n 0000870034 00000 n 0000911707 00000 n 0000971397 00000 n 0000869757 00000 n 0000911486 00000 n 0000971136 00000 n 0000887037 00000 n 0000928313 00000 n 0000985715 00000 n 0000886824 00000 n 0000989630 00000 n 0000938517 00000 n 0000840990 00000 n 0000841021 00000 n 0000835623 00000 n 0000041310 00000 n 0000044581 00000 n 0000911225 00000 n 0000955570 00000 n 0000869492 00000 n 0000910921 00000 n 0000955280 00000 n 0000869214 00000 n 0000910699 00000 n 0000955046 00000 n 0000868954 00000 n 0000841195 00000 n 0000841226 00000 n 0000835789 00000 n 0000044603 00000 n 0000047632 00000 n 0000970867 00000 n 0000841387 00000 n 0000841418 00000 n 0000835963 00000 n 0000047654 00000 n 0000051803 00000 n 0000928021 00000 n 0000970596 00000 n 0000868717 00000 n 0001007473 00000 n 0000927765 00000 n 0000970265 00000 n 0000841553 00000 n 0000841584 00000 n 0000836137 00000 n 0000051825 00000 n 0000058982 00000 n 0000841771 00000 n 0000841802 00000 n 0000836303 00000 n 0000059004 00000 n 0000061107 00000 n 0000938257 00000 n 0000985455 00000 n 0000886523 00000 n 0000938010 00000 n 0000985110 00000 n 0001005668 00000 n 0000886289 00000 n 0000937678 00000 n 0000841911 00000 n 0000841942 00000 n 0000836469 00000 n 0000061129 00000 n 0000326588 00000 n 0000842116 00000 n 0001003737 00000 n 0000868438 00000 n 0000910495 00000 n 0000970062 00000 n 0000868116 00000 n 0000910255 00000 n 0000984790 00000 n 0000886049 00000 n 0000927507 00000 n 0000984550 00000 n 0000885845 00000 n 0000927306 00000 n 0000984337 00000 n 0000842868 00000 n 0000842903 00000 n 0000842934 00000 n 0000836679 00000 n 0000326612 00000 n 0000329065 00000 n 0000867887 00000 n 0000910028 00000 n 0000954787 00000 n 0000885616 00000 n 0000926963 00000 n 0000969721 00000 n 0000885333 00000 n 0000947717 00000 n 0000843134 00000 n 0000843165 00000 n 0000836853 00000 n 0000329087 00000 n 0000330515 00000 n 0000843313 00000 n 0000843344 00000 n 0000837027 00000 n 0000330537 00000 n 0000365324 00000 n 0000947512 00000 n 0000849113 00000 n 0000843427 00000 n 0000843458 00000 n 0000837193 00000 n 0000365347 00000 n 0000432666 00000 n 0000937462 00000 n 0000984079 00000 n 0000885070 00000 n 0000926701 00000 n 0000843619 00000 n 0000843650 00000 n 0000837359 00000 n 0000432689 00000 n 0000823888 00000 n 0000843824 00000 n 0000843855 00000 n 0000837525 00000 n 0000823912 00000 n 0000826594 00000 n 0000855188 00000 n 0000900759 00000 n 0000947261 00000 n 0000854944 00000 n 0000900463 00000 n 0000947018 00000 n 0000854688 00000 n 0000900232 00000 n 0000946779 00000 n 0000854438 00000 n 0000900014 00000 n 0000946548 00000 n 0000848873 00000 n 0000899776 00000 n 0000954593 00000 n 0000843925 00000 n 0000843956 00000 n 0000837699 00000 n 0000826616 00000 n 0000828876 00000 n 0000941834 00000 n 0000844446 00000 n 0000844130 00000 n 0000844161 00000 n 0000837873 00000 n 0000828898 00000 n 0000831642 00000 n 0000926437 00000 n 0000969501 00000 n 0000867593 00000 n 0000926277 00000 n 0000969206 00000 n 0000867289 00000 n 0000925973 00000 n 0000968901 00000 n 0000867011 00000 n 0000925756 00000 n 0000968648 00000 n 0000866728 00000 n 0000925447 00000 n 0000968335 00000 n 0000866442 00000 n 0000909753 00000 n 0000968095 00000 n 0000844244 00000 n 0000844275 00000 n 0000838039 00000 n 0000831664 00000 n 0000832574 00000 n 0000844345 00000 n 0000844376 00000 n 0000989823 00000 n 0000990364 00000 n 0000990838 00000 n 0000991022 00000 n 0000992479 00000 n 0000993248 00000 n 0000993380 00000 n 0000994541 00000 n 0000995078 00000 n 0000995665 00000 n 0000996089 00000 n 0000996266 00000 n 0000997078 00000 n 0000997439 00000 n 0000997524 00000 n 0000998642 00000 n 0000998888 00000 n 0001000251 00000 n 0001000984 00000 n 0001001092 00000 n 0001002300 00000 n 0001002830 00000 n 0001003559 00000 n 0001003820 00000 n 0001003879 00000 n 0001005359 00000 n 0001006109 00000 n 0001006226 00000 n 0001007266 00000 n 0001007784 00000 n 0001007905 00000 n 0001009727 00000 n 0001010100 00000 n trailer << /Size 787 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 1011619 %%EOF nlopt-2.6.1/src/algs/esch/000077500000000000000000000000001345435414600153245ustar00rootroot00000000000000nlopt-2.6.1/src/algs/esch/COPYRIGHT000066400000000000000000000021711345435414600166200ustar00rootroot00000000000000/* Copyright (c) 2008-2013 Carlos Henrique da Silva Santos * * 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. */ nlopt-2.6.1/src/algs/esch/README000066400000000000000000000024451345435414600162110ustar00rootroot00000000000000This is Carlos Henrique da Silva Santos's implementation of a modified version of the Evolutionary Algorithm described in the following paper and Ph.D. thesis: C. H. da Silva Santos, M. S. Gonçalves, and H. E. Hernandez-Figueroa, "Designing Novel Photonic Devices by Bio-Inspired Computing," IEEE Photonics Technology Letters 22(15), pp. 1177-1179 (2010). C. H. da Silva Santos, "Parallel and Bio-Inspired Computing Applied to Analyze Microwave and Photonic Metamaterial Strucutures," University of Campinas, (2010) http://www.bibliotecadigital.unicamp.br/document/?code=000767537&opt=4&lg=en_US The algorithms are adapted from ideas described in: H.-G. Beyer and H.-P. Schwefel. Evolution Strategies: A Comprehensive Introduction. Journal Natural Computing, 1(1):3–52, 2002. Ingo Rechenberg (1971): Evolutionsstrategie – Optimierung technischer Systeme nach Prinzipien der biologischen Evolution (PhD thesis). Reprinted by Fromman-Holzboog (1973). It is distributed under the "MIT license" given in the attached COPYRIGHT file (similar to the rest of NLopt), and was supportedfinancially by the São Paulo Science Foundation (FAPESP - Fundação de Amparo à Pesquisa do Estado de São Paulo) under the grant 2012/14553-9. Carlos Henrique da Silva Santos January 2013 nlopt-2.6.1/src/algs/esch/esch.c000066400000000000000000000240201345435414600164100ustar00rootroot00000000000000/* Copyright (c) 2008-2013 Carlos Henrique da Silva Santos * * 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. */ #include #include #include "esch.h" /****************************************************************************/ /* Cauchy random number distribution */ static double randcauchy(const double params[7]) { /* double min, double max, double mi, double t, double band */ double na_unif, cauchy_mit, limit_inf, limit_sup; double valor; double min = params[1], max = params[2], mi = params[3], t = params[4], band = params[5]; limit_inf = mi - (band*0.5); limit_sup = mi + (band*0.5); do { na_unif = nlopt_urand(0,1); /* ran2(0,1); */ cauchy_mit = t*tan((na_unif-0.5)*3.14159265358979323846) + mi; } while ( (cauchy_mitlimit_sup) ); if (cauchy_mit < 0) cauchy_mit = -cauchy_mit; else cauchy_mit = cauchy_mit + (band*0.5); valor = cauchy_mit/band; valor = min+(max-min)*valor; return valor; } /****************************************************************************/ /* main Individual representation type */ typedef struct IndividualStructure { double * parameters; double fitness; } Individual; static int CompareIndividuals(void *unused, const void *a_, const void *b_) { const Individual *a = (const Individual *) a_; const Individual *b = (const Individual *) b_; (void) unused; return a->fitness < b->fitness ? -1 : (a->fitness > b->fitness ? +1 : 0); } nlopt_result chevolutionarystrategy( unsigned nparameters, /* Number of input parameters */ nlopt_func f, /* Recursive Objective Funtion Call */ void * data_f, /* Data to Objective Function */ const double* lb, /* Lower bound values */ const double* ub, /* Upper bound values */ double* x, /*in: initial guess, out: minimizer */ double* minf, nlopt_stopping* stop, /* nlopt stop condition */ unsigned np, /* Number of Parents */ unsigned no) { /* Number of Offsprings */ /* variables from nlopt */ nlopt_result ret = NLOPT_SUCCESS; double vetor[8]; unsigned i, id, item; int parent1, parent2; unsigned crosspoint; /* crossover parameteres */ int contmutation, totalmutation; /* mutation parameters */ int idoffmutation, paramoffmutation; /* mutation parameters */ Individual * esparents; /* Parents population */ Individual * esoffsprings; /* Offsprings population */ Individual * estotal;/* copy containing Parents and Offsprings pops */ /* It is interesting to maintain the parents and offsprings * populations stablished and sorted; when the final iterations * is achieved, they are ranked and updated. */ /********************************* * controling the population size *********************************/ if (!np) np = 40; if (!no) no = 60; if ((np < 1)||(no<1)) { nlopt_stop_msg(stop, "populations %d, %d are too small", np, no); return NLOPT_INVALID_ARGS; } esparents = (Individual*) malloc(sizeof(Individual) * np); esoffsprings = (Individual*) malloc(sizeof(Individual) * no); estotal = (Individual*) malloc(sizeof(Individual) * (np+no)); if ((!esparents)||(!esoffsprings)||(!estotal)) { free(esparents); free(esoffsprings); free(estotal); return NLOPT_OUT_OF_MEMORY; } for (id=0; id < np; id++) esparents[id].parameters = NULL; for (id=0; id < no; id++) esoffsprings[id].parameters = NULL; /* From here the population is initialized */ /* we don't handle unbounded search regions; this check is unnecessary since it is performed in nlopt_optimize. for (j = 0; j < nparameters; ++j) if (nlopt_isinf(low[j]) || nlopt_isinf(up[j])) return NLOPT_INVALID_ARGS; */ /* main vector of parameters to randcauchy */ vetor[0] = 4; /* ignored */ vetor[3] = 0; vetor[4] = 1; vetor[5] = 10; vetor[6] = 1; vetor[7] = 0; /* ignored */ /************************************** * Initializing parents population **************************************/ for (id=0; id < np; id++) { esparents[id].parameters = (double*) malloc(sizeof(double) * nparameters); if (!esparents[id].parameters) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (item=0; itemnevals_p); if (*minf > esparents[id].fitness) { *minf = esparents[id].fitness; memcpy(x, esparents[id].parameters, nparameters * sizeof(double)); } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; if (ret != NLOPT_SUCCESS) goto done; } /************************************** * Main Loop - Generations **************************************/ while (1) { /************************************** * Crossover **************************************/ for (id=0; id < no; id++) { parent1 = nlopt_iurand((int) np); parent2 = nlopt_iurand((int) np); crosspoint = (unsigned) nlopt_iurand((int) nparameters); for (item=0; item < crosspoint; item++) esoffsprings[id].parameters[item] = esparents[parent1].parameters[item]; for (item=crosspoint; item < nparameters; item++) esoffsprings[id].parameters[item] = esparents[parent2].parameters[item]; } /************************************** * Gaussian Mutation **************************************/ totalmutation = (int) ((no * nparameters) / 10); if (totalmutation < 1) totalmutation = 1; for (contmutation=0; contmutation < totalmutation; contmutation++) { idoffmutation = nlopt_iurand((int) no); paramoffmutation = nlopt_iurand((int) nparameters); vetor[1] = lb[paramoffmutation]; vetor[2] = ub[paramoffmutation]; vetor[7] = vetor[7]+contmutation; esoffsprings[idoffmutation].parameters[paramoffmutation] = randcauchy(vetor); } /************************************** * Offsprings fitness evaluation **************************************/ for (id=0; id < no; id++){ /*esoffsprings[id].fitness = (double)fitness(esoffsprings[id].parameters, nparameters,fittype);*/ esoffsprings[id].fitness = f(nparameters, esoffsprings[id].parameters, NULL, data_f); estotal[id+np].fitness = esoffsprings[id].fitness; ++ *(stop->nevals_p); if (*minf > esoffsprings[id].fitness) { *minf = esoffsprings[id].fitness; memcpy(x, esoffsprings[id].parameters, nparameters * sizeof(double)); } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; if (ret != NLOPT_SUCCESS) goto done; } /************************************** * Individual selection **************************************/ /* all the individuals are copied to one vector to easily identify best solutions */ for (i=0; i < np; i++) estotal[i] = esparents[i]; for (i=0; i < no; i++) estotal[np+i] = esoffsprings[i]; /* Sorting */ nlopt_qsort_r(estotal, no+np, sizeof(Individual), NULL, CompareIndividuals); /* copy after sorting: */ for (i=0; i < no+np; i++) { if (i #include #include #include "isres.h" /* Improved Stochastic Ranking Evolution Strategy (ISRES) algorithm for nonlinearly-constrained global optimization, based on the method described in: Thomas Philip Runarsson and Xin Yao, "Search biases in constrained evolutionary optimization," IEEE Trans. on Systems, Man, and Cybernetics Part C: Applications and Reviews, vol. 35 (no. 2), pp. 233-243 (2005). It is a refinement of an earlier method described in: Thomas P. Runarsson and Xin Yao, "Stochastic ranking for constrained evolutionary optimization," IEEE Trans. Evolutionary Computation, vol. 4 (no. 3), pp. 284-294 (2000). This is an independent implementation by S. G. Johnson (2009) based on the papers above. Runarsson also has his own Matlab implemention available from his web page: http://www3.hi.is/~tpr */ static int key_compare(void *keys_, const void *a_, const void *b_) { const double *keys = (const double *) keys_; const int *a = (const int *) a_; const int *b = (const int *) b_; return keys[*a] < keys[*b] ? -1 : (keys[*a] > keys[*b] ? +1 : 0); } static unsigned imax2(unsigned a, unsigned b) { return (a > b ? a : b); } nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, /* fc <= 0 */ int p, nlopt_constraint *h, /* h == 0 */ const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int population) /* pop. size (= 0 for default) */ { const double ALPHA = 0.2; /* smoothing factor from paper */ const double GAMMA = 0.85; /* step-reduction factor from paper */ const double PHI = 1.0; /* expected rate of convergence, from paper */ const double PF = 0.45; /* fitness probability, from paper */ const double SURVIVOR = 1.0/7.0; /* survivor fraction, from paper */ int survivors; nlopt_result ret = NLOPT_SUCCESS; double *sigmas = 0, *xs; /* population-by-n arrays (row-major) */ double *fval; /* population array of function vals */ double *penalty; /* population array of penalty vals */ double *x0; int *irank = 0; int k, i, j, c; int mp = m + p; double minf_penalty = HUGE_VAL, minf_gpenalty = HUGE_VAL; double taup, tau; double *results = 0; /* scratch space for mconstraint results */ unsigned ires; *minf = HUGE_VAL; if (!population) population = 20 * (n + 1); if (population < 1) { nlopt_stop_msg(stop, "population %d is too small", population); return NLOPT_INVALID_ARGS; } survivors = (int) ceil(population * SURVIVOR); taup = PHI / sqrt(2*n); tau = PHI / sqrt(2*sqrt(n)); /* we don't handle unbounded search regions */ for (j = 0; j < n; ++j) if (nlopt_isinf(lb[j]) || nlopt_isinf(ub[j])) { nlopt_stop_msg(stop, "isres requires a finite search region"); return NLOPT_INVALID_ARGS; } ires = imax2(nlopt_max_constraint_dim(m, fc), nlopt_max_constraint_dim(p, h)); results = (double *) malloc(ires * sizeof(double)); if (ires > 0 && !results) return NLOPT_OUT_OF_MEMORY; sigmas = (double*) malloc(sizeof(double) * (population*n*2 + population + population + n)); if (!sigmas) { free(results); return NLOPT_OUT_OF_MEMORY; } xs = sigmas + population*n; fval = xs + population*n; penalty = fval + population; x0 = penalty + population; irank = (int*) malloc(sizeof(int) * population); if (!irank) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (k = 0; k < population; ++k) { for (j = 0; j < n; ++j) { sigmas[k*n+j] = (ub[j] - lb[j]) / sqrt(n); xs[k*n+j] = nlopt_urand(lb[j], ub[j]); } } memcpy(xs, x, sizeof(double) * n); /* use input x for xs_0 */ while (1) { /* each loop body = one generation */ int all_feasible = 1; /* evaluate f and constraint violations for whole population */ for (k = 0; k < population; ++k) { int feasible = 1; double gpenalty; ++ *(stop->nevals_p); fval[k] = f(n, xs + k*n, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } penalty[k] = 0; for (c = 0; c < m; ++c) { /* inequality constraints */ nlopt_eval_constraint(results, NULL, fc + c, n, xs + k*n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (ires = 0; ires < fc[c].m; ++ires) { double gval = results[ires]; if (gval > fc[c].tol[ires]) feasible = 0; if (gval < 0) gval = 0; penalty[k] += gval*gval; } } gpenalty = penalty[k]; for (c = m; c < mp; ++c) { /* equality constraints */ nlopt_eval_constraint(results, NULL, h + (c-m), n, xs + k*n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (ires = 0; ires < h[c-m].m; ++ires) { double hval = results[ires]; if (fabs(hval) > h[c-m].tol[ires]) feasible = 0; penalty[k] += hval*hval; } } if (penalty[k] > 0) all_feasible = 0; /* convergence criteria (FIXME: improve?) */ /* FIXME: with equality constraints, how do we decide which solution is the "best" so far? ... need some total order on the solutions? */ if ((penalty[k] <= minf_penalty || feasible) && (fval[k] <= *minf || minf_gpenalty > 0) && ((feasible ? 0 : penalty[k]) != minf_penalty || fval[k] != *minf)) { if (fval[k] < stop->minf_max && feasible) ret = NLOPT_MINF_MAX_REACHED; else if (!nlopt_isinf(*minf)) { if (nlopt_stop_f(stop, fval[k], *minf) && nlopt_stop_f(stop, feasible ? 0 : penalty[k], minf_penalty)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xs+k*n, x)) ret = NLOPT_XTOL_REACHED; } memcpy(x, xs+k*n, sizeof(double)*n); *minf = fval[k]; minf_penalty = feasible ? 0 : penalty[k]; minf_gpenalty = feasible ? 0 : gpenalty; if (ret != NLOPT_SUCCESS) goto done; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; if (ret != NLOPT_SUCCESS) goto done; } /* "selection" step: rank the population */ for (k = 0; k < population; ++k) irank[k] = k; if (all_feasible) /* special case: rank by objective function */ nlopt_qsort_r(irank, population, sizeof(int), fval,key_compare); else { /* Runarsson & Yao's stochastic ranking of the population */ for (i = 0; i < population; ++i) { int swapped = 0; for (j = 0; j < population-1; ++j) { double u = nlopt_urand(0,1); if (u < PF || (penalty[irank[j]] == 0 && penalty[irank[j+1]] == 0)) { if (fval[irank[j]] > fval[irank[j+1]]) { int irankj = irank[j]; irank[j] = irank[j+1]; irank[j+1] = irankj; swapped = 1; } } else if (penalty[irank[j]] > penalty[irank[j+1]]) { int irankj = irank[j]; irank[j] = irank[j+1]; irank[j+1] = irankj; swapped = 1; } } if (!swapped) break; } } /* evolve the population: differential evolution for the best survivors, and standard mutation of the best survivors for the rest: */ for (k = survivors; k < population; ++k) { /* standard mutation */ double taup_rand = taup * nlopt_nrand(0,1); int rk = irank[k], ri; i = k % survivors; ri = irank[i]; for (j = 0; j < n; ++j) { double sigmamax = (ub[j] - lb[j]) / sqrt(n); sigmas[rk*n+j] = sigmas[ri*n+j] * exp(taup_rand + tau*nlopt_nrand(0,1)); if (sigmas[rk*n+j] > sigmamax) sigmas[rk*n+j] = sigmamax; do { xs[rk*n+j] = xs[ri*n+j] + sigmas[rk*n+j] * nlopt_nrand(0,1); } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); sigmas[rk*n+j] = sigmas[ri*n+j] + ALPHA*(sigmas[rk*n+j] - sigmas[ri*n+j]); } } memcpy(x0, xs, n * sizeof(double)); for (k = 0; k < survivors; ++k) { /* differential variation */ double taup_rand = taup * nlopt_nrand(0,1); int rk = irank[k]; for (j = 0; j < n; ++j) { double xi = xs[rk*n+j]; if (k+1 < survivors) xs[rk*n+j] += GAMMA * (x0[j] - xs[(k+1)*n+j]); if (k+1 == survivors || xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]) { /* standard mutation for last survivor and for any survivor components that are now outside the bounds */ double sigmamax = (ub[j] - lb[j]) / sqrt(n); double sigi = sigmas[rk*n+j]; sigmas[rk*n+j] *= exp(taup_rand + tau*nlopt_nrand(0,1)); if (sigmas[rk*n+j] > sigmamax) sigmas[rk*n+j] = sigmamax; do { xs[rk*n+j] = xi + sigmas[rk*n+j] * nlopt_nrand(0,1); } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); sigmas[rk*n+j] = sigi + ALPHA * (sigmas[rk*n+j] - sigi); } } } } done: if (irank) free(irank); if (sigmas) free(sigmas); if (results) free(results); return ret; } nlopt-2.6.1/src/algs/isres/isres.h000066400000000000000000000033051345435414600170260ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef ISRES_H #define ISRES_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, /* fc <= 0 */ int p, nlopt_constraint *h, /* h == 0 */ const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int population); /* init. population */ #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/luksan/000077500000000000000000000000001345435414600156775ustar00rootroot00000000000000nlopt-2.6.1/src/algs/luksan/COPYRIGHT000066400000000000000000000037661345435414600172060ustar00rootroot00000000000000--------------------------------------------------------------------------- Copyright: Subroutines PBUN, PNEW, PVAR, PSEN, Copyright ACM, 2001. The original versions were published in Transactions on Mathematical Software, Vol.27, 2001, pp.193-213. Here are the author's modifications. They are posted here by permission of ACM for your personal use. Not for redistribution. Subroutines PLIP, PSEN, Copyright Jan Vlcek, 2007. The remaining subroutines, Copyright Ladislav Luksan, 2007. Many of sparse matrix modules were prepared by Miroslav Tuma. License: This library (with exception of PBUN, PNEW, PVAR, PSEN) is a free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version (see http://www.gnu.org/copyleft/gpl.html). This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. Permission is hereby granted to use or copy this program under the terms of the GNU LGPL, provided that the Copyright, this License, and the Availability of the original version is retained on all copies. User documentation of any code that uses this code or any modified version of this code must cite the Copyright, this License, the Availability note, and "Used by permission." Permission to modify the code and to distribute modified code is granted, provided the Copyright, this License, and the Availability note are retained, and a notice that the code was modified is included. Availability: http://www.cs.cas.cz/~luksan/subroutines.html Acknowledgements: This work was supported by the Grant Agency of the Czech Academy of Sciences, under grant IAA1030405. nlopt-2.6.1/src/algs/luksan/README000066400000000000000000000021201345435414600165520ustar00rootroot00000000000000These routines for nonlinear optimization are based on the Fortran 77 code placed online by Professor Ladislav Luksan at his web site: http://www.uivt.cas.cz/~luksan/subroutines.html and graciously licensed under the GNU Lesser General Public License (LGPL). See also the COPYRIGHT file for details. The C conversions were done via f2c by S. G. Johnson, with the f2c output manually cleaned up somewhat, and then converted to use the NLopt termination conditions, C dynamic allocation, etc. In particular, we converted the subroutines PLIS, PLIP, and PNET (as well as various auxiliary routines required by this code), all of which solve general nonlinear unconstrained or box-constrained optimization problems. Prof. Luksan also provides a large number of more specialized routines for cases where one has additional knowledge of the objective function, but these cases seem outside the scope of NLopt. [We also did not convert the PMIN, PBUN, PNEW, or PVAR subroutines since these were published in ACM Trans. on Math. Software (TOMS) and are subject to the non-free ACM licensing conditions.] nlopt-2.6.1/src/algs/luksan/luksan.h000066400000000000000000000132521345435414600173500ustar00rootroot00000000000000#ifndef LUKSAN_H #define LUKSAN_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result luksan_plis(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf); nlopt_result luksan_plip(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf, int method); nlopt_result luksan_pnet(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf, int mos1, int mos2); typedef struct { double fl, fu, pl, rl, pu, ru; int mes1, mes2, mes3, mode, mtyp; } ps1l01_state; /***************************** internal routines *************************/ /* mssubs.c: */ void luksan_mxdcmd__(int *n, int *m, double *a, double *x, double *alf, double *y, double *z__); void luksan_mxdrcb__(int *n, int *m, double *a, double *b, double *u, double *v, double *x, int * ix, int *job); void luksan_mxdrcf__(int *n, int *m, double *a, double *b, double *u, double *v, double *x, int * ix, int *job); void luksan_mxdrmm__(int *n, int *m, double *a, double *x, double *y); void luksan_mxdrsu__(int *n, int *m, double *a, double *b, double *u); void luksan_mxucop__(int *n, double *x, double *y, int *ix, int *job); void luksan_mxudir__(int *n, double *a, double *x, double *y, double *z__, int *ix, int *job); void luksan_mxuneg__(int *n, double *x, double *y, int *ix, int *job); void luksan_mxuzer__(int *n, double *x, int *ix, int *job); void luksan_mxvcop__(int *n, double *x, double *y); void luksan_mxvdif__(int *n, double *x, double *y, double *z__); void luksan_mxvneg__(int *n, double *x, double *y); void luksan_mxvscl__(int *n, double *a, double *x, double *y); void luksan_mxvset__(int *n, double *a, double *x); double luksan_mxudot__(int *n, double *x, double *y, int *ix, int *job); double luksan_mxvdot__(int *n, double *x, double *y); void luksan_mxvdir__(int *n, double *a, double *x, double *y, double *z__); void luksan_mxdcmu__(int *n, int *m, double *a, double *alf, double *x, double *y); void luksan_mxvlin__(int *n, double *a, double *x, double *b, double *y, double *z__); void luksan_mxdcmv__(int *n, int *m, double *a, double *alf, double *x, double *u, double *bet, double *y, double *v); void luksan_mxvsav__(int *n, double *x, double *y); void luksan_mxvine__(int *n, int *ix); double luksan_mxvmax__(int *n, double *x); /* pssubs.c: */ void luksan_pcbs04__(int *nf, double *x, int *ix, double *xl, double *xu, double *eps9, int *kbf); void luksan_ps1l01__(double *r__, double *rp, double *f, double *fo, double *fp, double *p, double *po, double *pp, double *minf, double *fmax, double *rmin, double *rmax, double *tols, double * tolp, double *par1, double *par2, int *kd, int *ld, int *nit, int *kit, int *nred, int *mred, int * maxst, int *iest, int *inits, int *iters, int *kters, int *mes, int *isys, ps1l01_state *state); void luksan_pulsp3__(int *n, int *m, int *mf, double *xm, double *gr, double *xo, double *go, double *r__, double *po, double *sig, int *iterh, int *met3); void luksan_pulvp3__(int *n, int *m, double *xm, double *xr, double *gr, double *s, double *so, double *xo, double *go, double *r__, double *po, double *sig, int *iterh, int *met2, int *met3, int *met5); void luksan_pyadc0__(int *nf, int *n, double *x, int *ix, double *xl, double *xu, int *inew); void luksan_pyfut1__(int *n, double *f, double * fo, double *umax, double *gmax, int xstop, const nlopt_stopping *stop, double *tolg, int *kd, int *nit, int *kit, int *mit, int *nfg, int *mfg, int *ntesx, int *mtesx, int *ntesf, int *mtesf, int *ites, int *ires1, int *ires2, int *irest, int *iters, int *iterm); void luksan_pyrmc0__(int *nf, int *n, int *ix, double *g, double *eps8, double *umax, double *gmax, double *rmax, int *iold, int *irest); void luksan_pytrcd__(int *nf, double *x, int *ix, double *xo, double *g, double *go, double *r__, double *f, double *fo, double *p, double *po, double *dmax__, int *kbf, int *kd, int *ld, int * iters); void luksan_pytrcg__(int *nf, int *n, int *ix, double *g, double *umax, double *gmax, int *kbf, int *iold); void luksan_pytrcs__(int *nf, double *x, int *ix, double *xo, double *xl, double *xu, double *g, double *go, double *s, double *ro, double *fp, double *fo, double *f, double *po, double *p, double *rmax, double *eta9, int *kbf); void luksan_pnint1__(double *rl, double *ru, double *fl, double *fu, double *pl, double *pu, double *r__, int *mode, int *mtyp, int *merr); /* Common Block Declarations */ typedef struct { int nres, ndec, nin, nit; /* int nfv; -- now stored in stop->nevals_p */ int nfg, nfh; } stat_common; /* number of double variables that can be stored in scratch memory ... it's >= 2007, and this is in the context of scientific computation, so assume that at least 10M are available, and that sizeof(double)==8 */ #define MEMAVAIL 1310720 #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* LUKSAN_H */ nlopt-2.6.1/src/algs/luksan/mssubs.c000066400000000000000000000563231345435414600173700ustar00rootroot00000000000000#include #include "luksan.h" #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define iabs(a) ((a) < 0 ? -(a) : (a)) /* subroutines extracted from mssubs.for */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* FUNCTION MXVMAX ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* L-INFINITY NORM OF A VECTOR. */ /* PARAMETERS : */ /* II N VECTOR DIMENSION. */ /* RI X(N) INPUT VECTOR. */ /* RR MXVMAX L-INFINITY NORM OF THE VECTOR X. */ double luksan_mxvmax__(int *n, double *x) { /* System generated locals */ int i__1; double d__1, d__2, d__3; /* Local variables */ int i__; double mxvmax; /* Parameter adjustments */ --x; /* Function Body */ mxvmax = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MAX */ d__2 = mxvmax, d__3 = (d__1 = x[i__], fabs(d__1)); mxvmax = MAX2(d__2,d__3); /* L1: */ } return mxvmax; } /* luksan_mxvmax__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVINE ALL SYSTEMS 94/12/01 */ /* PURPOSE : */ /* ELEMENTS OF THE INTEGER VECTOR ARE REPLACED BY THEIR ABSOLUTE VALUES. */ /* PARAMETERS : */ /* II N DIMENSION OF THE INTEGER VECTOR. */ /* IU IX(N) INTEGER VECTOR WHICH IS UPDATED SO THAT IX(I):=ABS(IX(I)) */ /* FOR ALL I. */ void luksan_mxvine__(int *n, int *ix) { /* System generated locals */ int i__1, i__2; /* Local variables */ int i__; /* Parameter adjustments */ --ix; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { ix[i__] = (i__2 = ix[i__], iabs(i__2)); /* L1: */ } return; } /* luksan_mxvine__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDCMV ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* RANK-TWO UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A. */ /* THIS MATRIX IS UPDATED BY THE RULE A:=A+ALF*X*TRANS(U)+BET*Y*TRANS(V). */ /* PARAMETERS : */ /* II N NUMBER OF ROWS OF THE MATRIX A. */ /* II M NUMBER OF COLUMNS OF THE MATRIX A. */ /* RU A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE */ /* ONE-DIMENSIONAL ARRAY. */ /* RI ALF SCALAR PARAMETER. */ /* RI X(N) INPUT VECTOR. */ /* RI U(M) INPUT VECTOR. */ /* RI BET SCALAR PARAMETER. */ /* RI Y(N) INPUT VECTOR. */ /* RI V(M) INPUT VECTOR. */ void luksan_mxdcmv__(int *n, int *m, double *a, double *alf, double *x, double *u, double *bet, double *y, double *v) { /* System generated locals */ int i__1, i__2; /* Local variables */ int i__, j, k; double tempa, tempb; /* Parameter adjustments */ --v; --y; --u; --x; --a; /* Function Body */ k = 0; i__1 = *m; for (j = 1; j <= i__1; ++j) { tempa = *alf * u[j]; tempb = *bet * v[j]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { a[k + i__] = a[k + i__] + tempa * x[i__] + tempb * y[i__]; /* L1: */ } k += *n; /* L2: */ } return; } /* luksan_mxdcmv__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVSAV ALL SYSTEMS 91/12/01 */ /* PORTABILITY : ALL SYSTEMS */ /* 91/12/01 LU : ORIGINAL VERSION */ /* PURPOSE : */ /* DIFFERENCE OF TWO VECTORS RETURNED IN THE SUBSTRACTED ONE. */ /* PARAMETERS : */ /* II N VECTOR DIMENSION. */ /* RI X(N) INPUT VECTOR. */ /* RU Y(N) UPDATE VECTOR WHERE Y:= X - Y. */ void luksan_mxvsav__(int *n, double *x, double *y) { /* System generated locals */ int i__1; /* Local variables */ int i__; double temp; /* Parameter adjustments */ --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = y[i__]; y[i__] = x[i__] - y[i__]; x[i__] = temp; /* L10: */ } return; } /* luksan_mxvsav__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVLIN ALL SYSTEMS 92/12/01 */ /* PURPOSE : */ /* LINEAR COMBINATION OF TWO VECTORS. */ /* PARAMETERS : */ /* II N VECTOR DIMENSION. */ /* RI A SCALING FACTOR. */ /* RI X(N) INPUT VECTOR. */ /* RI B SCALING FACTOR. */ /* RI Y(N) INPUT VECTOR. */ /* RO Z(N) OUTPUT VECTOR WHERE Z:= A*X + B*Y. */ void luksan_mxvlin__(int *n, double *a, double *x, double *b, double *y, double *z__) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --z__; --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = *a * x[i__] + *b * y[i__]; /* L1: */ } return; } /* luksan_mxvlin__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDCMU ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A. THIS MATRIX */ /* IS UPDATED BY THE RULE A:=A+ALF*X*TRANS(Y). */ /* PARAMETERS : */ /* II N NUMBER OF ROWS OF THE MATRIX A. */ /* II M NUMBER OF COLUMNS OF THE MATRIX A. */ /* RU A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE */ /* ONE-DIMENSIONAL ARRAY. */ /* RI ALF SCALAR PARAMETER. */ /* RI X(N) INPUT VECTOR. */ /* RI Y(M) INPUT VECTOR. */ void luksan_mxdcmu__(int *n, int *m, double *a, double *alf, double *x, double *y) { /* System generated locals */ int i__1, i__2; /* Local variables */ int i__, j, k; double temp; /* Parameter adjustments */ --y; --x; --a; /* Function Body */ k = 0; i__1 = *m; for (j = 1; j <= i__1; ++j) { temp = *alf * y[j]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { a[k + i__] += temp * x[i__]; /* L1: */ } k += *n; /* L2: */ } return; } /* luksan_mxdcmu__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVDIR ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* VECTOR AUGMENTED BY THE SCALED VECTOR. */ /* PARAMETERS : */ /* II N VECTOR DIMENSION. */ /* RI A SCALING FACTOR. */ /* RI X(N) INPUT VECTOR. */ /* RI Y(N) INPUT VECTOR. */ /* RO Z(N) OUTPUT VECTOR WHERE Z:= Y + A*X. */ void luksan_mxvdir__(int *n, double *a, double *x, double *y, double *z__) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --z__; --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = y[i__] + *a * x[i__]; /* L10: */ } } /* luksan_mxvdir__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDCMD ALL SYSTEMS 91/12/01 * PURPOSE : * MULTIPLICATION OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A * BY A VECTOR X AND ADDITION OF THE SCALED VECTOR ALF*Y. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II M NUMBER OF COLUMNS OF THE MATRIX A. * RI A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI X(M) INPUT VECTOR. * RI ALF SCALING FACTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR EQUAL TO A*X+ALF*Y. * * SUBPROGRAMS USED : * S MXVDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * S MXVSCL SCALING OF A VECTOR. */ void luksan_mxdcmd__(int *n, int *m, double *a, double *x, double *alf, double *y, double *z__) { /* System generated locals */ int i__1; /* Local variables */ int j, k; /* Parameter adjustments */ --z__; --y; --x; --a; /* Function Body */ luksan_mxvscl__(n, alf, &y[1], &z__[1]); k = 0; i__1 = *m; for (j = 1; j <= i__1; ++j) { luksan_mxvdir__(n, &x[j], &a[k + 1], &z__[1], &z__[1]); k += *n; /* L1: */ } return; } /* luksan_mxdcmd__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDRCB ALL SYSTEMS 91/12/01 * PURPOSE : * BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION OF * THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRICES A AND B. * II M NUMBER OF COLUMNS OF THE MATRICES A AND B. * RI A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI U(M) VECTOR OF SCALAR COEFFICIENTS. * RO V(M) VECTOR OF SCALAR COEFFICIENTS. * RU X(N) PREMULTIPLIED VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * * SUBPROGRAM USED : * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF VECTORS. * * METHOD : * H.MATTHIES, G.STRANG: THE SOLUTION OF NONLINEAR FINITE ELEMENT * EQUATIONS. INT.J.NUMER. METHODS ENGN. 14 (1979) 1613-1626. */ void luksan_mxdrcb__(int *n, int *m, double *a, double *b, double *u, double *v, double *x, int * ix, int *job) { /* System generated locals */ int i__1; double d__1; /* Local variables */ int i__, k; /* Parameter adjustments */ --ix; --x; --v; --u; --b; --a; /* Function Body */ k = 1; i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { v[i__] = u[i__] * luksan_mxudot__(n, &x[1], &a[k], &ix[1], job); d__1 = -v[i__]; luksan_mxudir__(n, &d__1, &b[k], &x[1], &x[1], &ix[1], job); k += *n; /* L1: */ } return; } /* luksan_mxdrcb__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDRCF ALL SYSTEMS 91/12/01 * PURPOSE : * FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION OF * THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRICES A AND B. * II M NUMBER OF COLUMNS OF THE MATRICES A AND B. * RI A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI U(M) VECTOR OF SCALAR COEFFICIENTS. * RI V(M) VECTOR OF SCALAR COEFFICIENTS. * RU X(N) PREMULTIPLIED VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * * SUBPROGRAM USED : * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF VECTORS. * * METHOD : * H.MATTHIES, G.STRANG: THE SOLUTION OF NONLINEAR FINITE ELEMENT * EQUATIONS. INT.J.NUMER. METHODS ENGN. 14 (1979) 1613-1626. */ void luksan_mxdrcf__(int *n, int *m, double *a, double *b, double *u, double *v, double *x, int * ix, int *job) { /* System generated locals */ double d__1; /* Local variables */ int i__, k; double temp; /* Parameter adjustments */ --ix; --x; --v; --u; --b; --a; /* Function Body */ k = (*m - 1) * *n + 1; for (i__ = *m; i__ >= 1; --i__) { temp = u[i__] * luksan_mxudot__(n, &x[1], &b[k], &ix[1], job); d__1 = v[i__] - temp; luksan_mxudir__(n, &d__1, &a[k], &x[1], &x[1], &ix[1], job); k -= *n; /* L1: */ } return; } /* luksan_mxdrcf__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDRMM ALL SYSTEMS 91/12/01 * PURPOSE : * MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR MATRIX A BY * A VECTOR X. * * PARAMETERS : * II N NUMBER OF COLUMNS OF THE MATRIX A. * II M NUMBER OF ROWS OF THE MATRIX A. * RI A(M*N) RECTANGULAR MATRIX STORED ROWWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI X(N) INPUT VECTOR. * RO Y(M) OUTPUT VECTOR EQUAL TO A*X. */ void luksan_mxdrmm__(int *n, int *m, double *a, double *x, double *y) { /* System generated locals */ int i__1, i__2; /* Local variables */ int i__, j, k; double temp; /* Parameter adjustments */ --y; --x; --a; /* Function Body */ k = 0; i__1 = *m; for (j = 1; j <= i__1; ++j) { temp = 0.; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { temp += a[k + i__] * x[i__]; /* L1: */ } y[j] = temp; k += *n; /* L2: */ } return; } /* luksan_mxdrmm__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXDRSU ALL SYSTEMS 91/12/01 * PURPOSE : * SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. SHIFT OF * ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN THE LIMITED * MEMORY BFGS METHOD. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A AND B. * II M NUMBER OF COLUMNS OF THE MATRIX A AND B. * RU A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RU B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RU U(M) VECTOR. */ void luksan_mxdrsu__(int *n, int *m, double *a, double *b, double *u) { int i__, k, l; /* Parameter adjustments */ --u; --b; --a; /* Function Body */ k = (*m - 1) * *n + 1; for (i__ = *m - 1; i__ >= 1; --i__) { l = k - *n; luksan_mxvcop__(n, &a[l], &a[k]); luksan_mxvcop__(n, &b[l], &b[k]); u[i__ + 1] = u[i__]; k = l; /* L1: */ } return; } /* luksan_mxdrsu__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXUCOP ALL SYSTEMS 99/12/01 * PURPOSE : * COPY OF THE VECTOR WITH INITIATION OF THE ACTIVE PART. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. */ void luksan_mxucop__(int *n, double *x, double *y, int *ix, int *job) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --ix; --y; --x; /* Function Body */ if (*job == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = x[i__]; /* L1: */ } } else if (*job > 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] >= 0) { y[i__] = x[i__]; } else { y[i__] = 0.; } /* L2: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] != -5) { y[i__] = x[i__]; } else { y[i__] = 0.; } /* L3: */ } } return; } /* luksan_mxucop__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXUDIR ALL SYSTEMS 99/12/01 * PURPOSE : * VECTOR AUGMENTED BY THE SCALED VECTOR IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A SCALING FACTOR. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= Y + A*X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. */ void luksan_mxudir__(int *n, double *a, double *x, double *y, double *z__, int *ix, int *job) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --ix; --z__; --y; --x; /* Function Body */ if (*job == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = y[i__] + *a * x[i__]; /* L1: */ } } else if (*job > 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] >= 0) { z__[i__] = y[i__] + *a * x[i__]; } /* L2: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] != -5) { z__[i__] = y[i__] + *a * x[i__]; } /* L3: */ } } return; } /* luksan_mxudir__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* FUNCTION MXVDOT ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* DOT PRODUCT OF TWO VECTORS. */ /* PARAMETERS : */ /* II N VECTOR DIMENSION. */ /* RI X(N) INPUT VECTOR. */ /* RI Y(N) INPUT VECTOR. */ /* RR MXVDOT VALUE OF DOT PRODUCT MXVDOT=TRANS(X)*Y. */ double luksan_mxvdot__(int *n, double *x, double *y) { /* System generated locals */ int i__1; /* Local variables */ int i__; double temp; /* Parameter adjustments */ --y; --x; /* Function Body */ temp = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp += x[i__] * y[i__]; /* L10: */ } return temp; } /* luksan_mxvdot__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* FUNCTION MXUDOT ALL SYSTEMS 99/12/01 * PURPOSE : * DOT PRODUCT OF VECTORS IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * RR MXUDOT VALUE OF DOT PRODUCT MXUDOT=TRANS(X)*Y. */ double luksan_mxudot__(int *n, double *x, double *y, int *ix, int *job) { /* System generated locals */ int i__1; /* Local variables */ int i__; double temp; /* Parameter adjustments */ --ix; --y; --x; /* Function Body */ temp = 0.; if (*job == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp += x[i__] * y[i__]; /* L1: */ } } else if (*job > 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] >= 0) { temp += x[i__] * y[i__]; } /* L2: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] != -5) { temp += x[i__] * y[i__]; } /* L3: */ } } return temp; } /* luksan_mxudot__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXUNEG ALL SYSTEMS 00/12/01 * PURPOSE : * COPY OF THE VECTOR WITH INITIATION OF THE ACTIVE PART. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. */ void luksan_mxuneg__(int *n, double *x, double *y, int *ix, int *job) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --ix; --y; --x; /* Function Body */ if (*job == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = -x[i__]; /* L1: */ } } else if (*job > 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] >= 0) { y[i__] = -x[i__]; } else { y[i__] = 0.; } /* L2: */ } } else { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] != -5) { y[i__] = -x[i__]; } else { y[i__] = 0.; } /* L3: */ } } return; } /* luksan_mxuneg__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXUZER ALL SYSTEMS 99/12/01 * PURPOSE : * VECTOR ELEMENTS CORRESPONDING TO ACTIVE BOUNDS ARE SET TO ZERO. * * PARAMETERS : * II N VECTOR DIMENSION. * RO X(N) OUTPUT VECTOR SUCH THAT X(I)=A FOR ALL I. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. */ void luksan_mxuzer__(int *n, double *x, int *ix, int *job) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --ix; --x; /* Function Body */ if (*job == 0) { return; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] < 0) { x[i__] = 0.; } /* L1: */ } return; } /* luksan_mxuzer__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVCOP ALL SYSTEMS 88/12/01 * PURPOSE : * COPYING OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. */ void luksan_mxvcop__(int *n, double *x, double *y) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = x[i__]; /* L10: */ } return; } /* luksan_mxvcop__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVDIF ALL SYSTEMS 88/12/01 * PURPOSE : * VECTOR DIFFERENCE. * * PARAMETERS : * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= X - Y. */ void luksan_mxvdif__(int *n, double *x, double *y, double *z__) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --z__; --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = x[i__] - y[i__]; /* L10: */ } return; } /* luksan_mxvdif__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVNEG ALL SYSTEMS 88/12/01 * PURPOSE : * CHANGE THE SIGNS OF VECTOR ELEMENTS. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= - X. */ void luksan_mxvneg__(int *n, double *x, double *y) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = -x[i__]; /* L10: */ } return; } /* luksan_mxvneg__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVSCL ALL SYSTEMS 88/12/01 * PURPOSE : * SCALING OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI A SCALING FACTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= A*X. */ void luksan_mxvscl__(int *n, double *a, double *x, double *y) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --y; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { y[i__] = *a * x[i__]; /* L1: */ } return; } /* luksan_mxvscl__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE MXVSET ALL SYSTEMS 88/12/01 * PURPOSE : * A SCALAR IS SET TO ALL THE ELEMENTS OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A INITIAL VALUE. * RO X(N) OUTPUT VECTOR SUCH THAT X(I)=A FOR ALL I. */ void luksan_mxvset__(int *n, double *a, double *x) { /* System generated locals */ int i__1; /* Local variables */ int i__; /* Parameter adjustments */ --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { x[i__] = *a; /* L10: */ } return; } /* luksan_mxvset__ */ nlopt-2.6.1/src/algs/luksan/mssubs.for000066400000000000000000003323031345435414600177270ustar00rootroot00000000000000* SUBROUTINE MXBSBM ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF A BLOCKED SYMMETRIC MATRIX A BY A VECTOR X. * * PARAMETERS : * PARAMETERS : * II L BLOCK DIMENSION. * RI ABL(L*(L+1)/2) VALUES OF NONZERO ELEMENTS OF THE GIVEN BLOCK. * II JBL(L) INDICES OF THE INDIVIDUAL BLOCKS * RI X(N) UNPACKED INPUT VECTOR. * RI Y(N) UNPACKED OR PACKED OUTPUT VECTOR EQUAL TO A*X. * II JOB FORM OF THE VECTOR Y. JOB=1-UNPACKED FORM. JOB=2-PACKED * FORM. * SUBROUTINE MXBSBM(L,ABL,JBL,X,Y,JOB) INTEGER L,JBL(*),JOB DOUBLE PRECISION ABL(*),X(*),Y(*) INTEGER I,J,IP,JP,K DOUBLE PRECISION TEMP DOUBLE PRECISION ZERO PARAMETER (ZERO = 0.0D 0) DO 1 I=1,L IP=JBL(I) IF (IP.GT.0) THEN IF (JOB.EQ.1) THEN Y(IP)=ZERO ELSE Y(I)=ZERO END IF END IF 1 CONTINUE K=0 DO 4 I=1,L IP=JBL(I) IF (IP.GT.0) TEMP=X(IP) IF (JOB.EQ.1) THEN DO 2 J=1,I-1 JP=JBL(J) K=K+1 IF (IP.GT.0.AND.JP.GT.0) THEN Y(IP)=Y(IP)+ABL(K)*X(JP) Y(JP)=Y(JP)+ABL(K)*TEMP END IF 2 CONTINUE K=K+1 IF (IP.GT.0) Y(IP)=Y(IP)+ABL(K)*TEMP ELSE DO 3 J=1,I-1 JP=JBL(J) K=K+1 IF (IP.GT.0.AND.JP.GT.0) THEN Y(I)=Y(I)+ABL(K)*X(JP) Y(J)=Y(J)+ABL(K)*TEMP END IF 3 CONTINUE K=K+1 IF (IP.GT.0) Y(I)=Y(I)+ABL(K)*TEMP END IF 4 CONTINUE RETURN END * SUBROUTINE MXBSBU ALL SYSTEMS 92/12/01 * PURPOSE : * CORRECTION OF A BLOCKED SYMMETRIC MATRIX A. THE CORRECTION IS DEFINED * AS A:=A+ALF*X*TRANS(X) WHERE ALF IS A GIVEN SCALING FACTOR AND X IS * A GIVEN VECTOR. * * PARAMETERS : * II L BLOCK DIMENSION. * RI ABL(L*(L+1)/2) VALUES OF NONZERO ELEMENTS OF THE GIVEN BLOCK. * II JBL(L) INDICES OF THE INDIVIDUAL BLOCKS * RI ALF SCALING FACTOR. * RI X(N) UNPACKED OR PACKED INPUT VECTOR. * II JOB FORM OF THE VECTOR X. JOB=1-UNPACKED FORM. JOB=2-PACKED * FORM. * SUBROUTINE MXBSBU(L,ABL,JBL,ALF,X,JOB) INTEGER L,JBL(*),JOB DOUBLE PRECISION ABL(*),ALF,X(*) INTEGER I,J,IP,JP,K K=0 IF (JOB.EQ.1) THEN DO 3 I=1,L IP=JBL(I) DO 2 J=1,I JP=JBL(J) K=K+1 IF (IP.GT.0.AND.JP.GT.0) THEN ABL(K)=ABL(K)+ALF*X(IP)*X(JP) END IF 2 CONTINUE 3 CONTINUE ELSE DO 5 I=1,L IP=JBL(I) DO 4 J=1,I JP=JBL(J) K=K+1 IF (IP.GT.0.AND.JP.GT.0) THEN ABL(K)=ABL(K)+ALF*X(I)*X(J) END IF 4 CONTINUE 5 CONTINUE END IF RETURN END * SUBROUTINE MXBSMI ALL SYSTEMS 91/12/01 * PURPOSE : * BLOCKS OF THE SYMMETRIC BLOCKED MATRIX ARE SET TO THE UNIT MATRICES. * * PARAMETERS : * II NBLKS NUMBER OF BLOCKS OF THE MATRIX. * RI ABL(NBLA) VALUES OF THE NONZERO ELEMENTS OF THE MATRIX. * II IBLBG(NBLKS+1) BEGINNINGS OF THE BLOCKS IN THE MATRIX. * * SUBROUTINES USED : * MXDSMI DENSE SYMMETRIC MATRIX IS SET TO THE UNIT MATRIX. * SUBROUTINE MXBSMI(NBLKS,ABL,IBLBG) INTEGER NBLKS,IBLBG(*) DOUBLE PRECISION ABL(*) INTEGER I,K,KBEG,KLEN K=1 DO 1 I=1,NBLKS KBEG=IBLBG(I) KLEN=IBLBG(I+1)-KBEG CALL MXDSMI(KLEN,ABL(K)) K=K+KLEN*(KLEN+1)/2 1 CONTINUE RETURN END * SUBROUTINE MXDCMD ALL SYSTEMS 91/12/01 * PURPOSE : * MULTIPLICATION OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A * BY A VECTOR X AND ADDITION OF THE SCALED VECTOR ALF*Y. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II M NUMBER OF COLUMNS OF THE MATRIX A. * RI A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI X(M) INPUT VECTOR. * RI ALF SCALING FACTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR EQUAL TO A*X+ALF*Y. * * SUBPROGRAMS USED : * S MXVDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * S MXVSCL SCALING OF A VECTOR. * SUBROUTINE MXDCMD(N,M,A,X,ALF,Y,Z) INTEGER N,M DOUBLE PRECISION A(*),X(*),ALF,Y(*),Z(*) INTEGER J,K CALL MXVSCL(N,ALF,Y,Z) K=0 DO 1 J=1,M CALL MXVDIR(N,X(J),A(K+1),Z,Z) K=K+N 1 CONTINUE RETURN END * SUBROUTINE MXDCMU ALL SYSTEMS 91/12/01 * PURPOSE : * UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A. THIS MATRIX * IS UPDATED BY THE RULE A:=A+ALF*X*TRANS(Y). * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II M NUMBER OF COLUMNS OF THE MATRIX A. * RU A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI ALF SCALAR PARAMETER. * RI X(N) INPUT VECTOR. * RI Y(M) INPUT VECTOR. * SUBROUTINE MXDCMU(N,M,A,ALF,X,Y) INTEGER N,M DOUBLE PRECISION A(*),ALF,X(*),Y(*) DOUBLE PRECISION TEMP INTEGER I,J,K K=0 DO 2 J=1,M TEMP=ALF*Y(J) DO 1 I=1,N A(K+I)=A(K+I)+TEMP*X(I) 1 CONTINUE K=K+N 2 CONTINUE RETURN END * SUBROUTINE MXDCMV ALL SYSTEMS 91/12/01 * PURPOSE : * RANK-TWO UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX A. * THIS MATRIX IS UPDATED BY THE RULE A:=A+ALF*X*TRANS(U)+BET*Y*TRANS(V). * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II M NUMBER OF COLUMNS OF THE MATRIX A. * RU A(N*M) RECTANGULAR MATRIX STORED COLUMNWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI ALF SCALAR PARAMETER. * RI X(N) INPUT VECTOR. * RI U(M) INPUT VECTOR. * RI BET SCALAR PARAMETER. * RI Y(N) INPUT VECTOR. * RI V(M) INPUT VECTOR. * SUBROUTINE MXDCMV(N,M,A,ALF,X,U,BET,Y,V) INTEGER N,M DOUBLE PRECISION A(*),ALF,X(*),U(*),BET,Y(*),V(*) DOUBLE PRECISION TEMPA,TEMPB INTEGER I,J,K K=0 DO 2 J=1,M TEMPA=ALF*U(J) TEMPB=BET*V(J) DO 1 I=1,N A(K+I)=A(K+I)+TEMPA*X(I)+TEMPB*Y(I) 1 CONTINUE K=K+N 2 CONTINUE RETURN END * SUBROUTINE MXDPGB ALL SYSTEMS 91/12/01 * PURPOSE : * SOLUTION OF A SYSTEM OF LINEAR EQUATIONS WITH A DENSE SYMMETRIC * POSITIVE DEFINITE MATRIX A+E USING THE FACTORIZATION A+E=L*D*TRANS(L) * OBTAINED BY THE SUBROUTINE MXDPGF. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(N*(N+1)/2) FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXDPGF. * RU X(N) ON INPUT THE RIGHT HAND SIDE OF A SYSTEM OF LINEAR * EQUATIONS. ON OUTPUT THE SOLUTION OF A SYSTEM OF LINEAR * EQUATIONS. * II JOB OPTION. IF JOB=0 THEN X:=(A+E)**(-1)*X. IF JOB>0 THEN * X:=L**(-1)*X. IF JOB<0 THEN X:=TRANS(L)**(-1)*X. * * METHOD : * BACK SUBSTITUTION * SUBROUTINE MXDPGB(N,A,X,JOB) INTEGER JOB,N DOUBLE PRECISION A(*),X(*) INTEGER I,II,IJ,J IF (JOB.GE.0) THEN * * PHASE 1 : X:=L**(-1)*X * IJ = 0 DO 20 I = 1,N DO 10 J = 1,I - 1 IJ = IJ + 1 X(I) = X(I) - A(IJ)*X(J) 10 CONTINUE IJ = IJ + 1 20 CONTINUE END IF IF (JOB.EQ.0) THEN * * PHASE 2 : X:=D**(-1)*X * II = 0 DO 30 I = 1,N II = II + I X(I) = X(I)/A(II) 30 CONTINUE END IF IF (JOB.LE.0) THEN * * PHASE 3 : X:=TRANS(L)**(-1)*X * II = N* (N-1)/2 DO 50 I = N - 1,1,-1 IJ = II DO 40 J = I + 1,N IJ = IJ + J - 1 X(I) = X(I) - A(IJ)*X(J) 40 CONTINUE II = II - I 50 CONTINUE END IF RETURN END * SUBROUTINE MXDPGF ALL SYSTEMS 89/12/01 * PURPOSE : * FACTORIZATION A+E=L*D*TRANS(L) OF A DENSE SYMMETRIC POSITIVE DEFINITE * MATRIX A+E WHERE D AND E ARE DIAGONAL POSITIVE DEFINITE MATRICES AND * L IS A LOWER TRIANGULAR MATRIX. IF A IS SUFFICIENTLY POSITIVE * DEFINITE THEN E=0. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RU A(N*(N+1)/2) ON INPUT A GIVEN DENSE SYMMETRIC (USUALLY POSITIVE * DEFINITE) MATRIX A STORED IN THE PACKED FORM. ON OUTPUT THE * COMPUTED FACTORIZATION A+E=L*D*TRANS(L). * IO INF AN INFORMATION OBTAINED IN THE FACTORIZATION PROCESS. IF * INF=0 THEN A IS SUFFICIENTLY POSITIVE DEFINITE AND E=0. IF * INF<0 THEN A IS NOT SUFFICIENTLY POSITIVE DEFINITE AND E>0. IF * INF>0 THEN A IS INDEFINITE AND INF IS AN INDEX OF THE * MOST NEGATIVE DIAGONAL ELEMENT USED IN THE FACTORIZATION * PROCESS. * RU ALF ON INPUT A DESIRED TOLERANCE FOR POSITIVE DEFINITENESS. ON * OUTPUT THE MOST NEGATIVE DIAGONAL ELEMENT USED IN THE * FACTORIZATION PROCESS (IF INF>0). * RO TAU MAXIMUM DIAGONAL ELEMENT OF THE MATRIX E. * * METHOD : * P.E.GILL, W.MURRAY : NEWTON TYPE METHODS FOR UNCONSTRAINED AND * LINEARLY CONSTRAINED OPTIMIZATION, MATH. PROGRAMMING 28 (1974) * PP. 311-350. * SUBROUTINE MXDPGF(N,A,INF,ALF,TAU) DOUBLE PRECISION ALF,TAU INTEGER INF,N DOUBLE PRECISION A(*) DOUBLE PRECISION BET,DEL,GAM,RHO,SIG,TOL INTEGER I,IJ,IK,J,K,KJ,KK,L L = 0 INF = 0 TOL = ALF * * ESTIMATION OF THE MATRIX NORM * ALF = 0.0D0 BET = 0.0D0 GAM = 0.0D0 TAU = 0.0D0 KK = 0 DO 20 K = 1,N KK = KK + K BET = MAX(BET,ABS(A(KK))) KJ = KK DO 10 J = K + 1,N KJ = KJ + J - 1 GAM = MAX(GAM,ABS(A(KJ))) 10 CONTINUE 20 CONTINUE BET = MAX(TOL,BET,GAM/N) * DEL = TOL*BET DEL = TOL*MAX(BET,1.0D0) KK = 0 DO 60 K = 1,N KK = KK + K * * DETERMINATION OF A DIAGONAL CORRECTION * SIG = A(KK) IF (ALF.GT.SIG) THEN ALF = SIG L = K END IF GAM = 0.0D0 KJ = KK DO 30 J = K + 1,N KJ = KJ + J - 1 GAM = MAX(GAM,ABS(A(KJ))) 30 CONTINUE GAM = GAM*GAM RHO = MAX(ABS(SIG),GAM/BET,DEL) IF (TAU.LT.RHO-SIG) THEN TAU = RHO - SIG INF = -1 END IF * * GAUSSIAN ELIMINATION * A(KK) = RHO KJ = KK DO 50 J = K + 1,N KJ = KJ + J - 1 GAM = A(KJ) A(KJ) = GAM/RHO IK = KK IJ = KJ DO 40 I = K + 1,J IK = IK + I - 1 IJ = IJ + 1 A(IJ) = A(IJ) - A(IK)*GAM 40 CONTINUE 50 CONTINUE 60 CONTINUE IF (L.GT.0 .AND. ABS(ALF).GT.DEL) INF = L RETURN END * SUBROUTINE MXDRMM ALL SYSTEMS 91/12/01 * PURPOSE : * MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR MATRIX A BY * A VECTOR X. * * PARAMETERS : * II N NUMBER OF COLUMNS OF THE MATRIX A. * II M NUMBER OF ROWS OF THE MATRIX A. * RI A(M*N) RECTANGULAR MATRIX STORED ROWWISE IN THE * ONE-DIMENSIONAL ARRAY. * RI X(N) INPUT VECTOR. * RO Y(M) OUTPUT VECTOR EQUAL TO A*X. * SUBROUTINE MXDRMM(N,M,A,X,Y) INTEGER N,M DOUBLE PRECISION A(*),X(*),Y(*) DOUBLE PRECISION TEMP INTEGER I,J,K DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D 0) K=0 DO 2 J=1,M TEMP=ZERO DO 1 I=1,N TEMP=TEMP+A(K+I)*X(I) 1 CONTINUE Y(J)=TEMP K=K+N 2 CONTINUE RETURN END * SUBROUTINE MXDRCB ALL SYSTEMS 91/12/01 * PURPOSE : * BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION OF * THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRICES A AND B. * II M NUMBER OF COLUMNS OF THE MATRICES A AND B. * RI A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI U(M) VECTOR OF SCALAR COEFFICIENTS. * RO V(M) VECTOR OF SCALAR COEFFICIENTS. * RU X(N) PREMULTIPLIED VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * * SUBPROGRAM USED : * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF VECTORS. * * METHOD : * H.MATTHIES, G.STRANG: THE SOLUTION OF NONLINEAR FINITE ELEMENT * EQUATIONS. INT.J.NUMER. METHODS ENGN. 14 (1979) 1613-1626. * SUBROUTINE MXDRCB(N,M,A,B,U,V,X,IX,JOB) INTEGER N,M,IX(*),JOB DOUBLE PRECISION A(*),B(*),U(*),V(*),X(*) DOUBLE PRECISION MXUDOT INTEGER I,K K=1 DO 1 I=1,M V(I)=U(I)*MXUDOT(N,X,A(K),IX,JOB) CALL MXUDIR(N,-V(I),B(K),X,X,IX,JOB) K=K+N 1 CONTINUE RETURN END * SUBROUTINE MXDRCF ALL SYSTEMS 91/12/01 * PURPOSE : * FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION OF * THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRICES A AND B. * II M NUMBER OF COLUMNS OF THE MATRICES A AND B. * RI A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RI U(M) VECTOR OF SCALAR COEFFICIENTS. * RI V(M) VECTOR OF SCALAR COEFFICIENTS. * RU X(N) PREMULTIPLIED VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * * SUBPROGRAM USED : * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF VECTORS. * * METHOD : * H.MATTHIES, G.STRANG: THE SOLUTION OF NONLINEAR FINITE ELEMENT * EQUATIONS. INT.J.NUMER. METHODS ENGN. 14 (1979) 1613-1626. * SUBROUTINE MXDRCF(N,M,A,B,U,V,X,IX,JOB) INTEGER N,M,IX(*),JOB DOUBLE PRECISION A(*),B(*),U(*),V(*),X(*) DOUBLE PRECISION TEMP,MXUDOT INTEGER I,K K=(M-1)*N+1 DO 1 I=M,1,-1 TEMP=U(I)*MXUDOT(N,X,B(K),IX,JOB) CALL MXUDIR(N,V(I)-TEMP,A(K),X,X,IX,JOB) K=K-N 1 CONTINUE RETURN END * SUBROUTINE MXDRSU ALL SYSTEMS 91/12/01 * PURPOSE : * SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. SHIFT OF * ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN THE LIMITED * MEMORY BFGS METHOD. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A AND B. * II M NUMBER OF COLUMNS OF THE MATRIX A AND B. * RU A(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RU B(N*M) RECTANGULAR MATRIX STORED AS A ONE-DIMENSIONAL ARRAY. * RU U(M) VECTOR. * SUBROUTINE MXDRSU(N,M,A,B,U) INTEGER N,M DOUBLE PRECISION A(*),B(*),U(*) INTEGER I,K,L K=(M-1)*N+1 DO 1 I=M-1,1,-1 L=K-N CALL MXVCOP(N,A(L),A(K)) CALL MXVCOP(N,B(L),B(K)) U(I+1)=U(I) K=L 1 CONTINUE RETURN END * SUBROUTINE MXDSMI ALL SYSTEMS 88/12/01 * PURPOSE : * DENSE SYMMETRIC MATRIX A IS SET TO THE UNIT MATRIX WITH THE SAME * ORDER. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RO A(N*(N+1)/2) DENSE SYMMETRIC MATRIX STORED IN THE PACKED FORM * WHICH IS SET TO THE UNIT MATRIX (I.E. A:=I). * SUBROUTINE MXDSMI(N,A) INTEGER N DOUBLE PRECISION A(*) INTEGER I, M DOUBLE PRECISION ZERO,ONE PARAMETER (ZERO=0.0D 0,ONE=1.0D 0) M = N * (N+1) / 2 DO 1 I = 1, M A(I) = ZERO 1 CONTINUE M = 0 DO 2 I = 1, N M = M + I A(M) = ONE 2 CONTINUE RETURN END * SUBROUTINE MXDSMS ALL SYSTEMS 91/12/01 * PURPOSE : * SCALING OF A DENSE SYMMETRIC MATRIX. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RU A(N*(N+1)/2) DENSE SYMMETRIC MATRIX STORED IN THE PACKED FORM * WHICH IS SCALED BY THE VALUE ALF (I.E. A:=ALF*A). * RI ALF SCALING FACTOR. * SUBROUTINE MXDSMS( N, A, ALF) INTEGER N DOUBLE PRECISION A(*), ALF INTEGER I,M M = N * (N+1) / 2 DO 1 I = 1, M A(I) = A(I) * ALF 1 CONTINUE RETURN END * SUBROUTINE MXLIIM ALL SYSTEMS 96/12/01 * PURPOSE : * MATRIX MULTIPLICATION FOR LIMITED STORAGE INVERSE COLUMN UPDATE * METHOD. * * PARAMETERS : * II N NUMBER OF VARIABLES. * II M NUMBER OF QUASI-NEWTON STEPS. * RI D(N) DIAGONAL OF A DECOMPOSED TRIDIAGONAL MATRIX. * RI DL(N) SUBDIAGONAL OF A DECOMPOSED TRIDIAGONAL MATRIX. * RI DU(N) SUPERDIAGONAL OF A DECOMPOSED TRIDIAGONAL MATRIX. * RI DU2(N) SECOND SUPERDIAGONAL OF A DECOMPOSED TRIDIAGONAL MATRIX. * II ID(N) PERMUTATION VECTOR. * RI XM(N*M) SET OF VECTORS FOR INVERSE COLUMN UPDATE. * RI GM(M) SET OF VALUES FOR INVERSE COLUMN UPDATE. * II IM(M) SET OF INDICES FOR INVERSE COLUMN UPDATE. * RI U(N) INPUT VECTOR. * RO V(N) OUTPUT VECTOR. * * SUBPROGRAMS USED : * S MXSGIB BACK SUBSTITUTION AFTER INCOMPLETE LU DECOMPOSITION. * S MXVCOP COPYING OF A VECTOR. * S MXVDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * SUBROUTINE MXLIIM(N,M,A,IA,JA,IP,ID,XM,GM,IM,U,V,S) INTEGER M,N DOUBLE PRECISION A(*),GM(*),S(*),U(*),V(*),XM(*) INTEGER IA(*),ID(*),IM(*),IP(*),JA(*) INTEGER I,L CALL MXVCOP(N,U,V) CALL MXSGIB(N,A,IA,JA,IP,ID,V,S,0) L = 1 DO 10 I = 1,M CALL MXVDIR(N,U(IM(I))/GM(I),XM(L),V,V) L = L + N 10 CONTINUE RETURN END * SUBROUTINE MXSCMD ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF A DENSE RECTANGULAR MATRIX A BY A VECTOR X AND * ADDITIOON OF THE SCALED VECTOR ALF*Y. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II NA NUMBER OF COLUMNS OF THE MATRIX A. * II MA NUMBER OF ELEMENTS IN THE FIELD A. * RI A(MA) RECTANGULAR MATRIX STORED AS A TWO-DIMENSIONAL ARRAY. * II IA(NA+1) POSITION OF THE FIRST RORWS ELEMENTS IN THE FIELD A. * II JA(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD A. * RI X(NA) INPUT VECTOR. * RI ALF SCALING FACTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR EQUAL TO A*X+ALF*Y. * * SUBPROGRAMS USED : * S MXVSCL SCALING OF A VECTOR. * SUBROUTINE MXSCMD(N,NA,A,IA,JA,X,ALF,Y,Z) INTEGER N,NA,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),ALF,Y(*),Z(*) INTEGER I,J,K,L,JP CALL MXVSCL(N,ALF,Y,Z) DO 2 I=1,NA K=IA(I) L=IA(I+1)-K DO 1 J=1,L JP=JA(K) IF (JP.GT.0) Z(JP)=Z(JP)+A(K)*X(I) K=K+1 1 CONTINUE 2 CONTINUE RETURN END * SUBROUTINE MXSCMM ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF A DENSE RECTANGULAR MATRIX A BY A VECTOR X. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II NA NUMBER OF COLUMNS OF THE MATRIX A. * II MA NUMBER OF ELEMENTS IN THE FIELD A. * RI A(MA) RECTANGULAR MATRIX STORED AS A TWO-DIMENSIONAL ARRAY. * II IA(NA+1) POSITION OF THE FIRST RORWS ELEMENTS IN THE FIELD A. * II JA(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD A. * RI X(NA) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR EQUAL TO A*X. * * SUBPROGRAMS USED : * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE MXSCMM(N,NA,A,IA,JA,X,Y) INTEGER N,NA,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),Y(*) INTEGER I,J,K,L,JP CALL MXVSET(N,0.0D 0,Y) DO 2 I=1,NA K=IA(I) L=IA(I+1)-K DO 1 J=1,L JP=JA(K) IF (JP.GT.0) Y(JP)=Y(JP)+A(K)*X(I) K=K+1 1 CONTINUE 2 CONTINUE RETURN END * SUBROUTINE MXSGIB ALL SYSTEMS 95/12/01 * PURPOSE : * SOLUTION OF A SYSTEM OF LINEAR EQUATIONS WITH A SPARSE UNSYMMETRIC * MATRIX A USING INCOMPLETE FACTORIZATION OBTAINED BY THE SUBROUTINE * MXSGIF. * * PARAMETERS : * II N MATRIX DIMENSION. * II M NUMBER OF MATRIX NONZERO ELEMENTS. * RU A(M) NONZERO ELEMENTS OF THE MATRIX A. * II IA(N+1) ROW POINTERS OF THE MATRIX A. * II JA(M) COLUMN INDICES OF THE MATRIX A. * IO IP(N) PERMUTATION VECTOR. * II ID(N) DIAGONAL POINTERS OF THE MATRIX A. * RU X(N) ON INPUT THE RIGHT HAND SIDE OF A SYSTEM OF LINEAR * EQUATIONS. ON OUTPUT THE SOLUTION OF A SYSTEM OF LINEAR * EQUATIONS. * RA Y(N) AUXILIARY VECTOR. * JOB OPTION. JOB=0 - SOLUTION WITH THE ORIGINAL MATRIX. * JOB=1 - SOLUTION WITH THE MATRIX TRANSPOSE. * SUBROUTINE MXSGIB(N,A,IA,JA,IP,ID,X,Y,JOB) DOUBLE PRECISION CON PARAMETER (CON=1.0D120) INTEGER JOB,N DOUBLE PRECISION A(*),X(*),Y(*) INTEGER IA(*),ID(*),IP(*),JA(*) DOUBLE PRECISION APOM INTEGER J,JJ,JP,K,KSTOP,KSTRT IF (JOB.LE.0) THEN DO 20 K = 1,N KSTRT = IA(K) KSTOP = IA(K+1) - 1 DO 10 JJ = KSTRT,KSTOP J = JA(JJ) JP = IP(J) IF (JP.LT.K) THEN X(K) = X(K) - A(JJ)*X(JP) IF (ABS(X(K)).GE.CON) X(K) = SIGN(CON,X(K)) END IF 10 CONTINUE 20 CONTINUE DO 40 K = N,1,-1 KSTRT = IA(K) KSTOP = IA(K+1) - 1 DO 30 JJ = KSTRT,KSTOP J = JA(JJ) JP = IP(J) IF (JP.GT.K) X(K) = X(K) - A(JJ)*X(JP) IF (JP.EQ.K) APOM = A(JJ) 30 CONTINUE X(K) = X(K)/APOM 40 CONTINUE CALL MXVSFP(N,IP,X,Y) ELSE CALL MXVSBP(N,IP,X,Y) DO 60 K = 1,N X(K) = X(K)/A(ID(K)) KSTRT = IA(K) KSTOP = IA(K+1) - 1 DO 50 JJ = KSTRT,KSTOP J = JA(JJ) JP = IP(J) IF (JP.GT.K) X(JP) = X(JP) - A(JJ)*X(K) 50 CONTINUE 60 CONTINUE DO 80 K = N,1,-1 KSTRT = IA(K) KSTOP = IA(K+1) - 1 DO 70 JJ = KSTRT,KSTOP J = JA(JJ) JP = IP(J) IF (JP.LT.K) X(JP) = X(JP) - A(JJ)*X(K) 70 CONTINUE 80 CONTINUE END IF RETURN END * SUBROUTINE MXSGIF ALL SYSTEMS 95/12/01 * PURPOSE : * INCOMPLETE FACTORIZATION OF A GENERAL SPARSE MATRIX A. * * PARAMETERS : * II N MATRIX DIMENSION. * II M NUMBER OF MATRIX NONZERO ELEMENTS. * RU A(M) NONZERO ELEMENTS OF THE MATRIX A. * II IA(N+1) ROW POINTERS OF THE MATRIX A. * II JA(M) COLUMN INDICES OF THE MATRIX A. * IO IP(N) PERMUTATION VECTOR. * IO ID(N) DIAGONAL POINTERS OF THE MATRIX A. * RA IW(N) AUXILIARY VECTOR. * RI TOL PIVOT TOLERANCE. * IO INF INFORMATION. * SUBROUTINE MXSGIF(N,A,IA,JA,IP,ID,IW,TOL,INF) DOUBLE PRECISION ZERO,ONE,CON PARAMETER (ZERO=0.0D0,ONE=1.0D0,CON=1.0D-30) DOUBLE PRECISION TOL INTEGER INF,N DOUBLE PRECISION A(*) INTEGER IA(*),ID(*),IP(*),IW(*),JA(*) DOUBLE PRECISION TEMP INTEGER I,II,J,JJ,JSTOP,JSTRT,K,KK,KSTOP,KSTRT INF = 0 DO 10 I = 1,N IF (IP(I).LE.0 .OR. IP(I).GT.N) THEN CALL MXVINP(N,IP) GO TO 20 END IF 10 CONTINUE 20 CALL MXVINS(N,0,IW) DO 70 K = 1,N KSTRT = IA(K) KSTOP = IA(K+1) - 1 ID(K) = 0 DO 30 JJ = KSTRT,KSTOP J = JA(JJ) IW(J) = JJ IF (IP(J).EQ.K) ID(K) = JJ 30 CONTINUE IF (ID(K).EQ.0) THEN INF = -45 RETURN END IF IF (TOL.GT.ZERO) A(ID(K)) = (ONE+TOL)*A(ID(K)) IF (ABS(A(ID(K))).LT.TOL) A(ID(K)) = A(ID(K)) + * SIGN(TOL,A(ID(K))) DO 50 JJ = KSTRT,KSTOP J = IP(JA(JJ)) IF (J.LT.K) THEN JSTRT = IA(J) JSTOP = IA(J+1) - 1 TEMP = A(JJ)/A(ID(J)) A(JJ) = TEMP DO 40 II = JSTRT,JSTOP I = JA(II) IF (IP(I).GT.J) THEN KK = IW(I) IF (KK.NE.0) A(KK) = A(KK) - TEMP*A(II) END IF 40 CONTINUE END IF 50 CONTINUE KK = ID(K) IF (ABS(A(KK)).LT.CON) THEN INF = K IF (A(KK).EQ.ZERO) THEN A(KK) = CON ELSE A(KK) = SIGN(CON,A(KK)) END IF END IF DO 60 JJ = KSTRT,KSTOP J = JA(JJ) IW(J) = 0 60 CONTINUE 70 CONTINUE RETURN END * SUBROUTINE MXSPCA ALL SYSTEMS 93/12/01 * PURPOSE : * REWRITE SYMMETRIC MATRIX INTO THE PERMUTED FACTORIZED COMPACT SCHEME. * MOIDIFIED VERSION FOR THE USE WITH MXSPCJ. * * PARAMETERS: * II N SIZE OF THE SYSTEM SOLVED. * II NB NUMBER OF NONZEROS IN THE UPPER TRIANGLE OF THE ORIGINAL * MATRIX. * II ML SIZE OF THE COMPACT FACTOR. * RU A(MMAX) NUMERICAL VALUES OF THE SPARSE HESSIAN APPROXIMATION * STORED AT THE POSITIONS 1, ...,NB. * IU JA(MMAX) INDICES OF THE NONZERO ELEMENTS OF THE HESSIAN MATRIX IN * THE PACKED ROW FORM AT THE FIRST NB POSITIONS. * NEW POSITIONS * IN THE PERMUTED FACTOR STORED IN A(NB+1), ..., A(2*NB), * INDICES OF COMPACT SCHEME IN A(2*NB+1), ..., A(2*NB+ML). * II PSL(N+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * RI T CORRECTION FACTOR THAT IS ADDED TO THE DIAGONAL. * * SUBROUTINE MXSPCA(N,NB,ML,A,IA,JA,T) INTEGER N,NB,ML,IA(*),JA(*) DOUBLE PRECISION A(*),T INTEGER I,J DO 100 I=1,N J=ABS(JA(IA(I)+NB+ML)) A(NB+J)=A(NB+J)+T 100 CONTINUE RETURN END * SUBROUTINE MXSPCB ALL SYSTEMS 92/12/01 * PURPOSE : * SOLUTION OF A SYSTEM OF LINEAR EQUATIONS WITH A SPARSE SYMMETRIC * POSITIVE DEFINITE MATRIX A+E USING THE FACTORIZATION A+E=L*D*TRANS(L) * STORED IN THE COMPACT SCHEME. THIS FACTORIZATION CAN BE OBTAINED * USING THE SUBROUTINE MXSPCF. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) FACTORS L,D OF THE FACTORIZATION A+E=L*D*TRANS(L) * STORED USING THE COMPACT SCHEME OF STORING. * II PSL(N+1) POINTER ARRAY OF THE FACTORIZED SPARSE MATRIX * II SL(MMAX) ARRAY OF COLUMN INDICES OF THE FACTORS L AND D * STORED USING THE COMPACT SCHEME. * RU X(N) ON INPUT THE RIGHT HAND SIDE OF A SYSTEM OF LINEAR * EQUATIONS. ON OUTPUT THE SOLUTION OF A SYSTEM OF LINEAR * EQUATIONS. * II JOB OPTION. IF JOB=0 THEN X:=(A+E)**(-1)*X. IF JOB>0 THEN * X:=L**(-1)*X. IF JOB<0 THEN X:=TRANS(L)**(-1)*X. * * METHOD : * BACK SUBSTITUTION * SUBROUTINE MXSPCB(N,A,PSL,SL,X,JOB) INTEGER N DOUBLE PRECISION A(*),X(*) INTEGER PSL(*),SL(*),JOB INTEGER I,J,IS * * FIRST PHASE * IF (JOB.GE.0) THEN DO 300 I=1,N IS=SL(I)+N+1 DO 200 J=PSL(I)+I,PSL(I+1)+I-1 X(SL(IS))=X(SL(IS)) - A(J)*X(I) IS=IS+1 200 CONTINUE 300 CONTINUE END IF * * SECOND PHASE * IF (JOB.EQ.0) THEN DO 400 I=1,N X(I) = X(I)/A(PSL(I)+I-1) 400 CONTINUE END IF * * THIRD PHASE * IF (JOB.LE.0) THEN DO 600 I=N,1,-1 IS=SL(I)+N+1 DO 500 J=PSL(I)+I,PSL(I+1)+I-1 X(I)=X(I)-A(J)*X(SL(IS)) IS=IS+1 500 CONTINUE 600 CONTINUE END IF RETURN END * SUBROUTINE MXSPCC ALL SYSTEMS 92/12/01 * PURPOSE : * SPARSE MATRIX REORDER, SYMBOLIC FACTORIZATION, DATA STRUCTURES * TRANSFORMATION - INITIATION OF THE DIRECT SPARSE SOLVER. * MODIFIED VERSION WITH CHANGED DATA STRUCTURES. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * II NJA NUMBER OF NONZERO ELEMENTS OF THE MATRIX. * IO ML SIZE OF THE COMPACT STRUCTURE OF THE TRIANGULAR FACTOR * OF THE HESSIAN APPROXIMATION. * II MMAX SIZE OF THE ARRAYS JA,A. * RO A(MMAX) NUMERICAL VALUES OF THE SPARSE HESSIAN APPROXIMATION * STORED AT THE POSITIONS 1, ...,NJA. LOWER TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION STORED AT THE * POSITIONS NJA+1, ..., NJA+MB. * II IA(N) POINTERS OF THE DIAGONAL ELEMENTS OF THE HESSIAN MATRIX. * II JA(MMAX) INDICES OF THE NONZERO ELEMENTS OF THE HESSIAN MATRIX IN * THE PACKED ROW FORM AT THE FIRST NJA POSITIONS. COMPACT * STRUCTURE OF INDICES OF ITS TRIANGULAR FACTOR IS ROWWISE * STORED. * II PSL(N+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * IO PERM(N) PERMUTATION VECTOR. * IO INVP(N) INVERSE PERMUTATION VECTOR. * IA WN11(N) AUXILIARY VECTOR. * IA WN12(N) AUXILIARY VECTOR. * IA WN13(N) AUXILIARY VECTOR. * IA WN14(N) AUXILIARY VECTOR. * IO ITERM TERMINATION INDICATOR. TERMINATION IF ITERM .NE. 0. * * COMMON DATA : * * SUBPROGRAMS USED : * S MXSTG1 WIDTHENING OF THE PACKED FORM OF THE SPARSE MATRIX. * S MXSSMN SPARSE MATRIX REORDERING. * S MXVSIP INVERSE PERMUTATION COMPUTING. * S MXSPCI SYMBOLIC FACTORIZATION. * S MXSTL1 PACKING OF THE WIDTHENED FORM OF THE SPARSE MATRIX. * SUBROUTINE MXSPCC(N,NJA,ML,MMAX,A,IA,JA,PSL,PERM,INVP,WN11,WN12, * WN13,WN14,ITERM) INTEGER N,NJA,MMAX,ML,ITERM INTEGER PERM(*),INVP(*),WN11(*),WN12(*),WN13(*),WN14(*) INTEGER PSL(*),IA(*),JA(*) INTEGER JSTRT,JSTOP,I,J,K,L,NJASAVE INTEGER LL,LL1,NJABIG,KSTRT DOUBLE PRECISION A(*) IF (ML.GT.0) RETURN IF (2*NJA.GE.MMAX) THEN ITERM=-41 GO TO 1000 END IF * * WIDTHENING OF THE PACKED FORM * NJASAVE=NJA CALL MXSTG1(N,NJA,IA,JA,WN12,WN11) NJABIG=NJA * * REORDERING OF THE SPARSE MATRIX * CALL MXSSMN(N,IA,JA,PERM,WN11,WN12,WN13) * * FIND THE INVERSE PERMUTATION VECTOR INVP * CALL MXVSIP(N,PERM,INVP) * * SHRINK THE STRUCTURE * CALL MXSTL1(N,NJA,IA,JA,WN11) DO 40 I=1,N WN11(I)=0 WN12(I)=0 40 CONTINUE * * WN11 CONTAINS BEGINNINGS OF THE FACTOR ROWS * DO 50 I=1,N K=PERM(I) JSTRT=IA(K) JSTOP=IA(K+1)-1 DO 60 J=JSTRT,JSTOP L=JA(J) L=INVP(L) IF (L.GE.I) THEN WN12(I)=WN12(I)+1 ELSE WN12(L)=WN12(L)+1 END IF 60 CONTINUE 50 CONTINUE WN11(1)=1 DO 69 I=1,N-1 WN11(I+1)=WN11(I)+WN12(I) 69 CONTINUE * * CREATE UPPER TRIANGULAR STRUCTURE NECESSARY FOR THE TRANSFER * DO 300 I=1,N K=PERM(I) JSTRT=IA(K) JSTOP=IA(K+1)-1 DO 200 J=JSTRT,JSTOP L=JA(J) L=INVP(L) IF (L.GE.I) THEN LL1=WN11(I) WN11(I)=LL1+1 JA(NJABIG+LL1)=L A(J)=LL1 A(NJA+LL1)=J ELSE LL1=WN11(L) WN11(L)=LL1+1 JA(NJABIG+LL1)=I A(J)=LL1 A(NJA+LL1)=J END IF 200 CONTINUE 300 CONTINUE * * SORT INDICES IN THE PERMUTED UPPER TRIANGLE * DO 599 I=1,N WN11(I)=0 599 CONTINUE WN11(1)=1 WN14(1)=1 DO 67 I=2,N+1 WN11(I)=WN11(I-1)+WN12(I-1) WN14(I)=WN11(I) 67 CONTINUE DO 602 I=1,N WN12(I)=0 602 CONTINUE JSTOP=WN11(N+1) DO 499 I=N,1,-1 JSTRT=WN11(I) CALL MXVSR5(JSTOP-JSTRT,JSTRT-1,JA(NJABIG+JSTRT), & A,A(NJASAVE+JSTRT)) JSTOP=JSTRT 499 CONTINUE * * WIDTHENING OF THE PERMUTED PACKED FORM. * NJASAVE=NJA CALL MXSTG1(N,NJA,IA,JA,WN12,WN11) NJABIG=NJA * * SYMBOLIC FACTORIZATION. * CALL MXSPCI(N,ML,MMAX-2*NJA,IA,JA,PSL,A(2*NJASAVE+1),PERM, & INVP,WN11,WN12,WN13,ITERM) IF (ITERM.NE.0) THEN ITERM=-42 GO TO 1000 END IF * * RETRIEVE PARAMETERS * CALL MXSTL1(N,NJA,IA,JA,WN11) * * SHIFT PERMUTED UPPER TRIANGLE. * DO 73 I=1,NJASAVE JA(NJA+I)=JA(NJABIG+I) 73 CONTINUE * * SHIFT STRUCTURE SL. * IF (2*NJASAVE+ML.GE.MMAX) THEN ITERM=-41 GO TO 1000 END IF DO 70 I=1,ML JA(2*NJASAVE+I)=A(2*NJASAVE+I) 70 CONTINUE * * SET POINTERS * DO 600 I=1,N WN12(I)=0 600 CONTINUE LL1=PSL(N)+N-1 JSTOP=WN14(N+1) DO 500 I=N,1,-1 JSTRT=WN14(I) DO 700 J=JSTRT,JSTOP-1 K=JA(NJASAVE+J) WN12(K)=J LL=A(NJASAVE+J) WN13(K)=LL 700 CONTINUE JSTOP=JSTRT KSTRT=JA(2*NJASAVE+I)+N+1+2*NJASAVE DO 800 J=KSTRT+PSL(I+1)-PSL(I)-1,KSTRT,-1 L=JA(J) IF (WN12(L).NE.0) THEN LL=WN13(L) A(LL)=LL1 WN12(L)=0 END IF LL1=LL1-1 800 CONTINUE K=WN12(I) WN12(I)=0 LL=WN13(I) A(LL)=LL1 LL1=LL1-1 500 CONTINUE DO 76 I=1,ML JA(NJASAVE+I)=JA(2*NJASAVE+I) 76 CONTINUE DO 72 I=1,NJASAVE JA(ML+NJASAVE+I)=A(I) 72 CONTINUE 1000 CONTINUE RETURN END * SUBROUTINE MXSPCD ALL SYSTEMS 92/12/01 * PURPOSE : * COMPUTATION OF A DIRECTION OF NEGATIVE CURVATURE WITH RESPECT TO A * SPARSE SYMMETRIC MATRIX A USING THE FACTORIZATION A+E=L*D*TRANS(L) * STORED IN THE COMPACT SPARSE FORM. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * II MMAX LENGTH OF THE PRINCIPAL MATRIX VECTORS (SL,A). * RI A(MMAX) FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGF.IT CONTAINS THE NUMERICAL VALUES OF THE * FACTORS STORED IN THE COMPACT FORM ACCORDING TO THE * INFORMATION IN THE VECTORS PSL,SL. * II PSL(N+1) POINTER VECTOR OF THE FACTORIZED MATRIX A. * II SL(MMAX) COMPACT SHEME OF THE FACTORIZED MATRIX A. * RO X(N) COMPUTED DIRECTION OF NEGATIVE CURVATURE (I.E. * TRANS(X)*A*X<0) IF IT EXISTS. * II INF INFORMATION OBTAINED IN THE FACTORIZATION PROCESS. THE * DIRECTION OF NEGATIVE CURVATURE EXISTS ONLY IF INF>0. * * METHOD : * P.E.GILL, W.MURRAY : NEWTON TYPE METHODS FOR UNCONSTRAINED AND * LINEARLY CONSTRAINED OPTIMIZATION, MATH. PROGRAMMING 28 (1974) * PP. 311-350. * SUBROUTINE MXSPCD(N,A,PSL,SL,X,INF) INTEGER N,INF,PSL(*),SL(*) DOUBLE PRECISION A(*),X(*) INTEGER I, J, IS * * RIGHT HAND SIDE FORMATION * DO 100 I=1,N X(I) = 0.0D 0 100 CONTINUE IF (INF .LE. 0) RETURN X(INF) = 1.0D 0 * * BACK SUBSTITUTION * DO 300 I=INF-1,1,-1 IS=SL(I)+N+1 DO 200 J=PSL(I)+I,PSL(I+1)+I-1 X(I)=X(I)-A(J)*X(SL(IS)) IS=IS+1 200 CONTINUE 300 CONTINUE RETURN END * SUBROUTINE MXSPCF ALL SYSTEMS 90/12/01 * PURPOSE : * NUMERICAL FACTORIZATION A+E=L*D*TRANS(L) OF A SPARSE * SYMMETRIC POSITIVE DEFINITE MATRIX A+E WHERE D AND E ARE DIAGONAL * POSITIVE DEFINITE MATRICES AND L IS A LOWER TRIANGULAR MATRIX. IF * A IS SUFFICIENTLY POSITIVE DEFINITE THEN E=0. THE STRUCTURE ON * INPUT WAS OBTAINED BY THE SYMBOLIC FACTORIZATION AND IT MAKES * USE OF THE COMPACT SCHEME OF STORING THE SPARSE MATRIX IN THE * POINTER ARRAY PSL ,INDEX ARRAY SL. NUMERICAL VALUES OF THE FACTOR * CAN BE FOUND IN THE ARRAY A. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RU A(MMAX) ON INPUT NUMERICAL VALUES OF THE LOWER HALF OF THE * MATRIX THAT IS BEEING FACTORIZED(INCLUDING THE DIAGONAL * ELEMENTS. ON OUTPUT IT CONTAINS FACTORS L AND D AS IF THEY * FORM THE LOWER HALF OF THE MATRIX.STRUCTURE INFORMATION * IS SAVED IN THE COMPACT SCHEME IN THE PAIR OF VECTORS PSL * AND SL. * II PSL(NF+1) POINTER VECTOR OF THE FACTOR * II SL(MMAX) STRUCTURE OF THE FACTOR IN THE COMPACT FORM * IA WN11(NF+1) AUXILIARY VECTOR. * IA WN12(NF+1) AUXILIARY VECTOR. * RA RN01(NF+1) AUXILIARY VECTOR. * IO INF AN INFORMATION OBTAINED IN THE FACTORIZATION PROCESS. IF * INF=0 THEN A IS SUFFICIENTLY POSITIVE DEFINITE AND E=0. IF * INF<0 THEN A IS NOT SUFFICIENTLY POSITIVE DEFINITE AND E>0. IF * INF>0 THEN THEN A IS INDEFINITE AND INF IS AN INDEX OF THE * MOST NEGATIVE DIAGONAL ELEMENT USED IN THE FACTORIZATION * PROCESS. * RU ALF ON INPUT A DESIRED TOLERANCE FOR POSITIVE DEFINITENESS. ON * OUTPUT THE MOST NEGATIVE DIAGONAL ELEMENT USED IN THE * FACTORIZATION PROCESS (IF INF>0). * RO TAU MAXIMUM DIAGONAL ELEMENT OF THE MATRIX E. * * METHOD : * S.C.EISENSTAT,M.C.GURSKY,M.H.SCHULTZ,A.H.SHERMAN:YALE SPARSE MATRIX * PACKAGE I. THE SYMMETRIC CODES,YALE UNIV. RES. REPT. * NO.112,1977. * SUBROUTINE MXSPCF(N,A,PSL,SL,WN11,WN12,RN01,INF,ALF,TAU) INTEGER N,PSL(*),SL(*),WN11(*),WN12(*),INF DOUBLE PRECISION A(*),RN01(*),ALF DOUBLE PRECISION BET,GAM,DEL,RHO,SIG,TOL,TADD,TBDD,TAU INTEGER I, J, K, L, II INTEGER ISTRT,ISTOP,NEWK,KPB,ISUB L = 0 INF = 0 TOL = ALF ALF = 0.0D 0 BET = 0.0D 0 GAM = 0.0D 0 TAU = 0.0D 0 DO 60 I=1,N BET=MAX(BET,ABS(A(PSL(I)+I-1))) DO 50 J=PSL(I)+I,PSL(I+1)+I-1 GAM = MAX( GAM, ABS(A(J)) ) 50 CONTINUE 60 CONTINUE BET = MAX(TOL,BET,GAM/N) DEL = TOL*BET DO 100 I=1,N WN11(I)=0 RN01(I)=0.0D 0 100 CONTINUE DO 600 J=1,N * * DETERMINATION OF A DIAGONAL CORRECTION * SIG=A(PSL(J)+J-1) RHO=0.0D 0 NEWK=WN11(J) 200 K=NEWK IF (K.EQ.0) GO TO 400 NEWK=WN11(K) KPB=WN12(K) TADD=A(KPB+K) TBDD=TADD*A(PSL(K)+K-1) RHO=RHO+TADD*TBDD ISTRT=KPB+1 ISTOP=PSL(K+1)-1 IF (ISTOP.LT.ISTRT) GO TO 200 WN12(K)=ISTRT I=SL(K)+(KPB-PSL(K))+1 ISUB=SL(N+1+I) WN11(K)=WN11(ISUB) WN11(ISUB)=K DO 300 II=ISTRT,ISTOP ISUB=SL(N+1+I) RN01(ISUB)=RN01(ISUB)+A(II+K)*TBDD I=I+1 300 CONTINUE GO TO 200 400 SIG=A(PSL(J)+J-1)-RHO IF (ALF.GT.SIG) THEN ALF=SIG L=J END IF GAM=0.0D 0 ISTRT=PSL(J) ISTOP=PSL(J+1)-1 IF (ISTOP.LT.ISTRT) GO TO 370 WN12(J)=ISTRT I=SL(J) ISUB=SL(N+1+I) WN11(J)=WN11(ISUB) WN11(ISUB)=J DO 500 II=ISTRT,ISTOP ISUB=SL(N+1+I) A(II+J)=(A(II+J)-RN01(ISUB)) RN01(ISUB)=0.0D 0 I=I+1 500 CONTINUE DO 350 K=PSL(J)+J,PSL(J+1)+J-1 GAM=MAX(GAM,ABS(A(K))) 350 CONTINUE GAM=GAM*GAM 370 RHO=MAX(ABS(SIG),GAM/BET,DEL) IF (TAU.LT.RHO-SIG) THEN TAU=RHO-SIG INF=-1 END IF * * GAUSSIAN ELIMINATION * A(PSL(J)+J-1)=RHO DO 550 II=ISTRT,ISTOP A(II+J)=A(II+J)/RHO 550 CONTINUE 600 CONTINUE IF (L.NE.0.AND.ABS(ALF).GT.DEL) INF=L RETURN END * SUBROUTINE MXSPCI ALL SYSTEMS 89/12/01 * PURPOSE : * SYMBOLIC FACTORIZATION OF A SPARSE SYMMETRIC MATRIX GIVEN IN THE * NORMAL SCHEME PA,SA. ON OUTPUT WE HAVE POINTER VECTOR OF THE FACTOR * PSL AND VECTOR OF COLUMN INDICES SL. ML IS THE NUMBER OF THE INDICES * USED FOR THE VECTOR SL, WHERE WE HAVE FACTOR IN THE COMPACT FORM. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * IO ML NUMBER OF THE NONZERO ELEMENTS IN THE FACTOR'S COMPACT SCHEME * II MMAX LENGTH OF THE ARRAY SL. IN THE CASE OF THE * INSUFFICIENT SPACE IT IS TO BE INCREASED. * II PA(N+1) POINTER VECTOR OF THE INPUT MATRIX * II SA(MMAX) VECTOR OF THE COLUMN INDICES OF THE INPUT MATRIX * IO PSL(N+1) POINTER VECTOR OF THE FACTOR * RO SL(MMAX) COMPACT SCHEME OF THE INDICES OF THE FACTOR * II PERM(N) PERMUTATION VECTOR * II INVP(N) INVERSE PERMUTATION VECTOR * IA WN11(N+1) WORK VECTOR OF THE LENGTH N+1 * IA WN12(N+1) WORK VECTOR OF THE LENGTH N+1 * IA WN13(N+1) WORK VECTOR OF THE LENGTH N+1 * IO ISPACE AN INFORMATION ON SPACE OBTAINED DURING THE PROCESS * OF THE FACTORIZATION. * ISPACE=0 THE FACTORIZATION HAS TERMINATED NORMALLY * ISPACE=1 INSUFFICIENT SPACE AVAILABLE * * METHOD : * S.C.EISENSTAT,M.C.GURSKY,M.H.SCHULTZ,A.H.SHERMAN:YALE SPARSE MATRIX * PACKAGE I. THE SYMMETRIC CODES,ACM TRANS. ON MATH. SOFTWARE. * * NOTE: TYPE OF SL CHANGED FOR THE UFO APPLICATION. * SUBROUTINE MXSPCI(N,ML,MMAX,PA,SA,PSL,SL,PERM,INVP, & WN11,WN12,WN13,ISPACE) INTEGER N,MMAX,PA(*),SA(*),PSL(*) INTEGER PERM(*),INVP(*),WN11(*),WN12(*),WN13(*) INTEGER ISPACE,I,INZ,J,JSTOP,JSTRT,K,KNZ,KXSUB,MRGK,LMAX,ML INTEGER NABOR,NODE,NP1,NZBEG,NZEND,RCHM,MRKFLG,M DOUBLE PRECISION SL(*) NZBEG=1 NZEND=0 PSL(1)=1 DO 100 K=1,N WN11(K)=0 WN13(K)=0 100 CONTINUE NP1=N+1 DO 1500 K=1,N KNZ=0 MRGK=WN11(K) MRKFLG=0 WN13(K)=K IF (MRGK.NE.0) WN13(K)=WN13(MRGK) SL(K)=NZEND NODE=PERM(K) JSTRT=PA(NODE) JSTOP=PA(NODE+1)-1 IF (JSTRT.GT.JSTOP) GO TO 1500 WN12(K)=NP1 DO 300 J=JSTRT,JSTOP NABOR=SA(J) IF (NABOR.EQ.NODE) GO TO 300 NABOR=INVP(NABOR) IF (NABOR.LE.K) GO TO 300 RCHM=K 200 M=RCHM RCHM=WN12(M) IF (RCHM.LE.NABOR) GO TO 200 KNZ=KNZ+1 WN12(M)=NABOR WN12(NABOR)=RCHM IF (WN13(NABOR).NE.WN13(K)) MRKFLG=1 300 CONTINUE LMAX=0 IF (MRKFLG.NE.0.OR.MRGK.EQ.0) GO TO 350 IF (WN11(MRGK).NE.0) GO TO 350 SL(K)=SL(MRGK)+1 KNZ=PSL(MRGK+1)-(PSL(MRGK)+1) GO TO 1400 350 I=K 400 I=WN11(I) IF (I.EQ.0) GO TO 800 INZ=PSL(I+1)-(PSL(I)+1) JSTRT=SL(I)+1 JSTOP=SL(I)+INZ IF (INZ.LE.LMAX) GO TO 500 LMAX=INZ SL(K)=JSTRT 500 RCHM=K DO 700 J=JSTRT,JSTOP NABOR=SL(N+1+J) 600 M=RCHM RCHM=WN12(M) IF (RCHM.LT.NABOR) GO TO 600 IF (RCHM.EQ.NABOR) GO TO 700 KNZ=KNZ+1 WN12(M)=NABOR WN12(NABOR)=RCHM RCHM=NABOR 700 CONTINUE GO TO 400 800 IF (KNZ.EQ.LMAX) GO TO 1400 IF (NZBEG.GT.NZEND) GO TO 1200 I=WN12(K) DO 900 JSTRT=NZBEG,NZEND IF (SL(N+1+JSTRT)-I .GE.0) THEN IF (SL(N+1+JSTRT).EQ.I) THEN GO TO 1000 ELSE GO TO 1200 END IF END IF 900 CONTINUE GO TO 1200 1000 SL(K)=JSTRT DO 1100 J=JSTRT,NZEND IF (SL(N+1+J).NE.I) GO TO 1200 I=WN12(I) IF (I.GT.N) GO TO 1400 1100 CONTINUE NZEND=JSTRT-1 1200 NZBEG=NZEND+1 NZEND=NZEND+KNZ * * A VARIANT IS USED WHEN CALLED SO THAT SL(X)=A(NB+X) * IF (NZEND.GE.MMAX-N-1) GO TO 1600 I=K DO 1300 J=NZBEG,NZEND I=WN12(I) SL(N+1+J)=I WN13(I)=K 1300 CONTINUE SL(K)=NZBEG WN13(K)=K 1400 IF (KNZ.GT.1) THEN KXSUB=SL(K) I=SL(N+1+KXSUB) WN11(K)=WN11(I) WN11(I)=K END IF PSL(K+1)=PSL(K)+KNZ 1500 CONTINUE SL(N)=SL(N)+1 SL(N+1)=SL(N) ML=N+SL(N+1) ISPACE=0 RETURN 1600 ISPACE=1 RETURN END * SUBROUTINE MXSPCM ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF A GIVEN VECTOR X BY A SPARSE SYMMETRIC POSITIVE * DEFINITE MATRIX A+E USING THE FACTORIZATION A+E=L*D*TRANS(L) OBTAINED * BY THE SUBROUTINE MXSPGN. FACTORS ARE STORED IN THE COMPACT FORM. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGN.IT CONTAINS THE NUMERICAL VALUES OF THE * FACTORS STORED IN THE COMPACT FORM ACCORDING TO THE * INFORMATION IN THE VECTORS PSL,SL. * II PSL(N+1) POINTER ARRAY OF THE FACTORIZED SPARSE MATRIX * II SL(MMAX) INDICES OF THE COMPACT SCHEME OF THE FACTORS. * RU X(N) ON INPUT THE GIVEN VECTOR, ON OUTPUT THE RESULT * OF MULTIPLICATION. * RA RN01(N) AUXILIARY VECTOR. * II JOB OPTION. IF JOB=0 THEN X:=(A+E)*X. IF JOB>0 THEN * X:=TRANS(L)*X. IF JOB<0 THEN X:=L*X. * SUBROUTINE MXSPCM(N,A,PSL,SL,X,RN01,JOB) INTEGER N INTEGER PSL(*),SL(*),JOB DOUBLE PRECISION A(*),X(*),RN01(*),ZERO PARAMETER(ZERO=0.0D0) INTEGER I,J,IS DO 50 I=1,N RN01(I)=ZERO 50 CONTINUE * * FIRST PHASE:X=TRANS(L)*X * IF (JOB.GE.0) THEN DO 300 I=1,N IS=SL(I)+N+1 DO 200 J=PSL(I)+I,PSL(I+1)+I-1 X(I)=X(I)+A(J)*X(SL(IS)) IS=IS+1 200 CONTINUE 300 CONTINUE END IF * * SECOND PHASE:X=D*X * IF (JOB.EQ.0) THEN DO 400 I=1,N X(I) = X(I)*A(PSL(I)+I-1) 400 CONTINUE END IF * * THIRD PHASE:X=L*X * IF (JOB.LE.0) THEN DO 600 I=N,1,-1 IS=SL(I)+N+1 DO 500 J=PSL(I)+I,PSL(I+1)+I-1 RN01(SL(IS))=RN01(SL(IS))+A(J)*X(I) IS=IS+1 500 CONTINUE 600 CONTINUE DO 700 I=1,N X(I)=RN01(I)+X(I) 700 CONTINUE END IF RETURN END * SUBROUTINE MXSPCN ALL SYSTEMS 93/12/01 * PURPOSE : * ESTIMATION OF THE MINIMUM EIGENVALUE AND THE CORRESPONDING EIGENVECTOR * OF A SPARSE SYMMETRIC POSITIVE DEFINITE MATRIX A+E USING THE * FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE SUBROUTINE MXSPCF. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) FACTORS L,D OF THE FACTORIZATION A+E=L*D*TRANS(L) * STORED USING THE COMPACT SCHEME OF STORING. * II PSL(N+1) POINTER ARRAY OF THE FACTORIZED SPARSE MATRIX * II SL(MMAX) ARRAY OF COLUMN INDICES OF THE FACTORS L AND D * STORED USING THE COMPACT SCHEME. * SUBROUTINE MXDPGF. * RO X(N) ESTIMATED EIGENVECTOR. * RO ALF ESTIMATED EIGENVALUE. * II JOB OPTION. IF JOB=0 THEN ONLY ESTIMATED EIGENVALUE IS * COMPUTED. IS JOB>0 THEN BOTH ESTIMATED EIGENVALUE AND * ESTIMATED EIGENVECTOR ARE COMPUTED. * SUBROUTINE MXSPCN(N,A,PSL,SL,X,ALF,JOB) INTEGER N DOUBLE PRECISION A(*),X(*),ALF INTEGER PSL(*),SL(*),JOB DOUBLE PRECISION XP,XM,FP,FM,MXVDOT INTEGER I,K,IS DOUBLE PRECISION ZERO,ONE PARAMETER (ZERO=0.0D 0,ONE=1.0D 0) * * COMPUTATION OF THE VECTOR V WITH POSSIBLE MAXIMUM NORM SUCH * THAT L*D**(1/2)*V=U WHERE U HAS ELEMENTS +1 OR -1 * DO 2 I=1,N X(I)=ZERO 2 CONTINUE DO 6 K=1,N XP=-X(K)+ONE XM=-X(K)-ONE FP=ABS(XP) FM=ABS(XM) IS=SL(K)+N+1 DO 3 I=PSL(K)+K,PSL(K+1)+K-1 FP=FP+ABS(X(SL(IS))+A(I)*XP) FM=FM+ABS(X(SL(IS))+A(I)*XM) IS=IS+1 3 CONTINUE IF (FP.GE.FM) THEN X(K)=XP IS=SL(K)+N+1 DO 4 I=PSL(K)+K,PSL(K+1)+K-1 X(SL(IS))=X(SL(IS))+A(I)*XP IS=IS+1 4 CONTINUE ELSE X(K)=XM IS=SL(K)+N+1 DO 5 I=PSL(K)+K,PSL(K+1)+K-1 X(SL(IS))=X(SL(IS))+A(I)*XM IS=IS+1 5 CONTINUE END IF 6 CONTINUE * * COMPUTATION OF THE VECTOR X SUCH THAT * D**(1/2)*TRANS(L)*X=V * FM=ZERO DO 7 K=1,N IF (JOB.LE.0) THEN FP=SQRT(A(PSL(K)+K-1)) X(K)=X(K)/FP FM=FM+X(K)*X(K) ELSE X(K)=X(K)/A(PSL(K)+K-1) END IF 7 CONTINUE FP=DBLE(N) IF (JOB.LE.0) THEN * * FIRST ESTIMATION OF THE MINIMUM EIGENVALUE BY THE FORMULA * ALF=(TRANS(U)*U)/(TRANS(V)*V) * ALF=FP/FM RETURN END IF FM=ZERO DO 9 K=N,1,-1 IS=SL(K)+N+1 DO 8 I=PSL(K)+K,PSL(K+1)+K-1 X(K)=X(K)-A(I)*X(SL(IS)) IS=IS+1 8 CONTINUE FM=FM+X(K)*X(K) 9 CONTINUE FM=SQRT(FM) IF (JOB.LE.1) THEN * * SECOND ESTIMATION OF THE MINIMUM EIGENVALUE BY THE FORMULA * ALF=SQRT(TRANS(U)*U)/SQRT(TRANS(X)*X) * ALF=SQRT(FP)/FM ELSE * * INVERSE ITERATIONS * DO 11 K=2,JOB * * SCALING THE VECTOR X BY ITS NORM * DO 10 I=1,N X(I)=X(I)/FM 10 CONTINUE CALL MXSPCB(N,A,PSL,SL,X,0) FM=SQRT(MXVDOT(N,X,X)) 11 CONTINUE ALF=ONE/FM END IF * * SCALING THE VECTOR X BY ITS NORM * DO 12 I=1,N X(I)=X(I)/FM 12 CONTINUE RETURN END * FUNCTION MXSPCP ALL SYSTEMS 92/12/01 * PURPOSE : * COMPUTATION OF THE NUMBER MXSPCP=TRANS(X)*D**(-1)*X WHERE D IS A * DIAGONAL MATRIX IN THE FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGN. THE FACTORS ARE STORED IN THE COMPACT FORM. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGN.IT CONTAINS THE NUMERICAL VALUES OF THE * FACTORS STORED IN THE COMPACT FORM ACCORDING TO THE * INFORMATION IN THE VECTORS PSL,SL. * II PSL(N+1) POINTER VECTOR OF THE FACTORIZED MATRIX A. * RI X(N) INPUT VECTOR * RR MXSPCP COMPUTED NUMBER MXSPCP=TRANS(X)*D**(-1)*X * FUNCTION MXSPCP(N,A,PSL,X) INTEGER N DOUBLE PRECISION A(*), X(*), MXSPCP DOUBLE PRECISION TEMP INTEGER PSL(*),I TEMP = 0.0D 0 DO 100 I=1,N TEMP = TEMP + X(I)*X(I)/A(PSL(I)+I-1) 100 CONTINUE MXSPCP = TEMP RETURN END * FUNCTION MXSPCQ ALL SYSTEMS 92/12/01 * PURPOSE : * COMPUTATION OF THE NUMBER MXSPCQ=TRANS(X)*D*X WHERE D IS A * DIAGONAL MATRIX IN THE FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGN. FACTORS ARE STORED IN THE COMPACT FORM. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPGN.IT CONTAINS THE NUMERICAL VALUES OF THE * FACTORS STORED IN THE COMPACT FORM ACCORDING TO THE * INFORMATION IN THE VECTORS PSL,SL. * II PSL(N+1) POINTER VECTOR OF THE FACTORIZED MATRIX A * RI X(N) INPUT VECTOR * RR MXSPCQ COMPUTED NUMBER MXSPCQ=TRANS(X)*D*X * FUNCTION MXSPCQ(N,A,PSL,X) INTEGER N DOUBLE PRECISION A(*), X(*), MXSPCQ DOUBLE PRECISION TEMP INTEGER PSL(N+1),I DOUBLE PRECISION ZERO PARAMETER (ZERO = 0.0D0) TEMP = ZERO DO 100 I=1,N TEMP = TEMP + X(I)*X(I)*A(PSL(I)+I-1) 100 CONTINUE MXSPCQ = TEMP RETURN END * SUBROUTINE MXSPCT ALL SYSTEMS 92/12/01 * PURPOSE : * REWRITE SYMMETRIC MATRIX INTO THE PERMUTED FACTORIZED COMPACT SCHEME. * MOIDIFIED VERSION FOR THE USE WITH MXSPCJ. * * PARAMETERS: * II N SIZE OF THE SYSTEM SOLVED. * II NB NUMBER OF NONZEROS IN THE UPPER TRIANGLE OF THE ORIGINAL * MATRIX. * II ML SIZE OF THE COMPACT FACTOR. * II MMAX DECLARED LENGTH OF THE ARRAYS JA,A. * RU A(MMAX) NUMERICAL VALUES OF THE SPARSE HESSIAN APPROXIMATION * STORED AT THE POSITIONS 1, ...,NB. * IU JA(MMAX) INDICES OF THE NONZERO ELEMENTS OF THE HESSIAN MATRIX IN * THE PACKED ROW FORM AT THE FIRST NB POSITIONS. * NEW POSITIONS * IN THE PERMUTED FACTOR STORED IN A(NB+1), ..., A(2*NB), * INDICES OF COMPACT SCHEME IN A(2*NB+1), ..., A(2*NB+ML). * II PSL(N+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * IO ITERM ERROR FLAG. IF ITERM < 0 - LACK OF SPACE IN JA. * * SUBROUTINE MXSPCT(N,NB,ML,MMAX,A,JA,PSL,ITERM) INTEGER N,NB,ML,MMAX,JA(*) INTEGER PSL(*),ITERM DOUBLE PRECISION A(*) INTEGER I,J * * WN11 CONTAINS BEGINNINGS OF THE FACTOR ROWS * ITERM=0 * * LACK OF SPACE * IF (MMAX.LE.NB+PSL(N+1)+N-1) THEN ITERM=-43 RETURN END IF IF (MMAX.LE.2*NB+ML) THEN ITERM=-44 RETURN END IF DO 50 I=NB+1,NB+PSL(N+1)+N-1 A(I)=0.0D 0 50 CONTINUE DO 100 I=NB+ML+1,2*NB+ML J=JA(I) A(NB+J)=A(I-NB-ML) 100 CONTINUE RETURN END * SUBROUTINE MXSPTB ALL SYSTEMS 94/12/01 * PURPOSE : * SOLUTION OF A SYSTEM OF LINEAR EQUATIONS WITH A SPARSE SYMMETRIC * POSITIVE DEFINITE MATRIX A+E USING INCOMPLETE ILUT-TYPE FACTORIZATION * A+E=L*D*TRANS(L) OBTAINED BY THE SUBROUTINE MXSPTF. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(MMAX) INCOMPLETE FACTORIZATION A+E=L*D*TRANS(L) OBTAINED BY THE * SUBROUTINE MXSPTF. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(MMAX) INDICES OF THE NONZERO ELEMENTS OF A. * RU X(N) ON INPUT THE RIGHT HAND SIDE OF A SYSTEM OF LINEAR * EQUATIONS. ON OUTPUT THE SOLUTION OF A SYSTEM OF LINEAR * EQUATIONS. * II JOB OPTION. IF JOB=0 THEN X:=(A+E)**(-1)*X. IF JOB>0 THEN * X:=L**(-1)*X. IF JOB<0 THEN X:=TRANS(L)**(-1)*X. * * METHOD : * BACK SUBSTITUTION * SUBROUTINE MXSPTB(N,A,IA,JA,X,JOB) INTEGER N,IA(*),JA(*),JOB DOUBLE PRECISION A(*),X(*) INTEGER I,J,K DOUBLE PRECISION TEMP,SUM * * FIRST PHASE * IF (JOB.GE.0) THEN DO 300 I=1,N K=IA(I) IF (K.LE.0) GO TO 300 TEMP=X(I)*A(K) DO 200 J=IA(I)+1,IA(I+1)-1 K=JA(J) IF (K.GT.0) X(K)=X(K)-A(J)*TEMP 200 CONTINUE IF (JOB.EQ.0) X(I)=TEMP 300 CONTINUE END IF * * THIRD PHASE * IF (JOB.LE.0) THEN DO 600 I=N,1,-1 K=IA(I) IF (K.LE.0) GO TO 600 SUM=0.0D 0 TEMP=A(K) DO 500 J=IA(I)+1,IA(I+1)-1 K=JA(J) IF (K.GT.0) SUM=SUM+A(J)*X(K) 500 CONTINUE SUM=SUM*TEMP X(I)=X(I)-SUM 600 CONTINUE END IF RETURN END * SUBROUTINE MXSPTF ALL SYSTEMS 03/12/01 * PURPOSE : * INCOMPLETE CHOLESKY FACTORIZATION A+E=L*D*TRANS(L) OF A SPARSE * SYMMETRIC POSITIVE DEFINITE MATRIX A+E WHERE D AND E ARE DIAGONAL * POSITIVE DEFINITE MATRICES AND L IS A LOWER TRIANGULAR MATRIX. * METHOD IS BASED ON THE SIMPLE IC(0) ALGORITHM WITHOUT DIAGONAL * COMPENSATION. SPARSE RIGHT-LOOKING IMPLEMENTATION. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(M) SPARSE SYMMETRIC (USUALLY POSITIVE DEFINITE) MATRIX. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * IA WN01(N+1) AMXILIARY ARRAY. * IO INF AN INFORMATION OBTAINED IN THE FACTORIZATION PROCESS. IF * INF=0 THEN A IS SUFFICIENTLY POSITIVE DEFINITE AND E=0. IF * INF<0 THEN A IS NOT SUFFICIENTLY POSITIVE DEFINITE AND E>0. IF * INF>0 THEN A IS INDEFINITE AND INF IS AN INDEX OF THE * MOST NEGATIVE DIAGONAL ELEMENT USED IN THE FACTORIZATION * PROCESS. * RU ALF ON INPUT A DESIRED TOLERANCE FOR POSITIVE DEFINITENESS. * ON OUTPUT THE MOST NEGATIVE DIAGONAL ELEMENT USED IN THE * FACTORIZATION PROCESS (IF INF>0). * RO TAU MAXIMUM DIAGONAL ELEMENT OF THE MATRIX E. * * METHOD : * P.E.GILL, W.MURRAY : NEWTON TYPE METHODS FOR UNCONSTRAINED AND * LINEARLY CONSTRAINED OPTIMIZATION, MATH. PROGRAMMING 28 (1974) * PP. 311-350. * SUBROUTINE MXSPTF(N,A,IA,JA,WN01,INF,ALF,TAU) INTEGER N,IA(*),JA(*),WN01(*),INF DOUBLE PRECISION A(*),ALF,TAU INTEGER I,J,K,L,II,LL,K1,L1,L2,JSTRT,JSTOP,IDIAG,KSTRT,KSTOP,NJA DOUBLE PRECISION PTOL,BET,GAM,TEMP,DEL,DIAG,NDIAG,INVDIAG PTOL=ALF NJA=IA(N+1)-1 * * INITIALIZE AMXILIARY VECTOR * INF=0 CALL MXVINS(N,0,WN01) * * GILL-MURRAY MODIFICATION * ALF=0.0D 0 BET=0.0D 0 GAM=0.0D 0 TAU=0.0D 0 DO 2 I=1,N IDIAG=IA(I) IF (JA(IDIAG).LE.0) GO TO 2 TEMP=A(IDIAG) BET=MAX(BET,ABS(TEMP)) DO 1 J=IA(I)+1,IA(I+1)-1 IF (JA(J).LE.0) GO TO 1 TEMP=A(J) GAM=MAX(GAM,ABS(TEMP)) 1 CONTINUE 2 CONTINUE BET=MAX(PTOL,BET,GAM/DBLE(N)) DEL=PTOL*BET * * COMPUTE THE PRECONDITIONER * LL=0 DO 8 K=1,N KSTRT=IA(K) KSTOP=IA(K+1)-1 IF (JA(KSTRT).LE.0) GO TO 8 DIAG=A(KSTRT) IF (ALF.GT.DIAG) THEN ALF=DIAG LL=K END IF GAM=0.0D 0 DO 3 J=KSTRT+1,KSTOP IF (JA(J).LE.0) GO TO 3 TEMP=A(J) GAM=MAX(GAM,ABS(TEMP)) 3 CONTINUE GAM=GAM*GAM INVDIAG=MAX(ABS(DIAG),GAM/BET,DEL) IF (TAU.LT.INVDIAG-DIAG) THEN TAU=INVDIAG-DIAG INF=-1 END IF INVDIAG=1.0D 0/INVDIAG A(KSTRT)=INVDIAG * * RIGHT-LOOKING UPDATE * * * SET POINTERS * DO 4 II=KSTRT,KSTOP K1=JA(II) IF (K1.GT.0) WN01(K1)=II 4 CONTINUE * * INNER LOOP * DO 6 I=KSTRT+1,KSTOP J=JA(I) IF (J.LE.0) GO TO 6 NDIAG=A(I) JSTRT=IA(J) JSTOP=IA(J+1)-1 DO 5 L=JSTRT,JSTOP L1=JA(L) IF (L1.LE.0) GO TO 5 L2=WN01(L1) IF (L2.NE.0) THEN A(L)=A(L)-(A(L2)*INVDIAG)*NDIAG END IF 5 CONTINUE 6 CONTINUE * * CLEAR THE POINTERS * DO 7 II=KSTRT,KSTOP K1=JA(II) IF (K1.GT.0) WN01(K1)=0 7 CONTINUE 8 CONTINUE IF (LL.GT.0.AND.ABS(ALF).GT.DEL) INF=LL RETURN END * SUBROUTINE MXSRMD ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF TRANSPOSE OF A DENSE RECTANGULAR MATRIX A BY * A VECTOR X AND ADDITION OF A SCALED VECTOR ALF*Y. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II NA NUMBER OF COLUMNS OF THE MATRIX A. * II MA NUMBER OF ELEMENTS IN THE FIELD A. * RI A(MA) RECTANGULAR MATRIX STORED AS A TWO-DIMENSIONAL ARRAY. * II IA(NA+1) POSITION OF THE FIRST RORWS ELEMENTS IN THE FIELD A. * II JA(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD A. * RI X(N) INPUT VECTOR. * RI ALF SCALING FACTOR. * RI Y(NA) INPUT VECTOR. * RO Z(NA) OUTPUT VECTOR EQUAL TO TRANS(A)*X+ALF*Y. * SUBROUTINE MXSRMD(NA,A,IA,JA,X,ALF,Y,Z) INTEGER NA,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),ALF,Y(*),Z(*) DOUBLE PRECISION TEMP INTEGER I,J,K,L,JP DO 2 I=1,NA K=IA(I) L=IA(I+1)-K TEMP=ALF*Y(I) DO 1 J=1,L JP=JA(K) IF (JP.GT.0) TEMP=TEMP+A(K)*X(JP) K=K+1 1 CONTINUE Z(I)=TEMP 2 CONTINUE RETURN END * SUBROUTINE MXSRMM ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF TRANSPOSE OF A DENSE RECTANGULAR MATRIX A BY * A VECTOR X. * * PARAMETERS : * II N NUMBER OF ROWS OF THE MATRIX A. * II NA NUMBER OF COLUMNS OF THE MATRIX A. * II MA NUMBER OF ELEMENTS IN THE FIELD A. * RI A(MA) RECTANGULAR MATRIX STORED AS A TWO-DIMENSIONAL ARRAY. * II IA(NA+1) POSITION OF THE FIRST RORWS ELEMENTS IN THE FIELD A. * II JA(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD A. * RI X(N) INPUT VECTOR. * RO Y(M) OUTPUT VECTOR EQUAL TO TRANS(A)*X. * SUBROUTINE MXSRMM(NA,A,IA,JA,X,Y) INTEGER NA,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),Y(*) DOUBLE PRECISION TEMP INTEGER I,J,K,L,JP DO 2 I=1,NA K=IA(I) L=IA(I+1)-K TEMP=0.0D 0 DO 1 J=1,L JP=JA(K) IF (JP.GT.0) TEMP=TEMP+A(K)*X(JP) K=K+1 1 CONTINUE Y(I)=TEMP 2 CONTINUE RETURN END * SUBROUTINE MXSRSP ALL SYSTEMS 95/12/01 * PURPOSE : CREATE ROW PERMUTATIONS FOR OBTAINING DIAGONAL NONZEROS. * * PARAMETERS : * II N NUMBER OF COLUMNS OF THE MATRIX. * II M NUMBER OF NONZEROS MEMBERS IN THE MATRIX. * II IA(M+1) ROW POINTERS OF THE SPARSE MATRIX. * II JA(M) COLUMN INDICES OF THE SPARSE MATRIX. * IO IP(N) PERMUTATION VECTOR. * II NR NUMBER OF STRUCTURALLY INDEPENDENT ROWS. * IA IW1(N) AMXILIARY VECTOR. * IA IW2(N) AMXILIARY VECTOR. * IA IW3(N) AMXILIARY VECTOR. * IA IW4(N) AMXILIARY VECTOR. * SUBROUTINE MXSRSP(N,IA,JA,IP,NR,IW1,IW2,IW3,IW4) INTEGER N,NR INTEGER IA(*),IP(*),IW1(*),IW2(*),IW3(*),IW4(*),JA(*) INTEGER I,I1,I2,II,J,J1,K,KK,L DO 10 I = 1,N IW2(I) = IA(I+1) - IA(I) - 1 IW3(I) = 0 IP(I) = 0 10 CONTINUE NR = 0 * * MAIN LOOP. * EACH PASS ROUND THIS LOOP EITHER RESULTS IN A NEW ASSIGNMENT * OR GIVES A ROW WITH NO ASSIGNMENT. * DO 100 L = 1,N J = L IW1(J) = -1 DO 70 K = 1,L * * LOOK FOR A CHEAP ASSIGNMENT * I1 = IW2(J) IF (I1.LT.0) GO TO 30 I2 = IA(J+1) - 1 I1 = I2 - I1 DO 20 II = I1,I2 I = JA(II) IF (IP(I).EQ.0) GO TO 80 20 CONTINUE * * NO CHEAP ASSIGNMENT IN ROW. * IW2(J) = -1 * * BEGIN LOOKING FOR ASSIGNMENT CHAIN STARTING WITH ROW J. * 30 CONTINUE IW4(J) = IA(J+1) - IA(J) - 1 * * INNER LOOP. EXTENDS CHAIN BY ONE OR BACKTRACKS. * DO 60 KK = 1,L I1 = IW4(J) IF (I1.LT.0) GO TO 50 I2 = IA(J+1) - 1 I1 = I2 - I1 * * FORWARD SCAN. * DO 40 II = I1,I2 I = JA(II) IF (IW3(I).EQ.L) GO TO 40 * * COLUMN I HAS NOT YET BEEN ACCESSED DURING THIS PASS. * J1 = J J = IP(I) IW3(I) = L IW1(J) = J1 IW4(J1) = I2 - II - 1 GO TO 70 40 CONTINUE * * BACKTRACKING STEP. * 50 CONTINUE J = IW1(J) IF (J.EQ.-1) GO TO 100 60 CONTINUE 70 CONTINUE * * NEW ASSIGNMENT IS MADE. * 80 CONTINUE IP(I) = J IW2(J) = I2 - II - 1 NR = NR + 1 DO 90 K = 1,L J = IW1(J) IF (J.EQ.-1) GO TO 100 II = IA(J+1) - IW4(J) - 2 I = JA(II) IP(I) = J 90 CONTINUE 100 CONTINUE * * IF MATRIX IS STRUCTURALLY SINGULAR, WE NOW COMPLETE THE * PERMUTATION IP. * IF (NR.EQ.N) RETURN DO 110 I = 1,N IW2(I) = 0 110 CONTINUE K = 0 DO 130 I = 1,N IF (IP(I).NE.0) GO TO 120 K = K + 1 IW4(K) = I GO TO 130 120 CONTINUE J = IP(I) IW2(J) = I 130 CONTINUE K = 0 DO 140 I = 1,N IF (IW2(I).NE.0) GO TO 140 K = K + 1 L = IW4(K) IP(L) = I 140 CONTINUE RETURN END * SUBROUTINE MXSSDA ALL SYSTEMS 91/12/01 * PURPOSE : * A SPARSE SYMMETRIC MATRIX A IS AUGMENTED BY THE SCALED UNIT MATRIX * SUCH THAT A:=A+ALF*I (I IS THE UNIT MATRIX OF ORDER N). * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * RI ALF SCALING FACTOR. * SUBROUTINE MXSSDA(N,A,IA,ALF) INTEGER N,IA(*) DOUBLE PRECISION A(*), ALF INTEGER I DO 100 I=1,N A(IA(I))=A(IA(I))+ALF 100 CONTINUE RETURN END * FUNCTION MXSSDL ALL SYSTEMS 88/12/01 * PURPOSE : * DETERMINATION OF A MINIMUM DIAGONAL ELEMENT OF A SPARSE SYMMETRIC * MATRIX * * PARAMETERS : * II N ORDER OF THE MATRIX A * RI A(MMAX) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * USUAL FORM. * II IA(N+1) POINTER VECTOR OF THE DIAGONAL OF THE SPARSE MATRIX. * II JA(MMAX) INDICES OF NONZERO ELEMENTS OF THE SPARSE MATRIX. * IO INF INDEX OF INIMUM DIAGONAL ELEMENT OF THE MATRIX A. * RR MXSSDL MINIMUM DIAGONAL ELEMENT OF THE MATRIX A. * FUNCTION MXSSDL(N,A,IA,JA,INF) INTEGER N,IA(*),JA(*),INF DOUBLE PRECISION A(*),MXSSDL DOUBLE PRECISION CON PARAMETER (CON=1.0D 60) INTEGER I,J INF=0 MXSSDL = CON DO 100 I=1,N J=IA(I) IF (JA(J).GT.0.AND.MXSSDL.GT.A(J)) THEN INF=I MXSSDL=A(J) END IF 100 CONTINUE RETURN END * SUBROUTINE MXSSMD ALL SYSTEMS 93/12/01 * PURPOSE : * MULTIPLICATION OF A SPARSE SYMMETRIC MATRIX A BY A VECTOR X * AND ADDITION OF A SCALED VECTOR ALF*Y. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * RI X(N) INPUT VECTOR. * RI ALF SCALING FACTOR. * RI Y(NA) INPUT VECTOR. * RO Z(NA) OUTPUT VECTOR EQUAL TO A*X+ALF*Y. * SUBROUTINE MXSSMD(N,A,IA,JA,X,ALF,Y,Z) INTEGER N,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),ALF,Y(*),Z(*) INTEGER I,J,K,JSTRT,JSTOP DO 100 I=1,N Z(I)=ALF*Y(I) 100 CONTINUE JSTOP=0 DO 300 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN DO 200 J=JSTRT,JSTOP K=JA(J) IF (J.EQ.JSTRT) THEN Z(I)=Z(I)+A(J)*X(I) ELSE IF (K.GT.0) THEN Z(K)=Z(K)+A(J)*X(I) Z(I)=Z(I)+A(J)*X(K) END IF 200 CONTINUE END IF 300 CONTINUE RETURN END * SUBROUTINE MXSSMG ALL SYSTEMS 91/12/01 * PURPOSE : * GERSHGORIN BOUNDS OF THE EIGENVALUAE OF A DENSE SYMMETRIC MATRIX. * AMIN .LE. ANY EIGENVALUE OF A .LE. AMAX. * * PARAMETERS : * II N DIMENSION OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * RO AMIN LOWER BOUND OF THE EIGENVALUE OF A. * RO AMAX UPPER BOUND OF THE EIGENVALUE OF A. * SUBROUTINE MXSSMG(N,A,IA,JA,AMIN,AMAX,X) INTEGER N,IA(*),JA(*) DOUBLE PRECISION A(*),AMIN,AMAX,X(*) INTEGER I,J,K,JSTRT,JSTOP DOUBLE PRECISION CMAX PARAMETER (CMAX=1.0D 60) DO 1 I=1,N X(I)=0.0D 0 1 CONTINUE JSTOP=0 DO 3 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN DO 2 K=JSTRT+1,JSTOP J=JA(K) IF (J.GT.0) THEN X(I)=X(I)+ABS(A(K)) X(J)=X(J)+ABS(A(K)) END IF 2 CONTINUE END IF 3 CONTINUE AMIN= CMAX AMAX=-CMAX DO 4 I=1,N K=IA(I) IF (K.GT.0) THEN AMAX=MAX(AMAX,A(K)+X(I)) AMIN=MIN(AMIN,A(K)-X(I)) END IF 4 CONTINUE RETURN END * SUBROUTINE MXSSMI ALL SYSTEMS 92/12/01 * PURPOSE : * SPARSE SYMMETRIC MATRIX A IS SET TO THE UNIT MATRIX WITH THE SAME * ORDER. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RU A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * SUBROUTINE MXSSMI(N,A,IA) INTEGER N,IA(*) DOUBLE PRECISION A(*) INTEGER I,K DO 100 I=1,IA(N+1)-1 A(I)=0.0D 0 100 CONTINUE DO 200 I=1,N K=ABS(IA(I)) A(K)=1.0D 0 200 CONTINUE RETURN END * SUBROUTINE MXSSMM ALL SYSTEMS 92/12/01 * PURPOSE : * MULTIPLICATION OF A SPARSE SYMMETRIC MATRIX BY A VECTOR X. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * II M NUMBER OF NONZERO ELEMENTS OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y := A * X. * SUBROUTINE MXSSMM(N,A,IA,JA,X,Y) INTEGER N,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),Y(*) INTEGER I,J,K,JSTRT,JSTOP DO 100 I=1,N Y(I)=0.0D 0 100 CONTINUE JSTOP=0 DO 300 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN DO 200 J=JSTRT,JSTOP K=JA(J) IF (J.EQ.JSTRT) THEN Y(I)=Y(I)+A(J)*X(I) ELSE IF (K.GT.0) THEN Y(K)=Y(K)+A(J)*X(I) Y(I)=Y(I)+A(J)*X(K) END IF 200 CONTINUE END IF 300 CONTINUE RETURN END * SUBROUTINE MXSSMN ALL SYSTEMS 89/12/01 * PURPOSE : * THIS SUBROUTINE FINDS THE PERMUTATION VECTOR PERM FOR THE * SPARSE SYMMETRIC MATRIX GIVEN IN THE VECTOR PAIR PA,SA.IT USES * THE SO-CALLED NESTED DISSECTION METHOD. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * II MMAX LENGTH OF THE PRINCIPAL MATRIX VECTORS. * II PA(N+1) POINTER VECTOR OF THE INPUT MATRIX. * II SA(MMAX) VECTOR OF THE COLUMN INDICES OF THE INPUT MATRIX. * IO PERM(N) PERMUTATION VECTOR. * IA WN11(N+1) AMXILIARY VECTOR. * IA WN12(N+1) AMXILIARY VECTOR. * IA WN13(N+1) AMXILIARY VECTOR. * * METHOD : * NESTED DISSECTION METHOD * SUBROUTINE MXSSMN(N,PA,SA,PERM,WN11,WN12,WN13) INTEGER N INTEGER PA(*),SA(*),PERM(*) INTEGER WN11(*),WN12(*),WN13(*) INTEGER I,J,K,NUM,ROOT,NLVL,LVLEND,LBEGIN,ICS INTEGER NN,N1,MINDEG,N2,LVSIZE,NDEG,NUNLVL,MIDLVL INTEGER TEMP,NPUL,NSEP,I1,I2,I3,I4,J1,J2 DO 100 I = 1, N WN11(I) = 1 100 CONTINUE NUM= 0 DO 2000 I = 1, N 200 IF ( WN11(I) .EQ. 0 ) GO TO 2000 ROOT = I WN11(ROOT) = 0 WN13(1) = ROOT NLVL = 0 LVLEND = 0 ICS = 1 300 LBEGIN = LVLEND + 1 LVLEND = ICS NLVL = NLVL + 1 WN12(NLVL) = LBEGIN DO 500 K = LBEGIN, LVLEND NN = WN13(K) DO 400 J=PA(NN),PA(NN+1)-1 N2 = SA(J) IF (N2.EQ.NN) GO TO 400 IF (WN11(N2).EQ.0) GO TO 400 ICS = ICS + 1 WN13(ICS) = N2 WN11(N2) = 0 400 CONTINUE 500 CONTINUE LVSIZE=ICS-LVLEND IF (LVSIZE.GT.0) GO TO 300 WN12(NLVL+1) = LVLEND + 1 DO 600 K = 1, ICS NN = WN13(K) WN11(NN) = 1 600 CONTINUE ICS = WN12(NLVL+1) - 1 IF ( NLVL .EQ. 1 .OR. NLVL .EQ. ICS )GO TO 1470 700 J1 = WN12(NLVL) MINDEG = ICS ROOT = WN13(J1) IF ( ICS .EQ. J1 ) GO TO 1000 DO 900 J = J1, ICS NN = WN13(J) NDEG = 0 DO 800 K=PA(NN),PA(NN+1)-1 N1 = SA(K) IF (N1.EQ.NN) GO TO 800 IF ( WN11(N1) .GT. 0 ) NDEG = NDEG + 1 800 CONTINUE IF ( NDEG .GE. MINDEG ) GO TO 900 ROOT = NN MINDEG = NDEG 900 CONTINUE 1000 CONTINUE WN11(ROOT) = 0 WN13(1) = ROOT NUNLVL = 0 LVLEND = 0 ICS = 1 1100 LBEGIN = LVLEND + 1 LVLEND = ICS NUNLVL = NUNLVL + 1 WN12(NUNLVL) = LBEGIN DO 1300 K = LBEGIN, LVLEND NN = WN13(K) DO 1200 J=PA(NN),PA(NN+1)-1 N2 = SA(J) IF (N2.EQ.NN) GO TO 1200 IF (WN11(N2).EQ.0) GO TO 1200 ICS = ICS + 1 WN13(ICS) = N2 WN11(N2) = 0 1200 CONTINUE 1300 CONTINUE LVSIZE=ICS-LVLEND IF (LVSIZE.GT.0) GO TO 1100 WN12(NUNLVL+1) = LVLEND + 1 DO 1400 K = 1, ICS NN = WN13(K) WN11(NN) = 1 1400 CONTINUE IF (NUNLVL .LE.NLVL) GO TO 1470 NLVL=NUNLVL IF (NLVL.LT.ICS) GO TO 700 1470 CONTINUE IF ( NLVL .GE. 3 ) GO TO 1600 NSEP = WN12(NLVL+1) - 1 DO 1500 K = 1, NSEP NN = WN13(K) PERM(NUM+K) = NN WN11(NN) = 0 1500 CONTINUE GO TO 1950 1600 MIDLVL = (NLVL+2)/2 I3 = WN12(MIDLVL) I1 = WN12(MIDLVL + 1) I4 = I1 - 1 I2 = WN12(MIDLVL+2) - 1 DO 1700 K = I1, I2 NN = WN13(K) PA(NN) = - PA(NN) 1700 CONTINUE NSEP = 0 DO 1800 K = I3, I4 NN = WN13(K) J1 = PA(NN) J2 = IABS(PA(NN+1)) - 1 DO 1750 J = J1, J2 N2 = SA(J) IF (N2.EQ.NN) GO TO 1750 IF ( PA(N2) .GT. 0 ) GO TO 1750 NSEP = NSEP + 1 PERM(NSEP+NUM) = NN WN11(NN) = 0 GO TO 1800 1750 CONTINUE 1800 CONTINUE DO 1900 K = I1, I2 NN = WN13(K) PA(NN) = - PA(NN) 1900 CONTINUE 1950 CONTINUE NUM = NUM + NSEP IF ( NUM .GE. N ) GO TO 2100 GO TO 200 2000 CONTINUE 2100 CONTINUE IF (N.LT.2) GO TO 2300 NPUL = N/2 DO 2200 I=1,NPUL TEMP=PERM(I) PERM(I)=PERM(N-I+1) PERM(N-I+1)=TEMP 2200 CONTINUE 2300 CONTINUE RETURN END * FUNCTION MXSSMQ ALL SYSTEMS 92/12/01 * PURPOSE : * VALUE OF A QUADRATIC FORM WITH A SPARSE SYMMETRIC MATRIX A. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RR MXSSMQ VALUE OF THE QUADRATIC FORM MXSSMQ=TRANS(Y)*A*X. * FUNCTION MXSSMQ(N,A,IA,JA,X,Y) INTEGER N,IA(*),JA(*) DOUBLE PRECISION A(*), X(*), Y(*), MXSSMQ DOUBLE PRECISION TEMP1,TEMP2 INTEGER I,J,K,JSTRT,JSTOP JSTOP=0 TEMP1=0.0D 0 DO 300 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN TEMP2=0.0D 0 DO 200 J=JSTRT,JSTOP K=JA(J) IF (J.EQ.JSTRT) THEN TEMP2=TEMP2+A(J)*Y(I) ELSE IF (K.GT.0) THEN TEMP2=TEMP2+2*Y(K)*A(J) END IF 200 CONTINUE TEMP1=TEMP1+X(I)*TEMP2 END IF 300 CONTINUE MXSSMQ=TEMP1 RETURN END * SUBROUTINE MXSSMY ALL SYSTEMS 93/12/01 * PURPOSE : * CORRECTION OF A SPARSE SYMMETRIC MATRIX A. THE CORRECTION IS DEFINED * AS A:=A+SUM OF (HALF*(X*TRANS(Y)+Y*TRANS(X)))(I)/SIGMA(I) WHERE * SIGMA(I) IS A DOT PRODUCT TRANS(X)*X WHERE ONLY CONTRIBUTIONS * CORRESPONDING TO NONZEROS IN ROW I ARE SUMMED UP, X AND Y ARE GIVEN * VECTORS. * * PARAMETERS : * II N ORDER OF THE MATRIX A. * RI A(M) ELEMENTS OF THE SPARSE SYMMETRIC MATRIX STORED IN THE * PACKED FORM. * II IA(N) POINTERS OF THE DIAGONAL ELEMENTS OF A. * II JA(M) INDICES OF THE NONZERO ELEMENTS OF A. * RA XS(N) AMXILIARY VECTOR - USED FOR SIGMA(I). * RI X(N) VECTOR IN THE CORRECTION TERM. * RI Y(N) VECTOR IN THE CORRECTION TERM. * SUBROUTINE MXSSMY(N,A,IA,JA,XS,X,Y) INTEGER N,IA(*),JA(*) DOUBLE PRECISION A(*),X(*),Y(*),XS(*),SIGMA,TEMP INTEGER I,J,K,JSTRT,JSTOP CALL MXVSET(N,0.0D 0,XS) * * COMPUTE SIGMA(I) * JSTOP=0 DO 200 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN SIGMA=0.0D 0 DO 100 J=JSTRT,JSTOP K=JA(J) IF (K.GT.0) THEN SIGMA=SIGMA+Y(K)*Y(K) IF (K.NE.I) XS(K)=XS(K)+Y(I)*Y(I) END IF 100 CONTINUE XS(I)=XS(I)+SIGMA END IF 200 CONTINUE * * UPDATE MATRIX * JSTOP=0 DO 400 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 IF (JA(JSTRT).GT.0) THEN IF (XS(I).EQ.0.0D 0) THEN TEMP=0.0D 0 ELSE TEMP=X(I)/XS(I) END IF DO 300 J=JSTRT,JSTOP K=JA(J) IF (K.GT.0) THEN IF (XS(K).EQ.0.0D 0) THEN A(J)=A(J)+0.5D 0*TEMP*Y(K) ELSE A(J)=A(J)+0.5D 0*(TEMP*Y(K)+Y(I)*X(K)/XS(K)) END IF END IF 300 CONTINUE END IF 400 CONTINUE RETURN END * SUBROUTINE MXSTG1 ALL SYSTEMS 89/12/01 * PURPOSE : * WIDTHENING THE PACKED FORM OF THE VECTORS IA, JA OF THE SPARSE MATRIX * * PARAMETERS : * II N ORDER OF THE SPARSE MATRIX. * IU M NUMBER OF NONZERO ELEMENTS IN THE MATRIX. * II MMAX LENGTH OF THE ARRAY JA. * II IA(N+1) POINTER VECTOR OF THE INPUT MATRIX. * II JA(MMAX) VECTOR OF THE COLUMN INDICES OF THE INPUT MATRIX. * IA PD(N+1) AMXILIARY VECTOR. * IA WN11(N+1) AMXILIARY VECTOR. * SUBROUTINE MXSTG1(N,M,IA,JA,PD,WN11) INTEGER N,M INTEGER IA(*),PD(*),JA(*),WN11(*) INTEGER I,J,L1,L,K * * UPPER TRIANGULAR INFORMATION TO THE AMXILIARY ARRAY * L1=IA(1) DO 100 I=1,N L=L1 L1=IA(I+1) WN11(I)=L1-L 100 CONTINUE * * LOWER TRIANGULAR INFORMATION TO THE AMXILIARY ARRAY * DO 300 I=1,N DO 200 J=IA(I)+1,IA(I+1)-1 K=ABS(JA(J)) WN11(K)=WN11(K)+1 200 CONTINUE 300 CONTINUE * * BY PARTIAL SUMMING WE GET POINTERS OF THE WIDE STRUCTURE * WN11(I) POINTS AT THE END OF THE ROW I * L=0 DO 400 I=2,N WN11(I)=WN11(I)+WN11(I-1) 400 CONTINUE * * DEFINE LENGTH OF THE WITHENED STRUCTURE * M=WN11(N) * * SHIFT OF UPPER TRIANGULAR ROWS * PD(1)=1 DO 600 I=N,1,-1 L=WN11(I) PD(I+1)=L+1 DO 500 J=IA(I+1)-1,IA(I),-1 JA(L)=JA(J) L=L-1 500 CONTINUE 600 CONTINUE * * FORMING OF THE LOWER TRIANGULAR PART * DO 800 I=1,N DO 700 J=WN11(I)+IA(I)+2-IA(I+1),WN11(I) K=ABS(JA(J)) JA(PD(K))=I PD(K)=PD(K)+1 700 CONTINUE 800 CONTINUE DO 900 I=1,N IA(I+1)=WN11(I)+1 900 CONTINUE RETURN END * SUBROUTINE MXSTL1 ALL SYSTEMS 91/12/01 * PURPOSE : * PACKING OF THE WIDTHENED FORM OF THE VECTORS IA, JA OF THE SPARSE * MATRIX * * PARAMETERS : * II N ORDER OF THE SPARSE MATRIX. * IU M NUMBER OF NONZERO ELEMENTS IN THE MATRIX. * II MMAX LENGTH OF THE ARRAY JA. * IU IA(N+1) POINTER VECTOR OF THE INPUT MATRIX. * IU JA(MMAX) VECTOR OF THE COLUMN INDICES OF THE INPUT MATRIX. * IA PD(N+1) AMXILIARY VECTOR. * SUBROUTINE MXSTL1(N,M,IA,JA,PD) INTEGER N,M INTEGER IA(*),PD(*),JA(*) INTEGER I,J,L,JSTRT,JSTOP L=1 * * PD DEFINITION * JSTOP=0 DO 60 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 DO 50 J=JSTRT,JSTOP IF (ABS(JA(J)).EQ.I) THEN PD(I)=J GO TO 60 END IF 50 CONTINUE 60 CONTINUE * * REWRITE THE STRUCTURE * DO 200 I=1,N DO 100 J=PD(I),IA(I+1)-1 JA(L)=JA(J) L=L+1 100 CONTINUE IA(I+1)=L 200 CONTINUE IA(1)=1 * * SET THE LENGTH OF THE PACKED STRUCTURE * M=L-1 RETURN END * SUBROUTINE MXSTL2 ALL SYSTEMS 90/12/01 * PURPOSE : * PACKING OF THE WIDTHENED FORM OF THE VECTORS A,IA,JA OF THE SPARSE * MATRIX * * PARAMETERS : * II N ORDER OF THE SPARSE MATRIX. * IU M NUMBER OF NONZERO ELEMENTS IN THE MATRIX. * II MMAX LENGTH OF THE ARRAY JA. * RU A(MMAX) VECTOR OF NUMERICAL VALUES OF THE MATRIX BEING SHRINKED. * IU IA(N+1) POINTER VECTOR OF THE INPUT MATRIX. * IU JA(MMAX) VECTOR OF THE COLUMN INDICES OF THE INPUT MATRIX. * IA PD(N+1) AMXILIARY VECTOR. * SUBROUTINE MXSTL2(N,M,A,IA,JA,PD) INTEGER N,M INTEGER IA(*),PD(*),JA(*) DOUBLE PRECISION A(*) INTEGER I,J,L,JSTRT,JSTOP L=1 * * PD DEFINITION * JSTOP=0 DO 60 I=1,N JSTRT=JSTOP+1 JSTOP=IA(I+1)-1 DO 50 J=JSTRT,JSTOP IF (ABS(JA(J)).EQ.I) THEN PD(I)=J GO TO 60 END IF 50 CONTINUE 60 CONTINUE * * REWRITE THE STRUCTURE * DO 200 I=1,N DO 100 J=PD(I),IA(I+1)-1 JA(L)=JA(J) A(L)=A(J) L=L+1 100 CONTINUE IA(I+1)=L 200 CONTINUE IA(1)=1 * * SET THE LENGTH OF THE PACKED STRUCTURE * M=L-1 RETURN END * SUBROUTINE MXTPGB ALL SYSTEMS 93/12/01 * PURPOSE : * BACK SUBSTITUTION FOR A DECOMPOSED TRIDIAGONAL MATRIX. * * PARAMETERS : * II N ORDER OF THE TRIDIAGONAL MATRIX T. * RI D(N) ELEMENTS OF THE DIAGONAL MATRIX D IN THE DECOMPOSITION * T=L*D*TRANS(L). * RI E(N) SUBDIAGONAL ELEMENTS OF THE LOWER TRIANGULAR MATRIX L IN * THE DECOMPOSITION T=L*D*TRANS(L). * RU X(N) ON INPUT THE RIGHT HAND SIDE OF A SYSTEM OF LINEAR * EQUATIONS. ON OUTPUT THE SOLUTION OF A SYSTEM OF LINEAR * EQUATIONS. * II JOB OPTION. IF JOB=0 THEN X:=T**(-1)*X. IF JOB>0 THEN * X:=L**(-1)*X. IF JOB<0 THEN X:=TRANS(L)**(-1)*X. * SUBROUTINE MXTPGB(N,D,E,X,JOB) INTEGER N,JOB DOUBLE PRECISION D(*),E(*),X(*) INTEGER I IF (JOB.GE.0) THEN * * PHASE 1 : X:=L**(-1)*X * DO 1 I=2,N X(I)=X(I)-X(I-1)*E(I-1) 1 CONTINUE END IF IF (JOB.EQ.0) THEN * * PHASE 2 : X:=D**(-1)*X * DO 2 I=1,N X(I)=X(I)/D(I) 2 CONTINUE END IF IF (JOB.LE.0) THEN * * PHASE 3 : X:=TRANS(L)**(-1)*X * DO 3 I=N-1,1,-1 X(I)=X(I)-X(I+1)*E(I) 3 CONTINUE END IF RETURN END * SUBROUTINE MXTPGF ALL SYSTEMS 03/12/01 * PURPOSE : * CHOLESKI DECOMPOSITION OF A TRIDIAGONAL MATRIX. * * PARAMETERS : * II N ORDER OF THE TRIDIAGONAL MATRIX T. * RU D(N) ON INPUT DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T. * ON OUTPUT ELEMENTS OF THE DIAGONAL MATRIX D IN THE * DECOMPOSITION T=L*D*TRANS(L). * RU E(N) ON INPUT SUBDIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T. * ON OUTPUT SUBDIAGONAL ELEMENTS OF THE LOWER TRIANGULAR MATRIX L * IN THE DECOMPOSITION T=L*D*TRANS(L). * IO INF AN INFORMATION OBTAINED IN THE FACTORIZATION PROCESS. IF * INF=0 THEN A IS SUFFICIENTLY POSITIVE DEFINITE AND E=0. IF * INF<0 THEN A IS NOT SUFFICIENTLY POSITIVE DEFINITE AND E>0. IF * INF>0 THEN A IS INDEFINITE AND INF IS AN INDEX OF THE * MOST NEGATIVE DIAGONAL ELEMENT USED IN THE FACTORIZATION * PROCESS. * RU ALF ON INPUT A DESIRED TOLERANCE FOR POSITIVE DEFINITENESS. ON * OUTPUT THE MOST NEGATIVE DIAGONAL ELEMENT USED IN THE * FACTORIZATION PROCESS (IF INF>0). * RO TAU MAXIMUM DIAGONAL ELEMENT OF THE MATRIX E. * SUBROUTINE MXTPGF(N,D,E,INF,ALF,TAU) INTEGER N,INF DOUBLE PRECISION D(*),E(*),ALF,TAU DOUBLE PRECISION DI,EI,BET,GAM,DEL,TOL INTEGER I,L DOUBLE PRECISION ZERO,ONE,TWO PARAMETER (ZERO=0.0D 0,ONE=1.0D 0,TWO=2.0D 0) L=0 INF=0 TOL=ALF * * ESTIMATION OF THE MATRIX NORM * ALF=ZERO GAM=ZERO TAU=ZERO BET=ABS(D(1)) DO 1 I=1,N-1 BET=MAX(BET,ABS(D(I+1))) GAM=MAX(GAM,ABS(E(I))) 1 CONTINUE BET=MAX(TOL,TWO*BET,GAM/MAX(ONE,DBLE(N-1))) DEL=TOL*MAX(BET,ONE) DO 2 I=1,N EI=D(I) IF (ALF.GT.EI) THEN ALF=EI L=I END IF GAM=ZERO IF (I.LT.N) GAM=E(I)**2 DI=MAX(ABS(EI),GAM/BET,DEL) IF (TAU.LT.DI-EI) THEN TAU=DI-EI INF=-1 END IF * * GAUSSIAN ELIMINATION * D(I)=DI IF (I.LT.N) THEN EI=E(I) E(I)=EI/DI D(I+1)=D(I+1)-E(I)*EI END IF 2 CONTINUE IF (L.GT.0.AND.ABS(ALF).GT.DEL) INF = L RETURN END * SUBROUTINE MXUCOP ALL SYSTEMS 99/12/01 * PURPOSE : * COPY OF THE VECTOR WITH INITIATION OF THE ACTIVE PART. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * SUBROUTINE MXUCOP(N,X,Y,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION X(*),Y(*) INTEGER I IF (JOB.EQ.0) THEN DO 1 I=1,N Y(I)=X(I) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) THEN Y(I)=X(I) ELSE Y(I)=0.0D 0 END IF 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) THEN Y(I)=X(I) ELSE Y(I)=0.0D 0 END IF 3 CONTINUE END IF RETURN END * FUNCTION MXUDEL ALL SYSTEMS 99/12/01 * PURPOSE : * SQUARED NORM OF A SHIFTED VECTOR IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A SCALING FACTOR. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * RR MXUDEL SQUARED NORM OF Y+A*X. * FUNCTION MXUDEL(N,A,X,Y,IX,JOB) INTEGER N,IX(N),JOB DOUBLE PRECISION A,X(N),Y(N),MXUDEL INTEGER I DOUBLE PRECISION TEMP TEMP=0.0D 0 IF (JOB.EQ.0) THEN DO 1 I=1,N TEMP=TEMP+(Y(I)+A*X(I))**2 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) TEMP=TEMP+(Y(I)+A*X(I))**2 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) TEMP=TEMP+(Y(I)+A*X(I))**2 3 CONTINUE END IF MXUDEL=TEMP RETURN END * SUBROUTINE MXUDIF ALL SYSTEMS 99/12/01 * PURPOSE : * VECTOR DIFFERENCE IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= X - Y. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * SUBROUTINE MXUDIF(N,X,Y,Z,IX,JOB) INTEGER N,IX(N),JOB DOUBLE PRECISION X(*),Y(*),Z(*) INTEGER I IF (JOB.EQ.0) THEN DO 1 I=1,N Z(I)=X(I)-Y(I) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) Z(I)=X(I)-Y(I) 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) Z(I)=X(I)-Y(I) 3 CONTINUE END IF RETURN END * SUBROUTINE MXUDIR ALL SYSTEMS 99/12/01 * PURPOSE : * VECTOR AUGMENTED BY THE SCALED VECTOR IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A SCALING FACTOR. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= Y + A*X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * SUBROUTINE MXUDIR(N,A,X,Y,Z,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION A, X(*), Y(*), Z(*) INTEGER I IF (JOB.EQ.0) THEN DO 1 I=1,N Z(I) = Y(I) + A*X(I) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) Z(I) = Y(I) + A*X(I) 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) Z(I) = Y(I) + A*X(I) 3 CONTINUE END IF RETURN END * FUNCTION MXUDOT ALL SYSTEMS 99/12/01 * PURPOSE : * DOT PRODUCT OF VECTORS IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * RR MXUDOT VALUE OF DOT PRODUCT MXUDOT=TRANS(X)*Y. * FUNCTION MXUDOT(N,X,Y,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION X(*),Y(*),MXUDOT DOUBLE PRECISION TEMP INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO = 0.0D 0) TEMP = ZERO IF (JOB.EQ.0) THEN DO 1 I=1,N TEMP=TEMP+X(I)*Y(I) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) TEMP=TEMP+X(I)*Y(I) 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) TEMP=TEMP+X(I)*Y(I) 3 CONTINUE END IF MXUDOT=TEMP RETURN END * SUBROUTINE MXUNEG ALL SYSTEMS 00/12/01 * PURPOSE : * COPY OF THE VECTOR WITH INITIATION OF THE ACTIVE PART. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * SUBROUTINE MXUNEG(N,X,Y,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION X(*),Y(*) INTEGER I IF (JOB.EQ.0) THEN DO 1 I=1,N Y(I)=-X(I) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) THEN Y(I)=-X(I) ELSE Y(I)=0.0D 0 END IF 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) THEN Y(I)=-X(I) ELSE Y(I)=0.0D 0 END IF 3 CONTINUE END IF RETURN END * FUNCTION MXUNOR ALL SYSTEMS 99/12/01 * PURPOSE : * EUCLIDEAN NORM OF A VECTOR IN A BOUND CONSTRAINED CASE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * RR MXUNOR EUCLIDEAN NORM OF X. * FUNCTION MXUNOR(N,X,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION X(*),MXUNOR DOUBLE PRECISION POM,DEN INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D 0) DEN=ZERO IF (JOB.EQ.0) THEN DO 1 I=1,N DEN=MAX(DEN,ABS(X(I))) 1 CONTINUE ELSE IF (JOB.GT.0) THEN DO 2 I=1,N IF (IX(I).GE. 0) DEN=MAX(DEN,ABS(X(I))) 2 CONTINUE ELSE DO 3 I=1,N IF (IX(I).NE.-5) DEN=MAX(DEN,ABS(X(I))) 3 CONTINUE END IF POM=ZERO IF (DEN.GT.ZERO) THEN IF (JOB.EQ.0) THEN DO 4 I=1,N POM=POM+(X(I)/DEN)**2 4 CONTINUE ELSE IF (JOB.GT.0) THEN DO 5 I=1,N IF (IX(I).GE. 0) POM=POM+(X(I)/DEN)**2 5 CONTINUE ELSE DO 6 I=1,N IF (IX(I).NE.-5) POM=POM+(X(I)/DEN)**2 6 CONTINUE END IF END IF MXUNOR=DEN*SQRT(POM) RETURN END * SUBROUTINE MXUZER ALL SYSTEMS 99/12/01 * PURPOSE : * VECTOR ELEMENTS CORRESPONDING TO ACTIVE BOUNDS ARE SET TO ZERO. * * PARAMETERS : * II N VECTOR DIMENSION. * RO X(N) OUTPUT VECTOR SUCH THAT X(I)=A FOR ALL I. * II IX(N) VECTOR CONTAINING TYPES OF BOUNDS. * II JOB OPTION. IF JOB.GT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).LE.-1. IF JOB.LT.0 THEN INDEX I IS NOT USED WHENEVER * IX(I).EQ.-5. * SUBROUTINE MXUZER(N,X,IX,JOB) INTEGER N,IX(*),JOB DOUBLE PRECISION X(*) INTEGER I IF (JOB.EQ.0) RETURN DO 1 I=1,N IF (IX(I).LT.0) X(I)=0.0D 0 1 CONTINUE RETURN END * SUBROUTINE MXVCOP ALL SYSTEMS 88/12/01 * PURPOSE : * COPYING OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= X. * SUBROUTINE MXVCOP(N,X,Y) INTEGER N DOUBLE PRECISION X(*),Y(*) INTEGER I DO 10 I = 1,N Y(I) = X(I) 10 CONTINUE RETURN END * SUBROUTINE MXVCOR ALL SYSTEMS 93/12/01 * PURPOSE : * CORRECTION OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A CORRECTION FACTOR. * RU X(N) CORRECTED VECTOR. ZERO ELEMENTS OF X ARE SET TO BE EQUAL A. * SUBROUTINE MXVCOR(N,A,X) INTEGER N DOUBLE PRECISION A,X(*) DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D 0) INTEGER I DO 1 I=1,N IF (X(I).EQ.ZERO) X(I)=A 1 CONTINUE RETURN END * SUBROUTINE MXVDIF ALL SYSTEMS 88/12/01 * PURPOSE : * VECTOR DIFFERENCE. * * PARAMETERS : * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= X - Y. * SUBROUTINE MXVDIF(N,X,Y,Z) INTEGER N DOUBLE PRECISION X(*),Y(*),Z(*) INTEGER I DO 10 I = 1,N Z(I) = X(I) - Y(I) 10 CONTINUE RETURN END * SUBROUTINE MXVDIR ALL SYSTEMS 91/12/01 * PURPOSE : * VECTOR AUGMENTED BY THE SCALED VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A SCALING FACTOR. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= Y + A*X. * SUBROUTINE MXVDIR(N,A,X,Y,Z) DOUBLE PRECISION A INTEGER N DOUBLE PRECISION X(*),Y(*),Z(*) INTEGER I DO 10 I = 1,N Z(I) = Y(I) + A*X(I) 10 CONTINUE RETURN END * FUNCTION MXVDOT ALL SYSTEMS 91/12/01 * PURPOSE : * DOT PRODUCT OF TWO VECTORS. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RR MXVDOT VALUE OF DOT PRODUCT MXVDOT=TRANS(X)*Y. * FUNCTION MXVDOT(N,X,Y) INTEGER N DOUBLE PRECISION X(*),Y(*),MXVDOT DOUBLE PRECISION TEMP INTEGER I TEMP = 0.0D0 DO 10 I = 1,N TEMP = TEMP + X(I)*Y(I) 10 CONTINUE MXVDOT = TEMP RETURN END * SUBROUTINE MXVICP ALL SYSTEMS 93/12/01 * PURPOSE : * COPYING OF AN INTEGER VECTOR. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * II IX(N) INPUT INTEGER VECTOR. * IO IY(N) OUTPUT INTEGER VECTOR SUCH THAT IY(I):= IX(I) FOR ALL I. * SUBROUTINE MXVICP(N,IX,IY) INTEGER N,IX(*),IY(*) INTEGER I DO 1 I=1,N IY(I)=IX(I) 1 CONTINUE RETURN END * SUBROUTINE MXVINB ALL SYSTEMS 91/12/01 * PURPOSE : * UPDATE OF AN INTEGER VECTOR. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * II M DIMENSION OF THE CHANGED INTEGER VECTOR. * II IX(N) INTEGER VECTOR. * IU JA(M) INTEGER VECTOR WHICH IS UPDATED SO THAT JA(I)=-JA(I) * IF IX(JA(I)).LT.0. * SUBROUTINE MXVINB(M,IX,JA) INTEGER M,IX(*),JA(*) INTEGER I DO 1 I=1,M JA(I)=ABS(JA(I)) IF (IX(JA(I)).LT.0) JA(I)=-JA(I) 1 CONTINUE RETURN END * SUBROUTINE MXVINE ALL SYSTEMS 94/12/01 * PURPOSE : * ELEMENTS OF THE INTEGER VECTOR ARE REPLACED BY THEIR ABSOLUTE VALUES. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * IU IX(N) INTEGER VECTOR WHICH IS UPDATED SO THAT IX(I):=ABS(IX(I)) * FOR ALL I. * SUBROUTINE MXVINE(N,IX) INTEGER N,IX(*) INTEGER I DO 1 I=1,N IX(I)=ABS(IX(I)) 1 CONTINUE RETURN END * SUBROUTINE MXVINI ALL SYSTEMS 99/12/01 * PURPOSE : * ELEMENTS CORRESPONDING TO FIXED VARIABLES ARE SET TO -5. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * IU IX(N) INTEGER VECTOR WHICH IS UPDATED SO THAT IX(I):=ABS(IX(I)) * FOR ALL I. * SUBROUTINE MXVINI(N,IX) INTEGER N,IX(*) INTEGER I DO 1 I=1,N IF (ABS(IX(I)).EQ.5) IX(I)=-5 1 CONTINUE RETURN END * SUBROUTINE MXVINP ALL SYSTEMS 91/12/01 * PURPOSE : * INITIATION OF A INTEGER PERMUTATION VECTOR. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * IO IP(N) INTEGER VECTOR SUCH THAT IP(I)=I FOR ALL I. * SUBROUTINE MXVINP(N,IP) INTEGER N INTEGER IP(*) INTEGER I DO 10 I = 1,N IP(I) = I 10 CONTINUE RETURN END * SUBROUTINE MXVINS ALL SYSTEMS 90/12/01 * PURPOSE : * INITIATION OF THE INTEGER VECTOR. * * PARAMETERS : * II N DIMENSION OF THE INTEGER VECTOR. * II IP INTEGER PARAMETER. * IO IX(N) INTEGER VECTOR SUCH THAT IX(I)=IP FOR ALL I. * SUBROUTINE MXVINS(N,IP,IX) INTEGER IP,N INTEGER IX(*) INTEGER I DO 10 I = 1,N IX(I) = IP 10 CONTINUE RETURN END * SUBROUTINE MXVLIN ALL SYSTEMS 92/12/01 * PURPOSE : * LINEAR COMBINATION OF TWO VECTORS. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A SCALING FACTOR. * RI X(N) INPUT VECTOR. * RI B SCALING FACTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= A*X + B*Y. * SUBROUTINE MXVLIN(N,A,X,B,Y,Z) INTEGER N DOUBLE PRECISION A, X(*), B, Y(*), Z(*) INTEGER I DO 1 I=1,N Z(I) = A*X(I) + B*Y(I) 1 CONTINUE RETURN END * FUNCTION MXVMAX ALL SYSTEMS 91/12/01 * PURPOSE : * L-INFINITY NORM OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RR MXVMAX L-INFINITY NORM OF THE VECTOR X. * FUNCTION MXVMAX(N,X) INTEGER N DOUBLE PRECISION X(*),MXVMAX INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D 0) MXVMAX=ZERO DO 1 I=1,N MXVMAX=MAX(MXVMAX,ABS(X(I))) 1 CONTINUE RETURN END * FUNCTION MXVMX1 ALL SYSTEMS 91/12/01 * PURPOSE : * L-INFINITY NORM OF A VECTOR WITH INDEX DETERMINATION. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * IO K INDEX OF ELEMENT WITH MAXIMUM ABSOLUTE VALUE. * RR MXVMX1 L-INFINITY NORM OF THE VECTOR X. * FUNCTION MXVMX1(N,X,K) INTEGER K,N DOUBLE PRECISION X(*),MXVMX1 INTEGER I K = 1 MXVMX1 = ABS(X(1)) DO 10 I = 2,N IF (ABS(X(I)).GT.MXVMX1) THEN K = I MXVMX1 = ABS(X(I)) END IF 10 CONTINUE RETURN END * SUBROUTINE MXVMUL ALL SYSTEMS 89/12/01 * PURPOSE : * VECTOR IS PREMULTIPLIED BY THE POWER OF A DIAGONAL MATRIX. * * PARAMETERS : * II N VECTOR DIMENSION. * RI D(N) DIAGONAL MATRIX STORED AS A VECTOR WITH N ELEMENTS. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:=(D**K)*X. * II K INTEGER EXPONENT. * SUBROUTINE MXVMUL(N,D,X,Y,K) INTEGER K,N DOUBLE PRECISION D(*),X(*),Y(*) INTEGER I IF (K.EQ.0) THEN CALL MXVCOP(N,X,Y) ELSE IF (K.EQ.1) THEN DO 10 I = 1,N Y(I) = X(I)*D(I) 10 CONTINUE ELSE IF (K.EQ.-1) THEN DO 20 I = 1,N Y(I) = X(I)/D(I) 20 CONTINUE ELSE DO 30 I = 1,N Y(I) = X(I)*D(I)**K 30 CONTINUE END IF RETURN END * SUBROUTINE MXVNEG ALL SYSTEMS 88/12/01 * PURPOSE : * CHANGE THE SIGNS OF VECTOR ELEMENTS. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= - X. * SUBROUTINE MXVNEG(N,X,Y) INTEGER N DOUBLE PRECISION X(*),Y(*) INTEGER I DO 10 I = 1,N Y(I) = -X(I) 10 CONTINUE RETURN END * FUNCTION MXVNOR ALL SYSTEMS 91/12/01 * PURPOSE : * EUCLIDEAN NORM OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RR MXVNOR EUCLIDEAN NORM OF X. * FUNCTION MXVNOR(N,X) INTEGER N DOUBLE PRECISION X(*),MXVNOR DOUBLE PRECISION DEN,POM INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D0) DEN = ZERO DO 10 I = 1,N DEN = MAX(DEN,ABS(X(I))) 10 CONTINUE POM = ZERO IF (DEN.GT.ZERO) THEN DO 20 I = 1,N POM = POM + (X(I)/DEN)**2 20 CONTINUE END IF MXVNOR = DEN*SQRT(POM) RETURN END * SUBROUTINE MXVSAB ALL SYSTEMS 91/12/01 * PURPOSE : * L-1 NORM OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RR MXVSAB L-1 NORM OF THE VECTOR X. * FUNCTION MXVSAB(N,X) INTEGER N DOUBLE PRECISION X(N),MXVSAB INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO=0.0D 0) MXVSAB=ZERO DO 1 I=1,N MXVSAB=MXVSAB+ABS(X(I)) 1 CONTINUE RETURN END * SUBROUTINE MXVSAV ALL SYSTEMS 91/12/01 * PORTABILITY : ALL SYSTEMS * 91/12/01 LU : ORIGINAL VERSION * * PURPOSE : * DIFFERENCE OF TWO VECTORS RETURNED IN THE SUBSTRACTED ONE. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RU Y(N) UPDATE VECTOR WHERE Y:= X - Y. * SUBROUTINE MXVSAV(N,X,Y) INTEGER N DOUBLE PRECISION X(*),Y(*) DOUBLE PRECISION TEMP INTEGER I DO 10 I = 1,N TEMP = Y(I) Y(I) = X(I) - Y(I) X(I) = TEMP 10 CONTINUE RETURN END * SUBROUTINE MXVSBP ALL SYSTEMS 91/12/01 * PURPOSE : * VECTOR X(N) IS PERMUTED ACCORDING TO THE FORMULA * X(PERM(I)):=X(I). * * PARAMETERS : * II N LENGTH OF VECTORS. * II PERM(N) INPUT PERMUTATION VECTOR. * RU X(N) VECTOR THAT IS TO BE PERMUTED. * RA RN01(N) AMXILIARY VECTOR. * SUBROUTINE MXVSBP(N,PERM,X,RN01) INTEGER N,PERM(*),I DOUBLE PRECISION RN01(*),X(*) DO 100 I=1,N RN01(PERM(I))=X(I) 100 CONTINUE DO 200 I=1,N X(I)=RN01(I) 200 CONTINUE RETURN END * SUBROUTINE MXVSCL ALL SYSTEMS 88/12/01 * PURPOSE : * SCALING OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI A SCALING FACTOR. * RO Y(N) OUTPUT VECTOR WHERE Y:= A*X. * SUBROUTINE MXVSCL(N,A,X,Y) INTEGER N DOUBLE PRECISION A, X(*), Y(*) INTEGER I DO 1 I=1,N Y(I) = A*X(I) 1 CONTINUE RETURN END * SUBROUTINE MXVSET ALL SYSTEMS 88/12/01 * PURPOSE : * A SCALAR IS SET TO ALL THE ELEMENTS OF A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI A INITIAL VALUE. * RO X(N) OUTPUT VECTOR SUCH THAT X(I)=A FOR ALL I. * SUBROUTINE MXVSET(N,A,X) DOUBLE PRECISION A INTEGER N DOUBLE PRECISION X(*) INTEGER I DO 10 I = 1,N X(I) = A 10 CONTINUE RETURN END * SUBROUTINE MXVSFP ALL SYSTEMS 91/12/01 * PURPOSE : * VECTOR X(N) IS PERMUTED ACCORDING TO THE FORMULA * X(I)=X(PERM(I)). * * PARAMETERS : * II N LENGTH OF VECTORS. * II PERM(N) INPUT PERMUTATION VECTOR. * RU X(N) VECTOR THAT IS TO BE PERMUTED. * RA RN01(N) AMXILIARY VECTOR. * SUBROUTINE MXVSFP(N,PERM,X,RN01) INTEGER N,PERM(*),I DOUBLE PRECISION RN01(*),X(*) C DO 100 I=1,N RN01(I)=X(PERM(I)) 100 CONTINUE DO 200 I=1,N X(I)=RN01(I) 200 CONTINUE RETURN END * SUBROUTINE MXVSIP ALL SYSTEMS 91/12/01 * PURPOSE : * THE VECTOR OF THE INVERSE PERMUTATION IS COMPUTED. * * PARAMETERS : * II N LENGTH OF VECTORS. * II PERM(N) INPUT PERMUTATION VECTOR. * IO INVP(N) INVERSE PERMUTATION VECTOR. * SUBROUTINE MXVSIP(N,PERM,INVP) INTEGER N,PERM(*),INVP(*) INTEGER I,J DO 100 I=1,N J=PERM(I) INVP(J)=I 100 CONTINUE RETURN END * SUBROUTINE MXVSR2 ALL SYSTEMS 92/12/01 * PURPOSE : * RADIXSORT. * * PARAMETERS : * II MCOLS NUMBER OF INTEGER VALUES OF THE SORTED ARRAY. * RI DEG(MCOLS) VALUES OF THE SORTED ARRAY. * RO ORD(MCOLS) SORTED OUTPUT. * RA RADIX(MCOLS+1) AUXILIARY ARRAY. * II WN01(MCOLS) INDICES OF THE SORTED ARRAY. * II LENGTH NUMBER OF SORTED PIECES. * SUBROUTINE MXVSR2(MCOLS,DEG,ORD,RADIX,WN01,LENGTH) INTEGER MCOLS,WN01(*) DOUBLE PRECISION DEG(*),ORD(*),RADIX(*) INTEGER LENGTH,I,L,L1,L2 * * RADIX IS SHIFTED : 0-(MCOLS-1) --- 1-MCOLS * DO 50 I=1,MCOLS+1 RADIX(I)=0 50 CONTINUE DO 100 I=1,LENGTH L2=WN01(I) L=DEG(L2) RADIX(L+1)=RADIX(L+1)+1 100 CONTINUE * * RADIX COUNTS THE NUMBER OF VERTICES WITH DEG(I)>=L * L=0 DO 200 I=MCOLS,0,-1 L=RADIX(I+1)+L RADIX(I+1)=L 200 CONTINUE * * ARRAY ORD IS FILLED * DO 300 I=1,LENGTH L2=WN01(I) L=DEG(L2) L1=RADIX(L+1) ORD(L1)=L2 RADIX(L+1)=L1-1 300 CONTINUE RETURN END * SUBROUTINE MXVSR5 ALL SYSTEMS 92/12/01 * PURPOSE : * SHELLSORT. * * PARAMETERS : * II K NUMBER OF INTEGER VALUES OF THE SORTED ARRAY. * II L CORRECTION FOR THE ABSOLUTE INDEX IN THE SORTED ARRAY * IU ARRAY(K) INTEGER SORTED ARRAY. * RO ARRAYC(K) REAL OUTPUT ARRAY. * RU ARRAYD(K) REAL ARRAY WHICH IS PERMUTED IN THE SAME WAY * AS THE INTEGER SORTED ARRAY. * SUBROUTINE MXVSR5(K,L,ARRAY,ARRAYC,ARRAYD) INTEGER K,L INTEGER ARRAY(*) DOUBLE PRECISION ARRAYC(*),ARRAYD(*) INTEGER IS,LA,LT,LS,LLS,I,J,JS,KHALF DOUBLE PRECISION LD * * NOTHING TO BE SORTED * IF (K.LE.1) GO TO 400 * * SHELLSORT * * L - CORRECTION FOR THE ABSOLUTE INDEX IN THE SORTED ARRAY * LS=131071 KHALF=K/2 DO 300 LT=1,17 IF (LS.GT.KHALF) THEN LS=LS/2 GO TO 300 END IF LLS=K-LS DO 200 I=1,LLS IS=I+LS LA=ARRAY(IS) LD=ARRAYD(IS) J=I JS=IS 100 IF (LA.GE.ARRAY(J)) THEN ARRAY(JS)=LA ARRAYD(JS)=LD ARRAYC(INT(LD))=JS+L GO TO 200 ELSE ARRAY(JS)=ARRAY(J) ARRAYD(JS)=ARRAYD(J) ARRAYC(INT(ARRAYD(J)))=JS+L JS=J J=J-LS END IF IF (J.GE.1) GO TO 100 ARRAY(JS)=LA ARRAYD(JS)=LD ARRAYC(INT(LD))=JS+L 200 CONTINUE LS=LS/2 300 CONTINUE 400 CONTINUE RETURN END * SUBROUTINE MXVSR7 ALL SYSTEMS 94/12/01 * PURPOSE : * SHELLSORT * * PARAMETERS : * II K LENGTH OF SORTED VECTOR. * IU ARRAY(K) SORTED ARRAY. * IU ARRAYB(K) SECOND SORTED ARRAY. * SUBROUTINE MXVSR7(K,ARRAY,ARRAYB) INTEGER K INTEGER ARRAY(*),ARRAYB(*) INTEGER IS,LA,LB,LT,LS,LLS,I,J,JS,KHALF * * NOTHING TO BE SORTED * IF (K.LE.1) GO TO 400 * * SHELLSORT * LS=131071 KHALF=K/2 DO 300 LT=1,17 IF (LS.GT.KHALF) THEN LS=LS/2 GO TO 300 END IF LLS=K-LS DO 200 I=1,LLS IS=I+LS LA=ARRAY(IS) LB=ARRAYB(IS) J=I JS=IS 100 IF (LA.GE.ARRAY(J)) THEN ARRAY(JS)=LA ARRAYB(JS)=LB GO TO 200 ELSE ARRAY(JS)=ARRAY(J) ARRAYB(JS)=ARRAYB(J) JS=J J=J-LS END IF IF (J.GE.1) GO TO 100 ARRAY(JS)=LA ARRAYB(JS)=LB 200 CONTINUE LS=LS/2 300 CONTINUE 400 CONTINUE RETURN END * SUBROUTINE MXVSRT ALL SYSTEMS 91/12/01 * PURPOSE : * SHELLSORT * * PARAMETERS : * II K LENGTH OF SORTED VECTOR. * IU ARRAY(K) SORTED ARRAY. * SUBROUTINE MXVSRT(K,ARRAY) INTEGER K INTEGER ARRAY(*) INTEGER IS,LA,LT,LS,LLS,I,J,JS,KHALF * * NOTHING TO BE SORTED * IF (K.LE.1) GO TO 400 * * SHELLSORT * LS=131071 KHALF=K/2 DO 300 LT=1,17 IF (LS.GT.KHALF) THEN LS=LS/2 GO TO 300 END IF LLS=K-LS DO 200 I=1,LLS IS=I+LS LA=ARRAY(IS) J=I JS=IS 100 IF (LA.GE.ARRAY(J)) THEN ARRAY(JS)=LA GO TO 200 ELSE ARRAY(JS)=ARRAY(J) JS=J J=J-LS END IF IF (J.GE.1) GO TO 100 ARRAY(JS)=LA 200 CONTINUE LS=LS/2 300 CONTINUE 400 CONTINUE RETURN END * SUBROUTINE MXVSUM ALL SYSTEMS 88/12/01 * PURPOSE : * SUM OF TWO VECTORS. * * PARAMETERS : * II N VECTOR DIMENSION. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RO Z(N) OUTPUT VECTOR WHERE Z:= X + Y. * SUBROUTINE MXVSUM(N,X,Y,Z) INTEGER N DOUBLE PRECISION X(*),Y(*),Z(*) INTEGER I DO 10 I = 1,N Z(I) = X(I) + Y(I) 10 CONTINUE RETURN END * FUNCTION MXVVDP ALL SYSTEMS 92/12/01 * PURPOSE : * COMPUTATION OF THE NUMBER MXVVDP=TRANS(X)*D**(-1)*Y WHERE D IS A * DIAGONAL MATRIX STORED AS A VECTOR. * * PARAMETERS : * II N VECTOR DIMENSION. * RI D(N) DIAGONAL MATRIX STORED AS A VECTOR. * RI X(N) INPUT VECTOR. * RI Y(N) INPUT VECTOR. * RR MXVVDP COMPUTED NUMBER MXVVDP=TRANS(X)*D**(-1)*Y. * FUNCTION MXVVDP(N,D,X,Y) INTEGER N DOUBLE PRECISION D(*), X(*), Y(*), MXVVDP DOUBLE PRECISION TEMP INTEGER I DOUBLE PRECISION ZERO PARAMETER (ZERO = 0.0D 0) TEMP = ZERO DO 1 I = 1, N TEMP = TEMP + X(I)*Y(I)/D(I) 1 CONTINUE MXVVDP = TEMP RETURN END * SUBROUTINE MXWDIR ALL SYSTEMS 92/12/01 * PURPOSE : * VECTOR AUGMENTED BY THE SCALED VECTOR IN THE PACKED CASE. * * PARAMETERS : * II L PACKED VECTOR DIMENSION. * II N VECTOR DIMENSION. * II JBL(L) INDICES OF PACKED VECTOR. * RI A SCALING FACTOR. * RI X(L) PACKED INPUT VECTOR. * RI Y(N) UNPACKED INPUT VECTOR. * RO Z(N) UNPACKED OR PACKED OUTPUT VECTOR WHERE Z:= Y + A*X. * II JOB FORM OF THE VECTOR Z. JOB=1-UNPACKED FORM. JOB=2-PACKED * FORM. * SUBROUTINE MXWDIR(L,JBL,A,X,Y,Z,JOB) INTEGER L,JBL(*),JOB DOUBLE PRECISION A, X(*), Y(*), Z(*) INTEGER I,IP IF (JOB.EQ.1) THEN DO 1 I=1,L IP=JBL(I) IF (IP.GT.0) Z(IP)=Y(IP)+A*X(I) 1 CONTINUE ELSE DO 2 I=1,L IP=JBL(I) IF (IP.GT.0) Z(I)=Y(IP)+A*X(I) 2 CONTINUE END IF RETURN END * FUNCTION MXWDOT ALL SYSTEMS 92/12/01 * PURPOSE : * DOT PRODUCT OF TWO VECTORS IN THE PACKED CASE. * * PARAMETERS : * II L PACKED OR UNPACKED VECTOR DIMENSION. * II N UNPACKED VECTOR DIMENSION. * II JBL(L) INDICES OF PACKED VECTOR. * RI X(L) UNPACKED OR PACKED INPUT VECTOR. * RI Y(N) UNPACKED INPUT VECTOR. * II JOB FORM OF THE VECTOR X. JOB=1-UNPACKED FORM. JOB=2-PACKED * FORM. * RR MXWDOT VALUE OF DOT PRODUCT MXWDOT=TRANS(X)*Y. * FUNCTION MXWDOT(L,JBL,X,Y,JOB) INTEGER L,JBL(*),JOB DOUBLE PRECISION X(*), Y(*), MXWDOT DOUBLE PRECISION TEMP INTEGER I,IP TEMP=0.0D0 IF (JOB.EQ.1) THEN DO 1 I=1,L IP=JBL(I) IF (IP.GT.0) TEMP=TEMP+X(IP)*Y(IP) 1 CONTINUE ELSE DO 2 I=1,L IP=JBL(I) IF (IP.GT.0) TEMP=TEMP+X(I)*Y(IP) 2 CONTINUE END IF MXWDOT=TEMP RETURN END nlopt-2.6.1/src/algs/luksan/plip.c000066400000000000000000000363531345435414600170210ustar00rootroot00000000000000#include #include #include #include #include "luksan.h" #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define MIN2(a,b) ((a) < (b) ? (a) : (b)) /* *********************************************************************** */ /* SUBROUTINE PLIP ALL SYSTEMS 01/09/22 */ /* PURPOSE : */ /* GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT */ /* USE THE SHIFTED LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE */ /* PRODUCT FORM UPDATES. */ /* PARAMETERS : */ /* II NF NUMBER OF VARIABLES. */ /* II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. */ /* NB>0-SIMPLE BOUNDS ACCEPTED. */ /* RI X(NF) VECTOR OF VARIABLES. */ /* II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE */ /* X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). */ /* IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND */ /* XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. */ /* RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. */ /* RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. */ /* RA GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. */ /* RO S(NF) DIRECTION VECTOR. */ /* RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. */ /* RI GO(NF) GRADIENTS DIFFERENCE. */ /* RA SO(NF) AUXILIARY VECTOR. */ /* RA XM(NF*MF) AUXILIARY VECTOR. */ /* RA XR(MF) AUXILIARY VECTOR. */ /* RA GR(MF) AUXILIARY VECTOR. */ /* RI XMAX MAXIMUM STEPSIZE. */ /* RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. */ /* RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. */ /* RI TOLB TOLERANCE FOR THE FUNCTION VALUE. */ /* RI TOLG TOLERANCE FOR THE GRADIENT NORM. */ /* RI MINF_EST ESTIMATION OF THE MINIMUM FUNCTION VALUE. */ /* RO GMAX MAXIMUM PARTIAL DERIVATIVE. */ /* RO F VALUE OF THE OBJECTIVE FUNCTION. */ /* II MIT MAXIMUM NUMBER OF ITERATIONS. */ /* II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. */ /* II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. */ /* IEST=1-MINIMUM IS ESTIMATED BY THE VALUE MINF_EST. */ /* II MET METHOD USED. MET=1-RANK-ONE METHOD. MET=2-RANK-TWO */ /* METHOD. */ /* II MF NUMBER OF LIMITED MEMORY STEPS. */ /* IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. */ /* ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN */ /* MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN */ /* MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. */ /* ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. */ /* ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, */ /* BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. */ /* ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. */ /* ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. */ /* VARIABLES IN COMMON /STAT/ (STATISTICS) : */ /* IO NRES NUMBER OF RESTARTS. */ /* IO NDEC NUMBER OF MATRIX DECOMPOSITION. */ /* IO NIN NUMBER OF INNER ITERATIONS. */ /* IO NIT NUMBER OF ITERATIONS. */ /* IO NFV NUMBER OF FUNCTION EVALUATIONS. */ /* IO NFG NUMBER OF GRADIENT EVALUATIONS. */ /* IO NFH NUMBER OF HESSIAN EVALUATIONS. */ /* SUBPROGRAMS USED : */ /* S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. */ /* S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. */ /* S PULSP3 SHIFTED VARIABLE METRIC UPDATE. */ /* S PULVP3 SHIFTED LIMITED-MEMORY VARIABLE METRIC UPDATE. */ /* S PYADC0 ADDITION OF A BOX CONSTRAINT. */ /* S PYFUT1 TEST ON TERMINATION. */ /* S PYRMC0 DELETION OF A BOX CONSTRAINT. */ /* S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC */ /* UPDATE. */ /* S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. */ /* S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. */ /* S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR */ /* MATRIX A BY A VECTOR X. */ /* S MXDCMD MULTIPLICATION OF A COLUMNWISE STORED DENSE RECTANGULAR */ /* MATRIX A BY A VECTOR X AND ADDITION OF THE SCALED VECTOR */ /* ALF*Y. */ /* S MXUCOP COPYING OF A VECTOR. */ /* S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. */ /* RF MXUDOT DOT PRODUCT OF TWO VECTORS. */ /* S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. */ /* S MXUZER VECTOR ELEMENTS CORRESPONDING TO ACTIVE BOUNDS ARE SET */ /* TO ZERO. */ /* S MXVCOP COPYING OF A VECTOR. */ /* EXTERNAL SUBROUTINES : */ /* SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS */ /* THE VALUE OF THE OBJECTIVE FUNCTION. */ /* SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) */ /* IS THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* -- OBJ and DOBJ are replaced by a single function, objgrad, in NLopt */ /* METHOD : */ /* HYBRID METHOD WITH SPARSE MARWIL UPDATES FOR SPARSE LEAST SQUARES */ /* PROBLEMS. */ static void plip_(int *nf, int *nb, double *x, int * ix, double *xl, double *xu, double *gf, double *s, double *xo, double *go, double *so, double *xm, double *xr, double *gr, double *xmax, double *tolx, double *tolf, double *tolb, double *tolg, nlopt_stopping *stop, double * minf_est, double *gmax, double *f, int *mit, int *mfv, int *iest, int *met, int *mf, int *iterm, stat_common *stat_1, nlopt_func objgrad, void *objgrad_data) { /* System generated locals */ int i__1; double d__1, d__2; /* Builtin functions */ /* Local variables */ int i__, n; double p, r__; int kd, ld; double fo, fp; int nn; double po, pp, ro, rp; int kbf, mec, mfg; double par; int mes, kit; double alf1, alf2, eta9, par1, par2; int met3; double eps8, eps9; int mred, nred, iold; double maxf, dmax__; int xstop = 0; int inew; double told; int ites; double rmin, rmax, umax, tolp, tols; int isys; int ires1, ires2; int iterd, iterh, mtesf, ntesf; double gnorm; int iters, irest, inits, kters, maxst; double snorm; int mtesx, ntesx; ps1l01_state state; (void) tolb; /* INITIATION */ /* Parameter adjustments */ --gr; --xr; --xm; --so; --go; --xo; --s; --gf; --xu; --xl; --ix; --x; /* Function Body */ kbf = 0; if (*nb > 0) { kbf = 2; } stat_1->nres = 0; stat_1->ndec = 0; stat_1->nin = 0; stat_1->nit = 0; stat_1->nfg = 0; stat_1->nfh = 0; isys = 0; ites = 1; mtesx = 2; mtesf = 2; inits = 2; *iterm = 0; iterd = 0; iters = 2; iterh = 0; kters = 3; irest = 0; ires1 = 999; ires2 = 0; mred = 10; met3 = 4; mec = 4; mes = 4; eta9 = 1e120; eps8 = 1.; eps9 = 1e-8; alf1 = 1e-10; alf2 = 1e10; rmax = eta9; dmax__ = eta9; maxf = 1e20; if (*iest <= 0) { *minf_est = -HUGE_VAL; /* changed from -1e60 by SGJ */ } if (*iest > 0) { *iest = 1; } if (*xmax <= 0.) { *xmax = 1e16; } if (*tolx <= 0.) { *tolx = 1e-16; } if (*tolf <= 0.) { *tolf = 1e-14; } if (*tolg <= 0.) { *tolg = 1e-8; /* SGJ: was 1e-6, but this sometimes stops too soon */ } #if 0 /* removed by SGJ: this check prevented us from using minf_max <= 0, which doesn't make sense. Instead, if you don't want to have a lower limit, you should set minf_max = -HUGE_VAL */ if (*tolb <= 0.) { *tolb = *minf_est + 1e-16; } #endif told = 1e-4; tols = 1e-4; tolp = .9; if (*met <= 0) { *met = 2; } /* changed by SGJ: default is no limit (INT_MAX) on # iterations/fevals */ if (*mit <= 0) { *mit = INT_MAX; } if (*mfv <= 0) { *mfv = INT_MAX; } mfg = *mfv; kd = 1; ld = -1; kit = -(ires1 * *nf + ires2); fo = *minf_est; /* INITIAL OPERATIONS WITH SIMPLE BOUNDS */ if (kbf > 0) { i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { if ((ix[i__] == 3 || ix[i__] == 4) && xu[i__] <= xl[i__]) { xu[i__] = xl[i__]; ix[i__] = 5; } else if (ix[i__] == 5 || ix[i__] == 6) { xl[i__] = x[i__]; xu[i__] = x[i__]; ix[i__] = 5; } /* L2: */ } luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } if (*iterm != 0) { goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); luksan_pyfut1__(nf, f, &fo, &umax, gmax, xstop, stop, tolg, &kd, &stat_1->nit, &kit, mit, &stat_1->nfg, &mfg, &ntesx, &mtesx, &ntesf, &mtesf, &ites, &ires1, &ires2, &irest, & iters, iterm); if (*iterm != 0) { goto L11190; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } if (kbf > 0 && rmax > 0.) { luksan_pyrmc0__(nf, &n, &ix[1], &gf[1], &eps8, &umax, gmax, &rmax, & iold, &irest); } L11130: if (irest > 0) { nn = 0; par = 1.; ld = MIN2(ld,1); if (kit < stat_1->nit) { ++stat_1->nres; kit = stat_1->nit; } else { *iterm = -10; if (iters < 0) { *iterm = iters - 5; } } } if (*iterm != 0) { goto L11190; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } /* DIRECTION DETERMINATION */ gnorm = sqrt(luksan_mxudot__(nf, &gf[1], &gf[1], &ix[1], &kbf)); /* NEWTON LIKE STEP */ luksan_mxuneg__(nf, &gf[1], &s[1], &ix[1], &kbf); luksan_mxdrmm__(nf, &nn, &xm[1], &s[1], &gr[1]); luksan_mxdcmd__(nf, &nn, &xm[1], &gr[1], &par, &s[1], &s[1]); luksan_mxuzer__(nf, &s[1], &ix[1], &kbf); iterd = 1; snorm = sqrt(luksan_mxudot__(nf, &s[1], &s[1], &ix[1], &kbf)); /* TEST ON DESCENT DIRECTION AND PREPARATION OF LINE SEARCH */ if (kd > 0) { p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); } if (iterd < 0) { *iterm = iterd; } else { /* TEST ON DESCENT DIRECTION */ if (snorm <= 0.) { irest = MAX2(irest,1); } else if (p + told * gnorm * snorm <= 0.) { irest = 0; } else { /* UNIFORM DESCENT CRITERION */ irest = MAX2(irest,1); } if (irest == 0) { /* PREPARATION OF LINE SEARCH */ nred = 0; rmin = alf1 * gnorm / snorm; /* Computing MIN */ d__1 = alf2 * gnorm / snorm, d__2 = *xmax / snorm; rmax = MIN2(d__1,d__2); } } if (*iterm != 0) { goto L11190; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } if (irest != 0) { goto L11130; } luksan_pytrcs__(nf, &x[1], &ix[1], &xo[1], &xl[1], &xu[1], &gf[1], &go[1], &s[1], &ro, &fp, &fo, f, &po, &p, &rmax, &eta9, &kbf); if (rmax == 0.) { goto L11175; } L11170: luksan_ps1l01__(&r__, &rp, f, &fo, &fp, &p, &po, &pp, minf_est, &maxf, &rmin, &rmax, &tols, &tolp, &par1, &par2, &kd, &ld, &stat_1->nit, &kit, & nred, &mred, &maxst, iest, &inits, &iters, &kters, &mes, &isys, &state); if (isys == 0) { goto L11174; } luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); goto L11170; L11174: if (iters <= 0) { r__ = 0.; *f = fo; p = po; luksan_mxvcop__(nf, &xo[1], &x[1]); luksan_mxvcop__(nf, &go[1], &gf[1]); irest = MAX2(irest,1); ld = kd; goto L11130; } luksan_mxuneg__(nf, &go[1], &s[1], &ix[1], &kbf); luksan_pytrcd__(nf, &x[1], &ix[1], &xo[1], &gf[1], &go[1], &r__, f, &fo, & p, &po, &dmax__, &kbf, &kd, &ld, &iters); xstop = nlopt_stop_dx(stop, &x[1], &xo[1]); luksan_mxucop__(nf, &gf[1], &so[1], &ix[1], &kbf); if (nn < *mf) { luksan_pulsp3__(nf, &nn, mf, &xm[1], &gr[1], &xo[1], &go[1], &r__, & po, &par, &iterh, &met3); } else { luksan_pulvp3__(nf, &nn, &xm[1], &xr[1], &gr[1], &s[1], &so[1], &xo[1] , &go[1], &r__, &po, &par, &iterh, &mec, &met3, met); } L11175: if (iterh != 0) { irest = MAX2(irest,1); } if (kbf > 0) { luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } goto L11120; L11190: return; } /* plip_ */ /* NLopt wrapper around plip_, handling dynamic allocation etc. */ nlopt_result luksan_plip(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf, /* subspace dimension (0 for default) */ int method) /* 1 or 2, see below */ { int i, *ix, nb = 1; double *work, *xl, *xu, *gf, *s, *xo, *go, *so, *xm, *xr, *gr; double gmax, minf_est; double xmax = 0; /* no maximum */ double tolg = 0; /* default gradient tolerance */ int iest = 0; /* we have no estimate of min function value */ int mit = 0; /* default no limit on #iterations */ int mfv = stop->maxeval; stat_common stat; int iterm; ix = (int*) malloc(sizeof(int) * n); if (!ix) return NLOPT_OUT_OF_MEMORY; if (mf <= 0) { mf = MAX2(MEMAVAIL/n, 10); if (stop->maxeval && stop->maxeval <= mf) mf = MAX2(stop->maxeval, 1); } retry_alloc: work = (double*) malloc(sizeof(double) * (n * 7 + MAX2(n,n*mf) + MAX2(n,mf)*2)); if (!work) { if (mf > 0) { mf = 0; /* allocate minimal memory */ goto retry_alloc; } free(ix); return NLOPT_OUT_OF_MEMORY; } xl = work; xu = xl + n; gf = xu + n; s = gf + n; xo = s + n; go = xo + n; so = go + n; xm = so + n; xr = xm + MAX2(n*mf,n); gr = xr + MAX2(n,mf); for (i = 0; i < n; ++i) { int lbu = lb[i] <= -0.99 * HUGE_VAL; /* lb unbounded */ int ubu = ub[i] >= 0.99 * HUGE_VAL; /* ub unbounded */ ix[i] = lbu ? (ubu ? 0 : 2) : (ubu ? 1 : (lb[i] == ub[i] ? 5 : 3)); xl[i] = lb[i]; xu[i] = ub[i]; } /* ? xo does not seem to be initialized in the original Fortran code, but it is used upon input to plip if mf > 0 ... perhaps ALLOCATE initializes arrays to zero by default? */ memset(xo, 0, sizeof(double) * MAX2(n,n*mf)); plip_(&n, &nb, x, ix, xl, xu, gf, s, xo, go, so, xm, xr, gr, &xmax, /* fixme: pass tol_rel and tol_abs and use NLopt check */ &stop->xtol_rel, &stop->ftol_rel, &stop->minf_max, &tolg, stop, &minf_est, &gmax, minf, &mit, &mfv, &iest, &method, /* 1 == rank-one method VAR1, 2 == rank-two method VAR2 */ &mf, &iterm, &stat, f, f_data); free(work); free(ix); switch (iterm) { case 1: return NLOPT_XTOL_REACHED; case 2: return NLOPT_FTOL_REACHED; case 3: return NLOPT_MINF_MAX_REACHED; case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; case 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } } nlopt-2.6.1/src/algs/luksan/plip.for000066400000000000000000000465721345435414600173710ustar00rootroot00000000000000************************************************************************ * SUBROUTINE PLIPU ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE UNCONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) METHOD USED. IPAR(5)=1-RANK-ONE METHOD. * IPAR(5)=2-RANK-TWO METHOD. * IPAR(6) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * IPAR(7) MAXIMUM NUMBER OF VARIABLE METRIC UPDATES. * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PLIP LIMITED MEMORY SHIFTED VARIABLE METRIC METHOD IN THE * PRODUCT FORM. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PLIPU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LS,LXO,LGO,LSO,LXM,LXR,LGR INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(5*NF+NF*MF+2*MF)) NB=0 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LS=LGF+NF LXO=LS+NF LGO=LXO+NF LSO=LGO+NF LXM=LSO+NF LXR=LXM+NF*MF LGR=LXR+MF CALL PLIP(NF,NB,X,IPAR,RA,RA,RA(LGF),RA(LS),RA(LXO),RA(LGO), & RA(LSO),RA(LXM),RA(LXR),RA(LGR),RPAR(1),RPAR(2),RPAR(3),RPAR(4), & RPAR(5),RPAR(6),GMAX,F,IPAR(1),IPAR(2),IPAR(4),IPAR(5),MF,IPRNT, & ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PLIPS ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) METHOD USED. IPAR(5)=1-RANK-ONE METHOD. * IPAR(5)=2-RANK-TWO METHOD. * IPAR(6) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * IPAR(7) MAXIMUM NUMBER OF VARIABLE METRIC UPDATES. * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIP. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PLIP LIMITED MEMORY SHIFTED VARIABLE METRIC METHOD IN THE * PRODUCT FORM. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PLIPS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IX(*),IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LS,LXO,LGO,LSO,LXM,LXR,LGR INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(5*NF+NF*MF+2*MF)) NB=1 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LS=LGF+NF LXO=LS+NF LGO=LXO+NF LSO=LGO+NF LXM=LSO+NF LXR=LXM+NF*MF LGR=LXR+MF CALL PLIP(NF,NB,X,IX,XL,XU,RA(LGF),RA(LS),RA(LXO),RA(LGO), & RA(LSO),RA(LXM),RA(LXR),RA(LGR),RPAR(1),RPAR(2),RPAR(3),RPAR(4), & RPAR(5),RPAR(6),GMAX,F,IPAR(1),IPAR(2),IPAR(4),IPAR(5),MF,IPRNT, & ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PLIP ALL SYSTEMS 01/09/22 * PURPOSE : * GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT * USE THE SHIFTED LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE * PRODUCT FORM UPDATES. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. * NB>0-SIMPLE BOUNDS ACCEPTED. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RA GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * RA SO(NF) AUXILIARY VECTOR. * RA XM(NF*MF) AUXILIARY VECTOR. * RA XR(MF) AUXILIARY VECTOR. * RA GR(MF) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. * RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. * RI TOLB TOLERANCE FOR THE FUNCTION VALUE. * RI TOLG TOLERANCE FOR THE GRADIENT NORM. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * RO F VALUE OF THE OBJECTIVE FUNCTION. * II MIT MAXIMUM NUMBER OF ITERATIONS. * II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * II MET METHOD USED. MET=1-RANK-ONE METHOD. MET=2-RANK-TWO * METHOD. * II MF NUMBER OF LIMITED MEMORY STEPS. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITION. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. * S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. * S PULSP3 SHIFTED VARIABLE METRIC UPDATE. * S PULVP3 SHIFTED LIMITED-MEMORY VARIABLE METRIC UPDATE. * S PYADC0 ADDITION OF A BOX CONSTRAINT. * S PYFUT1 TEST ON TERMINATION. * S PYRMC0 DELETION OF A BOX CONSTRAINT. * S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC * UPDATE. * S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. * S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. * S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR * MATRIX A BY A VECTOR X. * S MXDCMD MULTIPLICATION OF A COLUMNWISE STORED DENSE RECTANGULAR * MATRIX A BY A VECTOR X AND ADDITION OF THE SCALED VECTOR * ALF*Y. * S MXUCOP COPYING OF A VECTOR. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXUZER VECTOR ELEMENTS CORRESPONDING TO ACTIVE BOUNDS ARE SET * TO ZERO. * S MXVCOP COPYING OF A VECTOR. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * * METHOD : * HYBRID METHOD WITH SPARSE MARWIL UPDATES FOR SPARSE LEAST SQUARES * PROBLEMS. * SUBROUTINE PLIP(NF,NB,X,IX,XL,XU,GF,S,XO,GO,SO,XM,XR,GR,XMAX, & TOLX,TOLF,TOLB,TOLG,FMIN,GMAX,F,MIT,MFV,IEST,MET,MF,IPRNT,ITERM) INTEGER NF,NB,IX(*),MIT,MFV,IEST,MET,MF,IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),GF(*),S(*),XO(*),GO(*),SO(*), & XM(*),XR(*),GR(*),XMAX,TOLX,TOLF,TOLG,TOLB,FMIN,GMAX,F INTEGER ITERD,ITERS,ITERH,KD,LD,NTESX,NTESF,MTESX,MTESF,MRED,KIT, & IREST,KBF,MEC,MES,MES1,MES2,MES3,MAXST,ISYS,ITES,INITS,KTERS, & IRES1,IRES2,NRED,INEW,IOLD,I,NN,N,MFG,META,MET3 DOUBLE PRECISION R,RO,RP,FO,FP,P,PO,PP,GNORM,SNORM,RMIN,RMAX, & UMAX,FMAX,DMAX,ETA0,ETA9,EPS8,EPS9,ALF1,ALF2,PAR1,PAR2,PAR,TOLD, & TOLS,TOLP DOUBLE PRECISION MXUDOT INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH IF (ABS(IPRNT).GT.1) WRITE(6,'(1X,''ENTRY TO PLIP :'')') * * INITIATION * KBF=0 IF (NB.GT.0) KBF=2 NRES=0 NDEC=0 NIN=0 NIT=0 NFV=0 NFG=0 NFH=0 ISYS=0 ITES=1 MTESX=2 MTESF=2 INITS=2 ITERM=0 ITERD=0 ITERS=2 ITERH=0 KTERS=3 IREST=0 IRES1=999 IRES2=0 MRED=10 META=1 MET3=4 MEC=4 MES=4 MES1=2 MES2=2 MES3=2 ETA0=1.0D-15 ETA9=1.0D 120 EPS8=1.00D 0 EPS9=1.00D-8 ALF1=1.0D-10 ALF2=1.0D 10 RMAX=ETA9 DMAX=ETA9 FMAX=1.0D 20 IF (IEST.LE.0) FMIN=-1.0D 60 IF (IEST.GT.0) IEST=1 IF (XMAX.LE.0.0D 0) XMAX=1.0D 16 IF (TOLX.LE.0.0D 0) TOLX=1.0D-16 IF (TOLF.LE.0.0D 0) TOLF=1.0D-14 IF (TOLG.LE.0.0D 0) TOLG=1.0D-6 IF (TOLB.LE.0.0D 0) TOLB=FMIN+1.0D-16 TOLD=1.0D-4 TOLS=1.0D-4 TOLP=0.9D 0 IF (MET.LE.0) MET=2 IF (MIT.LE.0) MIT=9000 IF (MFV.LE.0) MFV=9000 MFG=MFV KD= 1 LD=-1 KIT=-(IRES1*NF+IRES2) FO=FMIN * * INITIAL OPERATIONS WITH SIMPLE BOUNDS * IF (KBF.GT.0) THEN DO 2 I = 1,NF IF ((IX(I).EQ.3.OR.IX(I).EQ.4) .AND. XU(I).LE.XL(I)) THEN XU(I) = XL(I) IX(I) = 5 ELSE IF (IX(I).EQ.5 .OR. IX(I).EQ.6) THEN XL(I) = X(I) XU(I) = X(I) IX(I) = 5 END IF 2 CONTINUE CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL PYADC0(NF,N,X,IX,XL,XU,INEW) END IF IF (ITERM.NE.0) GO TO 11190 CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 11120 CONTINUE CALL PYTRCG(NF,NF,IX,GF,UMAX,GMAX,KBF,IOLD) IF (ABS(IPRNT).GT.1) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3)') NIT,NFV,NFG,F,GMAX CALL PYFUT1(NF,F,FO,UMAX,GMAX,DMAX,TOLX,TOLF,TOLB,TOLG,KD, & NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF,ITES, & IRES1,IRES2,IREST,ITERS,ITERM) IF (ITERM.NE.0) GO TO 11190 IF (KBF.GT.0.AND.RMAX.GT.0.0D 0) THEN CALL PYRMC0(NF,N,IX,GF,EPS8,UMAX,GMAX,RMAX,IOLD,IREST) END IF 11130 CONTINUE IF (IREST.GT.0) THEN NN=0 PAR=1.0D 0 LD=MIN(LD,1) IF (KIT.LT.NIT) THEN NRES=NRES+1 KIT = NIT ELSE ITERM=-10 IF (ITERS.LT.0) ITERM=ITERS-5 END IF END IF IF (ITERM.NE.0) GO TO 11190 * * DIRECTION DETERMINATION * GNORM=SQRT(MXUDOT(NF,GF,GF,IX,KBF)) * * NEWTON LIKE STEP * CALL MXUNEG(NF,GF,S,IX,KBF) CALL MXDRMM(NF,NN,XM,S,GR) CALL MXDCMD(NF,NN,XM,GR,PAR,S,S) CALL MXUZER(NF,S,IX,KBF) ITERD=1 SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) * * TEST ON DESCENT DIRECTION AND PREPARATION OF LINE SEARCH * IF (KD.GT.0) P=MXUDOT(NF,GF,S,IX,KBF) IF (ITERD.LT.0) THEN ITERM=ITERD ELSE * * TEST ON DESCENT DIRECTION * IF (SNORM.LE.0.0D 0) THEN IREST=MAX(IREST,1) ELSE IF (P+TOLD*GNORM*SNORM.LE.0.0D 0) THEN IREST=0 ELSE * * UNIFORM DESCENT CRITERION * IREST=MAX(IREST,1) END IF IF (IREST.EQ.0) THEN * * PREPARATION OF LINE SEARCH * NRED = 0 RMIN=ALF1*GNORM/SNORM RMAX=MIN(ALF2*GNORM/SNORM,XMAX/SNORM) END IF END IF IF (ITERM.NE.0) GO TO 11190 IF (IREST.NE.0) GO TO 11130 CALL PYTRCS(NF,X,IX,XO,XL,XU,GF,GO,S,RO,FP,FO,F,PO,P,RMAX,ETA9, & KBF) IF (RMAX.EQ.0.0D 0) GO TO 11175 11170 CONTINUE CALL PS1L01(R,RP,F,FO,FP,P,PO,PP,FMIN,FMAX,RMIN,RMAX, & TOLS,TOLP,PAR1,PAR2,KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST, & INITS,ITERS,KTERS,MES,ISYS) IF (ISYS.EQ.0) GO TO 11174 CALL MXUDIR(NF,R,S,XO,X,IX,KBF) CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 P=MXUDOT(NF,GF,S,IX,KBF) GO TO 11170 11174 CONTINUE IF (ITERS.LE.0) THEN R=0.0D 0 F=FO P=PO CALL MXVCOP(NF,XO,X) CALL MXVCOP(NF,GO,GF) IREST=MAX(IREST,1) LD=KD GO TO 11130 END IF CALL MXUNEG(NF,GO,S,IX,KBF) CALL PYTRCD(NF,X,IX,XO,GF,GO,R,F,FO,P,PO,DMAX,KBF,KD,LD,ITERS) CALL MXUCOP(NF,GF,SO,IX,KBF) IF (NN.LT.MF) THEN CALL PULSP3(NF,NN,MF,XM,GR,XO,GO,R,PO,PAR,ITERH,MET3) ELSE CALL PULVP3(NF,NN,XM,XR,GR,S,SO,XO,GO,R,PO,PAR,ITERH,MEC,MET3, & MET) END IF 11175 CONTINUE IF (ITERH.NE.0) IREST=MAX(IREST,1) IF (KBF.GT.0) CALL PYADC0(NF,N,X,IX,XL,XU,INEW) GO TO 11120 11190 CONTINUE IF (IPRNT.GT.1.OR.IPRNT.LT.0) & WRITE(6,'(1X,''EXIT FROM PLIP :'')') IF (IPRNT.NE.0) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3,2X,''ITERM='',I3)') NIT,NFV,NFG, & F,GMAX,ITERM IF (IPRNT.LT.0) & WRITE (6,'(1X,''X='',5(G14.7,1X):/(3X,5(G14.7,1X)))') & (X(I),I=1,NF) RETURN END nlopt-2.6.1/src/algs/luksan/plip.txt000066400000000000000000000404221345435414600174060ustar00rootroot00000000000000*********************************************************************** * * * PLIP - A LIMITED MEMORY VARIABLE METRIC ALGORITHM FOR * * LARGE-SCALE OPTIMIZATION. * * * *********************************************************************** 1. Introduction: ---------------- The double-precision FORTRAN 77 basic subroutine PLIP is designed to find a close approximation to a local minimum of a nonlinear function F(X) with simple bounds on variables. Here X is a vector of NF variables and F(X) is a smooth function. We suppose that NF is large but the sparsity pattern of the Hessian matrix is not known (or the Hessian matrix is dense). Simple bounds are assumed in the form X(I) unbounded if IX(I) = 0, XL(I) <= X(I) if IX(I) = 1, X(I) <= XU(I) if IX(I) = 2, XL(I) <= X(I) <= XU(I) if IX(I) = 3, XL(I) = X(I) = XU(I) if IX(I) = 5, where 1 <= I <= NF. To simplify user's work, two additional easy to use subroutines are added. They call the basic general subroutine PLIP: PLIPU - unconstrained large-scale optimization, PLIPS - large-scale optimization with simple bounds. All subroutines contain a description of formal parameters and extensive comments. Furthermore, two test programs TLIPU and TLIPS are included, which contain several test problems (see e.g. [2]). These test programs serve as examples for using the subroutines, verify their correctness and demonstrate their efficiency. In this short guide, we describe all subroutines which can be called from the user's program. A detailed description of the method is given in [1]. In the description of formal parameters, we introduce a type of the argument that specifies whether the argument must have a value defined on entry to the subroutine (I), whether it is a value which will be returned (O), or both (U), or whether it is an auxiliary value (A). Note that the arguments of the type I can be changed on output under some circumstances, especially if improper input values were given. Besides formal parameters, we can use a COMMON /STAT/ block containing statistical information. This block, used in each subroutine has the following form: COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH The arguments have the following meaning: Argument Type Significance ---------------------------------------------------------------------- NRES O Positive INTEGER variable that indicates the number of restarts. NDEC O Positive INTEGER variable that indicates the number of matrix decompositions. NIN O Positive INTEGER variable that indicates the number of inner iterations (for solving linear systems). NIT O Positive INTEGER variable that indicates the number of iterations. NFV O Positive INTEGER variable that indicates the number of function evaluations. NFG O Positive INTEGER variable that specifies the number of gradient evaluations. NFH O Positive INTEGER variable that specifies the number of Hessian evaluations. 2. Subroutines PLIPU, PLIPS: ---------------------------- The calling sequences are CALL PLIPU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) CALL PLIPS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) The arguments have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) U On input, DOUBLE PRECISION vector with the initial estimate to the solution. On output, the approximation to the minimum. IX(NF) I On input (significant only if NB>0) INTEGER vector containing the simple bounds types: IX(I)=0 - the variable X(I) is unbounded, IX(I)=1 - the lower bound X(I) >= XL(I), IX(I)=2 - the upper bound X(I) <= XU(I), IX(I)=3 - the two side bound XL(I) <= X(I) <= XU(I), IX(I)=5 - the variable X(I) is fixed (given by its initial estimate). XL(NF) I DOUBLE PRECISION vector with lower bounds for variables (significant only if NB>0). XU(NF) I DOUBLE PRECISION vector with upper bounds for variables (significant only if NB>0). IPAR(7) I INTEGER parameters: IPAR(1)=MIT, IPAR(2)=MFV, IPAR(3)-NONE, IPAR(4)=IEST, IPAR(5)-MET, IPAR(6)-NONE, IPAR(7)=MF. Parameters MIT, MFV, IEST, MET, MF are described in Section 3 together with other parameters of the subroutine PLIP. RPAR(9) I DOUBLE PRECISION parameters: RPAR(1)=XMAX, RPAR(2)=TOLX, RPAR(3)=TOLF, RPAR(4)=TOLB, RPAR(5)=TOLG, RPAR(6)=FMIN, RPAR(7)-NONE, RPAR(6)-NONE, RPAR(9)-NONE. Parameters XMAX, TOLX, TOLF, TOLB, TOLG, FMIN are described in Section 3 together with other parameters of the subroutine PLIP. F O DOUBLE PRECISION value of the objective function at the solution X. GMAX O DOUBLE PRECISION maximum absolute value of a partial derivative of the Lagrangian function. IPRNT I INTEGER variable that specifies PRINT: IPRNT= 0 - print is suppressed, IPRNT= 1 - basic print of final results, IPRNT=-1 - extended print of final results, IPRNT= 2 - basic print of intermediate and final results, IPRNT=-2 - extended print of intermediate and final results. ITERM O INTEGER variable that indicates the cause of termination: ITERM= 1 - if |X - XO| was less than or equal to TOLX in two subsequent iterations, ITERM= 2 - if |F - FO| was less than or equal to TOLF in two subsequent iterations, ITERM= 3 - if F is less than or equal to TOLB, ITERM= 4 - if GMAX is less than or equal to TOLG, ITERM= 6 - if termination criterion was not satisfied, but the solution is probably acceptable, ITERM=11 - if NIT exceeded MIT, ITERM=12 - if NFV exceeded MFV, ITERM< 0 - if the method failed. The subroutines PLIPU, PLIPS require the user supplied subroutines OBJ and DOBJ that define the objective function and its gradient and have the form SUBROUTINE OBJ(NF,X,F) SUBROUTINE DOBJ(NF,X,G) The arguments of the user supplied subroutines have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) I DOUBLE PRECISION an estimate to the solution. F O DOUBLE PRECISION value of the objective function at the point X. G(NF) O DOUBLE PRECISION gradient of the objective function at the point X. 3. Subroutine PLIP: ------------------- This general subroutine is called from all subroutines described in Section 2. The calling sequence is CALL PLIP(NF,NB,X,IX,XL,XU,GF,S,XO,GO,SO,XM,XR,GR,XMAX,TOLX,TOLF, & TOLB,TOLG,FMIN,GMAX,F,MIT,MFV,IEST,MET,MF,IPRNT,ITERM) The arguments NF, NB, X, IX, XL, XU, GMAX, F, IPRNT, ITERM, have the same meaning as in Section 2. Other arguments have the following meaning: Argument Type Significance ---------------------------------------------------------------------- GF(NF) A DOUBLE PRECISION gradient of the objective function. S(NF) A DOUBLE PRECISION direction vector. XO(NF) A DOUBLE PRECISION array which contains increments of variables. GO(NF) A DOUBLE PRECISION array which contains increments of gradients. SO(NF) A DOUBLE PRECISION auxiliary array. XM(NF*MF) A DOUBLE PRECISION array which contains columns of the updated matrix stored in the product form. XR(MF) A DOUBLE PRECISION array which contains reduced increments of variables. GR(MF) A DOUBLE PRECISION array which contains reduced increments of gradients. XMAX I DOUBLE PRECISION maximum stepsize; the choice XMAX=0 causes that the default value 1.0D+16 will be taken. TOLX I DOUBLE PRECISION tolerance for the change of the coordinate vector X; the choice TOLX=0 causes that the default value TOLX=1.0D-16 will be taken. TOLF I DOUBLE PRECISION tolerance for the change of function values; the choice TOLF=0 causes that the default value TOLF=1.0D-14 will be taken. TOLB I DOUBLE PRECISION minimum acceptable function value; the choice TOLB=0 causes that the default value TOLB=FMIN+1.0D-16 will be taken. TOLG I DOUBLE PRECISION tolerance for the Lagrangian function gradient; the choice TOLG=0 causes that the default value TOLG=1.0D-6 will be taken. FMIN I DOUBLE PRECISION lower bound for the minimum function value. MIT I INTEGER variable that specifies the maximum number of iterations; the choice MIT=0 causes that the default value 9000 will be taken. MFV I INTEGER variable that specifies the maximum number of function evaluations; the choice MFV=0 causes that the default value 9000 will be taken. IEST I INTEGER estimation of the minimum functiom value for the line search: IEST=0 - estimation is not used, IEST=1 - lower bound FMIN is used as an estimation for the minimum function value. MET I INTEGER variable that specifies the limited-memory method: MET=1 - rank-one method, MET=2 - rank-two method. The choice MET=0 causes that the default value MET=2 will be taken. MF I The number of limited-memory variable metric updates in each iteration (they use MF stored vectors). The choice of parameter XMAX can be sensitive in many cases. First, the objective function can be evaluated only in a relatively small region (if it contains exponentials) so that the maximum stepsize is necessary. Secondly, the problem can be very ill-conditioned far from the solution point so that large steps can be unsuitable. Finally, if the problem has more local solutions, a suitably chosen maximum stepsize can lead to obtaining a better local solution. The subroutine PLIP requires the user supplied subroutines OBJ and DOBJ which are described in Section 2. 4. Verification of the subroutines: ----------------------------------- Subroutine PLIPU can be verified and tested using the program TLIPU. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation) and TFGU14 (gradient evaluation) containing 22 unconstrained test problems with at most 1000 variables [2]. The results obtained by the program TLIPU on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 5383 NFV= 5417 NFG= 5417 F= 0.601022658E-13 G= 0.599E-06 ITERM= 4 NIT= 530 NFV= 557 NFG= 557 F= 3.57276719 G= 0.124E-05 ITERM= 2 NIT= 125 NFV= 128 NFG= 128 F= 0.338270284E-12 G= 0.518E-06 ITERM= 4 NIT= 109 NFV= 114 NFG= 114 F= 269.499543 G= 0.669E-06 ITERM= 4 NIT= 26 NFV= 27 NFG= 27 F= 0.710072396E-11 G= 0.951E-06 ITERM= 4 NIT= 35 NFV= 36 NFG= 36 F= 0.142942272E-10 G= 0.737E-06 ITERM= 4 NIT= 36 NFV= 41 NFG= 41 F= 336.937181 G= 0.956E-06 ITERM= 4 NIT= 33 NFV= 36 NFG= 36 F= 761774.954 G= 0.192E-02 ITERM= 2 NIT= 15 NFV= 18 NFG= 18 F= 316.436141 G= 0.264E-06 ITERM= 4 NIT= 2003 NFV= 2030 NFG= 2030 F= -124.950000 G= 0.116E-04 ITERM= 2 NIT= 157 NFV= 175 NFG= 175 F= 10.7765879 G= 0.299E-06 ITERM= 4 NIT= 337 NFV= 350 NFG= 350 F= 982.273617 G= 0.145E-04 ITERM= 2 NIT= 9 NFV= 10 NFG= 10 F= 0.230414406E-14 G= 0.642E-07 ITERM= 4 NIT= 8 NFV= 10 NFG= 10 F= 0.128834241E-08 G= 0.977E-06 ITERM= 4 NIT= 1226 NFV= 1256 NFG= 1256 F= 1.92401599 G= 0.970E-06 ITERM= 4 NIT= 237 NFV= 246 NFG= 246 F= -427.404476 G= 0.501E-04 ITERM= 2 NIT= 598 NFV= 604 NFG= 604 F=-0.379921091E-01 G= 0.908E-06 ITERM= 4 NIT= 989 NFV= 998 NFG= 998 F=-0.245741193E-01 G= 0.975E-06 ITERM= 4 NIT= 1261 NFV= 1272 NFG= 1272 F= 59.5986241 G= 0.410E-05 ITERM= 2 NIT= 2045 NFV= 2058 NFG= 2058 F= -1.00013520 G= 0.911E-06 ITERM= 4 NIT= 2175 NFV= 2196 NFG= 2196 F= 2.13866377 G= 0.996E-06 ITERM= 4 NIT= 1261 NFV= 1292 NFG= 1292 F= 1.00000000 G= 0.927E-06 ITERM= 4 NITER =18598 NFVAL =18871 NSUCC = 22 TIME= 0:00:10.63 The rows corresponding to individual test problems contain the number of iterations NIT, the number of function evaluations NFV, the number of gradient evaluations NFG, the final value of the objective function F, the norm of gradient G and the cause of termination ITERM. Subroutine PLIPS can be verified and tested using the program TLIPS. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation), TFGU14 (gradient evaluation) containing 22 box constrained test problems with at most 1000 variables [2]. The results obtained by the program TLIPS on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 5263 NFV= 5321 NFG= 5321 F= 0.530131995E-13 G= 0.370E-05 ITERM= 2 NIT= 2293 NFV= 2447 NFG= 2447 F= 3930.43962 G= 0.251E-04 ITERM= 2 NIT= 127 NFV= 132 NFG= 132 F= 0.210550150E-12 G= 0.437E-06 ITERM= 4 NIT= 70 NFV= 72 NFG= 72 F= 269.522686 G= 0.794E-06 ITERM= 4 NIT= 26 NFV= 27 NFG= 27 F= 0.710072396E-11 G= 0.951E-06 ITERM= 4 NIT= 35 NFV= 36 NFG= 36 F= 0.142942272E-10 G= 0.737E-06 ITERM= 4 NIT= 37 NFV= 43 NFG= 43 F= 336.937181 G= 0.133E-05 ITERM= 2 NIT= 59 NFV= 65 NFG= 65 F= 761925.725 G= 0.399E-03 ITERM= 2 NIT= 508 NFV= 510 NFG= 510 F= 428.056916 G= 0.776E-06 ITERM= 4 NIT= 1253 NFV= 1277 NFG= 1277 F= -82.5400568 G= 0.120E-04 ITERM= 2 NIT= 13 NFV= 19 NFG= 19 F= 96517.2947 G= 0.150E-04 ITERM= 2 NIT= 95 NFV= 102 NFG= 102 F= 4994.21410 G= 0.790E-04 ITERM= 2 NIT= 9 NFV= 10 NFG= 10 F= 0.230414406E-14 G= 0.642E-07 ITERM= 4 NIT= 8 NFV= 10 NFG= 10 F= 0.128834241E-08 G= 0.977E-06 ITERM= 4 NIT= 1226 NFV= 1256 NFG= 1256 F= 1.92401599 G= 0.970E-06 ITERM= 4 NIT= 227 NFV= 228 NFG= 228 F= -427.391653 G= 0.952E-05 ITERM= 2 NIT= 598 NFV= 604 NFG= 604 F=-0.379921091E-01 G= 0.908E-06 ITERM= 4 NIT= 989 NFV= 998 NFG= 998 F=-0.245741193E-01 G= 0.975E-06 ITERM= 4 NIT= 1367 NFV= 1383 NFG= 1383 F= 1654.94525 G= 0.105E-04 ITERM= 2 NIT= 2274 NFV= 2303 NFG= 2303 F= -1.00013520 G= 0.798E-06 ITERM= 4 NIT= 1196 NFV= 1211 NFG= 1211 F= 2.41354873 G= 0.975E-06 ITERM= 4 NIT= 1361 NFV= 1381 NFG= 1381 F= 1.00000000 G= 0.962E-06 ITERM= 4 NITER =19034 NFVAL =19435 NSUCC = 22 TIME= 0:00:11.09 References: ----------- [1] Luksan L., Matonoha C., Vlcek J.: LSA: Algorithms for large-scale unconstrained and box constrained optimization Technical Report V-896. Prague, ICS AS CR, 2004. [2] Luksan L., Vlcek J.: Sparse and partially separable test problems for unconstrained and equality constrained optimization. Research Report V-767, Institute of Computer Science, Academy of Sciences of the Czech Republic, Prague, Czech Republic, 1998. nlopt-2.6.1/src/algs/luksan/plis.c000066400000000000000000000355761345435414600170320ustar00rootroot00000000000000#include #include #include #include #include "luksan.h" #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define MIN2(a,b) ((a) < (b) ? (a) : (b)) /* *********************************************************************** */ /* SUBROUTINE PLIS ALL SYSTEMS 01/09/22 */ /* PURPOSE : */ /* GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT */ /* USE THE LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG */ /* RECURRENCES. */ /* PARAMETERS : */ /* II NF NUMBER OF VARIABLES. */ /* II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. */ /* NB>0-SIMPLE BOUNDS ACCEPTED. */ /* RI X(NF) VECTOR OF VARIABLES. */ /* II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE */ /* X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). */ /* IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND */ /* XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. */ /* RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. */ /* RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. */ /* RO GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. */ /* RO S(NF) DIRECTION VECTOR. */ /* RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. */ /* RI GO(NF) GRADIENTS DIFFERENCE. */ /* RA UO(NF) AUXILIARY VECTOR. */ /* RA VO(NF) AUXILIARY VECTOR. */ /* RI XMAX MAXIMUM STEPSIZE. */ /* RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. */ /* RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. */ /* RI TOLB TOLERANCE FOR THE FUNCTION VALUE. */ /* RI TOLG TOLERANCE FOR THE GRADIENT NORM. */ /* RI MINF_EST ESTIMATION OF THE MINIMUM FUNCTION VALUE. */ /* RO GMAX MAXIMUM PARTIAL DERIVATIVE. */ /* RO F VALUE OF THE OBJECTIVE FUNCTION. */ /* II MIT MAXIMUM NUMBER OF ITERATIONS. */ /* II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. */ /* II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. */ /* IEST=1-MINIMUM IS ESTIMATED BY THE VALUE MINF_EST. */ /* II MF NUMBER OF LIMITED MEMORY STEPS. */ /* IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. */ /* ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN */ /* MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN */ /* MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. */ /* ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. */ /* ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, */ /* BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. */ /* ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. */ /* ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. */ /* VARIABLES IN COMMON /STAT/ (STATISTICS) : */ /* IO NRES NUMBER OF RESTARTS. */ /* IO NDEC NUMBER OF MATRIX DECOMPOSITION. */ /* IO NIN NUMBER OF INNER ITERATIONS. */ /* IO NIT NUMBER OF ITERATIONS. */ /* IO NFV NUMBER OF FUNCTION EVALUATIONS. */ /* IO NFG NUMBER OF GRADIENT EVALUATIONS. */ /* IO NFH NUMBER OF HESSIAN EVALUATIONS. */ /* SUBPROGRAMS USED : */ /* S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. */ /* S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. */ /* S PYADC0 ADDITION OF A BOX CONSTRAINT. */ /* S PYFUT1 TEST ON TERMINATION. */ /* S PYRMC0 DELETION OF A BOX CONSTRAINT. */ /* S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC */ /* UPDATE. */ /* S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. */ /* S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. */ /* S MXDRCB BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION */ /* OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. */ /* S MXDRCF FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION */ /* OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. */ /* S MXDRSU SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. */ /* SHIFT OF ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN */ /* THE LIMITED MEMORY BFGS METHOD. */ /* S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. */ /* RF MXUDOT DOT PRODUCT OF TWO VECTORS. */ /* S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. */ /* S MXVCOP COPYING OF A VECTOR. */ /* S MXVSCL SCALING OF A VECTOR. */ /* EXTERNAL SUBROUTINES : */ /* SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS */ /* THE VALUE OF THE OBJECTIVE FUNCTION. */ /* SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) */ /* IS THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* -- OBJ and DOBJ are replaced by a single function, objgrad, in NLopt */ /* METHOD : */ /* LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG */ /* RECURRENCES. */ static void plis_(int *nf, int *nb, double *x, int * ix, double *xl, double *xu, double *gf, double *s, double *xo, double *go, double *uo, double *vo, double *xmax, double *tolx, double *tolf, double * tolb, double *tolg, nlopt_stopping *stop, double *minf_est, double *gmax, double *f, int *mit, int *mfv, int *iest, int *mf, int *iterm, stat_common *stat_1, nlopt_func objgrad, void *objgrad_data) { /* System generated locals */ int i__1; double d__1, d__2; /* Builtin functions */ /* Local variables */ double a, b; int i__, k, n; double p, r__; int kd, ld; double fo, fp, po, pp, ro, rp; int kbf, mfg; int mes, kit; double alf1, alf2, eta9, par1, par2; double eps8, eps9; int mred, iold, nred; double maxf, dmax__; int xstop = 0; int inew; double told; int ites; double rmin, rmax, umax, tolp, tols; int isys; int ires1, ires2; int iterd, mtesf, ntesf; double gnorm; int iters, irest, inits, kters, maxst; double snorm; int mtesx, ntesx; ps1l01_state state; (void) tolb; /* INITIATION */ /* Parameter adjustments */ --vo; --uo; --go; --xo; --s; --gf; --xu; --xl; --ix; --x; /* Function Body */ kbf = 0; if (*nb > 0) { kbf = 2; } stat_1->nres = 0; stat_1->ndec = 0; stat_1->nin = 0; stat_1->nit = 0; stat_1->nfg = 0; stat_1->nfh = 0; isys = 0; ites = 1; mtesx = 2; mtesf = 2; inits = 2; *iterm = 0; iterd = 0; iters = 2; kters = 3; irest = 0; ires1 = 999; ires2 = 0; mred = 10; mes = 4; eta9 = 1e120; eps8 = 1.; eps9 = 1e-8; alf1 = 1e-10; alf2 = 1e10; rmax = eta9; dmax__ = eta9; maxf = 1e20; if (*iest <= 0) { *minf_est = -HUGE_VAL; /* changed from -1e60 by SGJ */ } if (*iest > 0) { *iest = 1; } if (*xmax <= 0.) { *xmax = 1e16; } if (*tolx <= 0.) { *tolx = 1e-16; } if (*tolf <= 0.) { *tolf = 1e-14; } if (*tolg <= 0.) { *tolg = 1e-8; /* SGJ: was 1e-6, but this sometimes stops too soon */ } #if 0 /* removed by SGJ: this check prevented us from using minf_max <= 0, which doesn't make sense. Instead, if you don't want to have a lower limit, you should set minf_max = -HUGE_VAL */ if (*tolb <= 0.) { *tolb = *minf_est + 1e-16; } #endif told = 1e-4; tols = 1e-4; tolp = .8; /* changed by SGJ: default is no limit (INT_MAX) on # iterations/fevals */ if (*mit <= 0) { *mit = INT_MAX; } if (*mfv <= 0) { *mfv = INT_MAX; } mfg = *mfv; kd = 1; ld = -1; kit = -(ires1 * *nf + ires2); fo = *minf_est; /* INITIAL OPERATIONS WITH SIMPLE BOUNDS */ if (kbf > 0) { i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { if ((ix[i__] == 3 || ix[i__] == 4) && xu[i__] <= xl[i__]) { xu[i__] = xl[i__]; ix[i__] = 5; } else if (ix[i__] == 5 || ix[i__] == 6) { xl[i__] = x[i__]; xu[i__] = x[i__]; ix[i__] = 5; } /* L2: */ } luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } if (*iterm != 0) { goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); luksan_pyfut1__(nf, f, &fo, &umax, gmax, xstop, stop, tolg, &kd, &stat_1->nit, &kit, mit, &stat_1->nfg, &mfg, &ntesx, &mtesx, &ntesf, &mtesf, &ites, &ires1, &ires2, &irest, & iters, iterm); if (*iterm != 0) { goto L11190; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } if (kbf > 0 && rmax > 0.) { luksan_pyrmc0__(nf, &n, &ix[1], &gf[1], &eps8, &umax, gmax, &rmax, & iold, &irest); } L11130: /* DIRECTION DETERMINATION */ gnorm = sqrt(luksan_mxudot__(nf, &gf[1], &gf[1], &ix[1], &kbf)); if (irest != 0) { goto L12620; } /* Computing MIN */ i__1 = stat_1->nit - kit; k = MIN2(i__1,*mf); if (k <= 0) { irest = MAX2(irest,1); goto L12620; } /* DETERMINATION OF THE PARAMETER B */ b = luksan_mxudot__(nf, &xo[1], &go[1], &ix[1], &kbf); if (b <= 0.) { irest = MAX2(irest,1); goto L12620; } uo[1] = 1. / b; luksan_mxuneg__(nf, &gf[1], &s[1], &ix[1], &kbf); luksan_mxdrcb__(nf, &k, &xo[1], &go[1], &uo[1], &vo[1], &s[1], &ix[1], & kbf); a = luksan_mxudot__(nf, &go[1], &go[1], &ix[1], &kbf); if (a > 0.) { d__1 = b / a; luksan_mxvscl__(nf, &d__1, &s[1], &s[1]); } luksan_mxdrcf__(nf, &k, &xo[1], &go[1], &uo[1], &vo[1], &s[1], &ix[1], & kbf); snorm = sqrt(luksan_mxudot__(nf, &s[1], &s[1], &ix[1], &kbf)); /* Computing MIN */ i__1 = k + 1; k = MIN2(i__1,*mf); luksan_mxdrsu__(nf, &k, &xo[1], &go[1], &uo[1]); L12620: iterd = 0; if (irest != 0) { /* STEEPEST DESCENT DIRECTION */ luksan_mxuneg__(nf, &gf[1], &s[1], &ix[1], &kbf); snorm = gnorm; if (kit < stat_1->nit) { ++stat_1->nres; kit = stat_1->nit; } else { *iterm = -10; if (iters < 0) { *iterm = iters - 5; } } } /* TEST ON DESCENT DIRECTION AND PREPARATION OF LINE SEARCH */ if (kd > 0) { p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); } if (iterd < 0) { *iterm = iterd; } else { /* TEST ON DESCENT DIRECTION */ if (snorm <= 0.) { irest = MAX2(irest,1); } else if (p + told * gnorm * snorm <= 0.) { irest = 0; } else { /* UNIFORM DESCENT CRITERION */ irest = MAX2(irest,1); } if (irest == 0) { /* PREPARATION OF LINE SEARCH */ nred = 0; rmin = alf1 * gnorm / snorm; /* Computing MIN */ d__1 = alf2 * gnorm / snorm, d__2 = *xmax / snorm; rmax = MIN2(d__1,d__2); } } if (*iterm != 0) { goto L11190; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } if (irest != 0) { goto L11130; } luksan_pytrcs__(nf, &x[1], &ix[1], &xo[1], &xl[1], &xu[1], &gf[1], &go[1], &s[1], &ro, &fp, &fo, f, &po, &p, &rmax, &eta9, &kbf); if (rmax == 0.) { goto L11175; } L11170: luksan_ps1l01__(&r__, &rp, f, &fo, &fp, &p, &po, &pp, minf_est, &maxf, &rmin, &rmax, &tols, &tolp, &par1, &par2, &kd, &ld, &stat_1->nit, &kit, & nred, &mred, &maxst, iest, &inits, &iters, &kters, &mes, &isys, &state); if (isys == 0) { goto L11174; } luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); goto L11170; L11174: if (iters <= 0) { r__ = 0.; *f = fo; p = po; luksan_mxvcop__(nf, &xo[1], &x[1]); luksan_mxvcop__(nf, &go[1], &gf[1]); irest = MAX2(irest,1); ld = kd; goto L11130; } luksan_pytrcd__(nf, &x[1], &ix[1], &xo[1], &gf[1], &go[1], &r__, f, &fo, & p, &po, &dmax__, &kbf, &kd, &ld, &iters); xstop = nlopt_stop_dx(stop, &x[1], &xo[1]); L11175: if (kbf > 0) { luksan_mxvine__(nf, &ix[1]); luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } goto L11120; L11190: return; } /* plis_ */ /* NLopt wrapper around plis_, handling dynamic allocation etc. */ nlopt_result luksan_plis(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf) /* subspace dimension, 0 for default */ { int i, *ix, nb = 1; double *work, *xl, *xu, *xo, *gf, *s, *go, *uo, *vo; double gmax, minf_est; double xmax = 0; /* no maximum */ double tolg = 0; /* default gradient tolerance */ int iest = 0; /* we have no estimate of min function value */ int mit = 0; /* default no limit on #iterations */ int mfv = stop->maxeval; stat_common stat; int iterm; ix = (int*) malloc(sizeof(int) * n); if (!ix) return NLOPT_OUT_OF_MEMORY; if (mf <= 0) { mf = MAX2(MEMAVAIL/n, 10); if (stop->maxeval && stop->maxeval <= mf) mf = MAX2(stop->maxeval, 1); } retry_alloc: work = (double*) malloc(sizeof(double) * (n * 4 + MAX2(n,n*mf)*2 + MAX2(n,mf)*2)); if (!work) { if (mf > 0) { mf = 0; /* allocate minimal memory */ goto retry_alloc; } free(ix); return NLOPT_OUT_OF_MEMORY; } xl = work; xu = xl + n; gf = xu + n; s = gf + n; xo = s + n; go = xo + MAX2(n,n*mf); uo = go + MAX2(n,n*mf); vo = uo + MAX2(n,mf); for (i = 0; i < n; ++i) { int lbu = lb[i] <= -0.99 * HUGE_VAL; /* lb unbounded */ int ubu = ub[i] >= 0.99 * HUGE_VAL; /* ub unbounded */ ix[i] = lbu ? (ubu ? 0 : 2) : (ubu ? 1 : (lb[i] == ub[i] ? 5 : 3)); xl[i] = lb[i]; xu[i] = ub[i]; } /* ? xo does not seem to be initialized in the original Fortran code, but it is used upon input to plis if mf > 0 ... perhaps ALLOCATE initializes arrays to zero by default? */ memset(xo, 0, sizeof(double) * MAX2(n,n*mf)); plis_(&n, &nb, x, ix, xl, xu, gf, s, xo, go, uo, vo, &xmax, /* fixme: pass tol_rel and tol_abs and use NLopt check */ &stop->xtol_rel, &stop->ftol_rel, &stop->minf_max, &tolg, stop, &minf_est, &gmax, minf, &mit, &mfv, &iest, &mf, &iterm, &stat, f, f_data); free(work); free(ix); switch (iterm) { case 1: return NLOPT_XTOL_REACHED; case 2: return NLOPT_FTOL_REACHED; case 3: return NLOPT_MINF_MAX_REACHED; case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; case 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } } nlopt-2.6.1/src/algs/luksan/plis.for000066400000000000000000000461211345435414600173620ustar00rootroot00000000000000************************************************************************ * SUBROUTINE PLISU ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE UNCONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(6) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(7) MAXIMUM NUMBER OF VARIABLE METRIC UPDATES. * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PLIS LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PLISU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LS,LXO,LGO,LUO,LVO INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(2*NF+2*NF*MF+2*MF)) NB=0 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LS=LGF+NF LXO=LS+NF LGO=LXO+NF*MF LUO=LGO+NF*MF LVO=LUO+MF CALL PLIS(NF,NB,X,IPAR,RA,RA,RA(LGF),RA(LS),RA(LXO),RA(LGO), & RA(LUO),RA(LVO),RPAR(1),RPAR(2),RPAR(3),RPAR(4),RPAR(5),RPAR(6), & GMAX,F,IPAR(1),IPAR(2),IPAR(4),MF,IPRNT,ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PLISS ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(6) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * IPAR(7) MAXIMUM NUMBER OF VARIABLE METRIC UPDATES. * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PLIS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PLIS LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PLISS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IX(*),IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LS,LXO,LGO,LUO,LVO INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(2*NF+2*NF*MF+2*MF)) NB=1 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LS=LGF+NF LXO=LS+NF LGO=LXO+NF*MF LUO=LGO+NF*MF LVO=LUO+MF CALL PLIS(NF,NB,X,IX,XL,XU,RA(LGF),RA(LS),RA(LXO),RA(LGO), & RA(LUO),RA(LVO),RPAR(1),RPAR(2),RPAR(3),RPAR(4),RPAR(5),RPAR(6), & GMAX,F,IPAR(1),IPAR(2),IPAR(4),MF,IPRNT,ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PLIS ALL SYSTEMS 01/09/22 * PURPOSE : * GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT * USE THE LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. * NB>0-SIMPLE BOUNDS ACCEPTED. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RO GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * RA UO(NF) AUXILIARY VECTOR. * RA VO(NF) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. * RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. * RI TOLB TOLERANCE FOR THE FUNCTION VALUE. * RI TOLG TOLERANCE FOR THE GRADIENT NORM. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * RO F VALUE OF THE OBJECTIVE FUNCTION. * II MIT MAXIMUM NUMBER OF ITERATIONS. * II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * II MF NUMBER OF LIMITED MEMORY STEPS. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITION. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. * S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. * S PYADC0 ADDITION OF A BOX CONSTRAINT. * S PYFUT1 TEST ON TERMINATION. * S PYRMC0 DELETION OF A BOX CONSTRAINT. * S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC * UPDATE. * S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. * S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. * S MXDRCB BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION * OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * S MXDRCF FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION * OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * S MXDRSU SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. * SHIFT OF ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN * THE LIMITED MEMORY BFGS METHOD. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVCOP COPYING OF A VECTOR. * S MXVSCL SCALING OF A VECTOR. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * * METHOD : * LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * SUBROUTINE PLIS(NF,NB,X,IX,XL,XU,GF,S,XO,GO,UO,VO,XMAX,TOLX, & TOLF,TOLB,TOLG,FMIN,GMAX,F,MIT,MFV,IEST,MF,IPRNT,ITERM) INTEGER NF,NB,IX(*),MIT,MFV,IEST,MF,IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),GF(*),S(*),XO(*),GO(*),UO(*), & VO(*),TOLX,TOLF,TOLG,TOLB,FMIN,XMAX,GMAX,F INTEGER ITERD,ITERS,KD,LD,NTESX,NTESF,MTESX,MTESF,MRED,KIT, & IREST,KBF,MES,MES1,MES2,MES3,MAXST,ISYS,ITES,INITS,KTERS, & IRES1,IRES2,INEW,IOLD,I,N,MFG,K,NRED DOUBLE PRECISION R,RO,RP,FO,FP,P,PO,PP,GNORM,SNORM,RMIN,RMAX, & UMAX,FMAX,DMAX,ETA0,ETA9,EPS8,EPS9,ALF1,ALF2,PAR1,PAR2,A,B, & TOLD,TOLS,TOLP DOUBLE PRECISION MXUDOT INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH IF (ABS(IPRNT).GT.1) WRITE(6,'(1X,''ENTRY TO PLIS :'')') * * INITIATION * KBF=0 IF (NB.GT.0) KBF=2 NRES=0 NDEC=0 NIN=0 NIT=0 NFV=0 NFG=0 NFH=0 ISYS=0 ITES=1 MTESX=2 MTESF=2 INITS=2 ITERM=0 ITERD=0 ITERS=2 KTERS=3 IREST=0 IRES1=999 IRES2=0 MRED=10 MES=4 MES1=2 MES2=2 MES3=2 ETA0=1.0D-15 ETA9=1.0D 120 EPS8=1.00D 0 EPS9=1.00D-8 ALF1=1.0D-10 ALF2=1.0D 10 RMAX=ETA9 DMAX=ETA9 FMAX=1.0D 20 IF (IEST.LE.0) FMIN=-1.0D 60 IF (IEST.GT.0) IEST=1 IF (XMAX.LE.0.0D 0) XMAX=1.0D 16 IF (TOLX.LE.0.0D 0) TOLX=1.0D-16 IF (TOLF.LE.0.0D 0) TOLF=1.0D-14 IF (TOLG.LE.0.0D 0) TOLG=1.0D-6 IF (TOLB.LE.0.0D 0) TOLB=FMIN+1.0D-16 TOLD=1.0D-4 TOLS=1.0D-4 TOLP=0.8D 0 IF (MIT.LE.0) MIT=9000 IF (MFV.LE.0) MFV=9000 MFG=MFV KD= 1 LD=-1 KIT=-(IRES1*NF+IRES2) FO=FMIN * * INITIAL OPERATIONS WITH SIMPLE BOUNDS * IF (KBF.GT.0) THEN DO 2 I = 1,NF IF ((IX(I).EQ.3.OR.IX(I).EQ.4) .AND. XU(I).LE.XL(I)) THEN XU(I) = XL(I) IX(I) = 5 ELSE IF (IX(I).EQ.5 .OR. IX(I).EQ.6) THEN XL(I) = X(I) XU(I) = X(I) IX(I) = 5 END IF 2 CONTINUE CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL PYADC0(NF,N,X,IX,XL,XU,INEW) END IF IF (ITERM.NE.0) GO TO 11190 CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 11120 CONTINUE CALL PYTRCG(NF,NF,IX,GF,UMAX,GMAX,KBF,IOLD) IF (ABS(IPRNT).GT.1) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3)') NIT,NFV,NFG,F,GMAX CALL PYFUT1(NF,F,FO,UMAX,GMAX,DMAX,TOLX,TOLF,TOLB,TOLG,KD, & NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF,ITES, & IRES1,IRES2,IREST,ITERS,ITERM) IF (ITERM.NE.0) GO TO 11190 IF (KBF.GT.0.AND.RMAX.GT.0.0D 0) THEN CALL PYRMC0(NF,N,IX,GF,EPS8,UMAX,GMAX,RMAX,IOLD,IREST) END IF 11130 CONTINUE * * DIRECTION DETERMINATION * GNORM=SQRT(MXUDOT(NF,GF,GF,IX,KBF)) IF (IREST.NE.0) GO TO 12620 K=MIN(NIT-KIT,MF) IF (K.LE.0) THEN IREST=MAX(IREST,1) GO TO 12620 END IF * * DETERMINATION OF THE PARAMETER B * B=MXUDOT(NF,XO,GO,IX,KBF) IF (B.LE.0.0D 0) THEN IREST=MAX(IREST,1) GO TO 12620 END IF UO(1)=1.0D 0/B CALL MXUNEG(NF,GF,S,IX,KBF) CALL MXDRCB(NF,K,XO,GO,UO,VO,S,IX,KBF) A=MXUDOT(NF,GO,GO,IX,KBF) IF (A.GT.0.0D 0) THEN CALL MXVSCL(NF,B/A,S,S) END IF CALL MXDRCF(NF,K,XO,GO,UO,VO,S,IX,KBF) SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) K=MIN(K+1,MF) CALL MXDRSU(NF,K,XO,GO,UO) 12620 CONTINUE ITERD=0 IF (IREST.NE.0) THEN * * STEEPEST DESCENT DIRECTION * CALL MXUNEG(NF,GF,S,IX,KBF) SNORM=GNORM IF (KIT.LT.NIT) THEN NRES=NRES+1 KIT = NIT ELSE ITERM=-10 IF (ITERS.LT.0) ITERM=ITERS-5 END IF END IF * * TEST ON DESCENT DIRECTION AND PREPARATION OF LINE SEARCH * IF (KD.GT.0) P=MXUDOT(NF,GF,S,IX,KBF) IF (ITERD.LT.0) THEN ITERM=ITERD ELSE * * TEST ON DESCENT DIRECTION * IF (SNORM.LE.0.0D 0) THEN IREST=MAX(IREST,1) ELSE IF (P+TOLD*GNORM*SNORM.LE.0.0D 0) THEN IREST=0 ELSE * * UNIFORM DESCENT CRITERION * IREST=MAX(IREST,1) END IF IF (IREST.EQ.0) THEN * * PREPARATION OF LINE SEARCH * NRED = 0 RMIN=ALF1*GNORM/SNORM RMAX=MIN(ALF2*GNORM/SNORM,XMAX/SNORM) END IF END IF IF (ITERM.NE.0) GO TO 11190 IF (IREST.NE.0) GO TO 11130 CALL PYTRCS(NF,X,IX,XO,XL,XU,GF,GO,S,RO,FP,FO,F,PO,P,RMAX,ETA9, & KBF) IF (RMAX.EQ.0.0D 0) GO TO 11175 11170 CONTINUE CALL PS1L01(R,RP,F,FO,FP,P,PO,PP,FMIN,FMAX,RMIN,RMAX, & TOLS,TOLP,PAR1,PAR2,KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST, & INITS,ITERS,KTERS,MES,ISYS) IF (ISYS.EQ.0) GO TO 11174 CALL MXUDIR(NF,R,S,XO,X,IX,KBF) CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 P=MXUDOT(NF,GF,S,IX,KBF) GO TO 11170 11174 CONTINUE IF (ITERS.LE.0) THEN R=0.0D 0 F=FO P=PO CALL MXVCOP(NF,XO,X) CALL MXVCOP(NF,GO,GF) IREST=MAX(IREST,1) LD=KD GO TO 11130 END IF CALL PYTRCD(NF,X,IX,XO,GF,GO,R,F,FO,P,PO,DMAX,KBF,KD,LD,ITERS) 11175 CONTINUE IF (KBF.GT.0) THEN CALL MXVINE(NF,IX) CALL PYADC0(NF,N,X,IX,XL,XU,INEW) END IF GO TO 11120 11190 CONTINUE IF (IPRNT.GT.1.OR.IPRNT.LT.0) & WRITE(6,'(1X,''EXIT FROM PLIS :'')') IF (IPRNT.NE.0) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3,2X,''ITERM='',I3)') NIT,NFV,NFG, & F,GMAX,ITERM IF (IPRNT.LT.0) & WRITE (6,'(1X,''X='',5(G14.7,1X):/(3X,5(G14.7,1X)))') & (X(I),I=1,NF) RETURN END nlopt-2.6.1/src/algs/luksan/plis.txt000066400000000000000000000373061345435414600174200ustar00rootroot00000000000000*********************************************************************** * * * PLIS - A LIMITED MEMORY VARIABLE METRIC ALGORITHM FOR * * LARGE-SCALE OPTIMIZATION. * * * *********************************************************************** 1. Introduction: ---------------- The double-precision FORTRAN 77 basic subroutine PLIS is designed to find a close approximation to a local minimum of a nonlinear function F(X) with simple bounds on variables. Here X is a vector of NF variables and F(X) is a smooth function. We suppose that NF is large but the sparsity pattern of the Hessian matrix is not known (or the Hessian matrix is dense). Simple bounds are assumed in the form X(I) unbounded if IX(I) = 0, XL(I) <= X(I) if IX(I) = 1, X(I) <= XU(I) if IX(I) = 2, XL(I) <= X(I) <= XU(I) if IX(I) = 3, XL(I) = X(I) = XU(I) if IX(I) = 5, where 1 <= I <= NF. To simplify user's work, two additional easy to use subroutines are added. They call the basic general subroutine PLIS: PLISU - unconstrained large-scale optimization, PLISS - large-scale optimization with simple bounds. All subroutines contain a description of formal parameters and extensive comments. Furthermore, two test programs TLISU and TLISS are included, which contain several test problems (see e.g. [2]). These test programs serve as examples for using the subroutines, verify their correctness and demonstrate their efficiency. In this short guide, we describe all subroutines which can be called from the user's program. A detailed description of the method is given in [1]. In the description of formal parameters, we introduce a type of the argument that specifies whether the argument must have a value defined on entry to the subroutine (I), whether it is a value which will be returned (O), or both (U), or whether it is an auxiliary value (A). Note that the arguments of the type I can be changed on output under some circumstances, especially if improper input values were given. Besides formal parameters, we can use a COMMON /STAT/ block containing statistical information. This block, used in each subroutine has the following form: COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH The arguments have the following meaning: Argument Type Significance ---------------------------------------------------------------------- NRES O Positive INTEGER variable that indicates the number of restarts. NDEC O Positive INTEGER variable that indicates the number of matrix decompositions. NIN O Positive INTEGER variable that indicates the number of inner iterations (for solving linear systems). NIT O Positive INTEGER variable that indicates the number of iterations. NFV O Positive INTEGER variable that indicates the number of function evaluations. NFG O Positive INTEGER variable that specifies the number of gradient evaluations. NFH O Positive INTEGER variable that specifies the number of Hessian evaluations. 2. Subroutines PLISU, PLISS: ---------------------------- The calling sequences are CALL PLISU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) CALL PLISS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) The arguments have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) U On input, DOUBLE PRECISION vector with the initial estimate to the solution. On output, the approximation to the minimum. IX(NF) I On input (significant only if NB>0) INTEGER vector containing the simple bounds types: IX(I)=0 - the variable X(I) is unbounded, IX(I)=1 - the lower bound X(I) >= XL(I), IX(I)=2 - the upper bound X(I) <= XU(I), IX(I)=3 - the two side bound XL(I) <= X(I) <= XU(I), IX(I)=5 - the variable X(I) is fixed (given by its initial estimate). XL(NF) I DOUBLE PRECISION vector with lower bounds for variables (significant only if NB>0). XU(NF) I DOUBLE PRECISION vector with upper bounds for variables (significant only if NB>0). IPAR(7) I INTEGER parameters: IPAR(1)=MIT, IPAR(2)=MFV, IPAR(3)-NONE, IPAR(4)=IEST, IPAR(5)-NONE, IPAR(6)-NONE, IPAR(7)=MF. Parameters MIT, MFV, IEST, MF are described in Section 3 together with other parameters of the subroutine PLIS. RPAR(9) I DOUBLE PRECISION parameters: RPAR(1)=XMAX, RPAR(2)=TOLX, RPAR(3)=TOLF, RPAR(4)=TOLB, RPAR(5)=TOLG, RPAR(6)=FMIN, RPAR(7)-NONE, RPAR(6)-NONE, RPAR(9)-NONE. Parameters XMAX, TOLX, TOLF, TOLB, TOLG, FMIN are described in Section 3 together with other parameters of the subroutine PLIS. F O DOUBLE PRECISION value of the objective function at the solution X. GMAX O DOUBLE PRECISION maximum absolute value of a partial derivative of the Lagrangian function. IPRNT I INTEGER variable that specifies PRINT: IPRNT= 0 - print is suppressed, IPRNT= 1 - basic print of final results, IPRNT=-1 - extended print of final results, IPRNT= 2 - basic print of intermediate and final results, IPRNT=-2 - extended print of intermediate and final results. ITERM O INTEGER variable that indicates the cause of termination: ITERM= 1 - if |X - XO| was less than or equal to TOLX in two subsequent iterations, ITERM= 2 - if |F - FO| was less than or equal to TOLF in two subsequent iterations, ITERM= 3 - if F is less than or equal to TOLB, ITERM= 4 - if GMAX is less than or equal to TOLG, ITERM= 6 - if termination criterion was not satisfied, but the solution is probably acceptable, ITERM=11 - if NIT exceeded MIT, ITERM=12 - if NFV exceeded MFV, ITERM< 0 - if the method failed. The subroutines PLISU, PLISS require the user supplied subroutines OBJ and DOBJ that define the objective function and its gradient and have the form SUBROUTINE OBJ(NF,X,F) SUBROUTINE DOBJ(NF,X,G) The arguments of the user supplied subroutines have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) I DOUBLE PRECISION an estimate to the solution. F O DOUBLE PRECISION value of the objective function at the point X. G(NF) O DOUBLE PRECISION gradient of the objective function at the point X. 3. Subroutine PLIS: ------------------- This general subroutine is called from all subroutines described in Section 2. The calling sequence is CALL PLIS(NF,NB,X,IX,XL,XU,GF,S,XO,GO,UO,VO,XMAX,TOLX,TOLF,TOLB, & TOLG,FMIN,GMAX,F,MIT,MFV,IEST,MF,IPRNT,ITERM) The arguments NF, NB, X, IX, XL, XU, GMAX, F, IPRNT, ITERM, have the same meaning as in Section 2. Other arguments have the following meaning: Argument Type Significance ---------------------------------------------------------------------- GF(NF) A DOUBLE PRECISION gradient of the objective function. S(NF) A DOUBLE PRECISION direction vector. XO(NF*MF) A DOUBLE PRECISION array which contains increments of variables. GO(NF*MF) A DOUBLE PRECISION array which contains increments of gradients. UO(MF) A DOUBLE PRECISION Auxiliary array. VO(MF) A DOUBLE PRECISION Auxiliary array. XMAX I DOUBLE PRECISION maximum stepsize; the choice XMAX=0 causes that the default value 1.0D+16 will be taken. TOLX I DOUBLE PRECISION tolerance for the change of the coordinate vector X; the choice TOLX=0 causes that the default value TOLX=1.0D-16 will be taken. TOLF I DOUBLE PRECISION tolerance for the change of function values; the choice TOLF=0 causes that the default value TOLF=1.0D-14 will be taken. TOLB I DOUBLE PRECISION minimum acceptable function value; the choice TOLB=0 causes that the default value TOLB=FMIN+1.0D-16 will be taken. TOLG I DOUBLE PRECISION tolerance for the Lagrangian function gradient; the choice TOLG=0 causes that the default value TOLG=1.0D-6 will be taken. FMIN I DOUBLE PRECISION lower bound for the minimum function value. MIT I INTEGER variable that specifies the maximum number of iterations; the choice MIT=0 causes that the default value 9000 will be taken. MFV I INTEGER variable that specifies the maximum number of function evaluations; the choice MFV=0 causes that the default value 9000 will be taken. IEST I INTEGER estimation of the minimum functiom value for the line search: IEST=0 - estimation is not used, IEST=1 - lower bound FMIN is used as an estimation for the minimum function value. MF I The number of limited-memory variable metric updates in each iteration (they use 2*MF stored vectors). The choice of parameter XMAX can be sensitive in many cases. First, the objective function can be evaluated only in a relatively small region (if it contains exponentials) so that the maximum stepsize is necessary. Secondly, the problem can be very ill-conditioned far from the solution point so that large steps can be unsuitable. Finally, if the problem has more local solutions, a suitably chosen maximum stepsize can lead to obtaining a better local solution. The subroutine PLIS requires the user supplied subroutines OBJ and DOBJ which are described in Section 2. 4. Verification of the subroutines: ----------------------------------- Subroutine PLISU can be verified and tested using the program TLISU. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation) and TFGU14 (gradient evaluation) containing 22 unconstrained test problems with at most 1000 variables [2]. The results obtained by the program TLISU on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 4988 NFV= 5554 NFG= 5554 F= 0.963780013E-14 G= 0.891E-06 ITERM= 4 NIT= 425 NFV= 454 NFG= 454 F= 14.9944763 G= 0.773E-05 ITERM= 2 NIT= 74 NFV= 78 NFG= 78 F= 0.655101686E-09 G= 0.539E-06 ITERM= 4 NIT= 103 NFV= 112 NFG= 112 F= 269.499543 G= 0.899E-06 ITERM= 4 NIT= 24 NFV= 26 NFG= 26 F= 0.130639280E-11 G= 0.671E-06 ITERM= 4 NIT= 30 NFV= 31 NFG= 31 F= 0.216102227E-10 G= 0.946E-06 ITERM= 4 NIT= 38 NFV= 43 NFG= 43 F= 335.137433 G= 0.730E-06 ITERM= 4 NIT= 29 NFV= 33 NFG= 33 F= 761774.954 G= 0.432E-03 ITERM= 2 NIT= 13 NFV= 16 NFG= 16 F= 316.436141 G= 0.369E-06 ITERM= 4 NIT= 1540 NFV= 1582 NFG= 1582 F= -124.630000 G= 0.124E-04 ITERM= 2 NIT= 114 NFV= 138 NFG= 138 F= 10.7765879 G= 0.380E-06 ITERM= 4 NIT= 248 NFV= 267 NFG= 267 F= 982.273617 G= 0.123E-04 ITERM= 2 NIT= 7 NFV= 8 NFG= 8 F= 0.165734137E-12 G= 0.453E-06 ITERM= 4 NIT= 10 NFV= 12 NFG= 12 F= 0.128729169E-08 G= 0.916E-06 ITERM= 4 NIT= 2830 NFV= 2929 NFG= 2929 F= 1.92401599 G= 0.936E-06 ITERM= 4 NIT= 196 NFV= 210 NFG= 210 F= -427.404476 G= 0.991E-05 ITERM= 2 NIT= 1007 NFV= 1032 NFG= 1032 F=-0.379921091E-01 G= 0.876E-06 ITERM= 4 NIT= 1449 NFV= 1474 NFG= 1474 F=-0.245741193E-01 G= 0.862E-06 ITERM= 4 NIT= 1393 NFV= 1431 NFG= 1431 F= 59.5986241 G= 0.259E-05 ITERM= 2 NIT= 2129 NFV= 2191 NFG= 2191 F= -1.00013520 G= 0.908E-06 ITERM= 4 NIT= 2120 NFV= 2169 NFG= 2169 F= 2.13866377 G= 0.927E-06 ITERM= 4 NIT= 1305 NFV= 1346 NFG= 1346 F= 1.00000000 G= 0.982E-06 ITERM= 4 NITER =20072 NFVAL =21136 NSUCC = 22 TIME= 0:00:10.78 The rows corresponding to individual test problems contain the number of iterations NIT, the number of function evaluations NFV, the number of gradient evaluations NFG, the final value of the objective function F, the norm of gradient G and the cause of termination ITERM. Subroutine PLISS can be verified and tested using the program TLISS. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation), TFGU14 (gradient evaluation) containing 22 box constrained test problems with at most 1000 variables [2]. The results obtained by the program TLISS on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 5063 NFV= 5738 NFG= 5738 F= 0.00000000 G= 0.000E+00 ITERM= 3 NIT= 3167 NFV= 4664 NFG= 4664 F= 3926.45961 G= 0.626E-04 ITERM= 2 NIT= 113 NFV= 124 NFG= 124 F= 0.459503394E-12 G= 0.600E-06 ITERM= 4 NIT= 59 NFV= 64 NFG= 64 F= 269.522686 G= 0.838E-06 ITERM= 4 NIT= 24 NFV= 26 NFG= 26 F= 0.130639280E-11 G= 0.671E-06 ITERM= 4 NIT= 30 NFV= 31 NFG= 31 F= 0.216102227E-10 G= 0.946E-06 ITERM= 4 NIT= 33 NFV= 40 NFG= 40 F= 337.722479 G= 0.592E-06 ITERM= 4 NIT= 50 NFV= 55 NFG= 55 F= 761925.725 G= 0.240E-03 ITERM= 2 NIT= 505 NFV= 508 NFG= 508 F= 428.056916 G= 0.334E-07 ITERM= 4 NIT= 1167 NFV= 1227 NFG= 1227 F= -81.0913589 G= 0.100E-04 ITERM= 2 NIT= 20 NFV= 26 NFG= 26 F= 96517.2947 G= 0.745E-05 ITERM= 2 NIT= 91 NFV= 109 NFG= 109 F= 4994.21410 G= 0.104E-04 ITERM= 2 NIT= 7 NFV= 8 NFG= 8 F= 0.165734137E-12 G= 0.453E-06 ITERM= 4 NIT= 10 NFV= 12 NFG= 12 F= 0.128729169E-08 G= 0.916E-06 ITERM= 4 NIT= 2830 NFV= 2929 NFG= 2929 F= 1.92401599 G= 0.936E-06 ITERM= 4 NIT= 178 NFV= 184 NFG= 184 F= -427.391653 G= 0.107E-04 ITERM= 2 NIT= 1007 NFV= 1032 NFG= 1032 F=-0.379921091E-01 G= 0.876E-06 ITERM= 4 NIT= 1449 NFV= 1474 NFG= 1474 F=-0.245741193E-01 G= 0.862E-06 ITERM= 4 NIT= 1561 NFV= 1595 NFG= 1595 F= 1654.94525 G= 0.112E-04 ITERM= 2 NIT= 2075 NFV= 2121 NFG= 2121 F= -1.00013520 G= 0.916E-06 ITERM= 4 NIT= 1361 NFV= 1389 NFG= 1389 F= 2.41354873 G= 0.709E-06 ITERM= 4 NIT= 1562 NFV= 1598 NFG= 1598 F= 1.00000000 G= 0.786E-06 ITERM= 4 NITER =22362 NFVAL =24954 NSUCC = 22 TIME= 0:00:12.39 References: ----------- [1] Luksan L., Matonoha C., Vlcek J.: LSA: Algorithms for large-scale unconstrained and box constrained optimization Technical Report V-896. Prague, ICS AS CR, 2004. [2] Luksan L., Vlcek J.: Sparse and partially separable test problems for unconstrained and equality constrained optimization. Research Report V-767, Institute of Computer Science, Academy of Sciences of the Czech Republic, Prague, Czech Republic, 1998. nlopt-2.6.1/src/algs/luksan/pnet.c000066400000000000000000000462771345435414600170310ustar00rootroot00000000000000#include #include #include #include #include "luksan.h" #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define MIN2(a,b) ((a) < (b) ? (a) : (b)) /* Table of constant values */ static double c_b7 = 0.; /* *********************************************************************** */ /* SUBROUTINE PNET ALL SYSTEMS 01/09/22 */ /* PURPOSE : */ /* GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT */ /* USE THE LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG */ /* RECURRENCES. */ /* PARAMETERS : */ /* II NF NUMBER OF VARIABLES. */ /* II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. */ /* NB>0-SIMPLE BOUNDS ACCEPTED. */ /* RI X(NF) VECTOR OF VARIABLES. */ /* II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE */ /* X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). */ /* IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND */ /* XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. */ /* RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. */ /* RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. */ /* RO GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. */ /* RA GN(NF) OLD GRADIENT OF THE OBJECTIVE FUNCTION. */ /* RO S(NF) DIRECTION VECTOR. */ /* RA XO(NF) ARRAY CONTAINING INCREMENTS OF VARIABLES. */ /* RA GO(NF) ARRAY CONTAINING INCREMENTS OF GRADIENTS. */ /* RA XS(NF) AUXILIARY VECTOR. */ /* RA GS(NF) AUXILIARY VECTOR. */ /* RA XM(NF*MF) ARRAY CONTAINING INCREMENTS OF VARIABLES. */ /* RA GM(NF*MF) ARRAY CONTAINING INCREMENTS OF GRADIENTS. */ /* RA U1(MF) AUXILIARY VECTOR. */ /* RA U2(MF) AUXILIARY VECTOR. */ /* RI XMAX MAXIMUM STEPSIZE. */ /* RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. */ /* RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. */ /* RI TOLB TOLERANCE FOR THE FUNCTION VALUE. */ /* RI TOLG TOLERANCE FOR THE GRADIENT NORM. */ /* RI MINF_EST ESTIMATION OF THE MINIMUM FUNCTION VALUE. */ /* RO GMAX MAXIMUM PARTIAL DERIVATIVE. */ /* RO F VALUE OF THE OBJECTIVE FUNCTION. */ /* II MIT MAXIMUM NUMBER OF ITERATIONS. */ /* II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. */ /* II MFG MAXIMUM NUMBER OF GRADIENT EVALUATIONS. */ /* II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. */ /* IEST=1-MINIMUM IS ESTIMATED BY THE VALUE MINF_EST. */ /* II MOS1 CHOICE OF RESTARTS AFTER A CONSTRAINT CHANGE. */ /* MOS1=1-RESTARTS ARE SUPPRESSED. MOS1=2-RESTARTS WITH */ /* STEEPEST DESCENT DIRECTIONS ARE USED. */ /* II MOS1 CHOICE OF DIRECTION VECTORS AFTER RESTARTS. MOS1=1-THE */ /* NEWTON DIRECTIONS ARE USED. MOS1=2-THE STEEPEST DESCENT */ /* DIRECTIONS ARE USED. */ /* II MOS2 CHOICE OF PRECONDITIONING STRATEGY. MOS2=1-PRECONDITIONING */ /* IS NOT USED. MOS2=2-PRECONDITIONING BY THE LIMITED MEMORY */ /* BFGS METHOD IS USED. */ /* II MF THE NUMBER OF LIMITED-MEMORY VARIABLE METRIC UPDATES */ /* IN EACH ITERATION (THEY USE 2*MF STORED VECTORS). */ /* IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. */ /* ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN */ /* MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN */ /* MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. */ /* ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. */ /* ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. */ /* ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, */ /* BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. */ /* ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. */ /* ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. */ /* VARIABLES IN COMMON /STAT/ (STATISTICS) : */ /* IO NRES NUMBER OF RESTARTS. */ /* IO NDEC NUMBER OF MATRIX DECOMPOSITION. */ /* IO NIN NUMBER OF INNER ITERATIONS. */ /* IO NIT NUMBER OF ITERATIONS. */ /* IO NFV NUMBER OF FUNCTION EVALUATIONS. */ /* IO NFG NUMBER OF GRADIENT EVALUATIONS. */ /* IO NFH NUMBER OF HESSIAN EVALUATIONS. */ /* SUBPROGRAMS USED : */ /* S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. */ /* S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. */ /* S PYADC0 ADDITION OF A BOX CONSTRAINT. */ /* S PYFUT1 TEST ON TERMINATION. */ /* S PYRMC0 DELETION OF A BOX CONSTRAINT. */ /* S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC */ /* UPDATE. */ /* S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. */ /* S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. */ /* S MXDRCB BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION */ /* OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. */ /* S MXDRCF FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION */ /* OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. */ /* S MXDRSU SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. */ /* SHIFT OF ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN */ /* THE LIMITED MEMORY BFGS METHOD. */ /* S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. */ /* RF MXUDOT DOT PRODUCT OF TWO VECTORS. */ /* S MXVNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. */ /* S MXVCOP COPYING OF A VECTOR. */ /* S MXVSCL SCALING OF A VECTOR. */ /* S MXVSET INITIATINON OF A VECTOR. */ /* S MXVDIF DIFFERENCE OF TWO VECTORS. */ /* EXTERNAL SUBROUTINES : */ /* SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS */ /* THE VALUE OF THE OBJECTIVE FUNCTION. */ /* SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER */ /* OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) */ /* IS THE GRADIENT OF THE OBJECTIVE FUNCTION. */ /* -- OBJ and DOBJ are replaced by a single function, objgrad, in NLopt */ /* METHOD : */ /* LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG */ /* RECURRENCES. */ static void pnet_(int *nf, int *nb, double *x, int * ix, double *xl, double *xu, double *gf, double *gn, double *s, double *xo, double *go, double *xs, double *gs, double *xm, double *gm, double *u1, double *u2, double *xmax, double *tolx, double *tolf, double *tolb, double *tolg, nlopt_stopping *stop, double *minf_est, double * gmax, double *f, int *mit, int *mfv, int *mfg, int *iest, int *mos1, int *mos2, int *mf, int *iterm, stat_common *stat_1, nlopt_func objgrad, void *objgrad_data) { /* System generated locals */ int i__1; double d__1, d__2; /* Builtin functions */ /* Local variables */ double a = 0.0, b = 0.0; int i__, n; double p, r__; int kd, ld; double fo, fp, po, pp, ro, rp; int mx, kbf; double alf; double par; int mes, kit; double rho, eps; int mmx; double alf1, alf2, eta0, eta9, par1, par2; double rho1, rho2, eps8, eps9; int mred, iold, nred; double maxf, dmax__; int xstop = 0; int inew; double told; int ites; double rmin, rmax, umax, tolp, tols; int isys; int ires1, ires2; int iterd, mtesf, ntesf; double gnorm; int iters, irest, inits, kters, maxst; double snorm; int mtesx, ntesx; ps1l01_state state; (void) tolb; /* INITIATION */ /* Parameter adjustments */ --u2; --u1; --gm; --xm; --gs; --xs; --go; --xo; --s; --gn; --gf; --xu; --xl; --ix; --x; /* Function Body */ kbf = 0; if (*nb > 0) { kbf = 2; } stat_1->nres = 0; stat_1->ndec = 0; stat_1->nin = 0; stat_1->nit = 0; stat_1->nfg = 0; stat_1->nfh = 0; isys = 0; ites = 1; mtesx = 2; mtesf = 2; inits = 2; *iterm = 0; iterd = 0; iters = 2; kters = 3; irest = 0; ires1 = 999; ires2 = 0; mred = 10; mes = 4; eps = .8; eta0 = 1e-15; eta9 = 1e120; eps8 = 1.; eps9 = 1e-8; alf1 = 1e-10; alf2 = 1e10; rmax = eta9; dmax__ = eta9; maxf = 1e20; if (*iest <= 0) { *minf_est = -HUGE_VAL; /* changed from -1e60 by SGJ */ } if (*iest > 0) { *iest = 1; } if (*xmax <= 0.) { *xmax = 1e16; } if (*tolx <= 0.) { *tolx = 1e-16; } if (*tolf <= 0.) { *tolf = 1e-14; } if (*tolg <= 0.) { *tolg = 1e-8; /* SGJ: was 1e-6, but this sometimes stops too soon */ } #if 0 /* removed by SGJ: this check prevented us from using minf_max <= 0, which doesn't make sense. Instead, if you don't want to have a lower limit, you should set minf_max = -HUGE_VAL */ if (*tolb <= 0.) { *tolb = *minf_est + 1e-16; } #endif told = 1e-4; tols = 1e-4; tolp = .9; /* changed by SGJ: default is no limit (INT_MAX) on # iterations/fevals */ if (*mit <= 0) { *mit = INT_MAX; } if (*mfv <= 0) { *mfv = INT_MAX; } if (*mfg <= 0) { *mfg = INT_MAX; } if (*mos1 <= 0) { *mos1 = 1; } if (*mos2 <= 0) { *mos2 = 1; } kd = 1; ld = -1; kit = -(ires1 * *nf + ires2); fo = *minf_est; /* INITIAL OPERATIONS WITH SIMPLE BOUNDS */ if (kbf > 0) { i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { if ((ix[i__] == 3 || ix[i__] == 4) && xu[i__] <= xl[i__]) { xu[i__] = xl[i__]; ix[i__] = 5; } else if (ix[i__] == 5 || ix[i__] == 6) { xl[i__] = x[i__]; xu[i__] = x[i__]; ix[i__] = 5; } /* L2: */ } luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++(*stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11080; } ld = kd; L11020: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); luksan_mxvcop__(nf, &gf[1], &gn[1]); luksan_pyfut1__(nf, f, &fo, &umax, gmax, xstop, stop, tolg, &kd, &stat_1->nit, &kit, mit, &stat_1->nfg, mfg, & ntesx, &mtesx, &ntesf, &mtesf, &ites, &ires1, &ires2, &irest, & iters, iterm); if (*iterm != 0) { goto L11080; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11080; } if (kbf > 0) { luksan_pyrmc0__(nf, &n, &ix[1], &gn[1], &eps8, &umax, gmax, &rmax, & iold, &irest); if (umax > eps8 * *gmax) { irest = MAX2(irest,1); } } luksan_mxvcop__(nf, &x[1], &xo[1]); L11040: /* DIRECTION DETERMINATION */ if (irest != 0) { if (kit < stat_1->nit) { mx = 0; ++stat_1->nres; kit = stat_1->nit; } else { *iterm = -10; if (iters < 0) { *iterm = iters - 5; } goto L11080; } if (*mos1 > 1) { luksan_mxvneg__(nf, &gn[1], &s[1]); gnorm = sqrt(luksan_mxudot__(nf, &gn[1], &gn[1], &ix[1], &kbf)); snorm = gnorm; goto L12560; } } rho1 = luksan_mxudot__(nf, &gn[1], &gn[1], &ix[1], &kbf); gnorm = sqrt(rho1); /* Computing MIN */ d__1 = eps, d__2 = sqrt(gnorm); par = MIN2(d__1,d__2); if (par > .01) { /* Computing MIN */ d__1 = par, d__2 = 1. / (double) stat_1->nit; par = MIN2(d__1,d__2); } par *= par; /* CG INITIATION */ rho = rho1; snorm = 0.; luksan_mxvset__(nf, &c_b7, &s[1]); luksan_mxvneg__(nf, &gn[1], &gs[1]); luksan_mxvcop__(nf, &gs[1], &xs[1]); if (*mos2 > 1) { if (mx == 0) { b = 0.; } else { b = luksan_mxudot__(nf, &xm[1], &gm[1], &ix[1], &kbf); } if (b > 0.) { u1[1] = 1. / b; luksan_mxdrcb__(nf, &mx, &xm[1], &gm[1], &u1[1], &u2[1], &xs[1], & ix[1], &kbf); a = luksan_mxudot__(nf, &gm[1], &gm[1], &ix[1], &kbf); if (a > 0.) { d__1 = b / a; luksan_mxvscl__(nf, &d__1, &xs[1], &xs[1]); } luksan_mxdrcf__(nf, &mx, &xm[1], &gm[1], &u1[1], &u2[1], &xs[1], & ix[1], &kbf); } } rho = luksan_mxudot__(nf, &gs[1], &xs[1], &ix[1], &kbf); /* SIG=RHO */ mmx = *nf + 3; nred = 0; L12520: ++nred; if (nred > mmx) { goto L12550; } fo = *f; pp = sqrt(eta0 / luksan_mxudot__(nf, &xs[1], &xs[1], &ix[1], &kbf)); ld = 0; luksan_mxudir__(nf, &pp, &xs[1], &xo[1], &x[1], &ix[1], &kbf); objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; ld = kd; luksan_mxvdif__(nf, &gf[1], &gn[1], &go[1]); *f = fo; d__1 = 1. / pp; luksan_mxvscl__(nf, &d__1, &go[1], &go[1]); alf = luksan_mxudot__(nf, &xs[1], &go[1], &ix[1], &kbf); if (alf <= 1. / eta9) { /* IF (ALF.LE.1.0D-8*SIG) THEN */ /* CG FAILS (THE MATRIX IS NOT POSITIVE DEFINITE) */ if (nred == 1) { luksan_mxvneg__(nf, &gn[1], &s[1]); snorm = gnorm; } iterd = 0; goto L12560; } else { iterd = 2; } /* CG STEP */ alf = rho / alf; luksan_mxudir__(nf, &alf, &xs[1], &s[1], &s[1], &ix[1], &kbf); d__1 = -alf; luksan_mxudir__(nf, &d__1, &go[1], &gs[1], &gs[1], &ix[1], &kbf); rho2 = luksan_mxudot__(nf, &gs[1], &gs[1], &ix[1], &kbf); snorm = sqrt(luksan_mxudot__(nf, &s[1], &s[1], &ix[1], &kbf)); if (rho2 <= par * rho1) { goto L12560; } if (nred >= mmx) { goto L12550; } if (*mos2 > 1) { if (b > 0.) { luksan_mxvcop__(nf, &gs[1], &go[1]); luksan_mxdrcb__(nf, &mx, &xm[1], &gm[1], &u1[1], &u2[1], &go[1], & ix[1], &kbf); if (a > 0.) { d__1 = b / a; luksan_mxvscl__(nf, &d__1, &go[1], &go[1]); } luksan_mxdrcf__(nf, &mx, &xm[1], &gm[1], &u1[1], &u2[1], &go[1], & ix[1], &kbf); rho2 = luksan_mxudot__(nf, &gs[1], &go[1], &ix[1], &kbf); alf = rho2 / rho; luksan_mxudir__(nf, &alf, &xs[1], &go[1], &xs[1], &ix[1], &kbf); } else { alf = rho2 / rho; luksan_mxudir__(nf, &alf, &xs[1], &gs[1], &xs[1], &ix[1], &kbf); } } else { alf = rho2 / rho; luksan_mxudir__(nf, &alf, &xs[1], &gs[1], &xs[1], &ix[1], &kbf); } rho = rho2; /* SIG=RHO2+ALF*ALF*SIG */ goto L12520; L12550: /* AN INEXACT SOLUTION IS OBTAINED */ L12560: /* ------------------------------ */ /* END OF DIRECTION DETERMINATION */ /* ------------------------------ */ luksan_mxvcop__(nf, &xo[1], &x[1]); luksan_mxvcop__(nf, &gn[1], &gf[1]); if (kd > 0) { p = luksan_mxudot__(nf, &gn[1], &s[1], &ix[1], &kbf); } if (iterd < 0) { *iterm = iterd; } else { /* TEST ON DESCENT DIRECTION */ if (snorm <= 0.) { irest = MAX2(irest,1); } else if (p + told * gnorm * snorm <= 0.) { irest = 0; } else { /* UNIFORM DESCENT CRITERION */ irest = MAX2(irest,1); } if (irest == 0) { /* PREPARATION OF LINE SEARCH */ nred = 0; rmin = alf1 * gnorm / snorm; /* Computing MIN */ d__1 = alf2 * gnorm / snorm, d__2 = *xmax / snorm; rmax = MIN2(d__1,d__2); } } ld = kd; if (*iterm != 0) { goto L11080; } if (nlopt_stop_time(stop)) { *iterm = 100; goto L11080; } if (irest != 0) { goto L11040; } luksan_pytrcs__(nf, &x[1], &ix[1], &xo[1], &xl[1], &xu[1], &gf[1], &go[1], &s[1], &ro, &fp, &fo, f, &po, &p, &rmax, &eta9, &kbf); if (rmax == 0.) { goto L11075; } L11060: luksan_ps1l01__(&r__, &rp, f, &fo, &fp, &p, &po, &pp, minf_est, &maxf, &rmin, &rmax, &tols, &tolp, &par1, &par2, &kd, &ld, &stat_1->nit, &kit, & nred, &mred, &maxst, iest, &inits, &iters, &kters, &mes, &isys, &state); if (isys == 0) { goto L11064; } luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++*(stop->nevals_p); ++stat_1->nfg; ld = kd; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); goto L11060; L11064: if (iters <= 0) { r__ = 0.; *f = fo; p = po; luksan_mxvcop__(nf, &xo[1], &x[1]); luksan_mxvcop__(nf, &go[1], &gf[1]); irest = MAX2(irest,1); ld = kd; goto L11040; } luksan_pytrcd__(nf, &x[1], &ix[1], &xo[1], &gf[1], &go[1], &r__, f, &fo, & p, &po, &dmax__, &kbf, &kd, &ld, &iters); xstop = nlopt_stop_dx(stop, &x[1], &xo[1]); if (*mos2 > 1) { /* Computing MIN */ i__1 = mx + 1; mx = MIN2(i__1,*mf); luksan_mxdrsu__(nf, &mx, &xm[1], &gm[1], &u1[1]); luksan_mxvcop__(nf, &xo[1], &xm[1]); luksan_mxvcop__(nf, &go[1], &gm[1]); } L11075: if (kbf > 0) { luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); if (inew > 0) { irest = MAX2(irest,1); } } goto L11020; L11080: return; } /* pnet_ */ /* NLopt wrapper around pnet_, handling dynamic allocation etc. */ nlopt_result luksan_pnet(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int mf, /* subspace dimension (0 for default) */ int mos1, int mos2) /* 1 or 2 */ { int i, *ix, nb = 1; double *work; double *xl, *xu, *gf, *gn, *s, *xo, *go, *xs, *gs, *xm, *gm, *u1, *u2; double gmax, minf_est; double xmax = 0; /* no maximum */ double tolg = 0; /* default gradient tolerance */ int iest = 0; /* we have no estimate of min function value */ int mit = 0, mfg = 0; /* default no limit on #iterations */ int mfv = stop->maxeval; stat_common stat; int iterm; ix = (int*) malloc(sizeof(int) * n); if (!ix) return NLOPT_OUT_OF_MEMORY; if (mf <= 0) { mf = MAX2(MEMAVAIL/n, 10); if (stop->maxeval && stop->maxeval <= mf) mf = MAX2(stop->maxeval, 1); } retry_alloc: work = (double*) malloc(sizeof(double) * (n * 9 + MAX2(n,n*mf)*2 + MAX2(n,mf)*2)); if (!work) { if (mf > 0) { mf = 0; /* allocate minimal memory */ goto retry_alloc; } free(ix); return NLOPT_OUT_OF_MEMORY; } xl = work; xu = xl + n; gf = xu + n; gn = gf + n; s = gn + n; xo = s + n; go = xo + n; xs = go + n; gs = xs + n; xm = gs + n; gm = xm + MAX2(n*mf,n); u1 = gm + MAX2(n*mf,n); u2 = u1 + MAX2(n,mf); for (i = 0; i < n; ++i) { int lbu = lb[i] <= -0.99 * HUGE_VAL; /* lb unbounded */ int ubu = ub[i] >= 0.99 * HUGE_VAL; /* ub unbounded */ ix[i] = lbu ? (ubu ? 0 : 2) : (ubu ? 1 : (lb[i] == ub[i] ? 5 : 3)); xl[i] = lb[i]; xu[i] = ub[i]; } /* ? xo does not seem to be initialized in the original Fortran code, but it is used upon input to pnet if mf > 0 ... perhaps ALLOCATE initializes arrays to zero by default? */ memset(xo, 0, sizeof(double) * MAX2(n,n*mf)); pnet_(&n, &nb, x, ix, xl, xu, gf, gn, s, xo, go, xs, gs, xm, gm, u1, u2, &xmax, /* fixme: pass tol_rel and tol_abs and use NLopt check */ &stop->xtol_rel, &stop->ftol_rel, &stop->minf_max, &tolg, stop, &minf_est, &gmax, minf, &mit, &mfv, &mfg, &iest, &mos1, &mos2, &mf, &iterm, &stat, f, f_data); free(work); free(ix); switch (iterm) { case 1: return NLOPT_XTOL_REACHED; case 2: return NLOPT_FTOL_REACHED; case 3: return NLOPT_MINF_MAX_REACHED; case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; case 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } } nlopt-2.6.1/src/algs/luksan/pnet.for000066400000000000000000000562101345435414600173610ustar00rootroot00000000000000************************************************************************ * SUBROUTINE PNETU ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE UNCONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) MAXIMUM NUMBER OF GRADIENT EVALUATIONS. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) CHOICE OF DIRECTION VECTORS AFTER RESTARTS. * IPAR(5)=1-THE NEWTON DIRECTIONS ARE USED. IPAR(5)=2-THE * STEEPEST DESCENT DIRECTIONS ARE USED. * IPAR(6) CHOICE OF PRECONDITIONING STRATEGY. * IPAR(6)=1-PRECONDITIONING IS NOT USED. * IPAR(6)=2-PRECONDITIONING BY THE LIMITED MEMORY BFGS METHOD * IS USED. * IPAR(7) THE NUMBER OF LIMITED-MEMORY VARIABLE METRIC UPDATES * IN EACH ITERATION (THEY USE 2*MF STORED VECTORS). * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PNET LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PNETU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LGN,LS,LXO,LGO,LXS,LGS,LXM,LGM,LU1,LU2 INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(8*NF+2*NF*MF+2*MF)) NB=0 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LGN=LGF+NF LS=LGN+NF LXO=LS+NF LGO=LXO+NF LXS=LGO+NF LGS=LXS+NF LXM=LGS+NF LGM=LXM+NF*MF LU1=LGM+NF*MF LU2=LU1+MF CALL PNET(NF,NB,X,IPAR,RA,RA,RA(LGF),RA(LGN),RA(LS),RA(LXO), & RA(LGO),RA(LXS),RA(LGS),RA(LXM),RA(LGM),RA(LU1),RA(LU2),RPAR(1), & RPAR(2),RPAR(3),RPAR(4),RPAR(5),RPAR(6),GMAX,F,IPAR(1),IPAR(2), & IPAR(3),IPAR(4),IPAR(5),IPAR(6),MF,IPRNT,ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PNETS ALL SYSTEMS 97/01/22 * PURPOSE : * EASY TO USE SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * II IPAR(7) INTEGER PAREMETERS: * IPAR(1) MAXIMUM NUMBER OF ITERATIONS. * IPAR(2) MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * IPAR(3) MAXIMUM NUMBER OF GRADIENT EVALUATIONS. * IPAR(4) ESTIMATION INDICATOR. IPAR(4)=0-MINIMUM IS NOT * ESTIMATED. IPAR(4)=1-MINIMUM IS ESTIMATED BY THE VALUE * RPAR(6). * IPAR(5) CHOICE OF DIRECTION VECTORS AFTER RESTARTS. * IPAR(5)=1-THE NEWTON DIRECTIONS ARE USED. IPAR(5)=2-THE * STEEPEST DESCENT DIRECTIONS ARE USED. * IPAR(6) CHOICE OF PRECONDITIONING STRATEGY. * IPAR(6)=1-PRECONDITIONING IS NOT USED. * IPAR(6)=2-PRECONDITIONING BY THE LIMITED MEMORY BFGS METHOD * IS USED. * IPAR(7) THE NUMBER OF LIMITED-MEMORY VARIABLE METRIC UPDATES * IN EACH ITERATION (THEY USE 2*MF STORED VECTORS). * RI RPAR(9) REAL PARAMETERS: * RPAR(1) MAXIMUM STEPSIZE. * RPAR(2) TOLERANCE FOR THE CHANGE OF VARIABLES. * RPAR(3) TOLERANCE FOR THE CHANGE OF FUNCTION VALUES. * RPAR(4) TOLERANCE FOR THE FUNCTION FALUE. * RPAR(5) TOLERANCE FOR THE GRADIENT NORM. * RPAR(6) ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RPAR(7) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RPAR(8) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RPAR(9) THIS PARAMETER IS NOT USED IN THE SUBROUTINE PNET. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PNET LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * SUBROUTINE PNETS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) INTEGER NF,IX(*),IPAR(7),IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),RPAR(9),F,GMAX INTEGER MF,NB,LGF,LGN,LS,LXO,LGO,LXS,LGS,LXM,LGM,LU1,LU2 INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH DOUBLE PRECISION RA(:) ALLOCATABLE RA MF=IPAR(7) IF (MF.LE.0) MF=10 ALLOCATE (RA(8*NF+2*NF*MF+2*MF)) NB=1 * * POINTERS FOR AUXILIARY ARRAYS * LGF=1 LGN=LGF+NF LS=LGN+NF LXO=LS+NF LGO=LXO+NF LXS=LGO+NF LGS=LXS+NF LXM=LGS+NF LGM=LXM+NF*MF LU1=LGM+NF*MF LU2=LU1+MF CALL PNET(NF,NB,X,IX,XL,XU,RA(LGF),RA(LGN),RA(LS),RA(LXO), & RA(LGO),RA(LXS),RA(LGS),RA(LXM),RA(LGM),RA(LU1),RA(LU2),RPAR(1), & RPAR(2),RPAR(3),RPAR(4),RPAR(5),RPAR(6),GMAX,F,IPAR(1),IPAR(2), & IPAR(3),IPAR(4),IPAR(5),IPAR(6),MF,IPRNT,ITERM) DEALLOCATE (RA) RETURN END ************************************************************************ * SUBROUTINE PNET ALL SYSTEMS 01/09/22 * PURPOSE : * GENERAL SUBROUTINE FOR LARGE-SCALE BOX CONSTRAINED MINIMIZATION THAT * USE THE LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II NB CHOICE OF SIMPLE BOUNDS. NB=0-SIMPLE BOUNDS SUPPRESSED. * NB>0-SIMPLE BOUNDS ACCEPTED. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOVER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RO GF(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA GN(NF) OLD GRADIENT OF THE OBJECTIVE FUNCTION. * RO S(NF) DIRECTION VECTOR. * RA XO(NF) ARRAY CONTAINING INCREMENTS OF VARIABLES. * RA GO(NF) ARRAY CONTAINING INCREMENTS OF GRADIENTS. * RA XS(NF) AUXILIARY VECTOR. * RA GS(NF) AUXILIARY VECTOR. * RA XM(NF*MF) ARRAY CONTAINING INCREMENTS OF VARIABLES. * RA GM(NF*MF) ARRAY CONTAINING INCREMENTS OF GRADIENTS. * RA U1(MF) AUXILIARY VECTOR. * RA U2(MF) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RI TOLX TOLERANCE FOR CHANGE OF VARIABLES. * RI TOLF TOLERANCE FOR CHANGE OF FUNCTION VALUES. * RI TOLB TOLERANCE FOR THE FUNCTION VALUE. * RI TOLG TOLERANCE FOR THE GRADIENT NORM. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RO GMAX MAXIMUM PARTIAL DERIVATIVE. * RO F VALUE OF THE OBJECTIVE FUNCTION. * II MIT MAXIMUM NUMBER OF ITERATIONS. * II MFV MAXIMUM NUMBER OF FUNCTION EVALUATIONS. * II MFG MAXIMUM NUMBER OF GRADIENT EVALUATIONS. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * II MOS1 CHOICE OF RESTARTS AFTER A CONSTRAINT CHANGE. * MOS1=1-RESTARTS ARE SUPPRESSED. MOS1=2-RESTARTS WITH * STEEPEST DESCENT DIRECTIONS ARE USED. * II MOS1 CHOICE OF DIRECTION VECTORS AFTER RESTARTS. MOS1=1-THE * NEWTON DIRECTIONS ARE USED. MOS1=2-THE STEEPEST DESCENT * DIRECTIONS ARE USED. * II MOS2 CHOICE OF PRECONDITIONING STRATEGY. MOS2=1-PRECONDITIONING * IS NOT USED. MOS2=2-PRECONDITIONING BY THE LIMITED MEMORY * BFGS METHOD IS USED. * II MF THE NUMBER OF LIMITED-MEMORY VARIABLE METRIC UPDATES * IN EACH ITERATION (THEY USE 2*MF STORED VECTORS). * II IPRNT PRINT SPECIFICATION. IPRNT=0-NO PRINT. * ABS(IPRNT)=1-PRINT OF FINAL RESULTS. * ABS(IPRNT)=2-PRINT OF FINAL RESULTS AND ITERATIONS. * IPRNT>0-BASIC FINAL RESULTS. IPRNT<0-EXTENDED FINAL * RESULTS. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUEBT ITERATIONS. * ITERM=3-IF F IS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX IS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITION. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PCBS04 ELIMINATION OF BOX CONSTRAINT VIOLATIONS. * S PS1L01 STEPSIZE SELECTION USING LINE SEARCH. * S PYADC0 ADDITION OF A BOX CONSTRAINT. * S PYFUT1 TEST ON TERMINATION. * S PYRMC0 DELETION OF A BOX CONSTRAINT. * S PYTRCD COMPUTATION OF PROJECTED DIFFERENCES FOR THE VARIABLE METRIC * UPDATE. * S PYTRCG COMPUTATION OF THE PROJECTED GRADIENT. * S PYTRCS COMPUTATION OF THE PROJECTED DIRECTION VECTOR. * S MXDRCB BACKWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION * OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * S MXDRCF FORWARD PART OF THE STRANG FORMULA FOR PREMULTIPLICATION * OF THE VECTOR X BY AN IMPLICIT BFGS UPDATE. * S MXDRSU SHIFT OF COLUMNS OF THE RECTANGULAR MATRICES A AND B. * SHIFT OF ELEMENTS OF THE VECTOR U. THESE SHIFTS ARE USED IN * THE LIMITED MEMORY BFGS METHOD. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXVNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVCOP COPYING OF A VECTOR. * S MXVSCL SCALING OF A VECTOR. * S MXVSET INITIATINON OF A VECTOR. * S MXVDIF DIFFERENCE OF TWO VECTORS. * * EXTERNAL SUBROUTINES : * SE OBJ COMPUTATION OF THE VALUE OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL OBJ(NF,X,FF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND FF IS * THE VALUE OF THE OBJECTIVE FUNCTION. * SE DOBJ COMPUTATION OF THE GRADIENT OF THE OBJECTIVE FUNCTION. * CALLING SEQUENCE: CALL DOBJ(NF,X,GF) WHERE NF IS THE NUMBER * OF VARIABLES, X(NF) IS THE VECTOR OF VARIABLES AND GF(NF) * IS THE GRADIENT OF THE OBJECTIVE FUNCTION. * * METHOD : * LIMITED MEMORY VARIABLE METRIC METHOD BASED ON THE STRANG * RECURRENCES. * SUBROUTINE PNET(NF,NB,X,IX,XL,XU,GF,GN,S,XO,GO,XS,GS,XM,GM,U1,U2, & XMAX,TOLX,TOLF,TOLB,TOLG,FMIN,GMAX,F,MIT,MFV,MFG,IEST,MOS1,MOS2, & MF,IPRNT,ITERM) INTEGER NF,NB,IX(*),MIT,MFV,MFG,IEST,MOS1,MOS2,MF,IPRNT,ITERM DOUBLE PRECISION X(*),XL(*),XU(*),GF(*),GN(*),S(*),XO(*),GO(*), & XS(*),GS(*),XM(*),GM(*),U1(*),U2(*),XMAX,TOLX,TOLF,TOLG,TOLB, & FMIN,GMAX,F INTEGER ITERD,ITERS,KD,LD,NTESX,NTESF,MTESX,MTESF,MRED,KIT, & IREST,KBF,MES,MES1,MES2,MES3,MAXST,ISYS,ITES,INITS,KTERS, & IRES1,IRES2,INEW,IOLD,I,N,NRED,MX,MMX DOUBLE PRECISION R,RO,RP,FO,FP,P,PO,PP,GNORM,SNORM,RMIN,RMAX, & UMAX,FMAX,DMAX,ETA0,ETA9,EPS8,EPS9,ALF,ALF1,ALF2,RHO,RHO1,RHO2, & PAR,PAR1,PAR2,A,B,TOLD,TOLS,TOLP,EPS DOUBLE PRECISION MXUDOT INTEGER NRES,NDEC,NIN,NIT,NFV,NFG,NFH COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH IF (ABS(IPRNT).GT.1) WRITE(6,'(1X,''ENTRY TO PNET :'')') * * INITIATION * KBF=0 IF (NB.GT.0) KBF=2 NRES=0 NDEC=0 NIN=0 NIT=0 NFV=0 NFG=0 NFH=0 ISYS=0 ITES=1 MTESX=2 MTESF=2 INITS=2 ITERM=0 ITERD=0 ITERS=2 KTERS=3 IREST=0 IRES1=999 IRES2=0 MRED=10 MES=4 MES1=2 MES2=2 MES3=2 EPS=0.80D 0 ETA0=1.0D-15 ETA9=1.0D 120 EPS8=1.0D 0 EPS9=1.0D-8 ALF1=1.0D-10 ALF2=1.0D 10 RMAX=ETA9 DMAX=ETA9 FMAX=1.0D 20 IF (IEST.LE.0) FMIN=-1.0D 60 IF (IEST.GT.0) IEST=1 IF (XMAX.LE.0.0D 0) XMAX=1.0D 16 IF (TOLX.LE.0.0D 0) TOLX=1.0D-16 IF (TOLF.LE.0.0D 0) TOLF=1.0D-14 IF (TOLG.LE.0.0D 0) TOLG=1.0D-6 IF (TOLB.LE.0.0D 0) TOLB=FMIN+1.0D-16 TOLD=1.0D-4 TOLS=1.0D-4 TOLP=0.9D 0 IF (MIT.LE.0) MIT=5000 IF (MFV.LE.0) MFV=5000 IF (MFG.LE.0) MFG=30000 IF (MOS1.LE.0) MOS1=1 IF (MOS2.LE.0) MOS2=1 KD= 1 LD=-1 KIT=-(IRES1*NF+IRES2) FO=FMIN * * INITIAL OPERATIONS WITH SIMPLE BOUNDS * IF (KBF.GT.0) THEN DO 2 I = 1,NF IF ((IX(I).EQ.3.OR.IX(I).EQ.4) .AND. XU(I).LE.XL(I)) THEN XU(I) = XL(I) IX(I) = 5 ELSE IF (IX(I).EQ.5 .OR. IX(I).EQ.6) THEN XL(I) = X(I) XU(I) = X(I) IX(I) = 5 END IF 2 CONTINUE CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL PYADC0(NF,N,X,IX,XL,XU,INEW) END IF CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 LD=KD 11020 CONTINUE CALL PYTRCG(NF,NF,IX,GF,UMAX,GMAX,KBF,IOLD) CALL MXVCOP(NF,GF,GN) IF (ABS(IPRNT).GT.1) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3)') NIT,NFV,NFG,F,GMAX CALL PYFUT1(NF,F,FO,UMAX,GMAX,DMAX,TOLX,TOLF,TOLB,TOLG,KD,NIT,KIT, & MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF,ITES,IRES1,IRES2, & IREST,ITERS,ITERM) IF (ITERM.NE.0) GO TO 11080 IF (KBF.GT.0) THEN CALL PYRMC0(NF,N,IX,GN,EPS8,UMAX,GMAX,RMAX,IOLD,IREST) IF (UMAX.GT.EPS8*GMAX) IREST=MAX(IREST,1) END IF CALL MXVCOP(NF,X,XO) 11040 CONTINUE * * DIRECTION DETERMINATION * IF (IREST.NE.0) THEN IF (KIT.LT.NIT) THEN MX=0 NRES=NRES+1 KIT = NIT ELSE ITERM=-10 IF (ITERS.LT.0) ITERM=ITERS-5 GO TO 11080 END IF IF (MOS1.GT.1) THEN CALL MXVNEG(NF,GN,S) GNORM=SQRT(MXUDOT(NF,GN,GN,IX,KBF)) SNORM=GNORM GO TO 12560 END IF END IF RHO1=MXUDOT(NF,GN,GN,IX,KBF) GNORM=SQRT(RHO1) PAR=MIN(EPS,SQRT(GNORM)) IF (PAR.GT.1.0D 1*1.0D-3) THEN PAR=MIN(PAR,1.0D 0/DBLE(NIT)) END IF PAR=PAR*PAR * * CG INITIATION * RHO=RHO1 SNORM=0.0D 0 CALL MXVSET(NF,0.0D 0,S) CALL MXVNEG(NF,GN,GS) CALL MXVCOP(NF,GS,XS) IF (MOS2.GT.1) THEN IF (MX.EQ.0) THEN B=0.0D 0 ELSE B=MXUDOT(NF,XM,GM,IX,KBF) ENDIF IF (B.GT.0.0D 0) THEN U1(1)=1.0D 0/B CALL MXDRCB(NF,MX,XM,GM,U1,U2,XS,IX,KBF) A=MXUDOT(NF,GM,GM,IX,KBF) IF (A.GT.0.0D 0) CALL MXVSCL(NF,B/A,XS,XS) CALL MXDRCF(NF,MX,XM,GM,U1,U2,XS,IX,KBF) END IF END IF RHO=MXUDOT(NF,GS,XS,IX,KBF) C SIG=RHO MMX=NF+3 NRED=0 12520 CONTINUE NRED=NRED+1 IF (NRED.GT.MMX) GO TO 12550 FO=F PP=SQRT(ETA0/MXUDOT(NF,XS,XS,IX,KBF)) LD=0 CALL MXUDIR(NF,PP,XS,XO,X,IX,KBF) CALL DOBJ(NF,X,GF) NFG=NFG+1 LD=KD CALL MXVDIF(NF,GF,GN,GO) F=FO CALL MXVSCL(NF,1.0D 0/PP,GO,GO) ALF=MXUDOT(NF,XS,GO,IX,KBF) IF (ALF.LE.1.0D 0/ETA9) THEN C IF (ALF.LE.1.0D-8*SIG) THEN * * CG FAILS (THE MATRIX IS NOT POSITIVE DEFINITE) * IF (NRED.EQ.1) THEN CALL MXVNEG(NF,GN,S) SNORM=GNORM END IF ITERD=0 GO TO 12560 ELSE ITERD=2 END IF * * CG STEP * ALF=RHO/ALF CALL MXUDIR(NF, ALF,XS,S,S,IX,KBF) CALL MXUDIR(NF,-ALF,GO,GS,GS,IX,KBF) RHO2=MXUDOT(NF,GS,GS,IX,KBF) SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) IF (RHO2.LE.PAR*RHO1) GO TO 12560 IF (NRED.GE.MMX) GO TO 12550 IF (MOS2.GT.1) THEN IF (B.GT.0.0D 0) THEN CALL MXVCOP(NF,GS,GO) CALL MXDRCB(NF,MX,XM,GM,U1,U2,GO,IX,KBF) IF (A.GT.0.0D 0) CALL MXVSCL(NF,B/A,GO,GO) CALL MXDRCF(NF,MX,XM,GM,U1,U2,GO,IX,KBF) RHO2=MXUDOT(NF,GS,GO,IX,KBF) ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XS,GO,XS,IX,KBF) ELSE ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XS,GS,XS,IX,KBF) END IF ELSE ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XS,GS,XS,IX,KBF) END IF RHO=RHO2 C SIG=RHO2+ALF*ALF*SIG GO TO 12520 12550 CONTINUE * * AN INEXACT SOLUTION IS OBTAINED * 12560 CONTINUE * * ------------------------------ * END OF DIRECTION DETERMINATION * ------------------------------ * CALL MXVCOP(NF,XO,X) CALL MXVCOP(NF,GN,GF) IF (KD.GT.0) P=MXUDOT(NF,GN,S,IX,KBF) IF (ITERD.LT.0) THEN ITERM=ITERD ELSE * * TEST ON DESCENT DIRECTION * IF (SNORM.LE.0.0D 0) THEN IREST=MAX(IREST,1) ELSE IF (P+TOLD*GNORM*SNORM.LE.0.0D 0) THEN IREST=0 ELSE * * UNIFORM DESCENT CRITERION * IREST=MAX(IREST,1) END IF IF (IREST.EQ.0) THEN * * PREPARATION OF LINE SEARCH * NRED = 0 RMIN=ALF1*GNORM/SNORM RMAX=MIN(ALF2*GNORM/SNORM,XMAX/SNORM) END IF END IF LD=KD IF (ITERM.NE.0) GO TO 11080 IF (IREST.NE.0) GO TO 11040 CALL PYTRCS(NF,X,IX,XO,XL,XU,GF,GO,S,RO,FP,FO,F,PO,P,RMAX,ETA9, & KBF) IF (RMAX.EQ.0.0D 0) GO TO 11075 11060 CONTINUE CALL PS1L01(R,RP,F,FO,FP,P,PO,PP,FMIN,FMAX,RMIN,RMAX,TOLS,TOLP, & PAR1,PAR2,KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST,INITS,ITERS,KTERS, & MES,ISYS) IF (ISYS.EQ.0) GO TO 11064 CALL MXUDIR(NF,R,S,XO,X,IX,KBF) CALL PCBS04(NF,X,IX,XL,XU,EPS9,KBF) CALL OBJ(NF,X,F) NFV=NFV+1 CALL DOBJ(NF,X,GF) NFG=NFG+1 LD=KD P=MXUDOT(NF,GF,S,IX,KBF) GO TO 11060 11064 CONTINUE IF (ITERS.LE.0) THEN R=0.0D 0 F=FO P=PO CALL MXVCOP(NF,XO,X) CALL MXVCOP(NF,GO,GF) IREST=MAX(IREST,1) LD=KD GO TO 11040 END IF CALL PYTRCD(NF,X,IX,XO,GF,GO,R,F,FO,P,PO,DMAX,KBF,KD,LD,ITERS) IF (MOS2.GT.1) THEN MX=MIN(MX+1,MF) CALL MXDRSU(NF,MX,XM,GM,U1) CALL MXVCOP(NF,XO,XM) CALL MXVCOP(NF,GO,GM) END IF 11075 CONTINUE IF (KBF.GT.0) THEN CALL PYADC0(NF,N,X,IX,XL,XU,INEW) IF (INEW.GT.0) IREST=MAX(IREST,1) END IF GO TO 11020 11080 CONTINUE IF (IPRNT.GT.1.OR.IPRNT.LT.0) & WRITE(6,'(1X,''EXIT FROM PNET :'')') IF (IPRNT.NE.0) & WRITE (6,'(1X,''NIT='',I5,2X,''NFV='',I5,2X,''NFG='',I5,2X, & ''F='', G16.9,2X,''G='',E10.3,2X,''ITERM='',I3)') NIT,NFV,NFG, & F,GMAX,ITERM IF (IPRNT.LT.0) & WRITE (6,'(1X,''X='',5(G14.7,1X):/(3X,5(G14.7,1X)))') & (X(I),I=1,NF) RETURN END nlopt-2.6.1/src/algs/luksan/pnet.txt000066400000000000000000000420151345435414600174100ustar00rootroot00000000000000*********************************************************************** * * * PNET - A LIMITED MEMORY VARIABLE METRIC ALGORITHM FOR * * LARGE-SCALE OPTIMIZATION. * * * *********************************************************************** 1. Introduction: ---------------- The double-precision FORTRAN 77 basic subroutine PNET is designed to find a close approximation to a local minimum of a nonlinear function F(X) with simple bounds on variables. Here X is a vector of NF variables and F(X) is a smooth function. We suppose that NF is large but the sparsity pattern of the Hessian matrix is not known (or the Hessian matrix is dense). Simple bounds are assumed in the form X(I) unbounded if IX(I) = 0, XL(I) <= X(I) if IX(I) = 1, X(I) <= XU(I) if IX(I) = 2, XL(I) <= X(I) <= XU(I) if IX(I) = 3, XL(I) = X(I) = XU(I) if IX(I) = 5, where 1 <= I <= NF. To simplify user's work, two additional easy to use subroutines are added. They call the basic general subroutine PNET: PNETU - unconstrained large-scale optimization, PNETS - large-scale optimization with simple bounds. All subroutines contain a description of formal parameters and extensive comments. Furthermore, two test programs TNETU and TNETS are included, which contain several test problems (see e.g. [2]). These test programs serve as examples for using the subroutines, verify their correctness and demonstrate their efficiency. In this short guide, we describe all subroutines which can be called from the user's program. A detailed description of the method is given in [1]. In the description of formal parameters, we introduce a type of the argument that specifies whether the argument must have a value defined on entry to the subroutine (I), whether it is a value which will be returned (O), or both (U), or whether it is an auxiliary value (A). Note that the arguments of the type I can be changed on output under some circumstances, especially if improper input values were given. Besides formal parameters, we can use a COMMON /STAT/ block containing statistical information. This block, used in each subroutine has the following form: COMMON /STAT/ NRES,NDEC,NIN,NIT,NFV,NFG,NFH The arguments have the following meaning: Argument Type Significance ---------------------------------------------------------------------- NRES O Positive INTEGER variable that indicates the number of restarts. NDEC O Positive INTEGER variable that indicates the number of matrix decompositions. NIN O Positive INTEGER variable that indicates the number of inner iterations (for solving linear systems). NIT O Positive INTEGER variable that indicates the number of iterations. NFV O Positive INTEGER variable that indicates the number of function evaluations. NFG O Positive INTEGER variable that specifies the number of gradient evaluations. NFH O Positive INTEGER variable that specifies the number of Hessian evaluations. 2. Subroutines PNETU, PNETS: ---------------------------- The calling sequences are CALL PNETU(NF,X,IPAR,RPAR,F,GMAX,IPRNT,ITERM) CALL PNETS(NF,X,IX,XL,XU,IPAR,RPAR,F,GMAX,IPRNT,ITERM) The arguments have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) U On input, DOUBLE PRECISION vector with the initial estimate to the solution. On output, the approximation to the minimum. IX(NF) I On input (significant only if NB>0) INTEGER vector containing the simple bounds types: IX(I)=0 - the variable X(I) is unbounded, IX(I)=1 - the lower bound X(I) >= XL(I), IX(I)=2 - the upper bound X(I) <= XU(I), IX(I)=3 - the two side bound XL(I) <= X(I) <= XU(I), IX(I)=5 - the variable X(I) is fixed (given by its initial estimate). XL(NF) I DOUBLE PRECISION vector with lower bounds for variables (significant only if NB>0). XU(NF) I DOUBLE PRECISION vector with upper bounds for variables (significant only if NB>0). IPAR(7) I INTEGER parameters: IPAR(1)=MIT, IPAR(2)=MFV, IPAR(3)=MFG, IPAR(4)=IEST, IPAR(5)=MOS1, IPAR(6)=MOS2, IPAR(7)=MF. Parameters MIT, MFV, MFG, IEST, MOS1, MOS2, MF are described in Section 3 together with other parameters of the subroutine PNET. RPAR(9) I DOUBLE PRECISION parameters: RPAR(1)=XMAX, RPAR(2)=TOLX, RPAR(3)=TOLF, RPAR(4)=TOLB, RPAR(5)=TOLG, RPAR(6)=FMIN, RPAR(7)-NONE, RPAR(6)-NONE, RPAR(9)-NONE. Parameters XMAX, TOLX, TOLF, TOLB, TOLG, FMIN are described in Section 3 together with other parameters of the subroutine PNET. F O DOUBLE PRECISION value of the objective function at the solution X. GMAX O DOUBLE PRECISION maximum absolute value of a partial derivative of the Lagrangian function. IPRNT I INTEGER variable that specifies PRINT: IPRNT= 0 - print is suppressed, IPRNT= 1 - basic print of final results, IPRNT=-1 - extended print of final results, IPRNT= 2 - basic print of intermediate and final results, IPRNT=-2 - extended print of intermediate and final results. ITERM O INTEGER variable that indicates the cause of termination: ITERM= 1 - if |X - XO| was less than or equal to TOLX in two subsequent iterations, ITERM= 2 - if |F - FO| was less than or equal to TOLF in two subsequent iterations, ITERM= 3 - if F is less than or equal to TOLB, ITERM= 4 - if GMAX is less than or equal to TOLG, ITERM= 6 - if termination criterion was not satisfied, but the solution is probably acceptable, ITERM=11 - if NIT exceeded MIT, ITERM=12 - if NFV exceeded MFV, ITERM=13 - if NFG exceeded MFG, ITERM< 0 - if the method failed. The subroutines PNETU, PNETS require the user supplied subroutines OBJ and DOBJ that define the objective function and its gradient and have the form SUBROUTINE OBJ(NF,X,F) SUBROUTINE DOBJ(NF,X,G) The arguments of the user supplied subroutines have the following meaning. Argument Type Significance ---------------------------------------------------------------------- NF I Positive INTEGER variable that specifies the number of variables of the objective function. X(NF) I DOUBLE PRECISION an estimate to the solution. F O DOUBLE PRECISION value of the objective function at the point X. G(NF) O DOUBLE PRECISION gradient of the objective function at the point X. 3. Subroutine PNET: ------------------- This general subroutine is called from all subroutines described in Section 2. The calling sequence is CALL PNET(NF,NB,X,IX,XL,XU,GF,GN,S,XO,GO,XS,GS,XM,GM,U1,U2,XMAX, & TOLX,TOLF,TOLB,TOLG,FMIN,GMAX,F,MIT,MFV,MFG,IEST,MOS1,MOS2,MF, & IPRNT,ITERM) The arguments NF, NB, X, IX, XL, XU, GMAX, F, IPRNT, ITERM, have the same meaning as in Section 2. Other arguments have the following meaning: Argument Type Significance ----------------------------------------------------------------------- GF(NF) A DOUBLE PRECISION gradient of the objective function. GN(NF) A DOUBLE PRECISION old gradient of the objective function. S(NF) A DOUBLE PRECISION direction vector. XO(NF) A DOUBLE PRECISION array which contains increments of variables. GO(NF) A DOUBLE PRECISION array which contains increments of gradients. XS(NF) A DOUBLE PRECISION auxiliary array. GS(NF) A DOUBLE PRECISION auxiliary array. XM(NF*MF) A DOUBLE PRECISION array which contains increments of variables. GM(NF*MF) A DOUBLE PRECISION array which contains increments of gradients. U1(MF) A DOUBLE PRECISION auxiliary array. U2(MF) A DOUBLE PRECISION auxiliary array. XMAX I DOUBLE PRECISION maximum stepsize; the choice XMAX=0 causes that the default value 1.0D+16 will be taken. TOLX I DOUBLE PRECISION tolerance for the change of the coordinate vector X; the choice TOLX=0 causes that the default value TOLX=1.0D-16 will be taken. TOLF I DOUBLE PRECISION tolerance for the change of function values; the choice TOLF=0 causes that the default value TOLF=1.0D-14 will be taken. TOLB I DOUBLE PRECISION minimum acceptable function value; the choice TOLB=0 causes that the default value TOLB=FMIN+1.0D-16 will be taken. TOLG I DOUBLE PRECISION tolerance for the Lagrangian function gradient; the choice TOLG=0 causes that the default value TOLG=1.0D-6 will be taken. FMIN I DOUBLE PRECISION lower bound for the minimum function value. MIT I INTEGER variable that specifies the maximum number of iterations; the choice MIT=0 causes that the default value 5000 will be taken. MFV I INTEGER variable that specifies the maximum number of function evaluations; the choice MFV=0 causes that the default value 5000 will be taken. MFG I INTEGER variable that specifies the maximum number of gradient evaluations; the choice MFG=0 causes that the default value 30000 will be taken. IEST I INTEGER estimation of the minimum functiom value for the line search: IEST=0 - estimation is not used, IEST=1 - lower bound FMIN is used as an estimation for the minimum function value. MOS1 I INTEGER choice of restarts after constraint change: MOS1=1 - restarts are suppressed, MOS1=2 - restarts with steepest descent directions are used. MOS2 I INTEGER choice of preconditioning strategy: MOS2=1 - preconditioning is not used, MOS2=2 - preconditioning by the incomplete Gill-Murray decomposition, MOS2=3 - preconditioning by the incomplete Gill-Murray decomposition combined with preliminary solution of the preconditioned system. MF I The number of limited-memory variable metric updates in each iteration (they use 2*MF stored vectors). The choice of parameter XMAX can be sensitive in many cases. First, the objective function can be evaluated only in a relatively small region (if it contains exponentials) so that the maximum stepsize is necessary. Secondly, the problem can be very ill-conditioned far from the solution point so that large steps can be unsuitable. Finally, if the problem has more local solutions, a suitably chosen maximum stepsize can lead to obtaining a better local solution. The subroutine PNET requires the user supplied subroutines OBJ and DOBJ which are described in Section 2. 4. Verification of the subroutines: ----------------------------------- Subroutine PNETU can be verified and tested using the program TNETU. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation) and TFGU14 (gradient evaluation) containing 22 unconstrained test problems with at most 1000 variables [2]. The results obtained by the program TNETU on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 1481 NFV= 1656 NFG=26037 F= 0.117631766E-15 G= 0.354E-06 ITERM= 4 NIT= 132 NFV= 387 NFG= 7945 F= 0.153382199E-15 G= 0.988E-08 ITERM= 4 NIT= 19 NFV= 20 NFG= 110 F= 0.421204156E-09 G= 0.353E-06 ITERM= 4 NIT= 19 NFV= 20 NFG= 230 F= 269.499543 G= 0.779E-07 ITERM= 4 NIT= 12 NFV= 13 NFG= 49 F= 0.465606821E-11 G= 0.364E-06 ITERM= 4 NIT= 13 NFV= 14 NFG= 76 F= 0.366783327E-11 G= 0.404E-06 ITERM= 4 NIT= 9 NFV= 10 NFG= 37 F= 336.937181 G= 0.248E-06 ITERM= 4 NIT= 11 NFV= 12 NFG= 58 F= 761774.954 G= 0.155E-07 ITERM= 4 NIT= 7 NFV= 11 NFG= 28 F= 316.436141 G= 0.158E-07 ITERM= 4 NIT= 75 NFV= 153 NFG= 3213 F= -133.610000 G= 0.777E-08 ITERM= 4 NIT= 33 NFV= 45 NFG= 181 F= 10.7765879 G= 0.414E-07 ITERM= 4 NIT= 23 NFV= 30 NFG= 457 F= 982.273617 G= 0.591E-08 ITERM= 4 NIT= 7 NFV= 8 NFG= 16 F= 0.533593908E-15 G= 0.327E-07 ITERM= 4 NIT= 1 NFV= 2 NFG= 1005 F= 0.120245125E-08 G= 0.879E-07 ITERM= 4 NIT= 14 NFV= 15 NFG= 4033 F= 1.92401599 G= 0.468E-07 ITERM= 4 NIT= 13 NFV= 17 NFG= 295 F= -427.404476 G= 0.800E-08 ITERM= 4 NIT= 4 NFV= 5 NFG= 810 F=-0.379921091E-01 G= 0.537E-06 ITERM= 4 NIT= 4 NFV= 5 NFG= 1146 F=-0.245741193E-01 G= 0.425E-06 ITERM= 4 NIT= 10 NFV= 11 NFG= 1986 F= 59.5986241 G= 0.423E-06 ITERM= 4 NIT= 18 NFV= 39 NFG= 3051 F= -1.00013520 G= 0.712E-07 ITERM= 4 NIT= 7 NFV= 8 NFG= 4901 F= 2.13866377 G= 0.120E-08 ITERM= 4 NIT= 55 NFV= 145 NFG= 4760 F= 1.00000000 G= 0.206E-08 ITERM= 4 NITER = 1967 NFVAL = 2626 NSUCC = 22 TIME= 0:00:06.95 The rows corresponding to individual test problems contain the number of iterations NIT, the number of function evaluations NFV, the number of gradient evaluations NFG, the final value of the objective function F, the norm of gradient G and the cause of termination ITERM. Subroutine PNETS can be verified and tested using the program TNETS. This program calls the subroutines TIUD14 (initiation), TFFU14 (function evaluation), TFGU14 (gradient evaluation) containing 22 box constrained test problems with at most 1000 variables [2]. The results obtained by the program TNETS on a PC computer with Microsoft Power Station Fortran compiler have the following form. NIT= 1611 NFV= 1793 NFG=28524 F= 0.00000000 G= 0.000E+00 ITERM= 3 NIT= 259 NFV= 259 NFG= 4418 F= 3930.43956 G= 0.230E-07 ITERM= 4 NIT= 17 NFV= 18 NFG= 98 F= 0.158634811E-08 G= 0.954E-06 ITERM= 4 NIT= 12 NFV= 13 NFG= 105 F= 269.522686 G= 0.103E-07 ITERM= 4 NIT= 12 NFV= 13 NFG= 49 F= 0.465606821E-11 G= 0.364E-06 ITERM= 4 NIT= 13 NFV= 14 NFG= 76 F= 0.366783327E-11 G= 0.404E-06 ITERM= 4 NIT= 9 NFV= 10 NFG= 37 F= 336.937181 G= 0.248E-06 ITERM= 4 NIT= 40 NFV= 41 NFG= 248 F= 761925.725 G= 0.281E-06 ITERM= 4 NIT= 553 NFV= 555 NFG= 2056 F= 428.056916 G= 0.850E-07 ITERM= 4 NIT= 112 NFV= 137 NFG= 2109 F= -84.1426617 G= 0.732E-06 ITERM= 4 NIT= 7 NFV= 8 NFG= 17 F= 96517.2947 G= 0.112E-11 ITERM= 4 NIT= 133 NFV= 136 NFG= 2689 F= 4994.21410 G= 0.180E-06 ITERM= 4 NIT= 7 NFV= 8 NFG= 16 F= 0.533593908E-15 G= 0.327E-07 ITERM= 4 NIT= 1 NFV= 2 NFG= 1005 F= 0.120245125E-08 G= 0.879E-07 ITERM= 4 NIT= 14 NFV= 15 NFG= 4033 F= 1.92401599 G= 0.468E-07 ITERM= 4 NIT= 12 NFV= 13 NFG= 294 F= -427.391653 G= 0.594E-06 ITERM= 4 NIT= 4 NFV= 5 NFG= 810 F=-0.379921091E-01 G= 0.537E-06 ITERM= 4 NIT= 4 NFV= 5 NFG= 1146 F=-0.245741193E-01 G= 0.425E-06 ITERM= 4 NIT= 8 NFV= 9 NFG= 1902 F= 1654.94525 G= 0.690E-07 ITERM= 4 NIT= 16 NFV= 25 NFG= 3254 F= -1.00013520 G= 0.836E-08 ITERM= 4 NIT= 4 NFV= 5 NFG= 1211 F= 2.41354873 G= 0.135E-06 ITERM= 4 NIT= 52 NFV= 137 NFG= 4843 F= 1.00000000 G= 0.657E-06 ITERM= 4 NITER = 2900 NFVAL = 3221 NSUCC = 22 TIME= 0:00:08.56 References: ----------- [1] Luksan L., Matonoha C., Vlcek J.: LSA: Algorithms for large-scale unconstrained and box constrained optimization Technical Report V-896. Prague, ICS AS CR, 2004. [2] Luksan L., Vlcek J.: Sparse and partially separable test problems for unconstrained and equality constrained optimization. Research Report V-767, Institute of Computer Science, Academy of Sciences of the Czech Republic, Prague, Czech Republic, 1998. nlopt-2.6.1/src/algs/luksan/pssubs.c000066400000000000000000001047561345435414600173770ustar00rootroot00000000000000#include #include "luksan.h" #include "nlopt-util.h" #define FALSE_ 0 #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define MIN2(a,b) ((a) < (b) ? (a) : (b)) #define iabs(a) ((a) < 0 ? -(a) : (a)) /* subroutines extracted from pssubs.for */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PCBS04 ALL SYSTEMS 98/12/01 * PURPOSE : * INITIATION OF THE VECTOR CONTAINING TYPES OF CONSTRAINTS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RI EPS9 TOLERANCE FOR ACTIVE CONSTRAINTS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. */ void luksan_pcbs04__(int *nf, double *x, int *ix, double *xl, double *xu, double *eps9, int *kbf) { /* System generated locals */ int i__1, i__2; double d__1, d__2; /* Local variables */ int i__, ixi; double temp; /* Parameter adjustments */ --xu; --xl; --ix; --x; /* Function Body */ if (*kbf > 0) { i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { temp = 1.; ixi = (i__2 = ix[i__], iabs(i__2)); /* Computing MAX */ d__2 = (d__1 = xl[i__], fabs(d__1)); if ((ixi == 1 || ixi == 3 || ixi == 4) && x[i__] <= xl[i__] + * eps9 * MAX2(d__2,temp)) { x[i__] = xl[i__]; } /* Computing MAX */ d__2 = (d__1 = xu[i__], fabs(d__1)); if ((ixi == 2 || ixi == 3 || ixi == 4) && x[i__] >= xu[i__] - * eps9 * MAX2(d__2,temp)) { x[i__] = xu[i__]; } /* L1: */ } } return; } /* luksan_pcbs04__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PNINT1 ALL SYSTEMS 91/12/01 */ /* PURPOSE : */ /* EXTRAPOLATION OR INTERPOLATION FOR LINE SEARCH WITH DIRECTIONAL */ /* DERIVATIVES. */ /* PARAMETERS : */ /* RI RL LOWER VALUE OF THE STEPSIZE PARAMETER. */ /* RI RU UPPER VALUE OF THE STEPSIZE PARAMETER. */ /* RI FL VALUE OF THE OBJECTIVE FUNCTION FOR R=RL. */ /* RI FU VALUE OF THE OBJECTIVE FUNCTION FOR R=RU. */ /* RI PL DIRECTIONAL DERIVATIVE FOR R=RL. */ /* RI PU DIRECTIONAL DERIVATIVE FOR R=RU. */ /* RO R VALUE OF THE STEPSIZE PARAMETER OBTAINED. */ /* II MODE MODE OF LINE SEARCH. */ /* II MTYP METHOD SELECTION. MTYP=1-BISECTION. MTYP=2-QUADRATIC */ /* INTERPOLATION (WITH ONE DIRECTIONAL DERIVATIVE). */ /* MTYP=3-QUADRATIC INTERPOLATION (WITH TWO DIRECTIONAL */ /* DERIVATIVES). MTYP=4-CUBIC INTERPOLATION. MTYP=5-CONIC */ /* INTERPOLATION. */ /* IO MERR ERROR INDICATOR. MERR=0 FOR NORMAL RETURN. */ /* METHOD : */ /* EXTRAPOLATION OR INTERPOLATION WITH STANDARD MODEL FUNCTIONS. */ void luksan_pnint1__(double *rl, double *ru, double *fl, double *fu, double *pl, double *pu, double *r__, int *mode, int *mtyp, int *merr) { /* System generated locals */ double d__1, d__2; /* Local variables */ double a = 0.0, b = 0.0, c__, d__, den = 0.0, dis; int ntyp; *merr = 0; if (*mode <= 0) { return; } if (*pl >= 0.) { *merr = 2; return; } else if (*ru <= *rl) { *merr = 3; return; } for (ntyp = *mtyp; ntyp >= 1; --ntyp) { if (ntyp == 1) { /* BISECTION */ if (*mode == 1) { *r__ = *ru * 4.; return; } else { *r__ = (*rl + *ru) * .5; return; } } else if (ntyp == *mtyp) { a = (*fu - *fl) / (*pl * (*ru - *rl)); b = *pu / *pl; } if (ntyp == 2) { /* QUADRATIC EXTRAPOLATION OR INTERPOLATION WITH ONE DIRECTIONAL */ /* DERIVATIVE */ den = (1. - a) * 2.; } else if (ntyp == 3) { /* QUADRATIC EXTRAPOLATION OR INTERPOLATION WITH TWO DIRECTIONAL */ /* DERIVATIVES */ den = 1. - b; } else if (ntyp == 4) { /* CUBIC EXTRAPOLATION OR INTERPOLATION */ c__ = b - a * 2. + 1.; d__ = b - a * 3. + 2.; dis = d__ * d__ - c__ * 3.; if (dis < 0.) { goto L1; } den = d__ + sqrt(dis); } else if (ntyp == 5) { /* CONIC EXTRAPOLATION OR INTERPOLATION */ dis = a * a - b; if (dis < 0.) { goto L1; } den = a + sqrt(dis); if (den <= 0.) { goto L1; } /* Computing 3rd power */ d__1 = 1. / den; den = 1. - b * (d__1 * (d__1 * d__1)); } if (*mode == 1 && den > 0. && den < 1.) { /* EXTRAPOLATION ACCEPTED */ *r__ = *rl + (*ru - *rl) / den; /* Computing MAX */ d__1 = *r__, d__2 = *ru * 1.1; *r__ = MAX2(d__1,d__2); /* Computing MIN */ d__1 = *r__, d__2 = *ru * 1e3; *r__ = MIN2(d__1,d__2); return; } else if (*mode == 2 && den > 1.) { /* INTERPOLATION ACCEPTED */ *r__ = *rl + (*ru - *rl) / den; if (*rl == 0.) { /* Computing MAX */ d__1 = *r__, d__2 = *rl + (*ru - *rl) * .01; *r__ = MAX2(d__1,d__2); } else { /* Computing MAX */ d__1 = *r__, d__2 = *rl + (*ru - *rl) * .1; *r__ = MAX2(d__1,d__2); } /* Computing MIN */ d__1 = *r__, d__2 = *rl + (*ru - *rl) * .9; *r__ = MIN2(d__1,d__2); return; } L1: ; } return; } /* luksan_pnint1__ */ /* save and restore state, replacing old non-reeentrant implementation that used static local variables */ #define SS(var) state->var = var #define SAVE_STATE SS(fl); SS(fu); SS(pl); SS(rl); SS(pu); SS(ru); \ SS(mes1); SS(mes2); SS(mes3); SS(mode); SS(mtyp) #define RS(var) var = state->var #define RESTORE_STATE RS(fl); RS(fu); RS(pl); RS(rl); RS(pu); RS(ru); \ RS(mes1); RS(mes2); RS(mes3); RS(mode); RS(mtyp) /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PS1L01 ALL SYSTEMS 97/12/01 * PURPOSE : * STANDARD LINE SEARCH WITH DIRECTIONAL DERIVATIVES. * * PARAMETERS : * RO R VALUE OF THE STEPSIZE PARAMETER. * RO RP PREVIOUS VALUE OF THE STEPSIZE PARAMETER. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI FO INITIAL VALUE OF THE OBJECTIVE FUNCTION. * RO FP PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RO P VALUE OF THE DIRECTIONAL DERIVATIVE. * RI PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP PREVIOUS VALUE OF THE DIRECTIONAL DERIVATIVE. * RI FMIN LOWER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI MAXF UPPER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI RMIN MINIMUM VALUE OF THE STEPSIZE PARAMETER * RI RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER * RI TOLS TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE FUNCTION VALUE). * RI TOLP TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE DIRECTIONAL DERIVATIVE). * RO PAR1 PARAMETER FOR CONTROLLED SCALING OF VARIABLE METRIC * UPDATES. * RO PAR2 PARAMETER FOR CONTROLLED SCALING OF VARIABLE METRIC * UPDATES. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES OF OBJECTIVE * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO NRED ACTUAL NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * II MRED MAXIMUM NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * IO MAXST MAXIMUM STEPSIZE INDICATOR. MAXST=0 OR MAXST=1 IF MAXIMUM * STEPSIZE WAS NOT OR WAS REACHED. * II IEST LOWER BOUND SPECIFICATION. IEST=0 OR IEST=1 IF LOWER BOUND * IS NOT OR IS GIVEN. * II INITS CHOICE OF THE INITIAL STEPSIZE. INITS=0-INITIAL STEPSIZE * IS SPECIFIED IN THE CALLING PROGRAM. INITS=1-UNIT INITIAL * STEPSIZE. INITS=2-COMBINED UNIT AND QUADRATICALLY ESTIMATED * INITIAL STEPSIZE. INITS=3-QUADRATICALLY ESTIMATED INITIAL * STEPSIZE. * IO ITERS TERMINATION INDICATOR. ITERS=0-ZERO STEP. ITERS=1-PERFECT * LINE SEARCH. ITERS=2 GOLDSTEIN STEPSIZE. ITERS=3-CURRY * STEPSIZE. ITERS=4-EXTENDED CURRY STEPSIZE. * ITERS=5-ARMIJO STEPSIZE. ITERS=6-FIRST STEPSIZE. * ITERS=7-MAXIMUM STEPSIZE. ITERS=8-UNBOUNDED FUNCTION. * ITERS=-1-MRED REACHED. ITERS=-2-POSITIVE DIRECTIONAL * DERIVATIVE. ITERS=-3-ERROR IN INTERPOLATION. * II KTERS TERMINATION SELECTION. KTERS=1-PERFECT LINE SEARCH. * KTERS=2-GOLDSTEIN STEPSIZE. KTERS=3-CURRY STEPSIZE. * KTERS=4-EXTENDED CURRY STEPSIZE. KTERS=5-ARMIJO STEPSIZE. * KTERS=6-FIRST STEPSIZE. * II MES METHOD SELECTION. MES=1-BISECTION. MES=2-QUADRATIC * INTERPOLATION (WITH ONE DIRECTIONAL DERIVATIVE). * MES=3-QUADRATIC INTERPOLATION (WITH TWO DIRECTIONAL * DERIVATIVES). MES=4-CUBIC INTERPOLATION. MES=5-CONIC * INTERPOLATION. * IU ISYS CONTROL PARAMETER. * * SUBPROGRAM USED : * S PNINT1 EXTRAPOLATION OR INTERPOLATION WITH DIRECTIONAL * DERIVATIVES. * * METHOD : * SAFEGUARDED EXTRAPOLATION AND INTERPOLATION WITH STANDARD TERMINATION * CRITERIA. */ void luksan_ps1l01__(double *r__, double *rp, double *f, double *fo, double *fp, double *p, double *po, double *pp, double *minf, double *maxf, double *rmin, double *rmax, double *tols, double * tolp, double *par1, double *par2, int *kd, int *ld, int *nit, int *kit, int *nred, int *mred, int * maxst, int *iest, int *inits, int *iters, int *kters, int *mes, int *isys, ps1l01_state *state) { /* System generated locals */ double d__1, d__2; /* Local variables */ unsigned l1, l2, l3, m1, l5, m2, l7, m3; double fl, fu, pl, rl, pu, ru; int mes1, mes2, mes3, mode; int merr; int mtyp; int init1; double rtemp; RESTORE_STATE; if (*isys == 1) { goto L3; } mes1 = 2; mes2 = 2; mes3 = 2; *iters = 0; if (*po >= 0.) { *r__ = 0.; *iters = -2; goto L4; } if (*rmax <= 0.) { *iters = 0; goto L4; } /* INITIAL STEPSIZE SELECTION */ if (*inits > 0) { rtemp = *minf - *f; } else if (*iest == 0) { rtemp = *f - *fp; } else { /* Computing MAX */ d__1 = *f - *fp, d__2 = *minf - *f; rtemp = MAX2(d__1,d__2); } init1 = iabs(*inits); *rp = 0.; *fp = *fo; *pp = *po; if (init1 == 0) { } else if (init1 == 1 || (*inits >= 1 && *iest == 0)) { *r__ = 1.; } else if (init1 == 2) { /* Computing MIN */ d__1 = 1., d__2 = rtemp * 4. / *po; *r__ = MIN2(d__1,d__2); } else if (init1 == 3) { /* Computing MIN */ d__1 = 1., d__2 = rtemp * 2. / *po; *r__ = MIN2(d__1,d__2); } else if (init1 == 4) { *r__ = rtemp * 2. / *po; } *r__ = MAX2(*r__,*rmin); *r__ = MIN2(*r__,*rmax); mode = 0; ru = 0.; fu = *fo; pu = *po; /* NEW STEPSIZE SELECTION (EXTRAPOLATION OR INTERPOLATION) */ L2: luksan_pnint1__(&rl, &ru, &fl, &fu, &pl, &pu, r__, &mode, &mtyp, &merr); if (merr > 0) { *iters = -merr; goto L4; } else if (mode == 1) { --(*nred); *r__ = MIN2(*r__,*rmax); } else if (mode == 2) { ++(*nred); } /* COMPUTATION OF THE NEW FUNCTION VALUE AND THE NEW DIRECTIONAL */ /* DERIVATIVE */ *kd = 1; *ld = -1; *isys = 1; SAVE_STATE; return; L3: if (mode == 0) { *par1 = *p / *po; *par2 = *f - *fo; } if (*iters != 0) { goto L4; } if (*f <= *minf) { *iters = 7; goto L4; } else { l1 = *r__ <= *rmin && *nit != *kit; l2 = *r__ >= *rmax; l3 = *f - *fo <= *tols * *r__ * *po; l5 = *p >= *tolp * *po || (mes2 == 2 && mode == 2); l7 = mes2 <= 2 || mode != 0; m1 = FALSE_; m2 = FALSE_; m3 = l3; if (mes3 >= 1) { m1 = fabs(*p) <= fabs(*po) * .01 && *fo - *f >= fabs(*fo) * 9.9999999999999994e-12; l3 = l3 || m1; } if (mes3 >= 2) { m2 = fabs(*p) <= fabs(*po) * .5 && (d__1 = *fo - *f, fabs(d__1)) <= fabs(*fo) * 2.0000000000000001e-13; l3 = l3 || m2; } *maxst = 0; if (l2) { *maxst = 1; } } /* TEST ON TERMINATION */ if (l1 && ! l3) { *iters = 0; goto L4; } else if (l2 && l3 && ! l5) { *iters = 7; goto L4; } else if (m3 && mes1 == 3) { *iters = 5; goto L4; } else if (l3 && l5 && l7) { *iters = 4; goto L4; } else if (*kters < 0 || (*kters == 6 && l7)) { *iters = 6; goto L4; } else if (iabs(*nred) >= *mred) { *iters = -1; goto L4; } else { *rp = *r__; *fp = *f; *pp = *p; mode = MAX2(mode,1); mtyp = iabs(*mes); if (*f >= *maxf) { mtyp = 1; } } if (mode == 1) { /* INTERVAL CHANGE AFTER EXTRAPOLATION */ rl = ru; fl = fu; pl = pu; ru = *r__; fu = *f; pu = *p; if (! l3) { *nred = 0; mode = 2; } else if (mes1 == 1) { mtyp = 1; } } else { /* INTERVAL CHANGE AFTER INTERPOLATION */ if (! l3) { ru = *r__; fu = *f; pu = *p; } else { rl = *r__; fl = *f; pl = *p; } } goto L2; L4: *isys = 0; SAVE_STATE; return; } /* luksan_ps1l01__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PULSP3 ALL SYSTEMS 02/12/01 * PURPOSE : * LIMITED STORAGE VARIABLE METRIC UPDATE. * * PARAMETERS : * II N NUMBER OF VARIABLES (NUMBER OF ROWS OF XM). * II M NUMBER OF COLUMNS OF XM. * II MF MAXIMUM NUMBER OF COLUMNS OF XM. * RI XM(N*M) RECTANGULAR MATRIX IN THE PRODUCT FORM SHIFTED BROYDEN * METHOD (STORED COLUMNWISE): H-SIGMA*I=XM*TRANS(XM) * RO GR(M) MATRIX TRANS(XM)*GO. * RU XO(N) VECTORS OF VARIABLES DIFFERENCE XO AND VECTOR XO-TILDE. * RU GO(N) GRADIENT DIFFERENCE GO AND VECTOR XM*TRANS(XM)*GO. * RI R STEPSIZE PARAMETER. * RI PO OLD DIRECTIONAL DERIVATIVE (MULTIPLIED BY R) * RU SIG SCALING PARAMETER (ZETA AND SIGMA). * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET3 CHOICE OF SIGMA (1-CONSTANT, 2-QUADRATIC EQUATION). * * SUBPROGRAMS USED : * S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR * MATRIX BY A VECTOR. * S MXDCMU UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. * S MXVDIR VECTOR AUGMENTED BY A SCALED VECTOR. * RF MXVDOT DOT PRODUCT OF VECTORS. * S MXVSCL SCALING OF A VECTOR. * * METHOD : * SHIFTED BFGS METHOD IN THE PRODUCT FORM. */ void luksan_pulsp3__(int *n, int *m, int *mf, double *xm, double *gr, double *xo, double *go, double *r__, double *po, double *sig, int *iterh, int *met3) { /* System generated locals */ double d__1, d__2, d__3, d__4; /* Builtin functions */ /* Local variables */ double a, b, aa, bb, ah, den, par, pom; (void) r__; (void) po; /* Parameter adjustments */ --go; --xo; --gr; --xm; /* Function Body */ if (*m >= *mf) { return; } b = luksan_mxvdot__(n, &xo[1], &go[1]); if (b <= 0.) { *iterh = 2; goto L22; } luksan_mxdrmm__(n, m, &xm[1], &go[1], &gr[1]); ah = luksan_mxvdot__(n, &go[1], &go[1]); aa = luksan_mxvdot__(m, &gr[1], &gr[1]); a = aa + ah * *sig; /* DETERMINATION OF THE PARAMETER SIG (SHIFT) */ par = 1.; pom = b / ah; if (a > 0.) { den = luksan_mxvdot__(n, &xo[1], &xo[1]); if (*met3 <= 4) { /* Computing MAX */ d__1 = 0., d__2 = 1. - aa / a; /* Computing MAX */ d__3 = 0., d__4 = 1. - b * b / (den * ah); *sig = sqrt((MAX2(d__1,d__2))) / (sqrt((MAX2(d__3,d__4))) + 1.) * pom; } else { /* Computing MAX */ d__1 = 0., d__2 = *sig * ah / a; /* Computing MAX */ d__3 = 0., d__4 = 1. - b * b / (den * ah); *sig = sqrt((MAX2(d__1,d__2))) / (sqrt((MAX2(d__3,d__4))) + 1.) * pom; } /* Computing MAX */ d__1 = *sig, d__2 = pom * .2; *sig = MAX2(d__1,d__2); /* Computing MIN */ d__1 = *sig, d__2 = pom * .8; *sig = MIN2(d__1,d__2); } else { *sig = pom * .25; } /* COMPUTATION OF SHIFTED XO AND SHIFTED B */ bb = b - ah * *sig; d__1 = -(*sig); luksan_mxvdir__(n, &d__1, &go[1], &xo[1], &xo[1]); /* BFGS-BASED SHIFTED BFGS UPDATE */ pom = 1.; d__1 = -1. / bb; luksan_mxdcmu__(n, m, &xm[1], &d__1, &xo[1], &gr[1]); d__1 = sqrt(par / bb); luksan_mxvscl__(n, &d__1, &xo[1], &xm[*n * *m + 1]); ++(*m); L22: *iterh = 0; return; } /* luksan_pulsp3__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PULVP3 ALL SYSTEMS 03/12/01 * PURPOSE : * RANK-TWO LIMITED-STORAGE VARIABLE-METRIC METHODS IN THE PRODUCT FORM. * * PARAMETERS : * II N NUMBER OF VARIABLES (NUMBER OF ROWS OF XM). * II M NUMBER OF COLUMNS OF XM. * RI XM(N*M) RECTANGULAR MATRIX IN THE PRODUCT FORM SHIFTED BROYDEN * METHOD (STORED COLUMNWISE): H-SIGMA*I=XM*TRANS(XM) * RO XR(M) VECTOR TRANS(XM)*H**(-1)*XO. * RO GR(M) MATRIX TRANS(XM)*GO. * RA S(N) AUXILIARY VECTORS (H**(-1)*XO AND U). * RA SO(N) AUXILIARY VECTORS ((H-SIGMA*I)*H**(-1)*XO AND V). * RU XO(N) VECTORS OF VARIABLES DIFFERENCE XO AND VECTOR XO-TILDE. * RU GO(N) GRADIENT DIFFERENCE GO AND VECTOR XM*TRANS(XM)*GO. * RI R STEPSIZE PARAMETER. * RI PO OLD DIRECTIONAL DERIVATIVE (MULTIPLIED BY R) * RU SIG SCALING PARAMETER (ZETA AND SIGMA). * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET2 CHOICE OF THE CORRECTION PARAMETER (1-THE UNIT VALUE, * 2-THE BALANCING VALUE, 3-THE SQUARE ROOT, 4-THE GEOMETRIC * MEAN). * II MET3 CHOICE OF THE SHIFT PARAMETER (4-THE FIRST FORMULA, * 5-THE SECOND FORMULA). * II MET5 CHOICE OF THE METHOD (1-RANK-ONE METHOD, 2-RANK-TWO * METHOD). * * SUBPROGRAMS USED : * S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR * MATRIX BY A VECTOR. * S MXDCMU UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. RANK-ONE FORMULA. * S MXDCMV UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. RANK-TWO FORMULA. * S MXVDIR VECTOR AUGMENTED BY A SCALED VECTOR. * RF MXVDOT DOT PRODUCT OF VECTORS. * S MXVLIN LINEAR COMBINATION OF TWO VECTORS. * S MXVSCL SCALING OF A VECTOR. * * METHOD : * RANK-ONE LIMITED-STORAGE VARIABLE-METRIC METHOD IN THE PRODUCT FORM. */ void luksan_pulvp3__(int *n, int *m, double *xm, double *xr, double *gr, double *s, double *so, double *xo, double *go, double *r__, double *po, double *sig, int *iterh, int *met2, int *met3, int *met5) { /* System generated locals */ double d__1, d__2, d__3, d__4; /* Builtin functions */ /* Local variables */ double a, b, aa, bb, cc, ah, den, par, pom, zet; (void) po; /* Parameter adjustments */ --go; --xo; --so; --s; --gr; --xr; --xm; /* Function Body */ zet = *sig; /* COMPUTATION OF B */ b = luksan_mxvdot__(n, &xo[1], &go[1]); if (b <= 0.) { *iterh = 2; goto L22; } /* COMPUTATION OF GR=TRANS(XM)*GO, XR=TRANS(XM)*H**(-1)*XO */ /* AND S=H**(-1)*XO, SO=(H-SIGMA*I)*H**(-1)*XO. COMPUTATION */ /* OF AA=GR*GR, BB=GR*XR, CC=XR*XR. COMPUTATION OF A AND C. */ luksan_mxdrmm__(n, m, &xm[1], &go[1], &gr[1]); luksan_mxvscl__(n, r__, &s[1], &s[1]); luksan_mxdrmm__(n, m, &xm[1], &s[1], &xr[1]); d__1 = -(*sig); luksan_mxvdir__(n, &d__1, &s[1], &xo[1], &so[1]); ah = luksan_mxvdot__(n, &go[1], &go[1]); aa = luksan_mxvdot__(m, &gr[1], &gr[1]); bb = luksan_mxvdot__(m, &gr[1], &xr[1]); cc = luksan_mxvdot__(m, &xr[1], &xr[1]); a = aa + ah * *sig; /* DETERMINATION OF THE PARAMETER SIG (SHIFT) */ pom = b / ah; if (a > 0.) { den = luksan_mxvdot__(n, &xo[1], &xo[1]); if (*met3 <= 4) { /* Computing MAX */ d__1 = 0., d__2 = 1. - aa / a; /* Computing MAX */ d__3 = 0., d__4 = 1. - b * b / (den * ah); *sig = sqrt((MAX2(d__1,d__2))) / (sqrt((MAX2(d__3,d__4))) + 1.) * pom; } else { /* Computing MAX */ d__1 = 0., d__2 = *sig * ah / a; /* Computing MAX */ d__3 = 0., d__4 = 1. - b * b / (den * ah); *sig = sqrt((MAX2(d__1,d__2))) / (sqrt((MAX2(d__3,d__4))) + 1.) * pom; } /* Computing MAX */ d__1 = *sig, d__2 = pom * .2; *sig = MAX2(d__1,d__2); /* Computing MIN */ d__1 = *sig, d__2 = pom * .8; *sig = MIN2(d__1,d__2); } else { *sig = pom * .25; } /* COMPUTATION OF SHIFTED XO AND SHIFTED B */ b -= ah * *sig; d__1 = -(*sig); luksan_mxvdir__(n, &d__1, &go[1], &xo[1], &xo[1]); /* COMPUTATION OF THE PARAMETER RHO (CORRECTION) */ if (*met2 <= 1) { par = 1.; } else if (*met2 == 2) { par = *sig * ah / b; } else if (*met2 == 3) { par = sqrt(1. - aa / a); } else if (*met2 == 4) { par = sqrt(sqrt(1. - aa / a) * (*sig * ah / b)); } else { par = zet / (zet + *sig); } /* COMPUTATION OF THE PARAMETER THETA (BFGS) */ d__1 = sqrt(par * b / cc); pom = copysign(d__1, bb); /* COMPUTATION OF Q AND P */ if (*met5 == 1) { /* RANK ONE UPDATE OF XM */ luksan_mxvdir__(m, &pom, &xr[1], &gr[1], &xr[1]); luksan_mxvlin__(n, &par, &xo[1], &pom, &so[1], &s[1]); d__1 = -1. / (par * b + pom * bb); luksan_mxdcmu__(n, m, &xm[1], &d__1, &s[1], &xr[1]); } else { /* RANK TWO UPDATE OF XM */ d__1 = par / pom - bb / b; luksan_mxvdir__(n, &d__1, &xo[1], &so[1], &s[1]); d__1 = -1. / b; d__2 = -1. / cc; luksan_mxdcmv__(n, m, &xm[1], &d__1, &xo[1], &gr[1], &d__2, &s[1], &xr[1]); } L22: *iterh = 0; return; } /* luksan_pulvp3__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYADC0 ALL SYSTEMS 98/12/01 * PURPOSE : * NEW SIMPLE BOUNDS ARE ADDED TO THE ACTIVE SET. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N REDUCED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * IO INEW NUMBER OF ACTIVE CONSTRAINTS. */ void luksan_pyadc0__(int *nf, int *n, double *x, int *ix, double *xl, double *xu, int *inew) { /* System generated locals */ int i__1; /* Local variables */ int i__, ii, ixi; /* Parameter adjustments */ --ix; --x; --xl; --xu; /* Function Body */ *n = *nf; *inew = 0; i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { ii = ix[i__]; ixi = iabs(ii); if (ixi >= 5) { ix[i__] = -ixi; } else if ((ixi == 1 || ixi == 3 || ixi == 4) && x[i__] <= xl[i__]) { x[i__] = xl[i__]; if (ixi == 4) { ix[i__] = -3; } else { ix[i__] = -ixi; } --(*n); if (ii > 0) { ++(*inew); } } else if ((ixi == 2 || ixi == 3 || ixi == 4) && x[i__] >= xu[i__]) { x[i__] = xu[i__]; if (ixi == 3) { ix[i__] = -4; } else { ix[i__] = -ixi; } --(*n); if (ii > 0) { ++(*inew); } } /* L1: */ } return; } /* luksan_pyadc0__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYFUT1 ALL SYSTEMS 98/12/01 * PURPOSE : * TERMINATION CRITERIA AND TEST ON RESTART. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * RI F NEW VALUE OF THE OBJECTIVE FUNCTION. * RI FO OLD VALUE OF THE OBJECTIVE FUNCTION. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RO GMAX NORM OF THE TRANSFORMED GRADIENT. * RI DMAX MAXIMUM RELATIVE DIFFERENCE OF VARIABLES. * RI TOLX LOWER BOUND FOR STEPLENGTH. * RI TOLF LOWER BOUND FOR FUNCTION DECREASE. * RI TOLB LOWER BOUND FOR FUNCTION VALUE. * RI TOLG LOWER BOUND FOR GRADIENT. * II KD DEGREE OF REQUIRED DERIVATIVES. * IU NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER RESTART. * II MIT MAXIMUM NUMBER OF ITERATIONS. * IU NFV ACTUAL NUMBER OF COMPUTED FUNCTION VALUES. * II MFV MAXIMUM NUMBER OF COMPUTED FUNCTION VALUES. * IU NFG ACTUAL NUMBER OF COMPUTED GRADIENT VALUES. * II MFG MAXIMUM NUMBER OF COMPUTED GRADIENT VALUES. * IU NTESX ACTUAL NUMBER OF TESTS ON STEPLENGTH. * II MTESX MAXIMUM NUMBER OF TESTS ON STEPLENGTH. * IU NTESF ACTUAL NUMBER OF TESTS ON FUNCTION DECREASE. * II MTESF MAXIMUM NUMBER OF TESTS ON FUNCTION DECREASE. * II IRES1 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * II IRES2 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * IU IREST RESTART INDICATOR. RESTART IS PERFORMED IF IREST>0. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * IO ITERM TERMINATION INDICATOR. ITERM=1-TERMINATION AFTER MTESX * UNSUFFICIENT STEPLENGTHS. ITERM=2-TERMINATION AFTER MTESF * UNSUFFICIENT FUNCTION DECREASES. ITERM=3-TERMINATION ON LOWER * BOUND FOR FUNCTION VALUE. ITERM=4-TERMINATION ON LOWER BOUND * FOR GRADIENT. ITERM=11-TERMINATION AFTER MAXIMUM NUMBER OF * ITERATIONS. ITERM=12-TERMINATION AFTER MAXIMUM NUMBER OF * COMPUTED FUNCTION VALUES. */ void luksan_pyfut1__(int *n, double *f, double *fo, double *umax, double *gmax, int xstop, /* double *dmax__, */ const nlopt_stopping *stop, double *tolg, int *kd, int *nit, int *kit, int *mit, int *nfg, int *mfg, int *ntesx, int *mtesx, int *ntesf, int *mtesf, int *ites, int *ires1, int *ires2, int *irest, int *iters, int *iterm) { /* System generated locals */ double d__1, d__2; /* Builtin functions */ if (*iterm < 0) { return; } if (*ites <= 0) { goto L1; } if (*iters == 0) { goto L1; } if (*nit <= 0) { /* Computing MIN */ d__1 = sqrt((fabs(*f))), d__2 = fabs(*f) / 10.; *fo = *f + MIN2(d__1,d__2); } if (nlopt_stop_forced(stop)) { *iterm = -999; return; } if (*f <= stop->minf_max /* *tolb */) { *iterm = 3; return; } if (*kd > 0) { if (*gmax <= *tolg && *umax <= *tolg) { *iterm = 4; return; } } if (*nit <= 0) { *ntesx = 0; *ntesf = 0; } if (xstop) /* (*dmax__ <= *tolx) */ { *iterm = 1; ++(*ntesx); if (*ntesx >= *mtesx) { return; } } else { *ntesx = 0; } if (nlopt_stop_ftol(stop, *f, *fo)) { *iterm = 2; ++(*ntesf); if (*ntesf >= *mtesf) { return; } } else { *ntesf = 0; } L1: if (*nit >= *mit) { *iterm = 11; return; } if (nlopt_stop_evals(stop)) /* (*nfv >= *mfv) */ { *iterm = 12; return; } if (*nfg >= *mfg) { *iterm = 13; return; } *iterm = 0; if (*n > 0 && *nit - *kit >= *ires1 * *n + *ires2) { *irest = MAX2(*irest,1); } ++(*nit); return; } /* luksan_pyfut1__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYRMC0 ALL SYSTEMS 98/12/01 * PURPOSE : * OLD SIMPLE BOUND IS REMOVED FROM THE ACTIVE SET. TRANSFORMED * GRADIENT OF THE OBJECTIVE FUNCTION IS UPDATED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N REDUCED NUMBER OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI EPS8 TOLERANCE FOR CONSTRAINT TO BE REMOVED. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RI GMAX NORM OF THE TRANSFORMED GRADIENT. * RO RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * II IOLD NUMBER OF REMOVED CONSTRAINTS. * IU IREST RESTART INDICATOR. */ void luksan_pyrmc0__(int *nf, int *n, int *ix, double *g, double *eps8, double *umax, double *gmax, double *rmax, int *iold, int *irest) { /* System generated locals */ int i__1, i__2, i__3; /* Local variables */ int i__, ixi; /* Parameter adjustments */ --g; --ix; /* Function Body */ if (*n == 0 || *rmax > 0.) { if (*umax > *eps8 * *gmax) { *iold = 0; i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { ixi = ix[i__]; if (ixi >= 0) { } else if (ixi <= -5) { } else if ((ixi == -1 || ixi == -3) && -g[i__] <= 0.) { } else if ((ixi == -2 || ixi == -4) && g[i__] <= 0.) { } else { ++(*iold); /* Computing MIN */ i__3 = (i__2 = ix[i__], iabs(i__2)); ix[i__] = MIN2(i__3,3); if (*rmax == 0.) { goto L2; } } /* L1: */ } L2: if (*iold > 1) { *irest = MAX2(*irest,1); } } } return; } /* luksan_pyrmc0__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYTRCD ALL SYSTEMS 98/12/01 * PURPOSE : * VECTORS OF VARIABLES DIFFERENCE AND GRADIENTS DIFFERENCE ARE COMPUTED * AND SCALED AND REDUCED. TEST VALUE DMAX IS DETERMINED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RU GO(NF) GRADIENTS DIFFERENCE. * RO R VALUE OF THE STEPSIZE PARAMETER. * RO F NEW VALUE OF THE OBJECTIVE FUNCTION. * RI FO OLD VALUE OF THE OBJECTIVE FUNCTION. * RO P NEW VALUE OF THE DIRECTIONAL DERIVATIVE. * RI PO OLD VALUE OF THE DIRECTIONAL DERIVATIVE. * RO DMAX MAXIMUM RELATIVE DIFFERENCE OF VARIABLES. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * IO KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF COMPUTED DERIVATIVES. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * * SUBPROGRAMS USED : * S MXVDIF DIFFERENCE OF TWO VECTORS. * S MXVSAV DIFFERENCE OF TWO VECTORS WITH COPYING AND SAVING THE * SUBSTRACTED ONE. */ void luksan_pytrcd__(int *nf, double *x, int *ix, double *xo, double *g, double *go, double *r__, double *f, double *fo, double *p, double *po, double *dmax__, int *kbf, int *kd, int *ld, int * iters) { /* System generated locals */ int i__1; double d__1, d__2, d__3, d__4, d__5; /* Local variables */ int i__; /* Parameter adjustments */ --go; --g; --xo; --ix; --x; /* Function Body */ if (*iters > 0) { luksan_mxvdif__(nf, &x[1], &xo[1], &xo[1]); luksan_mxvdif__(nf, &g[1], &go[1], &go[1]); *po = *r__ * *po; *p = *r__ * *p; } else { *f = *fo; *p = *po; luksan_mxvsav__(nf, &x[1], &xo[1]); luksan_mxvsav__(nf, &g[1], &go[1]); *ld = *kd; } *dmax__ = 0.; i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { if (*kbf > 0) { if (ix[i__] < 0) { xo[i__] = 0.; go[i__] = 0.; goto L1; } } /* Computing MAX */ /* Computing MAX */ d__5 = (d__2 = x[i__], fabs(d__2)); d__3 = *dmax__, d__4 = (d__1 = xo[i__], fabs(d__1)) / MAX2(d__5,1.); *dmax__ = MAX2(d__3,d__4); L1: ; } return; } /* luksan_pytrcd__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYTRCG ALL SYSTEMS 99/12/01 * PURPOSE : * GRADIENT OF THE OBJECTIVE FUNCTION IS SCALED AND REDUCED. TEST VALUES * GMAX AND UMAX ARE COMPUTED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N ACTUAL NUMBER OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RI GMAX NORM OF THE TRANSFORMED GRADIENT. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II IOLD INDEX OF THE REMOVED CONSTRAINT. * * SUBPROGRAMS USED : * RF MXVMAX L-INFINITY NORM OF A VECTOR. */ void luksan_pytrcg__(int *nf, int *n, int *ix, double *g, double *umax, double *gmax, int *kbf, int *iold) { /* System generated locals */ int i__1; double d__1, d__2; /* Local variables */ int i__; double temp; /* Parameter adjustments */ --g; --ix; /* Function Body */ if (*kbf > 0) { *gmax = 0.; *umax = 0.; *iold = 0; i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { temp = g[i__]; if (ix[i__] >= 0) { /* Computing MAX */ d__1 = *gmax, d__2 = fabs(temp); *gmax = MAX2(d__1,d__2); } else if (ix[i__] <= -5) { } else if ((ix[i__] == -1 || ix[i__] == -3) && *umax + temp >= 0.) { } else if ((ix[i__] == -2 || ix[i__] == -4) && *umax - temp >= 0.) { } else { *iold = i__; *umax = fabs(temp); } /* L1: */ } } else { *umax = 0.; *gmax = luksan_mxvmax__(nf, &g[1]); } *n = *nf; return; } /* luksan_pytrcg__ */ /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */ /* SUBROUTINE PYTRCS ALL SYSTEMS 98/12/01 * PURPOSE : * SCALED AND REDUCED DIRECTION VECTOR IS BACK TRANSFORMED. VECTORS * X,G AND VALUES F,P ARE SAVED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RO XO(NF) SAVED VECTOR OF VARIABLES. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO GO(NF) SAVED GRADIENT OF THE OBJECTIVE FUNCTION. * RO S(NF) DIRECTION VECTOR. * RO RO SAVED VALUE OF THE STEPSIZE PARAMETER. * RO FP PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RU FO SAVED VALUE OF THE OBJECTIVE FUNCTION. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RO PO SAVED VALUE OF THE DIRECTIONAL DERIVATIVE. * RI P VALUE OF THE DIRECTIONAL DERIVATIVE. * RO RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * * SUBPROGRAMS USED : * S MXVCOP COPYING OF A VECTOR. */ void luksan_pytrcs__(int *nf, double *x, int *ix, double *xo, double *xl, double *xu, double *g, double *go, double *s, double *ro, double *fp, double *fo, double *f, double *po, double *p, double *rmax, double *eta9, int *kbf) { /* System generated locals */ int i__1; double d__1, d__2; /* Local variables */ int i__; /* Parameter adjustments */ --s; --go; --g; --xu; --xl; --xo; --ix; --x; /* Function Body */ *fp = *fo; *ro = 0.; *fo = *f; *po = *p; luksan_mxvcop__(nf, &x[1], &xo[1]); luksan_mxvcop__(nf, &g[1], &go[1]); if (*kbf > 0) { i__1 = *nf; for (i__ = 1; i__ <= i__1; ++i__) { if (ix[i__] < 0) { s[i__] = 0.; } else { if (ix[i__] == 1 || ix[i__] >= 3) { if (s[i__] < -1. / *eta9) { /* Computing MIN */ d__1 = *rmax, d__2 = (xl[i__] - x[i__]) / s[i__]; *rmax = MIN2(d__1,d__2); } } if (ix[i__] == 2 || ix[i__] >= 3) { if (s[i__] > 1. / *eta9) { /* Computing MIN */ d__1 = *rmax, d__2 = (xu[i__] - x[i__]) / s[i__]; *rmax = MIN2(d__1,d__2); } } } /* L1: */ } } return; } /* luksan_pytrcs__ */ nlopt-2.6.1/src/algs/luksan/pssubs.for000066400000000000000000005602701345435414600177400ustar00rootroot00000000000000* SUBROUTINE PA0GS3 ALL SYSTEMS 91/12/01 * PURPOSE : * NUMERICAL COMPUTATION OF THE GRADIENT OF THE APPROXIMATED * FUNCTION. * * PARAMETERS : * II N NUMBER OF VARIABLES. * II KA INDEX OF THE APPROXIMATED FUNCTION. * RI X(N) VECTOR OF VARIABLES. * RO FA VALUE OF THE APPROXIMATED FUNCTION. * RA GA(N) GRADIENT OF THE APPROXIMATED FUNCTION. * II IAG(N+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI ETA1 PRECISION OF THE COMPUTED FUNCTION VALUES. * IU NAV NUMBER OF APPROXIMATED FUNCTION EVALUATIONS. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SUBROUTINE PA0GS3(N,KA,X,FA,GA,IAG,JAG,ETA1,NAV) DOUBLE PRECISION ETA1,FA INTEGER KA,N,NAV DOUBLE PRECISION GA(*),X(*) INTEGER IAG(*),JAG(*) DOUBLE PRECISION ETA,FTEMP,XSTEP,XTEMP INTEGER IVAR,KVAR ETA = SQRT(ETA1) FTEMP = FA DO 10 KVAR = IAG(KA),IAG(KA+1) - 1 IVAR = JAG(KVAR) * * STEP SELECTION * XSTEP = ETA*MAX(ABS(X(IVAR)),1.0D0)*SIGN(1.0D0,X(IVAR)) XTEMP = X(IVAR) X(IVAR) = X(IVAR) + XSTEP XSTEP = X(IVAR) - XTEMP NAV = NAV + 1 CALL FUN(N,KA,X,FA) * * NUMERICAL DIFFERENTIATION * GA(IVAR) = (FA-FTEMP)/XSTEP X(IVAR) = XTEMP 10 CONTINUE FA = FTEMP RETURN END * SUBROUTINE PA0HS3 ALL SYSTEMS 99/12/01 * PURPOSE : * NUMERICAL COMPUTATION OF THE HESSIAN MATRIX OF THE APPROXIMATED * FUNCTION USING ITS VALUES. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II KA INDEX OF THE SELECTED FUNCTION. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RO HA(M) HESSIAN MATRIX OF THE APPROXIMATED FUNCTION. * RA GO(NF) AUXILIARY VECTOR. * RA GS(NF) AUXILIARY VECTOR. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI FA VALUE OF THE SELECTED FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED VALUES. * II KBF TYPE OF BOUNDS. KBF=0-BOUNDS ARE NOT USED. KBF=1-ONE SIDED * BOUNDS. KBF=1-TWO SIDED BOUNDS. * IO NAV NUMBER OF APPROXIMATED FUNTION VALUES. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SUBROUTINE PA0HS3(NF,KA,X,IX,HA,GO,GS,IAG,JAG,FA,ETA1,KBF,NAV) INTEGER NF,KA,IX(*),IAG(*),JAG(*),KBF,NAV DOUBLE PRECISION X(*),HA(*),GO(*),GS(*),FA,ETA1 DOUBLE PRECISION XTEMPI,XTEMPJ,FTEMP,ETA INTEGER I,J,IJ INTEGER IVAR,JVAR,KVAR,LVAR,MVAR ETA=ETA1**(1.0D 0/3.0D 0) FTEMP=FA MVAR=IAG(KA)-1 DO 4 KVAR=MVAR+1,IAG(KA+1)-1 IVAR=ABS(JAG(KVAR)) IF (KBF.GT.0) THEN IF (IX(IVAR).LE.-5) GO TO 4 END IF * * STEP SELECTION * XTEMPI=X(IVAR) IF (XTEMPI.GE.0.0D 0) THEN GO(IVAR)= ETA*MAX(ABS(XTEMPI),1.0D 0) ELSE GO(IVAR)=-ETA*MAX(ABS(XTEMPI),1.0D 0) END IF X(IVAR)=X(IVAR)+GO(IVAR) GO(IVAR)=X(IVAR)-XTEMPI CALL FUN(NF,KA,X,FA) NAV=NAV+1 GS(IVAR)=FA X(IVAR)=XTEMPI 4 CONTINUE * * NUMERICAL DIFFERENTIATION * DO 10 KVAR=MVAR+1,IAG(KA+1)-1 IVAR=ABS(JAG(KVAR)) IF (KBF.GT.0) THEN IF (IX(IVAR).LE.-5) GO TO 10 END IF XTEMPI=X(IVAR) X(IVAR)=XTEMPI+GO(IVAR) DO 9 LVAR=KVAR,IAG(KA+1)-1 JVAR=ABS(JAG(LVAR)) IF (KBF.GT.0) THEN IF (IX(JVAR).LE.-5) GO TO 9 END IF XTEMPJ=X(JVAR) X(JVAR)=X(JVAR)+GO(JVAR) CALL FUN(NF,KA,X,FA) NAV=NAV+1 I=KVAR-MVAR J=LVAR-MVAR IJ=MAX(I,J)*(MAX(I,J)-1)/2+MIN(I,J) HA(IJ)=((FTEMP-GS(IVAR))+(FA-GS(JVAR)))/(GO(IVAR)*GO(JVAR)) X(JVAR)=XTEMPJ 9 CONTINUE X(IVAR)=XTEMPI 10 CONTINUE FA=FTEMP RETURN END * SUBROUTINE PA0SQ3 ALL SYSTEMS 92/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT OF THE OBJECTIVE FUNCTION * WHICH IS DEFINED AS A SUM OF SQUARES. * * PARAMETERS: * II N NUMBER OF VARIABLES. * RI X(N) VECTOR OF VARIABLES. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO AF(N) VALUES OF THE APPROXIMATED FUNCTIONS. * RA GA(N) GRADIENT OF THE APPROXIMATED FUNCTION. * RI AG(IAG(N+1)-1) SPARSE RECTANGULAR MATRIX WHICH IS USED FOR THE * DIRECTION VECTOR DETERMINATION. * II IAG(N+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI G(N) GRADIENT OF THE OBJECTIVE FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED FUNCTION VALUES. * II KD DEGREE OF REQUIRED DERIVATIVES. * IU LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * II IDER DEGREE OF ANALYTICALLY COMPUTED DERIVATIVES (0 OR 1). * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * S PA0GS3 NUMERICAL DIFFERENTIATION. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PA0SQ3(N,X,F,AF,GA,AG,IAG,JAG,G,ETA1,KD,LD,NFV,NFG, & IDER) DOUBLE PRECISION ETA1,F INTEGER IDER,KD,LD,N,NFV,NFG DOUBLE PRECISION AF(*),AG(*),G(*),GA(*),X(*) INTEGER IAG(*),JAG(*) DOUBLE PRECISION FA INTEGER J,JP,K,KA,L,NAV IF (KD.LE.LD) RETURN IF (KD.GE.0 .AND. LD.LT.0) THEN F = 0.0D0 NFV=NFV+1 END IF IF (KD.GE.1 .AND. LD.LT.1) THEN CALL MXVSET(N,0.0D0,G) IF (IDER.GT.0) NFG=NFG+1 END IF NAV=0 DO 30 KA = 1,N IF (KD.LT.0) GO TO 30 IF (LD.GE.0) THEN FA = AF(KA) ELSE CALL FUN(N,KA,X,FA) AF(KA) = FA END IF IF (LD.GE.0) GO TO 10 F = F + FA*FA 10 IF (KD.LT.1) GO TO 30 IF (IDER.EQ.0) THEN CALL PA0GS3(N,KA,X,FA,GA,IAG,JAG,ETA1,NAV) ELSE CALL DFUN(N,KA,X,GA) END IF K = IAG(KA) L = IAG(KA+1) - K DO 20 J = 1,L JP = JAG(K) G(JP) = G(JP) + FA*GA(JP) AG(K) = GA(JP) K = K + 1 20 CONTINUE 30 CONTINUE IF (KD.GE.0 .AND. LD.LT.0) F = 0.5D0*F IF (IDER.EQ.0) NFV=NFV+NAV/N LD = KD RETURN END * SUBROUTINE PA1HS3 ALL SYSTEMS 99/12/01 * PURPOSE : * NUMERICAL COMPUTATION OF THE HESSIAN MATRIX OF THE APPROXIMATED * FUNCTION USING ITS GRADIENTS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II KA INDEX OF THE SELECTED FUNCTION. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RO HA(M) HESSIAN MATRIX OF THE APPROXIMATED FUNCTION. * RI GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RA GO(NF) AUXILIARY VECTOR. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI FA VALUE OF THE SELECTED FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED VALUES. * II KBF TYPE OF BOUNDS. KBF=0-BOUNDS ARE NOT USED. KBF=1-ONE SIDED * BOUNDS. KBF=2-TWO SIDED BOUNDS. * IO NAG NUMBER OF APPROXIMATED FUNTION GRADIENTS. * * SUBPROGRAMS USED : * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * SUBROUTINE PA1HS3(NF,KA,X,IX,HA,GA,GO,IAG,JAG,FA,ETA1,KBF,NAG) INTEGER NF,KA,IX(*),IAG(*),JAG(*),KBF,NAG DOUBLE PRECISION X(*),HA(*),GA(*),GO(*),FA,ETA1 DOUBLE PRECISION XSTEP,XTEMP,FTEMP,ETA INTEGER I,J,IJ INTEGER IVAR,JVAR,KVAR,LVAR,MVAR ETA=SQRT(ETA1) FTEMP=FA MVAR=IAG(KA)-1 DO 5 KVAR=MVAR+1,IAG(KA+1)-1 IVAR=ABS(JAG(KVAR)) IF (KBF.GT.0) THEN IF (IX(IVAR).LE.-5) GO TO 5 END IF * * STEP SELECTION * XTEMP=X(IVAR) IF (XTEMP.GE.0.0D 0) THEN XSTEP= ETA*MAX(ABS(XTEMP),1.0D 0) ELSE XSTEP=-ETA*MAX(ABS(XTEMP),1.0D 0) END IF X(IVAR)=XTEMP+XSTEP XSTEP=X(IVAR)-XTEMP CALL DFUN(NF,KA,X,GA) NAG=NAG+1 * * NUMERICAL DIFFERENTIATION * DO 4 LVAR=MVAR+1,IAG(KA+1)-1 JVAR=ABS(JAG(LVAR)) IF (KBF.GT.0) THEN IF (IX(JVAR).LE.-5) GO TO 4 END IF I=KVAR-MVAR J=LVAR-MVAR IJ=MAX(I,J)*(MAX(I,J)-1)/2+MIN(I,J) IF (LVAR .GE. KVAR) THEN HA(IJ)=(GA(JVAR)-GO(JVAR))/XSTEP ELSE HA(IJ)=0.5D 0*(HA(IJ)+(GA(JVAR)-GO(JVAR))/XSTEP) END IF 4 CONTINUE X(IVAR)=XTEMP 5 CONTINUE FA=FTEMP RETURN END * SUBROUTINE PA1SF3 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT OF THE OBJECTIVE FUNCTION * WHICH IS DEFINED AS A SUM OF SQUARES. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * RU GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO AG(MA) SPARSE JACOBIAN MATRIX. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * II ISNA SAVING SPECIFICATION. ISNA=0-NO SAVING. ISNA=1-FUNCTION * VALUES ARE SAVED. ISNA=2-FUNCTION VALUES AND GRADIENTS ARE * SAVED. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PA1SF3(NF,NA,X,GA,G,AG,IAG,JAG,F,AF,KD,LD,ISNA, & NFV,NFG) INTEGER NF,NA,IAG(*),JAG(*),KD,LD,ISNA,NFV,NFG DOUBLE PRECISION X(*),GA(*),G(*),AG(*),F,AF(*) INTEGER J,JP,K,L,KA DOUBLE PRECISION FA IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN F=0.0D 0 NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) NFG=NFG+1 END IF DO 5 KA=1,NA IF (KD.LT.0) GO TO 5 IF (LD.LT.0) THEN CALL FUN(NF,KA,X,FA) F=F+FA AF(KA)=FA ELSE FA=AF(KA) END IF IF (KD.LT.1) GO TO 5 IF (LD.LT.1) THEN CALL DFUN(NF,KA,X,GA) K=IAG(KA) L=IAG(KA+1)-K DO 4 J=1,L JP=ABS(JAG(K)) G(JP)=G(JP)+GA(JP) IF (ISNA.GT.1) AG(K)=GA(JP) K=K+1 4 CONTINUE END IF 5 CONTINUE LD=KD RETURN END * SUBROUTINE PA2SF4 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT AND THE HESSIAN MATRIX * OF THE OBJECTIVE FUNCTION WHICH IS DEFINED AS A SUM OF SQUARES. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RU GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA GO(NF) AUXILIARY VECTOR. * RU HA(MB) HESSIAN MATRIX OF THE APPROXIMATED FUNCTION. * RO H(M) SPARSE HESSIAN MATRIX OF THE OBJECTIVE FUNCTION. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED FUNCTION VALUES. * II KBF TYPE OF BOUNDS. KBF=0-BOUNDS ARE NOT USED. KBF=1-ONE SIDED * BOUNDS. KBF=2-TWO SIDED BOUNDS. * II KD DEGREE OF REQUIRED DERVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * IU IDECF DECOMPOSITION INDICATOR. IDECF=0-NO DECOMPOSITION. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * S PA1HS3 NUMERICAL COMPUTATION OF THE PARTIAL HESSIAN MATRIX. * S PASSH2 ADDITION OF THE PARTIAL HESSIAN MATRIX TO THE SPARSE * HESSIAN MATRIX. * SUBROUTINE PA2SF4(NF,NA,X,IX,GA,G,GO,HA,H,IH,JH,IAG,JAG,AF,F, & ETA1,KBF,KD,LD,NFV,NFG,IDECF) INTEGER NF,NA,IX(*),IH(*),JH(*),IAG(*),JAG(*),KBF,KD,LD,NFV,NFG, & IDECF DOUBLE PRECISION X(*),GA(*),G(*),GO(*),HA(*),H(*),AF(*),F,ETA1 DOUBLE PRECISION FA INTEGER J,JP,K,KA,L,NAG IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN F=0.0D 0 NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) NFG=NFG+1 END IF IF (KD.GE.2.AND.LD.LT.2) CALL MXVSET(IH(NF+1)-1,0.0D 0,H) NAG=0 DO 9 KA=1,NA IF (KD.LT.0) GO TO 9 IF (LD.LT.0) THEN CALL FUN(NF,KA,X,FA) F=F+FA AF(KA)=FA ELSE FA=AF(KA) END IF IF (KD.LT.1) GO TO 9 CALL DFUN(NF,KA,X,GA) IF (LD.LT.1) THEN K=IAG(KA) L=IAG(KA+1)-K DO 1 J=1,L JP=ABS(JAG(K)) G(JP)=G(JP)+GA(JP) K=K+1 1 CONTINUE END IF IF (KD.LT.2) GO TO 9 IDECF=0 CALL PA1HS3(NF,KA,X,IX,HA,GO,GA,IAG,JAG,FA,ETA1,KBF,NAG) CALL PASSH2(H,IH,JH,HA,IAG,JAG,KA,1.0D 0) 9 CONTINUE NFG=NFG+NAG/NA LD=KD RETURN END * SUBROUTINE PA2SQ4 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT AND THE HESSIAN MATRIX * OF THE OBJECTIVE FUNCTION WHICH IS DEFINED AS A SUM OF SQUARES. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * RU GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RO AG(MA) SPARSE JACOBIAN MATRIX. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO H(M) SPARSE HESSIAN MATRIX OF THE OBJECTIVE FUNCTION. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED FUNCTION VALUES. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * II ISNA SAVING SPECIFICATION. ISNA=0-NO SAVING. ISNA=1-FUNCTION * VALUES ARE SAVED. ISNA=2-FUNCTION VALUES AND GRADIENTS ARE * SAVED. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * II IDER DEGREE OF ANALYTICALLY COMPUTED DERIVATIVES (0 OR 1). * IU IDECF DECOMPOSITION INDICATOR. IDECF=0-NO DECOMPOSITION. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * S PASSH1 ADDITION OF THE PARTIAL GAUSS-NEWTON TERM TO THE SPARSE * HESSIAN MATRIX. * SUBROUTINE PA2SQ4(NF,NA,X,GA,AG,G,H,IH,JH,IAG,JAG,AF,F,ETA1,KD, & LD,ISNA,NFV,NFG,IDER,IDECF) INTEGER NF,NA,IH(*),JH(*),IAG(*),JAG(*),KD,LD,ISNA,NFV,NFG,IDER, & IDECF DOUBLE PRECISION X(*),GA(*),AG(*),G(*),H(*),AF(*),F,ETA1 INTEGER J,JP,K,KA,L,NAV DOUBLE PRECISION FA IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN F=0.0D 0 NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) IF (IDER.GT.0) NFG=NFG+1 END IF IF (KD.GE.2.AND.LD.LT.2) CALL MXVSET(IH(NF+1)-1,0.0D 0,H) NAV=0 DO 3 KA=1,NA IF (KD.LT.0) GO TO 3 IF (LD.LT.0) THEN CALL FUN(NF,KA,X,FA) F=F+FA*FA AF(KA)=FA ELSE FA=AF(KA) END IF IF (KD.LT.1) GO TO 3 IF (IDER.EQ.0) THEN CALL PA0GS3(NF,KA,X,FA,GA,IAG,JAG,ETA1,NAV) ELSE CALL DFUN(NF,KA,X,GA) END IF IF (LD.GE.1) GO TO 2 K=IAG(KA) L=IAG(KA+1)-K DO 1 J=1,L JP=ABS(JAG(K)) G(JP)=G(JP)+FA*GA(JP) IF (ISNA.GT.1) AG(K)=GA(JP) K=K+1 1 CONTINUE 2 IF (KD.LT.2) GO TO 3 IDECF=0 CALL PASSH1(H,IH,JH,IAG,JAG,GA,KA,1.0D 0) 3 CONTINUE IF (KD.GE.0.AND.LD.LT.0) F=5.0D-1*F IF (IDER.EQ.0) NFV=NFV+NAV/NA LD=KD RETURN END * SUBROUTINE PA2SQ8 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT AND THE HESSIAN MATRIX * OF THE OBJECTIVE FUNCTION WHICH IS DEFINED AS A SUM OF SQUARES. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RU GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA GO(NF) AUXILIARY VECTOR. * RA GS(NF) AUXILIARY VECTOR. * RU HA(ME) HESSIAN MATRIX OF THE APPROXIMATED FUNCTION. * RO H(M) SPARSE HESSIAN MATRIX OF THE OBJECTIVE FUNCTION. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED FUNCTION VALUES. * II KBF TYPE OF BOUNDS. KBF=0-BOUNDS ARE NOT USED. KBF=1-ONE SIDED * BOUNDS. KBF=2-TWO SIDED BOUNDS. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * II IPOM1 CORRECTION OPTION. IPOM1=0-THE NEWTON CORRECTION IS USED. * IPOM1=1-CORRECTION IS NOT USED. * II IDER DEGREE OF ANALYTICALLY COMPUTED DERIVATIVES (0 OR 1). * IU IDECF DECOMPOSITION INDICATOR. IDECF=0-NO DECOMPOSITION. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * S PA0HS3 NUMERICAL COMPUTATION OF THE PARTIAL HESSIAN MATRIX. * S PA1HS3 NUMERICAL COMPUTATION OF THE PARTIAL HESSIAN MATRIX. * S PASSH1 ADDITION OF THE PARTIAL GAUSS-NEWTON TERM TO THE SPARSE * HESSIAN MATRIX. * S PASSH2 ADDITION OF THE PARTIAL HESSIAN MATRIX TO THE SPARSE * HESSIAN MATRIX. * SUBROUTINE PA2SQ8(NF,NA,X,IX,GA,G,GO,GS,HA,H,IH,JH,IAG,JAG,AF,F, & ETA1,KBF,KD,LD,NFV,NFG,IPOM1,IDER,IDECF) INTEGER NF,NA,IX(*),IH(*),JH(*),IAG(*),JAG(*),KBF,KD,LD,NFV,NFG, & IPOM1,IDER,IDECF DOUBLE PRECISION X(*),GA(*),G(*),GO(*),GS(*),HA(*),H(*),AF(*),F, & ETA1 INTEGER J,JP,K,KA,L,NAV,NAG DOUBLE PRECISION FA IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN F=0.0D 0 NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) IF (IDER.GT.0) NFG=NFG+1 END IF IF (KD.GE.2.AND.LD.LT.2) CALL MXVSET(IH(NF+1)-1,0.0D 0,H) NAV=0 NAG=0 DO 9 KA=1,NA IF (KD.LT.0) GO TO 9 IF (LD.LT.0) THEN CALL FUN(NF,KA,X,FA) F=F+FA*FA AF(KA)=FA ELSE FA=AF(KA) END IF IF (KD.LT.1) GO TO 9 IF (IDER.EQ.0) THEN CALL PA0GS3(NF,KA,X,FA,GA,IAG,JAG,ETA1,NAV) ELSE CALL DFUN(NF,KA,X,GA) END IF IF (LD.LT.1) THEN K=IAG(KA) L=IAG(KA+1)-K DO 1 J=1,L JP=ABS(JAG(K)) G(JP)=G(JP)+FA*GA(JP) K=K+1 1 CONTINUE END IF IF (KD.LT.2) GO TO 9 IDECF=0 IF (IPOM1.EQ.0) THEN IF (IDER.EQ.0) THEN CALL PA0HS3(NF,KA,X,IX,HA,GO,GS,IAG,JAG,FA,ETA1,KBF,NAV) ELSE CALL PA1HS3(NF,KA,X,IX,HA,GO,GA,IAG,JAG,FA,ETA1,KBF,NAG) END IF END IF CALL PASSH1(H,IH,JH,IAG,JAG,GA,KA,1.0D 0) IF (IPOM1.EQ.0) CALL PASSH2(H,IH,JH,HA,IAG,JAG,KA,FA) 9 CONTINUE IF (KD.GE.0.AND.LD.LT.0) F=5.0D-1*F IF (IDER.EQ.0) NFV=NFV+NAV/NA IF (IDER.GT.0) NFG=NFG+NAG/NA LD=KD RETURN END * SUBROUTINE PALNG3 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE GRADIENT OF THE LINEAR APPROXIMATED FUNCTION. * * PARAMETERS : * RO AG(MA) SPARSE JACOBIAN MATRIX. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * II KA INDEX OF THE SELECTED FUNCTION. * SUBROUTINE PALNG3(AG,IAG,JAG,GA,KA) DOUBLE PRECISION AG(*),GA(*) INTEGER IAG(*),JAG(*),KA INTEGER J,JP,K,L K=IAG(KA) L=IAG(KA+1)-K DO 2 J=1,L JP=ABS(JAG(K)) GA(JP)=AG(K) K=K+1 2 CONTINUE RETURN END * SUBROUTINE PASED3 ALL SYSTEMS 07/12/01 * PURPOSE : * COMPRESSED SPARSE STRUCTURE OF THE JACOBIAN MATRIX IS COMPUTED FROM * THE COORDINATE FORM. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * II MA NUMBER OF NONZERO ELEMENTS IN THE SPARSE JACOBIAN MATRIX. * IU IAG(MA+NA) ON INPUT ROW INDICES OF NONZERO ELEMENTS IN THE FIELD AG. * ON OUTPUT POSITIONS OF THE FIRST ROW ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * IO IER ERROR MESAGE. IER=0-THE STANDARD INPUT DATA ARE CORRECT. * IER=1-ERROR IN THE ARRAY IAG. IER=2-ERROR IN THE ARRAY JAG. * SUBROUTINE PASED3(NA,MA,IAG,JAG,IER) INTEGER NA,MA,IAG(*),JAG(*),IER INTEGER I,J,K,L,KA IER=0 CALL MXVSR7(MA,IAG,JAG) IF (IAG(1).LT.1.OR.IAG(MA).GT.NA) THEN IER=1 RETURN END IF CALL MXVINS(NA,0,IAG(MA+1)) DO 1 J=1,MA IAG(IAG(J)+MA)=IAG(IAG(J)+MA)+1 1 CONTINUE IAG(1)=1 DO 2 KA=1,NA IAG(KA+1)=IAG(KA)+IAG(KA+MA) 2 CONTINUE I=0 DO 4 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K IF (L.GT.0) THEN CALL MXVSRT(L,JAG(K)) IF (JAG(K).LT.1.OR.JAG(K+L-1).GT.NA) THEN IER=2 RETURN END IF END IF IAG(KA)=IAG(KA)-I DO 3 J=1,L IF (J.GT.1.AND.JAG(K).EQ.JAG(K-1)) THEN I=I+1 ELSE JAG(K-I)=JAG(K) END IF K=K+1 3 CONTINUE 4 CONTINUE IAG(NA+1)=IAG(NA+1)-I MA=IAG(NA+1)-1 RETURN END * SUBROUTINE PASSH1 ALL SYSTEMS 98/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE SPARSE JACOBIAN * MATRIX. * * PARAMETERS : * RU H(M) NONZERO ELEMENTS OF THE SPARSE HESSIAN MATRIX. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) COLUMN INDICES OF THE NONZERO ELEMENTS OF H. * II IAG(NA+1) POSITIONS OF THE FIRST ROWS ELEMENTS IN THE SPARSE * JACOBIAN STRUCTURE. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE SPARSE JACOBIAN * STRUCTURE. * RI GA(NF) GRADIENT OF THE SELECTED FUNCTION. * II KA INDEX OF THE SELECTED FUNCTION (ROW OF THE SPARSE JACOBIAN * MATRIX). * RI FACTOR SCALING FACTOR. * SUBROUTINE PASSH1(H,IH,JH,IAG,JAG,GA,KA,FACTOR) INTEGER IH(*),JH(*),IAG(*),JAG(*),KA DOUBLE PRECISION H(*),GA(*),FACTOR DOUBLE PRECISION TEMP INTEGER I,J,JF,JA,K,LA LA=IAG(KA+1)-1 DO 6 K=IAG(KA),LA I=ABS(JAG(K)) TEMP=FACTOR*GA(I) JF=IH(I) DO 5 JA=K,LA J=ABS(JAG(JA)) 2 IF (ABS(JH(JF)).LT.J) THEN JF=JF+1 GO TO 2 END IF H(JF)=H(JF)+TEMP*GA(J) 5 CONTINUE 6 CONTINUE RETURN END * SUBROUTINE PASSH2 ALL SYSTEMS 98/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE SPARSE JACOBIAN * MATRIX. * * PARAMETERS : * RU H(M) NONZERO ELEMENTS OF THE SPARSE HESSIAN MATRIX. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) COLUMN INDICES OF THE NONZERO ELEMENTS OF H. * II HA(ME) PACKED HESSIAN MATRIX OF THE SELECTED FUNCTION. * II IAG(NA+1) POSITIONS OF THE FIRST ROWS ELEMENTS IN THE SPARSE * JACOBIAN STRUCTURE. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE SPARSE JACOBIAN * STRUCTURE. * II KA INDEX OF THE SELECTED FUNCTION (ROW OF THE SPARSE JACOBIAN * MATRIX). * RI FACTOR SCALING FACTOR. * SUBROUTINE PASSH2(H,IH,JH,HA,IAG,JAG,KA,FACTOR) INTEGER IH(*),JH(*),IAG(*),JAG(*),KA DOUBLE PRECISION H(*),HA(*),FACTOR INTEGER I,II,IA,J,JJ,JA,JF,K,KK,L KK=0 II=IAG(KA) L=IAG(KA+1)-II DO 6 IA=1,L KK=KK+IA I=ABS(JAG(II)) JF=IH(I) JJ=II K=KK DO 4 JA=IA,L J=ABS(JAG(JJ)) 2 IF (ABS(JH(JF)).LT.J) THEN JF=JF+1 GO TO 2 END IF H(JF)=H(JF)+FACTOR*HA(K) K=K+JA JJ=JJ+1 4 CONTINUE II=II+1 6 CONTINUE RETURN END * SUBROUTINE PASSH3 ALL SYSTEMS 98/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE SPARSE JACOBIAN * MATRIX. * * PARAMETERS : * RU H(M) NONZERO ELEMENTS OF THE SPARSE HESSIAN MATRIX. * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) COLUMN INDICES OF THE NONZERO ELEMENTS OF H. * II IAG(NA+1) POSITIONS OF THE FIRST ROWS ELEMENTS IN THE SPARSE * JACOBIAN STRUCTURE. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE SPARSE JACOBIAN * STRUCTURE. * RI GA(NF) GRADIENT OF THE SELECTED FUNCTION. * II KA INDEX OF THE SELECTED FUNCTION (ROW OF THE SPARSE JACOBIAN * MATRIX). * RI FACTOR SCALING FACTOR. * SUBROUTINE PASSH3(H,IH,JH,IAG,JAG,GA,KA,FACTOR) INTEGER IH(*),JH(*),IAG(*),JAG(*),KA DOUBLE PRECISION H(*),GA(*),FACTOR DOUBLE PRECISION TEMP INTEGER I,J,JF,JA,K,LA LA=IAG(KA+1)-1 DO 6 K=IAG(KA),LA I=ABS(JAG(K)) IF (I.LE.0) GO TO 6 TEMP=FACTOR*GA(I) JF=IH(I) DO 5 JA=K,LA J=ABS(JAG(JA)) IF (J.LE.0) GO TO 5 2 IF (ABS(JH(JF)).LT.J) THEN JF=JF+1 GO TO 2 END IF H(JF)=H(JF)+TEMP*GA(J) 5 CONTINUE 6 CONTINUE RETURN END * SUBROUTINE PCBS04 ALL SYSTEMS 98/12/01 * PURPOSE : * INITIATION OF THE VECTOR CONTAINING TYPES OF CONSTRAINTS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RI EPS9 TOLERANCE FOR ACTIVE CONSTRAINTS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * SUBROUTINE PCBS04(NF,X,IX,XL,XU,EPS9,KBF) INTEGER NF,IX(*),KBF DOUBLE PRECISION X(*),XL(*),XU(*),EPS9 DOUBLE PRECISION TEMP INTEGER I,IXI IF (KBF.GT.0) THEN DO 1 I=1,NF TEMP=1.0D 0 IXI=ABS(IX(I)) IF ((IXI.EQ.1.OR.IXI.EQ.3.OR.IXI.EQ.4).AND.X(I).LE.XL(I)+ & EPS9*MAX(ABS(XL(I)),TEMP)) X(I)=XL(I) IF ((IXI.EQ.2.OR.IXI.EQ.3.OR.IXI.EQ.4).AND.X(I).GE.XU(I)- & EPS9*MAX(ABS(XU(I)),TEMP)) X(I)=XU(I) 1 CONTINUE END IF RETURN END * SUBROUTINE PDSGM1 ALL SYSTEMS 01/09/22 * PURPOSE : * COMPUTATION OF A TRUST-REGION STEP BY THE DOG-LEG METHOD WITH DIRECT * MATRIX DECOMPOSITIONS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II MMAX MAXIMUM DIMENSION OF THE SPARSE TABLEAU. * II MH POINTER OBTAINED BY THE SUBROUTINE MXSPCC. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA H(MMAX) NONZERO ELEMENTS OF THE APPROXIMATION OF THE SPARSE * HESSIAN MATRIX TOGETHER WITH AN ADDITIONAL SPACE USED FOR * THE NUMERICAL DIFFERENTIATION. * II IH(NF+1) POINTERS OF DIAGONAL ELEMENTS OF THE MATRIX H. * IU JH(MMAX) INDICES OF NONZERO ELEMENTS OF THE MATRIX H * TOGETHER WITH AN ADDITIONAL SPACE USED FOR THE NUMERICAL * DIFFERENTIATION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * RA XS(NF) AUXILIARY VECTOR. * II PSL(NF+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * IA PERM(NF) PERMUTATION VECTOR. * IA WN11(NF+1) AUXILIARY VECTOR. * IA WN12(NF+1) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RU XDEL TRUST REGION RADIUS. * RO GNORM NORM OF THE GRADIENT VECTOR. * RO SNORM NORM OF THE DIRECTION VECTOR. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RO P VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP VALUE OF THE QUADRATIC TERM. * RI ETA2 TOLERANCE FOR POSITIVE DEFINITENESS. * RI ALF2 TOLERANCE FOR THE GRADIENT NORM. * II KD ORDER OF COMPUTED DERIVATIVES. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * IU IDEC DECOMPOSITION INDICATOR. IDEC=0-NO DECOMPOSITION. * IU NDEC NUMBER OF MATRIX DECOMPOSITIONS. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F WAS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX WAS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * VALUES ITERM<=-40 DETECT A LACK OF SPACE. * * SUBPROGRAMS USED : * S PNSTEP COMPUTATION OF THE BOUNDARY STEP. * S MXSPCB BACK SUBSTITUTION USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXSPCD COMPUTATION OF A DIRECTION OF NEGATIVE CURVATURE USING * THE SPARSE DECOMPOSITION OBTAINED BY MXSPCF. * S MXSPCF GILL-MURRAY DECOMPOSITION OD A SPARSE SYMMETRIC MATRIX. * S MXSPCM MATRIX-VECTOR PRODUCT USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * RF MXSPCQ GENERALIZED DOT PRODUCT USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXSPCT COPYING A SPARSE SYMMETRIC MATRIX INTO THE PERMUTED * FACTORIZED COMPACT SCHEME. * RF MXSSMQ COMPUTATION OF THE SPARSE QUADRATIC TERM. * S MXUCOP COPYING OF A VECTOR. * S MXUDIF DIFFERENCE OF TWO VECTORS. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVSBP INVERSE PERMUTATION OF A VECTOR * S MXVSCL SCALING OF A VECTOR. * S MXVSET INITIATION OF A VECTOR. * S MXVSFP PERMUTATION OF A VECTOR. * * METHOD : * J.E.DENNIS, H.H.W.MEI: AN UNCONSTRAINED OPTIMIZATION ALGORITHM WHICH * USES FUNCTION AND GRADIENT VALUES. REPORT NO. TR-75-246, DEPT. OF * COMPUTER SCIENCE, CORNELL UNIVERSITY 1975. * SUBROUTINE PDSGM1(NF,MMAX,MH,IX,G,H,IH,JH,S,XO,GO,XS,PSL,PERM, & WN11,WN12,XMAX,XDEL,GNORM,SNORM,FMIN,F,P,PP,ETA2,ALF2,KD,KBF, & IEST,IDEC,NDEC,ITERD,ITERM) INTEGER NF,MMAX,MH,IX(*),IH(*),JH(*),PSL(*),PERM(*),WN11(*), & WN12(*),KD,KBF,IEST,IDEC,NDEC,ITERD,ITERM DOUBLE PRECISION G(*),H(*),S(*),XO(*),GO(*),XS(*),XMAX,XDEL, & GNORM,SNORM,FMIN,F,P,PP,ETA2,ALF2 INTEGER MM,INF,MODE DOUBLE PRECISION B1,B2,B3,D3,S1,S2 DOUBLE PRECISION MXSSMQ,MXSPCQ,MXUDOT SAVE INF * * DIRECTION DETERMINATION * IF (IDEC.LT.0) IDEC=0 IF (IDEC.EQ.0) THEN ELSE IF (IDEC.EQ.1) THEN ELSE ITERD=-1 GO TO 13130 END IF MM=IH(NF+1)-1 B2=MXUDOT(NF,G,G,IX,KBF) GNORM=SQRT(B2) MODE=1 IF (ALF2*GNORM.LE.XDEL) THEN MODE=2 IF (IDEC.EQ.0) THEN CALL MXSPCT(NF,MM,MH,MMAX,H,JH,PSL,ITERM) IF (ITERM.NE.0) GO TO 13130 * * SPARSE GILL-MURRAY DECOMPOSITION * S1=ETA2 CALL MXSPCF(NF,H(MM+1),PSL,JH(MM+1),WN11,WN12,XS,INF,S1,S2) NDEC=NDEC+1 IDEC=1 END IF IF (INF.GT.0) THEN CALL MXSPCD(NF,H(MM+1),PSL,JH(MM+1),S,INF) CALL MXVSBP(NF,PERM,S,XS) * * DIRECTION OF NEGATIVE CURVATURE * SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) IF (SNORM*SNORM*GNORM+S1*XDEL.LE.0.0D 0) THEN CALL MXVSCL(NF,XDEL/SNORM,S,S) SNORM=XDEL ITERD=4 GO TO 13120 END IF ELSE IF (GNORM.LE.0.0D 0) THEN * * ZERO DIRECTION * SNORM=0.0D 0 CALL MXVSET(NF,0.0D 0,S) GO TO 13120 END IF END IF IF (IDEC.EQ.0) THEN B1=MXSSMQ(NF,H,IH,JH,G,G) ELSE CALL MXUCOP(NF,G,GO,IX,KBF) CALL MXVSFP(NF,PERM,GO,XS) CALL MXSPCM(NF,H(MM+1),PSL,JH(MM+1),GO,XS,1) B1=MXSPCQ(NF,H(MM+1),PSL,GO) END IF IF (XDEL.LE.0.0D 0) THEN * * INITIAL TRUST REGION BOUND * IF (B1.LE.0.0D 0) THEN XDEL=GNORM ELSE XDEL=(B2/B1)*GNORM END IF IF (IEST.EQ.1) XDEL=MIN(XDEL,4.0D 0*(F-FMIN)/GNORM) XDEL=MIN(XDEL,XMAX) END IF IF (B1.LE.0.0D 0.OR.B2*GNORM.GE.B1*XDEL) THEN * * SCALED STEEPEST DESCENT DIRECTION IS ACCEPTED * CALL MXVSCL(NF,-XDEL/GNORM,G,S) SNORM=XDEL ITERD=3 GO TO 13120 END IF IF (IDEC.EQ.0) THEN CALL MXSPCT(NF,MM,MH,MMAX,H,JH,PSL,ITERM) IF (ITERM.NE.0) THEN GO TO 13130 END IF * * SPARSE GILL-MURRAY DECOMPOSITION * S1=ETA2 CALL MXSPCF(NF,H(MM+1),PSL,JH(MM+1),WN11,WN12,XS,INF,S1,S2) NDEC=NDEC+1 IDEC=1 END IF * * COMPUTATION OF THE NEWTON DIRECTION * CALL MXUCOP(NF,G,GO,IX,KBF) CALL MXVSFP(NF,PERM,GO,XS) CALL MXSPCB(NF,H(MM+1),PSL,JH(MM+1),GO,0) CALL MXVSBP(NF,PERM,GO,XS) D3=SQRT(MXUDOT(NF,GO,GO,IX,KBF)) * * COMPUTATION OF THE STEEPEST DESCENT DIRECTION * B2=B2/B1 SNORM=B2*GNORM CALL MXVSCL(NF,-B2,G,S) CALL MXUNEG(NF,GO,GO,IX,KBF) CALL MXUDIF(NF,GO,S,XO,IX,KBF) B1=MXUDOT(NF,S,XO,IX,KBF) B2=MXUDOT(NF,XO,XO,IX,KBF) IF (B2.LE.1.0D-8*XDEL*XDEL) THEN * * NEWTON AND THE STEEPEST DESCENT DIRECTION ARE * APPROXIMATELY EQUAL * CALL MXUCOP(NF,GO,S,IX,KBF) SNORM=D3 ITERD=1 ELSE IF (B1.LE.0.0D 0) THEN * * BOUNDARY STEP WITH NEGATIVE INCREMENT * CALL PNSTEP(XDEL,SNORM,-B1,B2,B3) CALL MXUDIR(NF,-B3,XO,S,S,IX,KBF) SNORM=XDEL ITERD=3 ELSE IF (D3.LE.XDEL) THEN * * NEWTON DIRECTION IS ACCEPTED * CALL MXUCOP(NF,GO,S,IX,KBF) SNORM=D3 ITERD=1 ELSE * * DOUBLE DOGLEG STRATEGY * D3=XDEL/D3 B3=MXUDOT(NF,S,GO,IX,KBF) D3=MAX(D3,SNORM*SNORM/B3) CALL MXUDIR(NF,-D3,GO,S,XO,IX,KBF) B1=SNORM*SNORM-D3*B3 B2=MXUDOT(NF,XO,XO,IX,KBF) CALL PNSTEP(XDEL,SNORM,-B1,B2,B3) CALL MXUDIR(NF,-B3,XO,S,S,IX,KBF) SNORM=XDEL ITERD=3 END IF 13120 CONTINUE IF (IDEC.EQ.0) THEN PP=MXSSMQ(NF,H,IH,JH,S,S)*0.5D 0 ELSE CALL MXUCOP(NF,S,GO,IX,KBF) CALL MXVSFP(NF,PERM,GO,XS) CALL MXSPCM(NF,H(MM+1),PSL,JH(MM+1),GO,XS,1) PP=MXSPCQ(NF,H(MM+1),PSL,GO)*0.5D 0 IF (ITERD.EQ.1.AND.INF.NE.0) ITERD=2 END IF 13130 CONTINUE IF (KD.GT.0) P=MXUDOT(NF,G,S,IX,KBF) RETURN END * SUBROUTINE PDSGM4 ALL SYSTEMS 01/09/22 * PURPOSE : * COMPUTATION OF A TRUST-REGION STEP BY THE SHIFTED STEIHAUG-TOINT * METHOD WITH CONJUGATE GRADIENT ITERATIONS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II MMAX MAXIMUM DIMENSION OF THE SPARSE TABLEAU. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA H(MMAX) NONZERO ELEMENTS OF THE APPROXIMATION OF THE SPARSE * HESSIAN MATRIX TOGETHER WITH AN ADDITIONAL SPACE USED FOR * THE NUMERICAL DIFFERENTIATION. * II IH(NF+1) POINTERS OF DIAGONAL ELEMENTS OF THE MATRIX H. * IU JH(MMAX) INDICES OF NONZERO ELEMENTS OF THE MATRIX H * TOGETHER WITH AN ADDITIONAL SPACE USED FOR THE NUMERICAL * DIFFERENTIATION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * RA XS(NF) AUXILIARY VECTOR. * RA GS(NF) AUXILIARY VECTOR. * IA IW(NF+1) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RU XDEL TRUST REGION RADIUS. * RO GNORM NORM OF THE GRADIENT VECTOR. * RO GNORMO OLD NORM OF THE GRADIENT VECTOR. * RO SNORM NORM OF THE DIRECTION VECTOR. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RO P VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP VALUE OF THE QUADRATIC TERM. * RI ETA0 MACHINE PRECISION. * RI ETA2 TOLERANCE FOR POSITIVE DEFINITENESS. * RI DEL1 LOWER TOLERANCE FOR THE TRUST-REGION RADIUS. * II KD ORDER OF COMPUTED DERIVATIVES. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II MOS1 NUMBER OF LANCZOS STEPS IN THE SHIFTED STEIHAUG-TOINT * METHOD. * II MOS2 TYPE OF PRECONDITIONING. MOS2=1-PRECONDITIONING IS NOT * USED. MOS2=2-PRECONDITIONING BY THE INCOMPLETE GILL-MURRAY * DECOMPOSITION. MOS2=3-PRECONDITIONING BY THE INCOMPLETE * GILL-MURRAY DECOMPOSITION WITH A PRELIMINARY SOLUTION OF * THE PRECONDITIONED SYSTEM WHICH IS USED IF IT SATISFIES * THE TERMINATION CRITERION. * II MOS3 PRECONDITIONING IN ILL-CONTITIONED AND INDEFINITE CASES. * MOS3=0-PRECONDITIONING IN BOTH THESE CASES IS SUPPRESSED. * MOS3=1-PRECONDITIONING IN ILL-CONDITIONED CASE IS SUPPRESSED. * MOS3=2-PRECONDITIONING IS ALWAYS USED. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * IU IDEC DECOMPOSITION INDICATOR. IDEC=0-NO DECOMPOSITION. * IU NDEC NUMBER OF MATRIX DECOMPOSITIONS. * II NIT NUMBER OF OUTER ITERATIONS. * IU NIN NUMBER OF INNER CONJUGATE GRADIENT ITERATIONS. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F WAS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX WAS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * VALUES ITERM<=-40 DETECT A LACK OF SPACE. * * SUBPROGRAMS USED : * S PNSTEP COMPUTATION OF THE BOUNDARY STEP. * S MXSPTB BACK SUBSTITUTION AFTER THE GILL-MURRAY DECOMPOSITION. * S MXSPTF INCOMPLETE GILL-MURRAY DECOMPOSITION. * S MXSSDA SPARSE SYMMETRIC MATRIX IS AUGMENTED BY THE SCALED UNIT * MATRIX. * S MXSSMD MATRIX-VECTOR PRODUCT FOLLOWED BY THE ADDITION OF A * SCALED VECTOR. * S MXSSMM MATRIX-VECTOR PRODUCT. * RF MXSSMQ COMPUTATION OF THE SPARSE QUADRATIC TERM. * S MXTPGB BACK SUBSTITUTION FOR A DECOMPOSED TRIDIAGONAL MATRIX. * S MXTPGF CHOLESKI DECOMPOSITION OF A TRIDIAGONAL MATRIX. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDEL NORM OF VECTOR DIFFERENCE. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * RF MXUNOR EUCLIDEAN NORM OF A VECTOR. * S MXVCOP COPYING OF A VECTOR. * S MXVCOR CORRECTION OF A VECTOR (ZERO ELEMENTS ARE REPLACED BY * THE NONZERO NUMBER). * RF MXVDOT DOT PRODUCT OF TWO VECTORS. * S MXVNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVSCL SCALING OF A VECTOR. * S MXVSET INITIATION OF A VECTOR. * S MXVSUM SUM OF TWO VECTORS. * RF MXVVDP GENERALIZED DOT PRODUCT. * * METHOD : * L.LUKSAN, C.MATONOHA, J.VLCEK: A SHIFTED STEIHAUG-TOINT METHOD FOR * COMPUTING TRUST-REGION STEP. REPORT NO. V-914, INST. OF COMPUTER * SCIENCE, CZECH ACADEMY OF SCIENCES, 2004. * SUBROUTINE PDSGM4(NF,MMAX,IX,G,H,IH,JH,S,XO,GO,XS,GS,IW,XMAX, & XDEL,GNORM,GNORMO,SNORM,FMIN,F,P,PP,ETA0,ETA2,DEL1,KD,KBF, & MOS1,MOS2,MOS3,IEST,IDEC,NDEC,NIT,NIN,ITERD,ITERM) INTEGER NF,MMAX,IX(*),IH(*),JH(*),IW(*),KD,KBF,MOS1,MOS2,MOS3, & IEST,IDEC,NDEC,NIT,NIN,ITERD,ITERM DOUBLE PRECISION G(*),H(*),S(*),XO(*),GO(*),XS(*),GS(*),XMAX, & XDEL,GNORM,GNORMO,SNORM,FMIN,F,P,PP,ETA0,ETA2,DEL1 INTEGER NOS1,NOS2,NRED,I,M,INF DOUBLE PRECISION T,EL,EU,PAR,ALF,EPS,RHO,RHO1,RHO2,SIG,TAU DOUBLE PRECISION MXSSMQ,MXUDOT,MXUDEL,MXUNOR,MXVDOT,MXVVDP SAVE EPS * * DIRECTION DETERMINATION * IF (NIT.LE.1) THEN EPS=0.9D 0 GNORMO=1.0D 60 END IF IF (IDEC.LT.0) IDEC=0 IF (IDEC.NE.0.AND.IDEC.NE.1) THEN ITERD=-1 GO TO 13180 END IF GNORM=SQRT(MXUDOT(NF,G,G,IX,KBF)) IF (GNORM.GE.1.0D 3*GNORMO) EPS=1.0D-6 GNORMO=GNORM RHO1=MXUDOT(NF,G,G,IX,KBF) IF (XDEL.LE.0.0D 0) THEN * * INITIAL TRUST REGION BOUND * RHO2=MXSSMQ(NF,H,IH,JH,G,G) IF (RHO2.LE.0.0D 0) THEN XDEL=GNORM ELSE XDEL=(GNORM*GNORM/RHO2)*GNORM END IF IF (IEST.EQ.1) XDEL=MIN(XDEL,4.0D 0*(F-FMIN)/GNORM) XDEL=MIN(XDEL,XMAX) END IF PAR=MIN(EPS,SQRT(GNORM)) IF (PAR.GT.1.0D-2) THEN PAR=MIN(PAR,1.0D 0/DBLE(NIT)) END IF PAR=PAR*PAR NOS1=MIN(NF,MOS1) IF (NOS1.LE.1) THEN T=0.0D 0 ELSE * * INCOMPLETE LANCZOS TRIDIAGONALIZATION * INF=0 CALL MXVCOP(NF,G,XS) CALL MXVSET(NF,0.0D 0,GS) CALL MXVSCL(NF,1.0D 0/MXUNOR(NF,XS,IX,KBF),XS,XS) DO 13111 NRED=1,NOS1 IF (NRED.GT.1) THEN DO 13112 I=1,NF EL=XS(I) XS(I)=GS(I)/EU GS(I)=-EU*EL 13112 CONTINUE END IF CALL MXSSMD(NF,H,IH,JH,XS,1.0D 0,GS,GS) EL=MXUDOT(NF,XS,GS,IX,KBF) CALL MXUDIR(NF,-EL,XS,GS,GS,IX,KBF) EU=MXUNOR(NF,GS,IX,KBF) IF (EU.LE.0.0D 0) THEN INF=NRED GO TO 13116 END IF XO(NRED)=EL GO(NRED)=EU 13111 CONTINUE 13116 CONTINUE CALL MXVCOR(NOS1,ETA0,XO) T=0.0D 0 RHO2=DEL1*XDEL DO 13117 NRED=1,10 T=MIN(T,1.0D 5) IF (T.GE.1.0D 5) GO TO 13118 * * SOLUTION OF THE TRIDIAGONAL SYSTEM * ALF=ETA0 CALL MXVSET(NOS1,T,XS) CALL MXVSUM(NOS1,XO,XS,XS) CALL MXVCOP(NOS1,GO,GS) CALL MXTPGF(NOS1,XS,GS,INF,ALF,TAU) CALL MXVSET(NOS1,0.0D 0,S) S(1)=GNORM CALL MXTPGB(NOS1,XS,GS,S,0) RHO=MXVDOT(NOS1,S,S) IF (RHO.LE.XDEL**2) GO TO 13118 CALL MXTPGB(NOS1,XS,GS,S,1) * * MARQUARDT PARAMETER T IS COMPUTED USING THE ONE-DIMENSIONAL * NEWTON METHOD * T=T+(RHO/MXVVDP(NOS1,XS,S,S))*((SQRT(RHO)-RHO2)/RHO2) 13117 CONTINUE END IF 13118 CONTINUE CALL MXVNEG(NF,G,XO) NOS2=MOS2-1 IF (NOS2.GT.0) THEN * * INCOMPLETE GILL-MURRAY DECOMPOSITION * ALF=ETA2 M=IH(NF+1)-1 IF (2*M.GE.MMAX) THEN ITERM=-48 GO TO 13180 END IF CALL MXVCOP(M,H,H(M+1)) IF (T.GT.0.0D 0) CALL MXSSDA(NF,H(M+1),IH,T) CALL MXSPTF(NF,H(M+1),IH,JH,IW,INF,ALF,SIG) IF (INF+10.LT.0) THEN ITERM=-48 GO TO 13180 END IF IF (MOS3.EQ.0) THEN IF (INF.NE.0) NOS2=0 ELSE IF (MOS3.EQ.1) THEN IF (INF.LT.0) NOS2=0 END IF NDEC=NDEC+1 IDEC=1 IF (NOS2.GT.1) THEN * * PRELIMINARY INEXACT SOLUTION * CALL MXSPTB(NF,H(M+1),IH,JH,XO,0) SNORM=SQRT(MXUDOT(NF,XO,XO,IX,KBF)) IF (SNORM.LE.XDEL*1.0D 5) THEN CALL MXVCOP(NF,XO,S) IF (SNORM.LE.XDEL) THEN ITERD=2 ELSE CALL MXVSCL(NF,XDEL/SNORM,S,S) SNORM=XDEL ITERD=3 END IF CALL MXSSMD(NF,H,IH,JH,S,1.0D 0,G,GO) IF (MXUDOT(NF,GO,GO,IX,KBF).LE.1.0D-2*PAR*RHO1) GO TO 13180 END IF END IF END IF * * CG INITIATION * RHO=RHO1 SNORM=0.0D 0 CALL MXVSET(NF,0.0D 0,S) CALL MXVNEG(NF,G,XS) IF (NOS2.EQ.0) THEN ELSE IF (NOS2.EQ.1) THEN CALL MXSPTB(NF,H(M+1),IH,JH,XO,0) RHO=MXUDOT(NF,XS,XO,IX,KBF) ELSE RHO=MXUDOT(NF,XS,XO,IX,KBF) END IF DO 13120 NRED=1,NF+3 IF (T.GT.0.0D 0) THEN CALL MXSSMD(NF,H,IH,JH,XO,T,XO,GO) ELSE CALL MXSSMM(NF,H,IH,JH,XO,GO) END IF ALF=MXUDOT(NF,XO,GO,IX,KBF) IF (ALF.LE.0.0D 0) GO TO 13160 ALF=RHO/ALF RHO2=SQRT(MXUDEL(NF,ALF,XO,S,IX,KBF)) IF (RHO2.GE.XDEL) GO TO 13160 * * CG STEP * CALL MXUDIR(NF, ALF,XO,S,S,IX,KBF) CALL MXUDIR(NF,-ALF,GO,XS,XS,IX,KBF) NIN=NIN+1 SNORM=RHO2 RHO2=MXUDOT(NF,XS,XS,IX,KBF) IF (RHO2.LE.PAR*RHO1) GO TO 13150 IF (NRED.GE.NF+3) GO TO 13150 IF (NOS2.NE.0) THEN CALL MXVCOP(NF,XS,GO) CALL MXSPTB(NF,H(M+1),IH,JH,GO,0) RHO2=MXUDOT(NF,XS,GO,IX,KBF) ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XO,GO,XO,IX,KBF) ELSE ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XO,XS,XO,IX,KBF) END IF RHO=RHO2 13120 CONTINUE * * AN INEXACT SOLUTION IS OBTAINED * 13150 CONTINUE SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) ITERD=2 GO TO 13180 * * BOUNDARY STEP IS COMPUTED * 13160 CONTINUE RHO1=MXUDOT(NF,XO,S,IX,KBF) RHO2=MXUDOT(NF,XO,XO,IX,KBF) CALL PNSTEP(XDEL,SNORM,RHO1,RHO2,ALF) CALL MXUDIR(NF,ALF,XO,S,S,IX,KBF) SNORM=XDEL ITERD=3 NRED=-NRED 13180 CONTINUE PP=MXSSMQ(NF,H,IH,JH,S,S)*0.5D 0 IF (KD.GT.0) P=MXUDOT(NF,G,S,IX,KBF) RETURN END * SUBROUTINE PDSGM7 ALL SYSTEMS 01/09/22 * PURPOSE : * COMPUTATION OF A TRUST-REGION STEP BY THE MORE-SORENSEN METHOD WITH * DIRECT MATRIX DECOMPOSITIONS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II MMAX MAXIMUM DIMENSION OF THE SPARSE TABLEAU. * II MH POINTER OBTAINED BY THE SUBROUTINE MXSPCC. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA H(MMAX) NONZERO ELEMENTS OF THE APPROXIMATION OF THE SPARSE * HESSIAN MATRIX TOGETHER WITH AN ADDITIONAL SPACE USED FOR * THE NUMERICAL DIFFERENTIATION. * II IH(NF+1) POINTERS OF DIAGONAL ELEMENTS OF THE MATRIX H. * IU JH(MMAX) INDICES OF NONZERO ELEMENTS OF THE MATRIX H * TOGETHER WITH AN ADDITIONAL SPACE USED FOR THE NUMERICAL * DIFFERENTIATION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * II PSL(NF+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * IA PERM(NF) PERMUTATION VECTOR. * IA WN11(NF+1) AUXILIARY VECTOR. * IA WN12(NF+1) AUXILIARY VECTOR. * RI XMAX MAXIMUM STEPSIZE. * RI XDEL TRUST REGION RADIUS. * RO XDELO OLD TRUST REGION RADIUS. * RO GNORM NORM OF THE GRADIENT VECTOR. * RO SNORM NORM OF THE DIRECTION VECTOR. * RI FMIN ESTIMATION OF THE MINIMUM FUNCTION VALUE. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RO P VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP VALUE OF THE QUADRATIC TERM. * RI ETA2 TOLERANCE FOR POSITIVE DEFINITENESS. * RI DEL1 LOWER TOLERANCE FOR THE TRUST-REGION RADIUS. * RI DEL2 UPPER TOLERANCE FOR THE TRUST-REGION RADIUS. * II KD ORDER OF COMPUTED DERIVATIVES. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II IEST ESTIMATION INDICATOR. IEST=0-MINIMUM IS NOT ESTIMATED. * IEST=1-MINIMUM IS ESTIMATED BY THE VALUE FMIN. * II IDIR TRUST-REGION CHANGE INDICATOR. * IU IDEC DECOMPOSITION INDICATOR. IDEC=0-NO DECOMPOSITION. * IU NDEC NUMBER OF MATRIX DECOMPOSITIONS. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F WAS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX WAS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * VALUES ITERM<=-40 DETECT A LACK OF SPACE. * * SUBPROGRAMS USED : * S PNSTEP COMPUTATION OF THE BOUNDARY STEP. * S MXSPCA ADDITION OF THE LEVENBERG-MARQUARDT TERM TO THE SPARSE * SYMMETRIC MATRIX. * S MXSPCB BACK SUBSTITUTION USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXSPCD COMPUTATION OF A DIRECTION OF NEGATIVE CURVATURE USING * THE SPARSE DECOMPOSITION OBTAINED BY MXSPCF. * S MXSPCF GILL-MURRAY DECOMPOSITION OD A SPARSE SYMMETRIC MATRIX. * S MXSPCN ESTIMATION OF THE MINIMUM EIGENVALUE AND THE * CORRESPONDING EIGENVECTOR OF A SYMMETRIC MATRIX USING THE * SPARSE DECOMPOSITION OBTAINED BY MXSPCF. * RF MXSPCP GENERALIZED DOT PRODUCT USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXSPCT COPYING A SPARSE SYMMETRIC MATRIX INTO THE PERMUTED * FACTORIZED COMPACT SCHEME. * RF MXSSDL DETERMINATION OF A MINIMUM DIAGONAL ELEMENT OF A SPARSE * SYMMETRIC MATRIX. * S MXSSMG GERSHGORIN BOUNDS FOR EIGENVALUES OF A SPARSE SYMMETRIC * MATRIX * RF MXSSMQ COMPUTATION OF THE SPARSE QUADRATIC TERM. * S MXUCOP COPYING OF A VECTOR. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVSBP INVERSE PERMUTATION OF A VECTOR * S MXVSFP PERMUTATION OF A VECTOR. * * METHOD : * J.J.MORE, D.C.SORENSEN: COMPUTING A TRUST REGION STEP. REPORT NO. * ANL-81-83, ARGONNE NATIONAL LAB. 1981. * SUBROUTINE PDSGM7(NF,MMAX,MH,IX,G,H,IH,JH,S,XO,GO,PSL,PERM,WN11, & WN12,XMAX,XDEL,XDELO,GNORM,SNORM,FMIN,F,P,PP,ETA2,DEL1,DEL2,KD, & KBF,IEST,IDIR,IDEC,NDEC,ITERD,ITERM) INTEGER NF,MMAX,MH,IX(*),IH(*),JH(*),PSL(*),PERM(*),WN11(*), & WN12(*),KD,KBF,IEST,IDIR,IDEC,NDEC,ITERD,ITERM DOUBLE PRECISION G(*),H(*),S(*),XO(*),GO(*),XMAX,XDEL,XDELO, & GNORM,SNORM,FMIN,F,P,PP,ETA2,DEL1,DEL2 INTEGER NRED,MM,INF,MODE DOUBLE PRECISION T,TL,TU,E,EL,EU,ALF,RHO,RHO1,RHO2,CON DOUBLE PRECISION MXSSMQ,MXSPCP,MXSSDL,MXUDOT SAVE T,TL,TU,E,EL,EU * * DIRECTION DETERMINATION * IF (IDEC.LT.0) IDEC=0 IF (IDEC.NE.0) THEN ITERD=-1 GO TO 13250 END IF MM=IH(NF+1)-1 GNORM=SQRT(MXUDOT(NF,G,G,IX,KBF)) IF (XDEL.LE.0.0D 0) THEN * * INITIAL TRUST REGION BOUND * RHO1=MXSSMQ(NF,H,IH,JH,G,G) RHO2=GNORM*GNORM IF (RHO1.LE.0.0D 0) THEN XDEL=GNORM ELSE XDEL=(RHO2/RHO1)*GNORM END IF IF (IEST.EQ.1) XDEL=MIN(XDEL,4.0D 0*(F-FMIN)/GNORM) XDEL=MIN(XDEL,XMAX) END IF * * INITIAL BOUNDS FOR THE PARAMETER T * NRED=0 IF (IDIR.LE.0) THEN T=0.0D 0 E=-MXSSDL(NF,H,IH,JH,INF) CALL MXSSMG(NF,H,IH,JH,EL,EU,S) TL=GNORM/XDEL-EU TU=GNORM/XDEL-EL ELSE IF (IDIR.EQ.1) THEN T=T*XDELO/XDEL TL=MAX(TL,GNORM/XDEL-EU) TU=GNORM/XDEL-EL ELSE IF (IDIR.EQ.2) THEN T=T*XDELO/XDEL TL=GNORM/XDEL-EU TU=MIN(TU,GNORM/XDEL-EL) END IF TL=MAX(TL,0.0D 0,E) TU=MAX(TL,TU) T=MAX(T,TL) T=MIN(T,TU) 13220 CONTINUE TL=MAX(TL,E) IF (T.LE.E.AND.NRED.NE.0) THEN * * THE PARAMETER T IS SHIFTED * T=SQRT(TL*TU) T=MAX(T,TL+0.1D 0*(TU-TL)) T=MIN(T,TL+0.9D 0*(TU-TL)) END IF ALF=ETA2 CALL MXSPCT(NF,MM,MH,MMAX,H,JH,PSL,ITERM) IF (ITERM.NE.0) THEN GO TO 13250 END IF * * SPARSE GILL-MURRAY DECOMPOSITION * CALL MXSPCA(NF,MM,MH,H,IH,JH,T) CALL MXSPCF(NF,H(MM+1),PSL,JH(MM+1),WN11,WN12,GO,INF,ALF,RHO) NDEC=NDEC+1 IF (INF.GT.0) THEN * * NEW ESTIMATION E IS COMPUTED (THE MATRIX IS NOT POSITIVE DEFINITE) * IF (E.GE.TU) THEN ITERD=-2 GO TO 13250 ELSE MODE=2 CALL MXSPCD(NF,H(MM+1),PSL,JH(MM+1),S,INF) CALL MXVSBP(NF,PERM,S,GO) E=MAX(E,T-ALF/MXUDOT(NF,S,S,IX,KBF)) NRED=NRED+1 GO TO 13220 END IF ELSE * * STEP S IS COMPUTED * CALL MXUNEG(NF,G,S,IX,KBF) CALL MXVSFP(NF,PERM,S,GO) CALL MXSPCB(NF,H(MM+1),PSL,JH(MM+1),S,0) CALL MXVSBP(NF,PERM,S,GO) SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) MODE=1 END IF IF (TU-TL.LE.1.0D-8) THEN * * INTERVAL IS TOO SMALL * IF (T.NE.0.0D 0) THEN ITERD=5 ELSE ITERD=1 END IF GO TO 13240 ELSE IF (NRED.GE.20) THEN * * MAXIMUM NUMBER OF OLC REDUCTIONS * ITERD=6 GO TO 13240 ELSE IF (SNORM.GT.DEL2*XDEL) THEN * * STEP IS TOO LARGE * TL=MAX(TL,T) GO TO 13230 ELSE IF (SNORM.LT.DEL1*XDEL) THEN IF (T.NE.0.0D 0) THEN * * STEP IS TOO SMAL * TU=MIN(TU,T) ELSE * * STEP IS ACCEPTABLE * ITERD=1 GO TO 13240 END IF ELSE ITERD=3 GO TO 13240 END IF * * TRYING TO USE BOUNDARY STEP * CALL MXSPCN(NF,H(MM+1),PSL,JH(MM+1),XO,RHO,1) CALL MXVSBP(NF,PERM,XO,GO) RHO1=MXUDOT(NF,XO,S,IX,KBF) RHO2=MXUDOT(NF,XO,XO,IX,KBF) CALL PNSTEP(XDEL,SNORM,ABS(RHO1),RHO2,ALF) CON=(1.0D 0-DEL1)*(1.0D 0+DEL1) IF (ALF*ALF*RHO.LE.CON*(T*XDEL*XDEL-MXUDOT(NF,G,S,IX,KBF))) THEN IF (RHO1.LT.0.0D 0) ALF=-ALF CALL MXUDIR(NF,ALF,XO,S,S,IX,KBF) SNORM=XDEL ITERD=3 GO TO 13240 ELSE E=MAX(E,T-RHO) END IF 13230 CONTINUE IF (GNORM.LE.0.0D 0) THEN T=E ELSE * * NEW T IS COMPUTED USING ONE STEP OF THE NEWTON METHOD FOR * NONLINEAR EQUATION * CALL MXUCOP(NF,S,XO,IX,KBF) CALL MXVSFP(NF,PERM,XO,GO) CALL MXSPCB(NF,H(MM+1),PSL,JH(MM+1),XO,1) T=T+(SNORM*SNORM/MXSPCP(NF,H(MM+1),PSL,XO))*(SNORM-XDEL)/XDEL CALL MXVSBP(NF,PERM,XO,GO) END IF NRED=NRED+1 GO TO 13220 13240 CONTINUE PP=MXSSMQ(NF,H,IH,JH,S,S)*0.5D 0 13250 CONTINUE IF (KD.GT.0) P=MXUDOT(NF,G,S,IX,KBF) RETURN END * SUBROUTINE PDSLM1 ALL SYSTEMS 01/09/22 * PURPOSE : * DIRECTION DETERMINATION FOR LINE SEARCH USING DIRECT MATRIX * DECOMPOSITIONS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II MMAX MAXIMUM DIMENSION OF THE SPARSE TABLEAU. * II MH POINTER OBTAINED BY THE SUBROUTINE MXSPCC. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA H(MMAX) NONZERO ELEMENTS OF THE APPROXIMATION OF THE SPARSE * HESSIAN MATRIX TOGETHER WITH AN ADDITIONAL SPACE USED FOR * THE NUMERICAL DIFFERENTIATION. * II IH(NF+1) POINTERS OF DIAGONAL ELEMENTS OF THE MATRIX H. * IU JH(MMAX) INDICES OF NONZERO ELEMENTS OF THE MATRIX H * TOGETHER WITH AN ADDITIONAL SPACE USED FOR THE NUMERICAL * DIFFERENTIATION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * II PSL(NF+1) POINTER VECTOR OF THE COMPACT FORM OF THE TRIANGULAR * FACTOR OF THE HESSIAN APPROXIMATION. * IA PERM(NF) PERMUTATION VECTOR. * IA WN11(NF+1) AUXILIARY VECTOR. * IA WN12(NF+1) AUXILIARY VECTOR. * RO GNORM NORM OF THE GRADIENT VECTOR. * RO SNORM NORM OF THE DIRECTION VECTOR. * RI ETA2 TOLERANCE FOR POSITIVE DEFINITENESS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * IU IDEC DECOMPOSITION INDICATOR. IDEC=0-NO DECOMPOSITION. * IU NDEC NUMBER OF MATRIX DECOMPOSITIONS. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F WAS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX WAS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * VALUES ITERM<=-40 DETECT A LACK OF SPACE. * * SUBPROGRAMS USED : * S MXSPCB BACK SUBSTITUTION USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXSPCF GILL-MURRAY DECOMPOSITION OD A SPARSE SYMMETRIC MATRIX. * S MXSPCT COPYING A SPARSE SYMMETRIC MATRIX INTO THE PERMUTED * FACTORIZED COMPACT SCHEME. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXUNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVSBP INVERSE PERMUTATION OF A VECTOR * S MXVSFP PERMUTATION OF A VECTOR. * SUBROUTINE PDSLM1(NF,MMAX,MH,IX,G,H,IH,JH,S,XO,PSL,PERM,WN11, & WN12,GNORM,SNORM,ETA2,KBF,IDEC,NDEC,ITERD,ITERM) INTEGER NF,MMAX,MH,IX(*),IH(*),JH(*),PSL(*),PERM(*),WN11(*), & WN12(*),KBF,IDEC,NDEC,ITERD,ITERM DOUBLE PRECISION G(*),H(*),S(*),XO(*),GNORM,SNORM,ETA2 INTEGER MM,INF DOUBLE PRECISION ALF,BET DOUBLE PRECISION MXUDOT * * DIRECTION DETERMINATION * IF (IDEC.LT.0) IDEC=0 MM=IH(NF+1)-1 IF (IDEC.EQ.0) THEN CALL MXSPCT(NF,MM,MH,MMAX,H,JH,PSL,ITERM) IF (ITERM.NE.0) RETURN * * SPARSE GILL-MURRAY DECOMPOSITION * ALF=ETA2 CALL MXSPCF(NF,H(MM+1),PSL,JH(MM+1),WN11,WN12,XO,INF,ALF,BET) NDEC=NDEC+1 IDEC=1 ELSE IF (IDEC.EQ.1) THEN ELSE ITERD=-1 RETURN END IF GNORM=SQRT(MXUDOT(NF,G,G,IX,KBF)) * * NEWTON LIKE STEP * CALL MXUNEG(NF,G,S,IX,KBF) CALL MXVSFP(NF,PERM,S,XO) CALL MXSPCB(NF,H(MM+1),PSL,JH(MM+1),S,0) CALL MXVSBP(NF,PERM,S,XO) ITERD=1 SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) RETURN END * SUBROUTINE PDSLM3 ALL SYSTEMS 01/09/22 * PURPOSE : * DIRECTION DETERMINATION FOR LINE SEARCH USING CONJUGATE GRADIENT * ITERATIONS. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II M NUMBER OF NONZERO ELEMENTS IN THE HESSIAN MATRIX. * II MMAX MAXIMUM DIMENSION OF THE SPARSE TABLEAU. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. IX(I)=0-VARIABLE * X(I) IS UNBOUNDED. IX(I)=1-LOWER BOUND XL(I).LE.X(I). * IX(I)=2-UPPER BOUND X(I).LE.XU(I). IX(I)=3-TWO SIDE BOUND * XL(I).LE.X(I).LE.XU(I). IX(I)=5-VARIABLE X(I) IS FIXED. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA H(MMAX) NONZERO ELEMENTS OF THE APPROXIMATION OF THE SPARSE * HESSIAN MATRIX TOGETHER WITH AN ADDITIONAL SPACE USED FOR * THE NUMERICAL DIFFERENTIATION. * II IH(NF+1) POINTERS OF DIAGONAL ELEMENTS OF THE MATRIX H. * IU JH(MMAX) INDICES OF NONZERO ELEMENTS OF THE MATRIX H * TOGETHER WITH AN ADDITIONAL SPACE USED FOR THE NUMERICAL * DIFFERENTIATION. * RO S(NF) DIRECTION VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * RA XS(NF) AUXILIARY VECTOR. * RA IW(NF+1) AUXILIARY VECTOR. * RO GNORM NORM OF THE GRADIENT VECTOR. * RO SNORM NORM OF THE DIRECTION VECTOR. * RI ETA2 TOLERANCE FOR POSITIVE DEFINITENESS. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II MOS2 TYPE OF PRECONDITIONING. MOS2=1-PRECONDITIONING IS NOT * USED. MOS2=2-PRECONDITIONING BY THE INCOMPLETE GILL-MURRAY * DECOMPOSITION. MOS2=3-PRECONDITIONING BY THE INCOMPLETE * GILL-MURRAY DECOMPOSITION WITH A PRELIMINARY SOLUTION OF * THE PRECONDITIONED SYSTEM WHICH IS USED IF IT SATISFIES * THE TERMINATION CRITERION. * IU IDEC DECOMPOSITION INDICATOR. IDEC=0-NO DECOMPOSITION. * IU NDEC NUMBER OF MATRIX DECOMPOSITIONS. * II NIT NUMBER OF OUTER ITERATIONS. * IU NIN NUMBER OF INNER CONJUGATE GRADIENT ITERATIONS. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERM VARIABLE THAT INDICATES THE CAUSE OF TERMINATION. * ITERM=1-IF ABS(X-XO) WAS LESS THAN OR EQUAL TO TOLX IN * MTESX (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=2-IF ABS(F-FO) WAS LESS THAN OR EQUAL TO TOLF IN * MTESF (USUALLY TWO) SUBSEQUENT ITERATIONS. * ITERM=3-IF F WAS LESS THAN OR EQUAL TO TOLB. * ITERM=4-IF GMAX WAS LESS THAN OR EQUAL TO TOLG. * ITERM=6-IF THE TERMINATION CRITERION WAS NOT SATISFIED, * BUT THE SOLUTION OBTAINED IS PROBABLY ACCEPTABLE. * ITERM=11-IF NIT EXCEEDED MIT. ITERM=12-IF NFV EXCEEDED MFV. * ITERM=13-IF NFG EXCEEDED MFG. ITERM<0-IF THE METHOD FAILED. * VALUES ITERM<=-40 DETECT A LACK OF SPACE. * * SUBPROGRAMS USED : * S MXSPTB BACK SUBSTITUTION AFTER THE GILL-MURRAY DECOMPOSITION. * S MXSPTF INCOMPLETE GILL-MURRAY DECOMPOSITION. * S MXSSMD MATRIX-VECTOR PRODUCT FOLLOWED BY THE ADDITION OF A * SCALED VECTOR. * S MXSSMM MATRIX-VECTOR PRODUCT. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF TWO VECTORS. * S MXVCOP COPYING OF A VECTOR. * S MXVNEG COPYING OF A VECTOR WITH CHANGE OF THE SIGN. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PDSLM3(NF,M,MMAX,IX,G,H,IH,JH,S,XO,GO,XS,IW,GNORM, & SNORM,ETA2,ETA9,KBF,MOS2,IDEC,NDEC,NIT,NIN,ITERD,ITERM) INTEGER NF,M,MMAX,IX(*),IH(*),JH(*),IW(*),KBF,MOS2,IDEC,NDEC, & NIT,NIN,ITERD,ITERM DOUBLE PRECISION G(*),H(*),S(*),XO(*),GO(*),XS(*),GNORM,SNORM, & ETA2,ETA9 INTEGER NOS2,NRED,MMX,INF DOUBLE PRECISION PAR,ALF,EPS,RHO,RHO1,RHO2,SIG DOUBLE PRECISION MXUDOT SAVE EPS * * DIRECTION DETERMINATION * IF (NIT.LE.1) THEN EPS=0.9D 0 END IF NOS2=MOS2-1 IF (IDEC.LT.0) IDEC=0 IF (IDEC.NE.0.AND.IDEC.NE.1) THEN ITERD=-1 RETURN ELSE IF (IDEC.EQ.0) THEN IF (MOS2.GT.1) THEN * * INCOMPLETE GILL-MURRAY DECOMPOSITION * ALF=ETA2 IF (2*M.GE.MMAX) THEN ITERM=-48 RETURN END IF CALL MXVCOP(M,H,H(M+1)) CALL MXSPTF(NF,H(M+1),IH,JH,IW,INF,ALF,SIG) IF (INF+10.LT.0) THEN ITERM=-48 RETURN END IF IF (INF.NE.0) NOS2=0 NDEC=NDEC+1 IDEC=1 END IF END IF RHO1=MXUDOT(NF,G,G,IX,KBF) GNORM=SQRT(RHO1) PAR=MIN(EPS,SQRT(GNORM)) IF (PAR.GT.1.0D-2) THEN PAR=MIN(PAR,1.0D 0/DBLE(NIT)) END IF PAR=PAR*PAR IF (MOS2.GT.2) THEN * * PRELIMINARY INEXACT SOLUTION * CALL MXVNEG(NF,G,XO) IF (NOS2.NE.0) THEN CALL MXSPTB(NF,H(M+1),IH,JH,XO,0) CALL MXVCOP(NF,XO,S) CALL MXSSMD(NF,H,IH,JH,S,1.0D 0,G,GO) IF (MXUDOT(NF,GO,GO,IX,KBF).LE.1.0D-2*PAR*RHO1) THEN SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) ITERD=2 RETURN END IF END IF END IF * * CG INITIATION * RHO=RHO1 SNORM=0.0D 0 CALL MXVSET(NF,0.0D 0,S) CALL MXVNEG(NF,G,XS) IF (NOS2.EQ.0) THEN CALL MXVNEG(NF,G,XO) ELSE IF (MOS2.GT.2) THEN RHO=MXUDOT(NF,XS,XO,IX,KBF) ELSE CALL MXVNEG(NF,G,XO) CALL MXSPTB(NF,H(M+1),IH,JH,XO,0) RHO=MXUDOT(NF,XS,XO,IX,KBF) END IF C SIG=RHO MMX=NF+3 DO 10 NRED=1,MMX CALL MXSSMM(NF,H,IH,JH,XO,GO) ALF=MXUDOT(NF,XO,GO,IX,KBF) IF (ALF.LE.1.0D 0/ETA9) THEN C IF (ALF.LE.1.0D-8*SIG) THEN * * CG FAILS (THE MATRIX IS NOT POSITIVE DEFINITE) * IF (NRED.EQ.1) THEN CALL MXVNEG(NF,G,S) SNORM=GNORM END IF ITERD=0 RETURN ELSE ITERD=2 END IF * * CG STEP * ALF=RHO/ALF CALL MXUDIR(NF, ALF,XO,S,S,IX,KBF) CALL MXUDIR(NF,-ALF,GO,XS,XS,IX,KBF) NIN=NIN+1 RHO2=MXUDOT(NF,XS,XS,IX,KBF) SNORM=SQRT(MXUDOT(NF,S,S,IX,KBF)) IF (RHO2.LE.PAR*RHO1) RETURN IF (NRED.GE.MMX) RETURN IF (NOS2.NE.0) THEN CALL MXVCOP(NF,XS,GO) CALL MXSPTB(NF,H(M+1),IH,JH,GO,0) RHO2=MXUDOT(NF,XS,GO,IX,KBF) ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XO,GO,XO,IX,KBF) ELSE ALF=RHO2/RHO CALL MXUDIR(NF,ALF,XO,XS,XO,IX,KBF) END IF RHO=RHO2 C SIG=RHO2+ALF*ALF*SIG 10 CONTINUE RETURN END * SUBROUTINE PF1HS2 ALL SYSTEMS 99/12/01 * PURPOSE : * NUMERICAL COMPUTATION OF THE HESSIAN MATRIX OF THE MODEL FUNCTION * USING ITS GRADIENTS - SPARSE VERSION USING DIRECT COLOURING METHOD. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II ML SIZE OF THE COMPACT FACTOR. * II M NUMBER OF NONZERO ELEMENTS OF THE SPARSE HESSIAN MATRIX. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RA XO(NF) AUXILIARY VECTOR. * RO HF(M) HESSIAN MATRIX OF THE MODEL FUNCTION. * IU IH(NF+1) POINTER VECTOR OF SPARSE HESSIAN MATRIX. * IU JH(M) INDEX VECTOR OF THE HESSIAN MATRIX. * RI GF(NF) GRADIENT OF THE MODEL FUNCTION. * RA GO(NF) AUXILIARY VECTOR. * II COL(NF) VECTOR DISCERNING GROUPS OF THE HESSIAN COLUMN OF THE * SAME COLOUR. * IA WN11(NF+1) AUXILIARY VECTOR. * IA WN12(NF+1) AUXILIARY VECTOR. * RA XS(NF) AUXILIARY VECTOR USED FOR STEP SIZES. * RI FF VALUE OF THE MODEL FUNCTION. * RI ETA1 PRECISION OF THE COMPUTED VALUES. * II KBF TYPE OF BOUNDS. KBF=0-BOUNDS ARE NOT USED. KBF=1-ONE SIDED * BOUNDS. KBF=2-TWO SIDED BOUNDS. * IU ITERM TERMINATION INDICATOR. * IU ISYS CONTROL PARAMETER. * * SUBPROGRAMS USED : * S MXSTG1 WIDTHEN THE STRUCTURE. * S MXSTL2 SHRINK THE STRUCTURE. * S MXVCOP COPYING OF A VECTOR. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PF1HS2(NF,ML,M,X,IX,XO,HF,IH,JH,GF,GO,COL,WN11, & WN12,XS,FF,ETA1,KBF,ITERM,ISYS) INTEGER NF,ML,M,IX(*),IH(*),JH(*),COL(*),WN11(*), & WN12(*),KBF,ITERM,ISYS DOUBLE PRECISION X(*),XO(*),HF(*),GF(*),GO(*),XS(*), & FF,ETA1 DOUBLE PRECISION XTEMP,FTEMP,ETA INTEGER I,J,J1,K,K1,L,MX,MM,IVAR,JVAR SAVE MX,MM,IVAR,JVAR SAVE XTEMP,FTEMP,ETA IF (ITERM.NE.0) GO TO 12 IF (ISYS.EQ.1) GO TO 3 MM=IH(NF+1)-1 IF (3*MM-NF+ML.GE.M) THEN ITERM=-45 ISYS=0 RETURN END IF ETA=SQRT(ETA1) FTEMP=FF CALL MXVCOP(NF,X,XO) * * WIDTHEN THE STRUCTURE * K=2*MM-NF DO 50 I=ML+MM,1,-1 JH(K+I)=JH(MM+I) 50 CONTINUE CALL MXSTG1(NF,MX,IH,JH,WN12,WN11) CALL MXVSET(K,0.0D 0,HF) IVAR=1 2 CONTINUE IF (IVAR.GT.NF) GO TO 870 DO 200 J=IVAR,NF IF (COL(J).GE.1) THEN GO TO 200 ELSE JVAR=J GO TO 300 END IF 200 CONTINUE 300 CONTINUE DO 400 J=IVAR,JVAR L=ABS(COL(J)) IF (KBF.GT.0) THEN IF (IX(L).LE.-7) GO TO 400 END IF * * STEP SELECTION * XS(L)=ETA*MAX(ABS(X(L)),1.0D 0)*SIGN(1.0D 0,X(L)) XTEMP=X(L) X(L)=XTEMP+XS(L) XS(L)=X(L)-XTEMP 400 CONTINUE ISYS=1 RETURN 3 CONTINUE * * NUMERICAL DIFFERENTIATION * * * SET AUXILIARY VECTOR DISCERNING THE SINGLETONS IN A GROUP TO ZERO * DO 450 J1=1,NF WN11(J1)=0 450 CONTINUE * * DISCERN SINGLETONS OF THE GROUP OF THE SAME COLOR. * DO 600 J1=IVAR,JVAR L=ABS(COL(J1)) DO 500 K=IH(L),IH(L+1)-1 K1=ABS(JH(K)) IF (WN11(K1).EQ.0) THEN WN11(K1)=J1 ELSE WN11(K1)=-1 END IF 500 CONTINUE 600 CONTINUE * * NUMERICAL VALUES COMPUTATION * DO 800 J1=IVAR,JVAR L=ABS(COL(J1)) DO 700 K=IH(L),IH(L+1)-1 K1=ABS(JH(K)) IF (WN11(K1).GT.0) THEN HF(K)=(GF(K1)-GO(K1))/XS(L) END IF 700 CONTINUE 800 CONTINUE * * SET THE ORIGINAL VALUE OF X FOR THE COMPONENTS OF THE ACTUAL COLOR. * DO 850 J=IVAR,JVAR L=ABS(COL(J)) X(L)=XO(L) 850 CONTINUE IVAR=JVAR+1 GO TO 2 870 CONTINUE * * MOVE THE ELEMENTS OF THE HESSIAN APPROXIMATION INTO THE UPPER * TRIANGULAR PART * DO 900 I=1,NF WN11(I)=WN12(I)+1 900 CONTINUE DO 1100 I=1,NF IVAR=IH(I) JVAR=WN12(I)-1 DO 1000 J=IVAR,JVAR K=ABS(JH(J)) L=WN11(K) IF (HF(L).EQ.0) THEN HF(L)=HF(J) ELSE IF (HF(L).NE.0.AND.HF(J).NE.0) THEN HF(L)=0.5D 0*(HF(J)+HF(L)) END IF WN11(K)=WN11(K)+1 1000 CONTINUE 1100 CONTINUE FF=FTEMP * * SHRINK THE STRUCTURE * CALL MXSTL2(NF,MX,HF,IH,JH,WN12) K=2*MM-NF DO 1200 I=1,ML+MM JH(MM+I)=JH(K+I) 1200 CONTINUE * * RETRIEVE VALUES * CALL MXVCOP(NF,XO,X) 12 CONTINUE ISYS=0 RETURN END * SUBROUTINE PFSEB4 ALL SYSTEMS 98/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE PARTITIONED HESSIAN * MATRIX. * * PARAMETERS : * II NC NUMBER OF CONSTRAINTS. * RU B(M) ELEMENTS OF THE SPARSE MATRIX B. * IO IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF B. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF B. * II CH(MB) ELEMENTS OF THE PARTITIONED MATRIX H. * II ICG(NC+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JCG(MC) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * II ICA(NC) VECTOR CONTAINING TYPES OF CONSTRAINTS. * RI CZL(NC) VECTOR CONTAINING LOWER MULTIPLIERS FOR CONSTRAINTS. * RI CZU(NC) VECTOR CONTAINING UPPER MULTIPLIERS FOR CONSTRAINTS. * II JOB SUBJECTS OF UPDATES. JOB=0-CONSTRAINT FUNCTIONS. * JOB=1-CONSTRAINT FUNCTIONS MULTIPLIED BY SIGNS OF THE * LAGRANGIAN MULTIPLIERS. JOB-2-ACTIVE TERMS OF THE LAGRANGIAN * FUNCTION. JOB-3-ALL TERMS OF THE LAGRANGIAN FUNCTION. * SUBROUTINE PFSEB4(NC,B,IH,JH,CH,ICG,JCG,ICA,CZL,CZU,JOB) INTEGER NC,IH(*),JH(*),ICG(*),JCG(*),ICA(*),JOB DOUBLE PRECISION B(*),CH(*),CZL(*),CZU(*) INTEGER I,II,IC,J,JJ,JC,JF,K,KK,L,LL,KC DOUBLE PRECISION TEMP KK=0 DO 7 KC=1,NC IF (JOB.LE.1) THEN LL=ABS(ICA(KC)) IF (LL.EQ.3.OR.LL.EQ.4) THEN TEMP= CZU(KC)-CZL(KC) ELSE IF (LL.EQ.1) THEN TEMP=-CZL(KC) ELSE IF (LL.EQ.2) THEN TEMP= CZU(KC) ELSE IF (LL.EQ.5) THEN TEMP= CZL(KC) END IF IF (JOB.EQ.1) TEMP=ABS(TEMP) ELSE IF (JOB.EQ.2) THEN IF (ICA(KC).GE.0) GO TO 7 TEMP=1.0D 0 ELSE TEMP=1.0D 0 END IF II=ICG(KC) L=ICG(KC+1)-II DO 6 IC=1,L KK=KK+IC I=JCG(II) IF (I.LE.0) GO TO 5 JF=IH(I) JJ=II K=KK DO 4 JC=IC,L J=JCG(JJ) IF (J.LE.0) GO TO 3 2 IF (JH(JF).LT.J) THEN JF=JF+1 GO TO 2 END IF B(JF)=B(JF)+TEMP*CH(K) 3 K=K+JC JJ=JJ+1 4 CONTINUE 5 II=II+1 6 CONTINUE 7 CONTINUE RETURN END * SUBROUTINE PFSEB5 ALL SYSTEMS 06/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE PARTITIONED HESSIAN * MATRIX. * * PARAMETERS : * II NC NUMBER OF CONSTRAINTS. * RU B(M) ELEMENTS OF THE SPARSE MATRIX B. * IO IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF B. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF B. * II CH(MB) ELEMENTS OF THE PARTITIONED MATRIX H. * II ICG(NC+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JCG(MC) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI CZ(NC) VECTOR CONTAINING LAGRANGE MULTIPLIERS FOR CONSTRAINTS. * II JOB SUBJECTS OF UPDATES. JOB=0-CONSTRAINT FUNCTIONS. * JOB=1-CONSTRAINT FUNCTIONS MULTIPLIED BY SIGNS OF THE * LAGRANGIAN MULTIPLIERS. JOB-2-ACTIVE TERMS OF THE LAGRANGIAN * FUNCTION. JOB-3-ALL TERMS OF THE LAGRANGIAN FUNCTION. * SUBROUTINE PFSEB5(NC,B,IH,JH,CH,ICG,JCG,CZ,JOB) INTEGER NC,IH(*),JH(*),ICG(*),JCG(*),JOB DOUBLE PRECISION B(*),CH(*),CZ(*) INTEGER I,II,IC,J,JJ,JC,JF,K,KK,L,KC DOUBLE PRECISION TEMP KK=0 DO 7 KC=1,NC IF (JOB.EQ.0) THEN TEMP=CZ(KC) ELSE IF (JOB.EQ.1) THEN TEMP=ABS(CZ(KC)) ELSE TEMP=1.0D 0 END IF II=ICG(KC) L=ICG(KC+1)-II DO 6 IC=1,L KK=KK+IC I=JCG(II) IF (I.LE.0) GO TO 5 JF=IH(I) JJ=II K=KK DO 4 JC=IC,L J=JCG(JJ) IF (J.LE.0) GO TO 3 2 IF (JH(JF).LT.J) THEN JF=JF+1 GO TO 2 END IF B(JF)=B(JF)+TEMP*CH(K) 3 K=K+JC JJ=JJ+1 4 CONTINUE 5 II=II+1 6 CONTINUE 7 CONTINUE RETURN END * SUBROUTINE PFSED3 ALL SYSTEMS 07/12/01 * PURPOSE : * COMPRESSED SPARSE STRUCTURE OF THE HESSIAN MATRIX IS COMPUTED FROM * THE COORDINATE FORM. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II M NUMBER OF NONZERO ELEMENTS IN THE UPPER PART OF THE SPARSE * HESSIAN MATRIX. * IU IH(M+NF) ON INPUT ROW INDICES OF NONZERO ELEMENTS IN THE FIELD * H. ON OUTPUT POSITIONS OF DIAGONAL ELEMENTS IN THE FIELD H. * II JH(M+NF) COLUMN INDICES OF NONZERO ELEMENTS IN THE FIELD H. * IO IER ERROR MESAGE. IER=0-THE STANDARD INPUT DATA ARE CORRECT. * IER=1-ERROR IN THE ARRAY IH. IER=2-ERROR IN THE ARRAY JH. * SUBROUTINE PFSED3(NF,M,IH,JH,IER) INTEGER NF,M,IH(*),JH(*),IER INTEGER I,J,K,L,LL IER=0 DO 1 J=1,M IF (IH(J).GT.JH(J)) THEN K=IH(J) IH(J)=JH(J) JH(J)=K END IF 1 CONTINUE DO 2 I=1,NF IH(M+I)=I JH(M+I)=I 2 CONTINUE CALL MXVSR7(M+NF,IH,JH) IF (IH(1).LT.1.OR.IH(M+NF).GT.NF) THEN IER=1 RETURN END IF K=1 DO 3 J=1,M+NF IF (IH(J).EQ.K) THEN IH(K)=J K=K+1 END IF 3 CONTINUE IH(K)=J LL=0 DO 5 I=1,NF K=IH(I) L=IH(I+1)-K IF (L.GT.0) THEN CALL MXVSRT(L,JH(K)) IF (JH(K).LT.1.OR.JH(K+L-1).GT.NF) THEN IER=2 RETURN END IF END IF IH(I)=IH(I)-LL DO 4 J=1,L IF (J.GT.1.AND.JH(K).EQ.JH(K-1)) THEN LL=LL+1 ELSE JH(K-LL)=JH(K) END IF K=K+1 4 CONTINUE 5 CONTINUE IH(NF+1)=IH(NF+1)-LL M=IH(NF+1)-1 RETURN END * SUBROUTINE PFSET2 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE NUMBER OF NONZERO ELEMENTS OF THE SPARSE * HESSIAN MATRIX STORED IN THE BLOCKED FORM. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * II MB NUMBER OF NONZERO ELEMENTS OF THE PARTITIONED HESSIAN MATRIX * II MC MAXIMUM NUMBER OF ELEMENTS OF THE PARTIAL HESSIAN MATRIX. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE SPARSE * JACOBIAN MATRIX. * SUBROUTINE PFSET2(NA,MB,MC,IAG) INTEGER NA,MB,MC,IAG(*) INTEGER K,L,KA MB=0 MC=0 DO 1 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K MB=MB+L*(L+1)/2 MC=MAX(MC,L*(L+1)/2) 1 CONTINUE RETURN END * SUBROUTINE PFSET3 ALL SYSTEMS 97/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE STRUCTURE OF THE HESSIAN MATRIX FROM THE * SPARSE STRUCTURE OF THE JACOBIAN MATRIX. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * IO M NUMBER OF NONZERO ELEMENTS OF THE HESSIAN MATRIX. * II MMAX DECLARED LENGHT OF THE ARRAYS H AND JH. * IO IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * II IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * IU ITERM TERMINATION INDICATOR. * SUBROUTINE PFSET3(NF,NA,M,MMAX,IH,JH,IAG,JAG,ITERM) INTEGER NF,NA,M,MMAX,IH(*),JH(*),IAG(*),JAG(*),ITERM INTEGER I,J,JF,JA,K,LF,LA,KA M=IH(NF+1)-1 IF (M.GT.MMAX) THEN ITERM=-40 RETURN END IF DO 7 KA=1,NA LA=IAG(KA+1)-1 DO 6 K=IAG(KA),LA I=JAG(K) JF=IH(I) LF=IH(I+1)-1 DO 5 JA=K,LA J=JAG(JA) 2 IF (JH(JF).LT.J.AND.JF.LE.LF) THEN JF=JF+1 IF (JF.LE.LF) GO TO 2 END IF IF (JH(JF).GT.J .OR.JF.GT.LF) THEN DO 3 J=I+1,NF+1 IH(J)=IH(J)+1 3 CONTINUE DO 4 J=M,JF,-1 JH(J+1)=JH(J) 4 CONTINUE JH(JF)=JAG(JA) JF=JF+1 LF=LF+1 M=M+1 IF (M.GT.MMAX) THEN ITERM=-40 RETURN END IF END IF 5 CONTINUE 6 CONTINUE 7 CONTINUE RETURN END * SUBROUTINE PFSET4 ALL SYSTEMS 98/12/01 * PURPOSE : * COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE PARTITIONED HESSIAN * MATRIX. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RU B(M) ELEMENTS OF THE SPARSE MATRIX B. * IO IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF B. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF B. * II AH(MB) ELEMENTS OF THE PARTITIONED MATRIX H. * II IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * SUBROUTINE PFSET4(NA,B,IH,JH,AH,IAG,JAG) INTEGER NA,IH(*),JH(*),IAG(*),JAG(*) DOUBLE PRECISION B(*),AH(*) INTEGER I,II,IA,J,JJ,JA,JF,K,KK,L,KA KK=0 DO 7 KA=1,NA II=IAG(KA) L=IAG(KA+1)-II DO 6 IA=1,L KK=KK+IA I=JAG(II) IF (I.LE.0) GO TO 5 JF=IH(I) JJ=II K=KK DO 4 JA=IA,L J=JAG(JJ) IF (J.LE.0) GO TO 3 2 IF (JH(JF).LT.J) THEN JF=JF+1 GO TO 2 END IF B(JF)=B(JF)+AH(K) 3 K=K+JA JJ=JJ+1 4 CONTINUE 5 II=II+1 6 CONTINUE 7 CONTINUE RETURN END * FUNCTION PNFUZ1 ALL SYSTEMS 01/09/22 * PURPOSE : * COMPUTATION OF LOWER AND UPPER LAGRANGE MULTIPLIERS. * * PARAMETERS : * RO Z SLACK VARIABLE IN THE NONLINEAR PROGRAMMING FORMULATION OF * A MINIMAX PROBLEM. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI RPF3 BARRIER PARAMETER. * RO AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * RA AZL(NA) VECTOR OF LOWER LAGRANGE MULTIPLIERS. * RA AZU(NA) VECTOR OF UPPER LAGRANGE MULTIPLIERS. * II IEXT TYPE OF MINIMAX. IEXT<0-MINIMIZATION OF THE MAXIMUM * PARTIAL VALUE. IEXT-0-MINIMIZATION OF THE MAXIMUM PARTIAL * ABSOLUTE VALUE. IEXT>0-MAXIMIZATION OF THE MINIMUM PARTIAL * VALUE. * FUNCTION PNFUZ1(Z,NA,RPF3,AF,AZL,AZU,IEXT) INTEGER NA,IEXT DOUBLE PRECISION Z,RPF3,AF(*),AZL(*),AZU(*),PNFUZ1 INTEGER KA PNFUZ1=1.0D 0 DO 1 KA=1,NA IF (IEXT.LE.0) THEN AZU(KA)=RPF3/(Z-AF(KA)) PNFUZ1=PNFUZ1-AZU(KA) END IF IF (IEXT.GE.0) THEN AZL(KA)=RPF3/(Z+AF(KA)) PNFUZ1=PNFUZ1-AZL(KA) END IF 1 CONTINUE RETURN END * SUBROUTINE PNINT1 ALL SYSTEMS 91/12/01 * PURPOSE : * EXTRAPOLATION OR INTERPOLATION FOR LINE SEARCH WITH DIRECTIONAL * DERIVATIVES. * * PARAMETERS : * RI RL LOWER VALUE OF THE STEPSIZE PARAMETER. * RI RU UPPER VALUE OF THE STEPSIZE PARAMETER. * RI FL VALUE OF THE OBJECTIVE FUNCTION FOR R=RL. * RI FU VALUE OF THE OBJECTIVE FUNCTION FOR R=RU. * RI PL DIRECTIONAL DERIVATIVE FOR R=RL. * RI PU DIRECTIONAL DERIVATIVE FOR R=RU. * RO R VALUE OF THE STEPSIZE PARAMETER OBTAINED. * II MODE MODE OF LINE SEARCH. * II MTYP METHOD SELECTION. MTYP=1-BISECTION. MTYP=2-QUADRATIC * INTERPOLATION (WITH ONE DIRECTIONAL DERIVATIVE). * MTYP=3-QUADRATIC INTERPOLATION (WITH TWO DIRECTIONAL * DERIVATIVES). MTYP=4-CUBIC INTERPOLATION. MTYP=5-CONIC * INTERPOLATION. * IO MERR ERROR INDICATOR. MERR=0 FOR NORMAL RETURN. * * METHOD : * EXTRAPOLATION OR INTERPOLATION WITH STANDARD MODEL FUNCTIONS. * SUBROUTINE PNINT1(RL,RU,FL,FU,PL,PU,R,MODE,MTYP,MERR) DOUBLE PRECISION RL, RU, FL, FU, PL, PU, R INTEGER MODE,MTYP,MERR,NTYP DOUBLE PRECISION A,B,C,D,DIS,DEN DOUBLE PRECISION C1L,C1U,C2L,C2U,C3L PARAMETER (C1L=1.1D 0,C1U=1.0D 3,C2L=1.0D-2,C2U=0.9D 0, & C3L=0.1D 0) MERR=0 IF (MODE.LE.0) RETURN IF (PL.GE.0.0D 0) THEN MERR=2 RETURN ELSE IF (RU.LE.RL) THEN MERR=3 RETURN END IF DO 1 NTYP=MTYP,1,-1 IF (NTYP.EQ.1) THEN * * BISECTION * IF (MODE.EQ.1) THEN R=4.0D 0*RU RETURN ELSE R=0.5D 0*(RL+RU) RETURN END IF ELSE IF (NTYP.EQ.MTYP) THEN A = (FU-FL)/(PL*(RU-RL)) B = PU/PL END IF IF (NTYP.EQ.2) THEN * * QUADRATIC EXTRAPOLATION OR INTERPOLATION WITH ONE DIRECTIONAL * DERIVATIVE * DEN = 2.0D 0*(1.0D 0-A) ELSE IF (NTYP.EQ.3) THEN * * QUADRATIC EXTRAPOLATION OR INTERPOLATION WITH TWO DIRECTIONAL * DERIVATIVES * DEN = 1.0D 0 - B ELSE IF (NTYP.EQ.4) THEN * * CUBIC EXTRAPOLATION OR INTERPOLATION * C = B - 2.0D 0*A + 1.0D 0 D = B - 3.0D 0*A + 2.0D 0 DIS = D*D - 3.0D 0*C IF (DIS.LT.0.0D 0) GO TO 1 DEN = D + SQRT(DIS) ELSE IF (NTYP.EQ.5) THEN * * CONIC EXTRAPOLATION OR INTERPOLATION * DIS = A*A - B IF (DIS.LT.0.0D 0) GO TO 1 DEN = A + SQRT(DIS) IF (DEN.LE.0.0D 0) GO TO 1 DEN = 1.0D 0 - B*(1.0D 0/DEN)**3 END IF IF (MODE.EQ.1.AND.DEN.GT.0.0D 0.AND.DEN.LT.1.0D 0) THEN * * EXTRAPOLATION ACCEPTED * R = RL + (RU-RL)/DEN R = MAX(R,C1L*RU) R = MIN(R,C1U*RU) RETURN ELSE IF (MODE.EQ.2.AND.DEN.GT.1.0D 0) THEN * * INTERPOLATION ACCEPTED * R = RL + (RU-RL)/DEN IF (RL.EQ.0.0D 0) THEN R = MAX(R,RL+C2L*(RU-RL)) ELSE R = MAX(R,RL+C3L*(RU-RL)) END IF R = MIN(R,RL+C2U*(RU-RL)) RETURN END IF 1 CONTINUE END * SUBROUTINE PNINT3 ALL SYSTEMS 91/12/01 * PURPOSE : * EXTRAPOLATION OR INTERPOLATION FOR LINE SEARCH WITHOUT DIRECTIONAL * DERIVATIVES. * * PARAMETERS : * RI RO INITIAL VALUE OF THE STEPSIZE PARAMETER. * RI RL LOWER VALUE OF THE STEPSIZE PARAMETER. * RI RU UPPER VALUE OF THE STEPSIZE PARAMETER. * RI RI INNER VALUE OF THE STEPSIZE PARAMETER. * RI FO VALUE OF THE OBJECTIVE FUNCTION FOR R=RO. * RI FL VALUE OF THE OBJECTIVE FUNCTION FOR R=RL. * RI FU VALUE OF THE OBJECTIVE FUNCTION FOR R=RU. * RI FI VALUE OF THE OBJECTIVE FUNCTION FOR R=RI. * RO PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * RO R VALUE OF THE STEPSIZE PARAMETER OBTAINED. * II MODE MODE OF LINE SEARCH. * II MTYP METHOD SELECTION. MTYP=1-BISECTION. MTYP=2-TWO POINT * QUADRATIC INTERPOLATION. MTYP=2-THREE POINT QUADRATIC * INTERPOLATION. * IO MERR ERROR INDICATOR. MERR=0 FOR NORMAL RETURN. * * METHOD : * EXTRAPOLATION OR INTERPOLATION WITH STANDARD MODEL FUNCTIONS. * SUBROUTINE PNINT3(RO,RL,RU,RI,FO,FL,FU,FI,PO,R,MODE,MTYP,MERR) DOUBLE PRECISION RO,RL,RU,RI,FO,FL,FU,FI,PO,R INTEGER MODE,MTYP,MERR,NTYP DOUBLE PRECISION AL,AU,AI,DEN,DIS LOGICAL L1,L2 DOUBLE PRECISION ZERO,HALF,ONE,TWO,THREE,FOUR,C1L,C1U,C2L,C2U,C3L PARAMETER(ZERO=0.0D 0,HALF=0.5D 0,ONE=1.0D 0,TWO=2.0D 0, & THREE=3.0D 0,FOUR=4.0D 0,C1L=1.1D 0,C1U=1.0D 3, & C2L=1.0D-2,C2U=0.9D 0,C3L=1.0D-1) MERR = 0 IF (MODE .LE. 0) RETURN IF (PO .GE. ZERO) THEN MERR = 2 RETURN ELSE IF (RU .LE. RL) THEN MERR = 3 RETURN END IF L1 = RL .LE. RO L2 = RI .LE. RL DO 1 NTYP = MTYP, 1, -1 IF (NTYP .EQ. 1) THEN * * BISECTION * IF (MODE .EQ. 1) THEN R = TWO * RU RETURN ELSE IF (RI-RL.LE.RU-RI) THEN R=HALF*(RI+RU) RETURN ELSE R=HALF*(RL+RI) RETURN END IF ELSE IF (NTYP.EQ.MTYP.AND.L1) THEN IF (.NOT.L2) AI=(FI-FO)/(RI*PO) AU=(FU-FO)/(RU*PO) END IF IF (L1.AND.(NTYP.EQ.2.OR.L2)) THEN * * TWO POINT QUADRATIC EXTRAPOLATION OR INTERPOLATION * IF (AU.GE.ONE) GO TO 1 R=HALF*RU/(ONE-AU) ELSE IF (.NOT.L1.OR..NOT.L2.AND.NTYP.EQ.3) THEN * * THREE POINT QUADRATIC EXTRAPOLATION OR INTERPOLATION * AL=(FI-FL)/(RI-RL) AU=(FU-FI)/(RU-RI) DEN=AU-AL IF (DEN.LE.ZERO) GO TO 1 R=RI-HALF*(AU*(RI-RL)+AL*(RU-RI))/DEN ELSE IF (L1.AND..NOT.L2.AND.NTYP.EQ.4) THEN * * THREE POINT CUBIC EXTRAPOLATION OR INTERPOLATION * DIS=(AI-ONE)*(RU/RI) DEN=(AU-ONE)*(RI/RU)-DIS DIS=AU+AI-DEN-TWO*(ONE+DIS) DIS=DEN*DEN-THREE*DIS IF (DIS.LT.ZERO) GO TO 1 DEN=DEN+SQRT(DIS) IF (DEN.EQ.ZERO) GO TO 1 R=(RU-RI)/DEN ELSE GO TO 1 END IF IF (MODE .EQ. 1 .AND. R .GT. RU) THEN * * EXTRAPOLATION ACCEPTED * R = MAX( R, C1L*RU) R = MIN( R, C1U*RU) RETURN ELSE IF (MODE .EQ. 2 .AND. R .GT. RL .AND. R .LT. RU) THEN * * INTERPOLATION ACCEPTED * IF (RI.EQ.ZERO.AND.NTYP.NE.4) THEN R = MAX( R, RL + C2L*(RU-RL)) ELSE R = MAX( R, RL + C3L*(RU-RL)) END IF R = MIN( R, RL + C2U*(RU-RL)) IF (R.EQ.RI) GO TO 1 RETURN END IF 1 CONTINUE END * SUBROUTINE PNNEQ1 ALL SYSTEMS 92/12/01 * PURPOSE : * SOLUTION OF A SINGLE NONLINEAR EQUATION. * * PARAMETERS : * RI AA LEFT ENDPOINT OF THE INTERVAL. * RI BB RIGHT ENDPOINT OF THE INTERVAL. * RO X COMPUTED SOLUTION POINT. * RO F COMPUTED VALUE OF THE NONLINEAR FUNCTION. * RF FUN EXTERNAL FUNCTION. * RI EPSX REQUIRED PRECISION FOR THE SOLUTION POINT. * RI EPSF REQUIRED PRECISION FOR THE NONLINEAR FUNCTION. * IO IC NUMBER OF ITERATIONS. * IO IE ERROR SPECIFICATION. * IU ISYS CONTROL PARAMETER. * * METHOD : * D.LEE: THREE NEW RAPIDLY CONVERGENT ALGORITHMS FOR FINDING A ZERO * OF A FUNCTION, SIAM J. SCI. STAT. COMPUT. 6 (1985) 193-208. * SUBROUTINE PNNEQ1(AA,BB,X,F,EPSX,EPSF,IC,IE,ISYS) DOUBLE PRECISION AA,BB,X,F,EPSX,EPSF INTEGER IC,IE,ISYS INTEGER ITER,ITMAX,K,L DOUBLE PRECISION FA,FB,X1,X2,X3,F1,F2,F3,R,R1,RA,RB,D,D1,A,B,C,Z, & W,FW,GW,DEL,DDL,F21,F32 DOUBLE PRECISION ZERO,ONE,TWO,THREE,FOUR,HALF,CON PARAMETER (ZERO=0.0D 0,ONE=1.0D 0,TWO=2.0D 0,THREE=3.0D 0, & FOUR=4.0D 0,HALF=0.5D 0,CON=0.1D 0) SAVE A,B,C,FA,FB,X1,X2,X3,F1,F2,F3,R,D,FW SAVE L,ITER,ITMAX GO TO (1,2,3,4,6) ISYS+1 1 IE=0 ITMAX=IC IF (ITMAX.LE.0) ITMAX=100 X=AA ISYS=1 IC=1 RETURN 2 CONTINUE IF (ABS(F).LE.EPSF) GO TO 7 FA=F X=BB ISYS=2 IC=2 RETURN 3 CONTINUE IF (ABS(F).LE.EPSF) GO TO 7 FB=F IF (FA*FB.GT.0.0D 0) THEN X=AA F=FA IE=-2 GO TO 7 END IF X1=AA F1=FA X=HALF*(AA+BB) ISYS=3 IC=3 RETURN 4 CONTINUE X2=X F2=F IF (F1*F2.GT.0.0D 0) THEN X3=X1 F3=F1 X1=BB F1=FB ELSE X3=BB F3=FB END IF L=0 D=0.0D 0 R=0.0D 0 ITER=1 5 CONTINUE D1=D R1=R D=ABS(X1-X2) IF (ABS(F1).LT.ABS(F2)) THEN X=X1 F=F1 ELSE X=X2 F=F2 END IF DEL=EPSX*(ABS(X)+ONE) IF (ABS(F).LE.EPSF.OR.D.LE.TWO*DEL) GO TO 7 Z=X1+HALF*(X2-X1) DDL=MAX(CON*D,DEL) IF (THREE*D.LE.TWO*D1) THEN K=0 ELSE K=1 END IF IF (X2.EQ.X1) THEN F21=0.0D 0 ELSE F21=(F2-F1)/(X2-X1) ENDIF IF (X3.EQ.X2) THEN F32=0.0D 0 ELSE F32=(F3-F2)/(X3-X2) ENDIF A=(F32-F21)/(X3-X1) B=A*(X2+X1)-F21 C=F2-(A*X2-B)*X2 IF (ABS(A).LE.1.0D-10) THEN R=(F2*X1-F1*X2)/(F2-F1) ELSE R=B*B-FOUR*A*C IF (R.LT.0.0D 0) THEN R=(F2*X1-F1*X2)/(F2-F1) ELSE R=SQRT(R) RA=HALF*(B+R)/A RB=HALF*(B-R)/A IF (ABS(RA-Z).LE.ABS(RB-Z)) THEN R=RA ELSE R=RB END IF IF (R.LE.MIN(X1,X2).OR.R.GE.MAX(X1,X2)) THEN R=(F2*X1-F1*X2)/(F2-F1) END IF END IF END IF IF (L.GE.2) THEN W=R IF (ABS(W-X).LT.DEL) W=X+DEL*SIGN(ONE,Z-X) ELSE IF (K.EQ.1.OR.ABS(R-X).GE.ABS(Z-X)) THEN W=Z ELSE W=R+HALF*ABS(R-R1)*SIGN(ONE,R-X) IF (ABS(W-X).LT.DDL) W=X+DDL*SIGN(ONE,Z-X) IF (ABS(W-X).GE.ABS(Z-X)) W=Z END IF X=W FW=F ISYS=4 IC=IC+1 RETURN 6 CONTINUE GW=(A*X-B)*X+C IF (ABS(F-GW).LE.1.0D-1*ABS(FW).OR.ABS(FW).LE.1.0D-3* *MAX(ABS(F1),ABS(F2)).AND.L.GE.2) THEN L=L+1 ELSE L=0 END IF IF (F*SIGN(ONE,F1).GE.0.0D 0) THEN IF (D.LE.ABS(X3-X)) THEN X3=X1 F3=F1 X1=X2 F1=F2 X2=X F2=F ELSE X1=X F1=F END IF ELSE X3=X2 F3=F2 X2=X F2=F END IF ITER=ITER+1 IF (ITER.LE.ITMAX) GO TO 5 IE=-1 7 ISYS=0 RETURN END * SUBROUTINE PNSTEP ALL SYSTEMS 89/12/01 * PURPOSE : * DETERMINATION OF A SCALING FACTOR FOR THE BOUNDARY STEP. * * PARAMETERS : * RI DEL MAXIMUM STEPSIZE. * RI A INPUT PARAMETER. * RI B INPUT PARAMETER. * RI C INPUT PARAMETER. * RO ALF SCALING FACTOR FOR THE BOUNDARY STEP SUCH THAT * A**2+2*B*ALF+C*ALF**2=DEL**2. * SUBROUTINE PNSTEP(DEL,A,B,C,ALF) DOUBLE PRECISION DEL, A, B, C, ALF DOUBLE PRECISION DEN, DIS ALF = 0.0D 0 DEN = (DEL+A) * (DEL-A) IF (DEN .LE. 0.0D 0) RETURN DIS = B*B + C*DEN IF (B .GE. 0.0D 0) THEN ALF = DEN / (SQRT(DIS) + B) ELSE ALF = (SQRT(DIS) - B) / C END IF RETURN END * SUBROUTINE PNSTP4 ALL SYSTEMS 99/12/01 * PURPOSE : * STEPSIZE SELECTION USING POLYHEDRAL APPROXIMATION * FOR DESCENT STEP IN NONCONVEX VARIABLE METRIC METHOD. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * II MA DECLARED NUMBER OF LINEAR APPROXIMATED FUNCTIONS * II MAL CURRENT NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * RU X(N) VECTOR OF VARIABLES. * RI AF(4*MA) VECTOR OF BUNDLE FUNCTIONS VALUES. * RI AG(N*MA) MATRIX WHOSE COLUMNS ARE BUNDLE SUBGRADIENTS. * RI AY(N*MA) MATRIX WHOSE COLUMNS ARE VARIABLE VECTORS. * RI S(N) DIRECTION VECTOR. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RI DF DIRECTIONAL DERIVATIVE. * RO T VALUE OF THE STEPSIZE PARAMETER. * RO TB BUNDLE PARAMETER FOR MATRIX SCALING. * RI ETA5 DISTANCE MEASURE PARAMETER. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * RI MOS3 LOCALITY MEASURE PARAMETER. * SUBROUTINE PNSTP4(N,MA,MAL,X,AF,AG,AY,S,F,DF,T,TB,ETA5,ETA9,MOS3) DOUBLE PRECISION DF,ETA5,ETA9,F,T,TB INTEGER MA,MAL,MOS3,N DOUBLE PRECISION AF(*),AG(*),AY(*),S(*),X(*) DOUBLE PRECISION ALF,ALFL,ALFR,BET,BETL,BETR,DX,Q,R,W INTEGER I,J,JN,K,L,LQ W = DF*T* (1.0D0-T*0.5D0) * * INITIAL CHOICE OF POSSIBLY ACTIVE LINES * K = 0 L = -1 JN = 0 TB = SQRT(ETA9) BETR = -ETA9 DO 20 J = 1,MAL - 1 R = 0.0D0 BET = 0.0D0 ALFL = AF(J) - F DO 10 I = 1,N DX = X(I) - AY(JN+I) Q = AG(JN+I) R = R + DX*DX ALFL = ALFL + DX*Q BET = BET + S(I)*Q 10 CONTINUE IF (MOS3.NE.2) R = R** (DBLE(MOS3)*0.5D0) ALF = MAX(ABS(ALFL),ETA5*R) R = 1.0D0 - BET/DF IF (R*R+ (ALF+ALF)/DF.GT.1.0D-6) THEN K = K + 1 AF(MA+K) = ALF AF(MA+MA+K) = BET R = T*BET - ALF IF (R.GT.W) THEN W = R L = K END IF END IF IF (BET.GT.0.0D0) TB = MIN(TB,ALF/ (BET-DF)) BETR = MAX(BETR,BET-ALF) JN = JN + N 20 CONTINUE LQ = -1 IF (BETR.LE.DF*0.5D0) RETURN LQ = 1 IF (L.LT.0) RETURN BETR = AF(MA+MA+L) IF (BETR.LE.0.0D0) THEN IF (T.LT.1.0D0 .OR. BETR.EQ.0.0D0) RETURN LQ = 2 END IF ALFR = AF(MA+L) * * ITERATION LOOP * 30 IF (LQ.GE.1) THEN Q = 1.0D0 - BETR/DF R = Q + SQRT(Q*Q+ (ALFR+ALFR)/DF) IF (BETR.GE.0.0D0) R = - (ALFR+ALFR)/ (DF*R) R = MIN(1.95D0,MAX(0.0D0,R)) ELSE IF (ABS(BETR-BETL)+ABS(ALFR-ALFL).LT.-1.0D-4*DF) RETURN R = (ALFR-ALFL)/ (BETR-BETL) END IF IF (ABS(T-R).LT.1.0D-4) RETURN T = R AF(MA+L) = -1.0D0 W = T*BETR - ALFR L = -1 DO 40 J = 1,K ALF = AF(MA+J) IF (ALF.LT.0.0D0) GO TO 40 BET = AF(MA+MA+J) R = T*BET - ALF IF (R.GT.W) THEN W = R L = J END IF 40 CONTINUE IF (L.LT.0) RETURN BET = AF(MA+MA+L) IF (BET.EQ.0.0D0) RETURN * * NEW INTERVAL SELECTION * ALF = AF(MA+L) IF (BET.LT.0.0D0) THEN IF (LQ.EQ.2) THEN ALFR = ALF BETR = BET ELSE ALFL = ALF BETL = BET LQ = 0 END IF ELSE IF (LQ.EQ.2) THEN ALFL = ALFR BETL = BETR LQ = 0 END IF ALFR = ALF BETR = BET END IF GO TO 30 END * SUBROUTINE PNSTP5 ALL SYSTEMS 99/12/01 * PURPOSE : * STEPSIZE SELECTION USING POLYHEDRAL APPROXIMATION * FOR NULL STEP IN NONCONVEX VARIABLE METRIC METHOD. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * II MA DECLARED NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * II MAL CURRENT NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * RU X(N) VECTOR OF VARIABLES. * RI AF(4*MA) VECTOR OF BUNDLE FUNCTIONS VALUES. * RI AG(N*MA) MATRIX WHOSE COLUMNS ARE BUNDLE SUBGRADIENTS. * RI AY(N*MA) MATRIX WHOSE COLUMNS ARE VARIABLE VECTORS. * RI S(N) DIRECTION VECTOR. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RI DF DIRECTIONAL DERIVATIVE. * RO T VALUE OF THE STEPSIZE PARAMETER. * RO TB BUNDLE PARAMETER FOR MATRIX SCALING. * RI ETA5 DISTANCE MEASURE PARAMETER. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * RI MOS3 LOCALITY MEASURE PARAMETER. * SUBROUTINE PNSTP5(N,MA,MAL,X,AF,AG,AY,S,F,DF,T,TB,ETA5,ETA9,MOS3) DOUBLE PRECISION DF,ETA5,ETA9,F,T,TB INTEGER MA,MAL,MOS3,N DOUBLE PRECISION AF(*),AG(*),AY(*),S(*),X(*) DOUBLE PRECISION ALF,ALFL,ALFR,BET,BETL,BETR,DX,Q,R,W INTEGER I,J,JN,K,L W = DF*T * * INITIAL CHOICE OF POSSIBLY ACTIVE PARABOLAS * K = 0 L = -1 JN = 0 TB = SQRT(ETA9) BETR = -ETA9 DO 20 J = 1,MAL - 1 BET = 0.0D0 R = 0.0D0 ALFL = AF(J) - F DO 10 I = 1,N DX = X(I) - AY(JN+I) R = R + DX*DX Q = AG(JN+I) ALFL = ALFL + DX*Q BET = BET + S(I)*Q 10 CONTINUE IF (MOS3.NE.2) R = R** (DBLE(MOS3)*0.5D0) ALF = MAX(ABS(ALFL),ETA5*R) IF (BET+BET.GT.DF) TB = MIN(TB,ALF/ (BET-DF)) BETR = MAX(BETR,BET-ALF) IF (ALF.LT.BET-DF) THEN K = K + 1 R = T*BET - ALF AF(MA+K) = ALF AF(MA+MA+K) = BET IF (R.GT.W) THEN W = R L = K END IF END IF JN = JN + N 20 CONTINUE IF (L.LT.0) RETURN BETR = AF(MA+MA+L) ALFR = AF(MA+L) ALF = ALFR BET = BETR ALFL = 0.0D0 BETL = DF * * ITERATION LOOP * 30 W = BET/DF IF (ABS(BETR-BETL)+ABS(ALFR-ALFL).LT.-1.0D-4*DF) RETURN IF (BETR-BETL.EQ.0.0D0) STOP 11 R = (ALFR-ALFL)/ (BETR-BETL) IF (ABS(T-W).LT.ABS(T-R)) R = W Q = T T = R IF (ABS(T-Q).LT.1.0D-3) RETURN AF(MA+L) = -1.0D0 W = T*BET - ALF L = -1 DO 40 J = 1,K ALF = AF(MA+J) IF (ALF.LT.0.0D0) GO TO 40 BET = AF(MA+MA+J) R = T*BET - ALF IF (R.GT.W) THEN W = R L = J END IF 40 CONTINUE IF (L.LT.0) RETURN BET = AF(MA+MA+L) Q = BET - T*DF IF (Q.EQ.0.0D0) RETURN * * NEW INTERVAL SELECTION * ALF = AF(MA+L) IF (Q.LT.0.0D0) THEN ALFL = ALF BETL = BET ELSE ALFR = ALF BETR = BET END IF GO TO 30 END * SUBROUTINE PP0BA1 ALL SYSTEMS 05/12/01 * PURPOSE : * EVALUATION OF THE BARRIER FUNCTION FOR THE SUM OF ABSOLUTE VALUES. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI AS(NA) SUM OF ABSOLUTE VALUE SLACK VARIABLES. * RI RPF3 BARRIER COEFFICIENT. * RO F VALUE OF THE BARRIER FUNCTION. * SUBROUTINE PP0BA1(NA,AS,RPF3,F) INTEGER NA DOUBLE PRECISION AS(*),RPF3,F INTEGER KA F=-DBLE(NA)*RPF3*LOG(2.0D 0*RPF3) DO 1 KA=1,NA F=F+AS(KA)-RPF3*LOG(AS(KA)) 1 CONTINUE RETURN END * SUBROUTINE PP0BX1 ALL SYSTEMS 05/12/01 * PURPOSE : * EVALUATION OF THE BARRIER FUNCTION FOR THE MINIMAX OPTIMIZATION. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI Z MINIMAX SLACK VARIABLE. * RI AF(NA) VECTOR CONTAINING VALUES OF APPROXIMATED FUNCTIONS. * RO F VALUE OF THE BARRIERY FUNCTION. * RI FF VALUE OF THE THE OBJECTIVE FUNCTION. * RI PAR PARAMETER OF THE BEN-TAL BARRIER FUNCTION. * RI RPF3 BARRIER COEFFICIENT. * II MEP MERIT FUNCTION USED. MEP=1-LOGARITHMIC BARIER FUNCTION. * MEP=2-BEN-TAL BARRIER FUNCTION. MEP=3-COMPOSITE BARRIER * FUNCTION. * II IEXT KIND OF THE MINIMAX APPROXIMATION. IEXT=0-CHEBYSHEV * APPROXIMATION. IEXT=-1-MINIMAX. IEXT=+1-MAXIMIN. * SUBROUTINE PP0BX1(NA,Z,AF,F,FF,PAR,RPF3,MEP,IEXT) INTEGER NA,MEP,IEXT DOUBLE PRECISION Z,AF(*),PAR,RPF3,F,FF DOUBLE PRECISION FA INTEGER KA IF (Z.LE.FF) THEN F=1.0D 60 ELSE F=Z IF (MEP.EQ.1) THEN DO 11 KA=1,NA FA=AF(KA) IF (IEXT.LE.0) THEN F=F-RPF3*LOG(Z-FA) END IF IF (IEXT.GE.0) THEN F=F-RPF3*LOG(Z+FA) END IF 11 CONTINUE ELSE IF (MEP.EQ.2) THEN DO 21 KA=1,NA FA=AF(KA) IF (IEXT.LE.0) THEN IF (Z-FA.LE.PAR) THEN F=F-RPF3*LOG(Z-FA) ELSE F=F+(2.0D 0-0.5D 0*PAR/(Z-FA))*RPF3*PAR/(Z-FA) END IF END IF IF (IEXT.GE.0) THEN IF (Z+FA.LE.PAR) THEN F=F-RPF3*LOG(Z+FA) ELSE F=F+(2.0D 0-0.5D 0*PAR/(Z+FA))*RPF3*PAR/(Z+FA) END IF END IF 21 CONTINUE ELSE IF (MEP.EQ.3) THEN DO 31 KA=1,NA FA=AF(KA) IF (IEXT.LE.0) THEN F=F+RPF3*LOG(1.0D 0/(Z-FA)+1.0D 0) END IF IF (IEXT.GE.0) THEN F=F+RPF3*LOG(1.0D 0/(Z+FA)+1.0D 0) END IF 31 CONTINUE ELSE IF (MEP.EQ.4) THEN DO 41 KA=1,NA FA=AF(KA) IF (IEXT.LE.0) THEN F=F+RPF3*RPF3/(Z-FA) END IF IF (IEXT.GE.0) THEN F=F+RPF3*RPF3/(Z+FA) END IF 41 CONTINUE END IF END IF RETURN END * SUBROUTINE PP1MX3 ALL SYSTEMS 05/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT OF THE LAGRANGIAN FUNCTION * FOR THE MINIMAX OPTIMIZATION. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * RI GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RI AG(IAG(N+1)-1) SPARSE RECTANGULAR MATRIX WHICH IS USED FOR THE * DIRECTION VECTOR DETERMINATION. * II IAG(N+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI AZL(NA) LOWER LAGRANGE MULTIPLIERS. * RI AZU(NA) UPPER LAGRANGE MULTIPLIERS. * RI FA VALUE OF THE SELECTED FUNCTION. * RI AF(NA) VALUES OF THE APPROXIMATED FUNCTIONS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * II ISNA INDICATOR FOR STORING ELEMENTAL FUNCTION VALUES AND * GRADIENTS. ISNA=0-STORING SUPPRESSED. ISNA=1-STORING * ELEMENTAL FUNCTION VALUES. ISNA=2-STORING ELEMENTAL * FUNCTION VALUES AND GRADIENTS. * II IEXT TYPE OF MINIMAX. IEXT=0-MINIMIZATION OF THE MAXIMUM VALUE. * IEXT=1-MINIMIZATION OF THE MAXIMUM ABSOLUTE VALUE. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PP1MX3(NF,NA,X,GA,AG,IAG,JAG,G,AZL,AZU,FA,AF, & F,KD,LD,NFV,NFG,ISNA,IEXT) INTEGER NF,NA,IAG(*),JAG(*),KD,LD,NFV,NFG,ISNA,IEXT DOUBLE PRECISION X(*),GA(*),AG(*),G(*),AZL(*),AZU(*),FA,AF(*),F INTEGER J,JP,K,KA,L IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) NFG=NFG+1 END IF DO 3 KA=1,NA IF (LD.GE.0) GO TO 1 CALL FUN(NF,KA,X,FA) IF (ISNA.GE.1) AF(KA)=FA IF (IEXT.EQ.0) THEN IF (KA.EQ.1) F=ABS(FA) F=MAX(F,ABS(FA)) ELSE IF (IEXT.LT.0) THEN IF (KA.EQ.1) F= FA F=MAX(F, FA) ELSE IF (IEXT.GT.0) THEN IF (KA.EQ.1) F=-FA F=MAX(F,-FA) END IF 1 IF (KD.LT.1) GO TO 3 IF (LD.GE.1) GO TO 3 CALL DFUN(NF,KA,X,GA) K=IAG(KA) L=IAG(KA+1)-K DO 2 J=1,L JP=ABS(JAG(K)) IF (IEXT.EQ.0) THEN G(JP)=G(JP)+(AZU(KA)-AZL(KA))*GA(JP) ELSE IF (IEXT.LT.0) THEN G(JP)=G(JP)+AZU(KA)*GA(JP) ELSE IF (IEXT.GT.0) THEN G(JP)=G(JP)-AZL(KA)*GA(JP) END IF IF (ISNA.GE.2) AG(K)=GA(JP) K=K+1 2 CONTINUE 3 CONTINUE RETURN END * SUBROUTINE PP1SA3 ALL SYSTEMS 05/12/01 * PURPOSE : * COMPUTATION OF THE VALUE AND THE GRADIENT OF THE LAGRANGIAN FUNCTION * FOR THE SUM OF ABSOLUTE VALUES. * * PARAMETERS: * II NF NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI X(NF) VECTOR OF VARIABLES. * RI GA(NF) GRADIENT OF THE APPROXIMATED FUNCTION. * RI AG(IAG(N+1)-1) SPARSE RECTANGULAR MATRIX WHICH IS USED FOR THE * DIRECTION VECTOR DETERMINATION. * II IAG(N+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RO G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI AZ(NA) VECTOR OF LAGRANGE MULTIPLIERS. * RI FA VALUE OF THE SELECTED FUNCTION. * RI AF(NA) VALUES OF THE APPROXIMATED FUNCTIONS. * RO F VALUE OF THE OBJECTIVE FUNCTION. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES. * IU NFV NUMBER OF OBJECTIVE FUNCTION VALUES COMPUTED. * IU NFG NUMBER OF OBJECTIVE FUNCTION GRADIENTS COMPUTED. * II ISNA INDICATOR FOR STORING ELEMENTAL FUNCTION VALUES AND * GRADIENTS. ISNA=0-STORING SUPPRESSED. ISNA=1-STORING * ELEMENTAL FUNCTION VALUES. ISNA=2-STORING ELEMENTAL * FUNCTION VALUES AND GRADIENTS. * * SUBPROGRAMS USED : * SE FUN COMPUTATION OF THE VALUE OF THE APPROXIMATED FUNCTION. * SE DFUN COMPUTATION OF THE GRADIENT OF THE APPROXIMATED FUNCTION. * S MXVSET INITIATION OF A VECTOR. * SUBROUTINE PP1SA3(NF,NA,X,GA,AG,IAG,JAG,G,AZ,FA,AF,F,KD,LD,NFV, & NFG,ISNA) INTEGER NF,NA,IAG(*),JAG(*),KD,LD,NFV,NFG,ISNA DOUBLE PRECISION X(*),GA(*),AG(*),G(*),AZ(*),FA,AF(*),F INTEGER J,JP,K,KA,L IF (KD.LE.LD) RETURN IF (KD.GE.0.AND.LD.LT.0) THEN F=0.0D 0 NFV=NFV+1 END IF IF (KD.GE.1.AND.LD.LT.1) THEN CALL MXVSET(NF,0.0D 0,G) NFG=NFG+1 END IF DO 3 KA=1,NA IF (LD.GE.0) GO TO 1 CALL FUN(NF,KA,X,FA) IF (ISNA.GE.1) AF(KA)=FA F=F+ABS(FA) 1 IF (KD.LT.1) GO TO 3 IF (LD.GE.1) GO TO 3 CALL DFUN(NF,KA,X,GA) K=IAG(KA) L=IAG(KA+1)-K DO 2 J=1,L JP=ABS(JAG(K)) G(JP)=G(JP)+AZ(KA)*GA(JP) IF (ISNA.GE.2) AG(K)=GA(JP) K=K+1 2 CONTINUE 3 CONTINUE RETURN END * SUBROUTINE PPLAG1 ALL SYSTEMS 05/12/01 * PURPOSE : * COMPUTATION OF THE LAGRANGE MULTIPLIERS FOR THE SUM OF ABSOLUTE * VALUES. * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI AF(NA) VECTOR CONTAINING VALUES OF APPROXIMATED FUNCTIONS. * RA AS(NA) AUXILIARY ARRAY. * RO AZ(NA) LAGRANGE MULTIPLIERS. * RI RPF3 BARRIER COEFFICIENT. * SUBROUTINE PPLAG1(NA,AF,AS,AZ,RPF3) INTEGER NA DOUBLE PRECISION AF(*),AS(*),AZ(*),RPF3 DOUBLE PRECISION FA INTEGER KA DO 1 KA=1,NA FA=AF(KA) AS(KA)=RPF3+SQRT(RPF3**2+FA**2) AZ(KA)=FA/AS(KA) 1 CONTINUE RETURN END * SUBROUTINE PS0G01 ALL SYSTEMS 97/12/01 * PURPOSE : * SIMPLE SEARCH WITH TRUST REGION UPDATE. * * PARAMETERS : * RO R VALUE OF THE STEPSIZE PARAMETER. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI FO INITIAL VALUE OF THE OBJECTIVE FUNCTION. * RI PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * RI PP QUADRATIC PART OF THE PREDICTED FUNCTION VALUE. * RU XDEL TRUST REGION BOUND. * RO XDELO PREVIOUS TRUST REGION BOUND. * RI XMAX MAXIMUM STEPSIZE. * RI RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * RI SNORM EUCLIDEAN NORM OF THE DIRECTION VECTOR. * RI BET1 LOWER BOUND FOR STEPSIZE REDUCTION. * RI BET2 UPPER BOUND FOR STEPSIZE REDUCTION. * RI GAM1 LOWER BOUND FOR STEPSIZE EXPANSION. * RI GAM2 UPPER BOUND FOR STEPSIZE EXPANSION. * RI EPS4 FIRST TOLERANCE FOR RATIO DF/DFPRED. STEP BOUND IS * DECREASED IF DF/DFPREDEPS5. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES OF OBJECTIVE * FUNCTION. * IU IDIR INDICATOR FOR DIRECTION DETERMINATION. * IDIR=0-BASIC DETERMINATION. IDIR=1-DETERMINATION * AFTER STEPSIZE REDUCTION. IDIR=2-DETERMINATION AFTER * STEPSIZE EXPANSION. * IO ITERS TERMINATION INDICATOR. ITERS=0-ZERO STEP. ITERS=1-STEP * BOUND WAS DECREASED. ITERS=2-STEP BOUND WAS UNCHANGED. * ITERS=3-STEP BOUND WAS INCREASED. ITERS=6-FIRST STEPSIZE. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO MAXST MAXIMUM STEPSIZE INDICATOR. MAXST=0 OR MAXST=1 IF MAXIMUM * STEPSIZE WAS NOT OR WAS REACHED. * IO NRED ACTUAL NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * II MRED MAXIMUM NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * II KTERS TERMINATION SELECTION. KTERS=1-NORMAL TERMINATION. * KTERS=6-FIRST STEPSIZE. * II MES1 SWITCH FOR EXTRAPOLATION. MES1=1-CONSTANT INCREASING OF * THE INTERVAL. MES1=2-EXTRAPOLATION SPECIFIED BY THE PARAMETER * MES. MES1=3 SUPPRESSED EXTRAPOLATION. * II MES2 SWITCH FOR TERMINATION. MES2=1-NORMAL TERMINATION. * MES2=2-TERMINATION AFTER AT LEAST TWO STEPS (ASYMPTOTICALLY * PERFECT LINE SEARCH). * II MES3 SAFEGUARD AGAINST ROUNDING ERRORS. MES3=0-SAFEGUARD * SUPPRESSED. MES3=1-FIRST LEVEL OF SAFEGUARD. MES3=2-SECOND * LEVEL OF SAFEGUARD. * IU ISYS CONTROL PARAMETER. * * METHOD : * G.A.SCHULTZ, R.B.SCHNABEL, R.H.BYRD: A FAMILY OF TRUST-REGION-BASED * ALGORITHMS FOR UNCONSTRAINED MINIMIZATION WITH STRONG GLOBAL * CONVERGENCE PROPERTIES, SIAM J. NUMER.ANAL. 22 (1985) PP. 47-67. * SUBROUTINE PS0G01(R,F,FO,PO,PP,XDEL,XDELO,XMAX,RMAX,SNORM,BET1, & BET2,GAM1,GAM2,EPS4,EPS5,KD,LD,IDIR,ITERS,ITERD,MAXST,NRED,MRED, & KTERS,MES1,MES2,MES3,ISYS) INTEGER KD,LD,IDIR,ITERS,ITERD,MAXST,NRED,MRED,KTERS,MES1,MES2, & MES3,ISYS DOUBLE PRECISION R,F,FO,PO,PP,XDEL,XDELO,XMAX,RMAX,SNORM,BET1, & BET2,GAM1,GAM2,EPS4,EPS5 DOUBLE PRECISION DF,DFPRED INTEGER NRED1,NRED2 SAVE NRED1,NRED2 IF (ISYS.EQ.1) GO TO 2 IF (IDIR.EQ.0) THEN NRED1=0 NRED2=0 END IF IDIR=0 XDELO=XDEL * * COMPUTATION OF THE NEW FUNCTION VALUE * R=MIN(1.0D 0,RMAX) KD= 0 LD=-1 ISYS=1 RETURN 2 CONTINUE IF (KTERS.LT.0.OR.KTERS.GT.5) THEN ITERS=6 ELSE DF=FO-F DFPRED=-R*(PO+R*PP) IF (DF.LT.EPS4*DFPRED) THEN * * STEP IS TOO LARGE, IT HAS TO BE REDUCED * IF (MES1.EQ.1) THEN XDEL=BET2*SNORM ELSE IF (MES1.EQ.2) THEN XDEL=BET2*MIN(0.5D 0*XDEL,SNORM) ELSE XDEL=0.5D 0*PO*SNORM/(PO+DF) XDEL=MAX(XDEL,BET1*SNORM) XDEL=MIN(XDEL,BET2*SNORM) END IF ITERS=1 IF (MES3.LE.1) THEN NRED2=NRED2+1 ELSE IF (ITERD.GT.2) NRED2=NRED2+1 END IF ELSE IF (DF.LE.EPS5*DFPRED) THEN * * STEP IS SUITABLE * ITERS=2 ELSE * * STEP IS TOO SMALL, IT HAS TO BE ENLARGED * IF (MES2.EQ.2) THEN XDEL=MAX(XDEL,GAM1*SNORM) ELSE IF (ITERD.GT.2) THEN XDEL=GAM1*XDEL END IF ITERS=3 END IF XDEL=MIN(XDEL,XMAX,GAM2*SNORM) IF (FO.LE.F) THEN IF (NRED1.GE.MRED) THEN ITERS=-1 ELSE IDIR=1 ITERS=0 NRED1=NRED1+1 END IF END IF END IF MAXST=0 IF (XDEL.GE.XMAX) MAXST=1 IF (MES3.EQ.0) THEN NRED=NRED1 ELSE NRED=NRED2 END IF ISYS=0 RETURN END * SUBROUTINE PS0L02 ALL SYSTEMS 97/12/01 * PURPOSE : * EXTENDED LINE SEARCH WITHOUT DIRECTIONAL DERIVATIVES. * * PARAMETERS : * RO R VALUE OF THE STEPSIZE PARAMETER. * RO RO INITIAL VALUE OF THE STEPSIZE PARAMETER. * RO RP PREVIOUS VALUE OF THE STEPSIZE PARAMETER. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI FO INITIAL VALUE OF THE OBJECTIVE FUNCTION. * RO FP PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RI PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP PREVIOUS VALUE OF THE DIRECTIONAL DERIVATIVE. * RI FMIN LOWER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI FMAX UPPER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI RMIN MINIMUM VALUE OF THE STEPSIZE PARAMETER * RI RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER * RI TOLS TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE FUNCTION VALUE). * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES OF OBJECTIVE * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO NRED ACTUAL NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * II MRED MAXIMUM NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * IO MAXST MAXIMUM STEPSIZE INDICATOR. MAXST=0 OR MAXST=1 IF MAXIMUM * STEPSIZE WAS NOT OR WAS REACHED. * II IEST LOWER BOUND SPECIFICATION. IEST=0 OR IEST=1 IF LOWER BOUND * IS NOT OR IS GIVEN. * II INITS CHOICE OF THE INITIAL STEPSIZE. INITS=0-INITIAL STEPSIZE * IS SPECIFIED IN THE CALLING PROGRAM. INITS=1-UNIT INITIAL * STEPSIZE. INITS=2-COMBINED UNIT AND QUADRATICALLY ESTIMATED * INITIAL STEPSIZE. INITS=3-QUADRATICALLY ESTIMATED INITIAL * STEPSIZE. * IO ITERS TERMINATION INDICATOR. ITERS=0-ZERO STEP. ITERS=1-PERFECT * LINE SEARCH. ITERS=2 GOLDSTEIN STEPSIZE. ITERS=3-CURRY * STEPSIZE. ITERS=4-EXTENDED CURRY STEPSIZE. * ITERS=5-ARMIJO STEPSIZE. ITERS=6-FIRST STEPSIZE. * ITERS=7-MAXIMUM STEPSIZE. ITERS=8-UNBOUNDED FUNCTION. * ITERS=-1-MRED REACHED. ITERS=-2-POSITIVE DIRECTIONAL * DERIVATIVE. ITERS=-3-ERROR IN INTERPOLATION. * II KTERS TERMINATION SELECTION. KTERS=1-PERFECT LINE SEARCH. * KTERS=2-GOLDSTEIN STEPSIZE. KTERS=3-CURRY STEPSIZE. * KTERS=4-EXTENDED CURRY STEPSIZE. KTERS=5-ARMIJO STEPSIZE. * KTERS=6-FIRST STEPSIZE. * II MES METHOD SELECTION. MES=1-BISECTION. MES=2-QUADRATIC * INTERPOLATION (WITH ONE DIRECTIONAL DERIVATIVE). * MES=3-QUADRATIC INTERPOLATION (WITH TWO DIRECTIONAL * DERIVATIVES). MES=4-CUBIC INTERPOLATION. MES=5-CONIC * INTERPOLATION. * IU ISYS CONTROL PARAMETER. * * SUBPROGRAM USED : * S PNINT3 EXTRAPOLATION OR INTERPOLATION WITHOUT DIRECTIONAL * DERIVATIVES. * * METHOD : * SAFEGUARDED EXTRAPOLATION AND INTERPOLATION WITH EXTENDED TERMINATION * CRITERIA. * SUBROUTINE PS0L02(R,RO,RP,F,FO,FP,PO,PP,FMIN,FMAX,RMIN,RMAX,TOLS, & KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST,INITS,ITERS,KTERS,MES,ISYS) INTEGER KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST,INITS,ITERS,KTERS,MES, & ISYS DOUBLE PRECISION R,RO,RP,F,FO,FP,PO,PP,FMIN,FMAX,RMIN,RMAX,TOLS DOUBLE PRECISION RL,FL,RU,FU,RI,FI,RTEMP,TOL INTEGER MTYP,MERR,MODE,INIT1,MES1,MES2 LOGICAL L1,L2,L3,L4,L6,L7 PARAMETER(TOL=1.0D-2) SAVE MTYP,MODE,MES1,MES2 SAVE RL,FL,RU,FU,RI,FI IF (ISYS.EQ.1) GO TO 3 MES1=2 MES2=2 ITERS=0 IF (PO.GE.0.0D 0) THEN R=0.0D 0 ITERS=-2 GO TO 4 END IF IF (RMAX.LE.0.0D 0) THEN ITERS= 0 GO TO 4 END IF * * INITIAL STEPSIZE SELECTION * IF (INITS.GT.0) THEN RTEMP=FMIN-F ELSE IF (IEST.EQ.0) THEN RTEMP=F-FP ELSE RTEMP=MAX(F-FP,FMIN-F) END IF INIT1=ABS(INITS) RP=0.0D 0 FP=FO PP=PO IF (INIT1.EQ.0) THEN ELSE IF (INIT1.EQ.1.OR.INITS.GE.1.AND.IEST.EQ.0) THEN R=1.0D 0 ELSE IF (INIT1.EQ.2) THEN R=MIN(1.0D 0,4.0D 0*RTEMP/PO) ELSE IF (INIT1.EQ.3) THEN R=MIN(1.0D 0, 2.0D 0*RTEMP/PO) ELSE IF (INIT1.EQ.4) THEN R=2.0D 0*RTEMP/PO END IF RTEMP=R R=MAX(R,RMIN) R=MIN(R,RMAX) MODE=0 RL=0.0D 0 FL=FO RU=0.0D 0 FU=FO RI=0.0D 0 FI=FO * * NEW STEPSIZE SELECTION (EXTRAPOLATION OR INTERPOLATION) * 2 CALL PNINT3(RO,RL,RU,RI,FO,FL,FU,FI,PO,R,MODE,MTYP,MERR) IF (MERR.GT.0) THEN ITERS=-MERR GO TO 4 ELSE IF (MODE.EQ.1) THEN NRED=NRED-1 R=MIN(R,RMAX) ELSE IF (MODE.EQ.2) THEN NRED=NRED+1 END IF * * COMPUTATION OF THE NEW FUNCTION VALUE * KD= 0 LD=-1 ISYS=1 RETURN 3 CONTINUE IF (ITERS.NE.0) GO TO 4 IF (F.LE.FMIN) THEN ITERS=7 GO TO 4 ELSE L1=R.LE.RMIN.AND.NIT.NE.KIT L2=R.GE.RMAX L3=F-FO.LE.TOLS*R*PO.OR.F-FMIN.LE.(FO-FMIN)/1.0D 1 L4=F-FO.GE.(1.0D 0-TOLS)*R*PO.OR.MES2.EQ.2.AND.MODE.EQ.2 L6=RU-RL.LE.TOL*RU.AND.MODE.EQ.2 L7=MES2.LE.2.OR.MODE.NE.0 MAXST=0 IF (L2) MAXST=1 END IF * * TEST ON TERMINATION * IF (L1.AND..NOT.L3) THEN ITERS=0 GO TO 4 ELSE IF (L2.AND..NOT.F.GE.FU) THEN ITERS=7 GO TO 4 ELSE IF (L6) THEN ITERS=1 GO TO 4 ELSE IF (L3.AND.L7.AND.KTERS.EQ.5) THEN ITERS=5 GO TO 4 ELSE IF (L3.AND.L4.AND.L7.AND.(KTERS.EQ.2.OR.KTERS.EQ.3.OR. * KTERS.EQ.4)) THEN ITERS=2 GO TO 4 ELSE IF (KTERS.LT.0.OR.KTERS.EQ.6.AND.L7) THEN ITERS=6 GO TO 4 ELSE IF (ABS(NRED).GE.MRED) THEN ITERS=-1 GO TO 4 ELSE RP=R FP=F MODE=MAX(MODE,1) MTYP=ABS(MES) IF (F.GE.FMAX) MTYP=1 END IF IF (MODE.EQ.1) THEN * * INTERVAL CHANGE AFTER EXTRAPOLATION * RL=RI FL=FI RI=RU FI=FU RU=R FU=F IF (F.GE.FI) THEN NRED=0 MODE=2 ELSE IF ( MES1 .EQ. 1) THEN MTYP=1 END IF * * INTERVAL CHANGE AFTER INTERPOLATION * ELSE IF (R.LE.RI) THEN IF (F.LE.FI) THEN RU=RI FU=FI RI=R FI=F ELSE RL=R FL=F END IF ELSE IF (F.LE.FI) THEN RL=RI FL=FI RI=R FI=F ELSE RU=R FU=F END IF END IF GO TO 2 4 ISYS=0 RETURN END * SUBROUTINE PS1L01 ALL SYSTEMS 97/12/01 * PURPOSE : * STANDARD LINE SEARCH WITH DIRECTIONAL DERIVATIVES. * * PARAMETERS : * RO R VALUE OF THE STEPSIZE PARAMETER. * RO RP PREVIOUS VALUE OF THE STEPSIZE PARAMETER. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI FO INITIAL VALUE OF THE OBJECTIVE FUNCTION. * RO FP PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RO P VALUE OF THE DIRECTIONAL DERIVATIVE. * RI PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * RO PP PREVIOUS VALUE OF THE DIRECTIONAL DERIVATIVE. * RI FMIN LOWER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI FMAX UPPER BOUND FOR VALUE OF THE OBJECTIVE FUNCTION. * RI RMIN MINIMUM VALUE OF THE STEPSIZE PARAMETER * RI RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER * RI TOLS TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE FUNCTION VALUE). * RI TOLP TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE DIRECTIONAL DERIVATIVE). * RO PAR1 PARAMETER FOR CONTROLLED SCALING OF VARIABLE METRIC * UPDATES. * RO PAR2 PARAMETER FOR CONTROLLED SCALING OF VARIABLE METRIC * UPDATES. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES OF OBJECTIVE * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO NRED ACTUAL NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * II MRED MAXIMUM NUMBER OF EXTRAPOLATIONS OR INTERPOLATIONS. * IO MAXST MAXIMUM STEPSIZE INDICATOR. MAXST=0 OR MAXST=1 IF MAXIMUM * STEPSIZE WAS NOT OR WAS REACHED. * II IEST LOWER BOUND SPECIFICATION. IEST=0 OR IEST=1 IF LOWER BOUND * IS NOT OR IS GIVEN. * II INITS CHOICE OF THE INITIAL STEPSIZE. INITS=0-INITIAL STEPSIZE * IS SPECIFIED IN THE CALLING PROGRAM. INITS=1-UNIT INITIAL * STEPSIZE. INITS=2-COMBINED UNIT AND QUADRATICALLY ESTIMATED * INITIAL STEPSIZE. INITS=3-QUADRATICALLY ESTIMATED INITIAL * STEPSIZE. * IO ITERS TERMINATION INDICATOR. ITERS=0-ZERO STEP. ITERS=1-PERFECT * LINE SEARCH. ITERS=2 GOLDSTEIN STEPSIZE. ITERS=3-CURRY * STEPSIZE. ITERS=4-EXTENDED CURRY STEPSIZE. * ITERS=5-ARMIJO STEPSIZE. ITERS=6-FIRST STEPSIZE. * ITERS=7-MAXIMUM STEPSIZE. ITERS=8-UNBOUNDED FUNCTION. * ITERS=-1-MRED REACHED. ITERS=-2-POSITIVE DIRECTIONAL * DERIVATIVE. ITERS=-3-ERROR IN INTERPOLATION. * II KTERS TERMINATION SELECTION. KTERS=1-PERFECT LINE SEARCH. * KTERS=2-GOLDSTEIN STEPSIZE. KTERS=3-CURRY STEPSIZE. * KTERS=4-EXTENDED CURRY STEPSIZE. KTERS=5-ARMIJO STEPSIZE. * KTERS=6-FIRST STEPSIZE. * II MES METHOD SELECTION. MES=1-BISECTION. MES=2-QUADRATIC * INTERPOLATION (WITH ONE DIRECTIONAL DERIVATIVE). * MES=3-QUADRATIC INTERPOLATION (WITH TWO DIRECTIONAL * DERIVATIVES). MES=4-CUBIC INTERPOLATION. MES=5-CONIC * INTERPOLATION. * IU ISYS CONTROL PARAMETER. * * SUBPROGRAM USED : * S PNINT1 EXTRAPOLATION OR INTERPOLATION WITH DIRECTIONAL * DERIVATIVES. * * METHOD : * SAFEGUARDED EXTRAPOLATION AND INTERPOLATION WITH STANDARD TERMINATION * CRITERIA. * SUBROUTINE PS1L01(R,RP,F,FO,FP,P,PO,PP,FMIN,FMAX,RMIN,RMAX, & TOLS,TOLP,PAR1,PAR2,KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST,INITS, & ITERS,KTERS,MES,ISYS) INTEGER KD,LD,NIT,KIT,NRED,MRED,MAXST,IEST,INITS,ITERS,KTERS, & MES,ISYS DOUBLE PRECISION R,RP,F,FO,FP,P,PO,PP,FMIN,FMAX,RMIN,RMAX, & TOLS,TOLP,PAR1,PAR2 DOUBLE PRECISION RL,FL,PL,RU,FU,PU,RTEMP INTEGER MTYP,MERR,MODE,INIT1,MES1,MES2,MES3 LOGICAL L1,L2,L3,L5,L7,M1,M2,M3 DOUBLE PRECISION CON,CON1 PARAMETER (CON=1.0D-2,CON1=1.0D-13) SAVE MTYP,MODE,MES1,MES2,MES3 SAVE RL,FL,PL,RU,FU,PU IF (ISYS.EQ.1) GO TO 3 MES1=2 MES2=2 MES3=2 ITERS=0 IF (PO.GE.0.0D 0) THEN R=0.0D 0 ITERS=-2 GO TO 4 END IF IF (RMAX.LE.0.0D 0) THEN ITERS=0 GO TO 4 END IF * * INITIAL STEPSIZE SELECTION * IF (INITS.GT.0) THEN RTEMP=FMIN-F ELSE IF (IEST.EQ.0) THEN RTEMP=F-FP ELSE RTEMP=MAX(F-FP,FMIN-F) END IF INIT1=ABS(INITS) RP=0.0D 0 FP=FO PP=PO IF (INIT1.EQ.0) THEN ELSE IF (INIT1.EQ.1.OR.INITS.GE.1.AND.IEST.EQ.0) THEN R=1.0D 0 ELSE IF (INIT1.EQ.2) THEN R=MIN(1.0D 0,4.0D 0*RTEMP/PO) ELSE IF (INIT1.EQ.3) THEN R=MIN(1.0D 0, 2.0D 0*RTEMP/PO) ELSE IF (INIT1.EQ.4) THEN R=2.0D 0*RTEMP/PO END IF R=MAX(R,RMIN) R=MIN(R,RMAX) MODE=0 RU=0.0D 0 FU=FO PU=PO * * NEW STEPSIZE SELECTION (EXTRAPOLATION OR INTERPOLATION) * 2 CALL PNINT1(RL,RU,FL,FU,PL,PU,R,MODE,MTYP,MERR) IF (MERR.GT.0) THEN ITERS=-MERR GO TO 4 ELSE IF (MODE.EQ.1) THEN NRED=NRED-1 R=MIN(R,RMAX) ELSE IF (MODE.EQ.2) THEN NRED=NRED+1 END IF * * COMPUTATION OF THE NEW FUNCTION VALUE AND THE NEW DIRECTIONAL * DERIVATIVE * KD= 1 LD=-1 ISYS=1 RETURN 3 CONTINUE IF (MODE.EQ.0) THEN PAR1=P/PO PAR2=F-FO END IF IF (ITERS.NE.0) GO TO 4 IF (F.LE.FMIN) THEN ITERS=7 GO TO 4 ELSE L1=R.LE.RMIN.AND.NIT.NE.KIT L2=R.GE.RMAX L3=F-FO.LE.TOLS*R*PO L5=P.GE.TOLP*PO.OR.MES2.EQ.2.AND.MODE.EQ.2 L7=MES2.LE.2.OR.MODE.NE.0 M1=.FALSE. M2=.FALSE. M3=L3 IF (MES3.GE.1) THEN M1=ABS(P).LE.CON*ABS(PO).AND.FO-F.GE.(CON1/CON)*ABS(FO) L3=L3.OR.M1 END IF IF (MES3.GE.2) THEN M2=ABS(P).LE.0.5D 0*ABS(PO).AND.ABS(FO-F).LE.2.0D 0*CON1*ABS(FO) L3=L3.OR.M2 END IF MAXST=0 IF (L2) MAXST=1 END IF * * TEST ON TERMINATION * IF (L1.AND..NOT.L3) THEN ITERS=0 GO TO 4 ELSE IF (L2.AND.L3.AND..NOT.L5) THEN ITERS=7 GO TO 4 ELSE IF (M3.AND.MES1.EQ.3) THEN ITERS=5 GO TO 4 ELSE IF (L3.AND.L5.AND.L7) THEN ITERS=4 GO TO 4 ELSE IF (KTERS.LT.0.OR.KTERS.EQ.6.AND.L7) THEN ITERS=6 GO TO 4 ELSE IF (ABS(NRED).GE.MRED) THEN ITERS=-1 GO TO 4 ELSE RP=R FP=F PP=P MODE=MAX(MODE,1) MTYP=ABS(MES) IF (F.GE.FMAX) MTYP=1 END IF IF (MODE.EQ.1) THEN * * INTERVAL CHANGE AFTER EXTRAPOLATION * RL=RU FL=FU PL=PU RU=R FU=F PU=P IF (.NOT.L3) THEN NRED=0 MODE=2 ELSE IF ( MES1 .EQ. 1) THEN MTYP=1 END IF ELSE * * INTERVAL CHANGE AFTER INTERPOLATION * IF (.NOT.L3) THEN RU=R FU=F PU=P ELSE RL=R FL=F PL=P END IF END IF GO TO 2 4 ISYS=0 RETURN END * SUBROUTINE PS1L18 ALL SYSTEMS 99/12/01 * PURPOSE : * SPECIAL LINE SEARCH FOR NONSMOOTH NONCONVEX VARIABLE METRIC METHOD. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * II MA DECLARED NUMBER OF LINEAR APPROXIMATED FUNCTIONS * II MAL CURRENT NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * RU X(N) VECTOR OF VARIABLES. * RO G(N) SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RI S(N) DIRECTION VECTOR. * RU U(N) PREVIOUS VECTOR OF VARIABLES. * RI AF(4*MA) VECTOR OF BUNDLE FUNCTIONS VALUES. * RI AG(N*MA) MATRIX WHOSE COLUMNS ARE BUNDLE SUBGRADIENTS. * RI AY(N*MA) MATRIX WHOSE COLUMNS ARE VARIABLE VECTORS. * RO T VALUE OF THE STEPSIZE PARAMETER. * RO TB BUNDLE PARAMETER FOR MATRIX SCALING. * RO FO PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RU PO PREVIOUS DIRECTIONAL DERIVATIVE. * RU P DIRECTIONAL DERIVATIVE. * RI TMIN MINIMUM VALUE OF THE STEPSIZE PARAMETER. * RI TMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * RI SNORM EUCLIDEAN NORM OF THE DIRECTION VECTOR. * RI WK STOPPING PARAMETER. * RI EPS1 TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * CHANGE OF THE FUNCTION VALUE). * RI EPS2 TERMINATION TOLERANCE FOR LINE SEARCH (IN TEST ON THE * DIRECTIONAL DERIVATIVE). * RI ETA5 DISTANCE MEASURE PARAMETER. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * II KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF PREVIOUSLY COMPUTED DERIVATIVES OF OBJECTIVE * II JE EXTRAPOLATION INDICATOR. * RI MOS3 LOCALITY MEASURE PARAMETER. * IO ITERS NULL STEP INDICATOR. ITERS=0-NULL STEP. ITERS=1-DESCENT * STEP. * IU ISYS CONTROL PARAMETER. * * VARIABLES IN COMMON /STAT/ (STATISTICS) : * IO NRES NUMBER OF RESTARTS. * IO NDEC NUMBER OF MATRIX DECOMPOSITIONS. * IO NIN NUMBER OF INNER ITERATIONS. * IO NIT NUMBER OF ITERATIONS. * IO NFV NUMBER OF FUNCTION EVALUATIONS. * IO NFG NUMBER OF GRADIENT EVALUATIONS. * IO NFH NUMBER OF HESSIAN EVALUATIONS. * * SUBPROGRAMS USED : * S PNINT1 EXTRAPOLATION OR INTERPOLATION FOR LINE SEARCH * S PNSTP4 STEPSIZE DETERMINATION FOR DESCENT STEPS. * S PNSTP5 STEPSIZE DETERMINATION FOR NULL STEPS. * WITH DIRECTIONAL DERIVATIVES. * S MXVDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXVDOT DOT PRODUCT OF TWO VECTORS. * * METHOD : * SPECIAL METHOD OF STEP LENGTH DETERMINATION. * SUBROUTINE PS1L18(N,MA,MAL,X,G,S,U,AF,AG,AY,T,TB,FO,F,PO,P,TMIN, & TMAX,SNORM,WK,EPS1,EPS2,ETA5,ETA9,KD,LD,JE,MOS3,ITERS,ISYS) DOUBLE PRECISION EPS1,EPS2,ETA5,ETA9,F,FO,P,PO,SNORM,T,TB,TMAX, & TMIN,WK INTEGER ITERS,ISYS,JE,KD,LD,MA,MAL,MOS3,N DOUBLE PRECISION AF(*),AG(*),AY(*),G(*),S(*),U(*),X(*) DOUBLE PRECISION BET,FL,FU,PL,PU,TL,TU INTEGER IER DOUBLE PRECISION MXVDOT SAVE FL,FU,PL,PU,TL,TU IF (ISYS.GT.0) GO TO 25 IF (JE.GT.0) T = DBLE(2-JE/99)*T IF (JE.LE.0) T = MIN(1.0D0,TMAX) IF (PO.EQ.0.0D0 .OR. JE.GT.0) GO TO 10 IF (ITERS.EQ.1) THEN CALL PNSTP4(N,MA,MAL,X,AF,AG,AY,S,F,PO,T,TB,ETA5,ETA9,MOS3) ELSE CALL PNSTP5(N,MA,MAL,X,AF,AG,AY,S,F,PO,T,TB,ETA5,ETA9,MOS3) END IF 10 T = MIN(MAX(T,TMIN),TMAX) TL = 0.0D0 TU = T FL = FO PL = PO * * FUNCTION AND GRADIENT EVALUATION AT A NEW POINT * 20 CALL MXVDIR(N,T,S,U,X) KD= 1 LD=-1 ISYS=1 RETURN 25 CONTINUE P = MXVDOT(N,G,S) * * NULL/DESCENT STEP TEST (ITERS=0/1) * ITERS = 1 IF (F.LE.FO-T* (EPS1+EPS1)*WK) THEN TL = T FL = F PL = P ELSE TU = T FU = F PU = P END IF BET = MAX(ABS(FO-F+P*T),ETA5* (SNORM*T)**MOS3) IF (F.LE.FO-T*EPS1*WK .AND. (T.GE.TMIN.OR. & BET.GT.EPS1*WK)) GO TO 40 IF (P-BET.GE.-EPS2*WK .OR. TU-TL.LT.TMIN*1.0D-1) GO TO 30 IF (TL.EQ.0.0D0 .AND. PL.LT.0.0D0) THEN CALL PNINT1(TL,TU,FL,FU,PL,PU,T,2,2,IER) ELSE T = 5.0D-1* (TU+TL) END IF GO TO 20 30 ITERS = 0 40 CONTINUE ISYS=0 RETURN END * SUBROUTINE PUBBM1 ALL SYSTEMS 97/12/01 * PURPOSE : * PARTITIONED VARIABLE METRIC UPDATE. * * PARAMETERS : * II NA NUMBER OF BLOCKS OF THE MATRIX H. * RU AH(MB) APPROXIMATION OF THE PARTITIONED HESSIAN MATRIX. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RA S(NF) AUXILIARY VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI AGO(MA) GRADIENTS DIFFERENCE. * RI ETA0 MACHINE PRECISION. * RI ETA9 MAXIMUM MACHINE NUMBER. * IU ICOR SWITCH BETWEEN UPDATES. ICOR=0-THE BFGS UPDATE. * ICOR=1-THE RANK ONE UPDATE. * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET METHOD SELECTION. MET=0-NO UPDATE. MET=1-BFGS UPDATE. * MET=2-COMBINATION OF BFGS AND RANK-ONE UPDATES. * II MET1 SELECTION OF SELF SCALING. MET1=1-SELF SCALING SUPPRESSED. * MET1=2 SELF SCALING IN THE FIRST ITERATION AFTER RESTART. * MET1=3-SELF SCALING IN EACH ITERATION. * * SUBPROGRAMS USED : * S MXBSBM MULTIPLICATION OF A PARTITIONED MATRIX BY A VECTOR. * S MXBSBU UPDATE OF A PARTITIONED MATRIX. * S MXDSMS SCALING OF A DENSE SYMMETRIC MATRIX. * S MXWDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXWDOT DOT PRODUCT OF TWO SPARSE VECTORS. * SUBROUTINE PUBBM1(NA,AH,IAG,JAG,S,XO,AGO,ETA0,ETA9,ICOR,NIT,KIT, & ITERH,MET,MET1) INTEGER NA,IAG(*),JAG(*),ICOR,NIT,KIT,ITERH,MET, & MET1 DOUBLE PRECISION AH(*),S(*),XO(*),AGO(*),ETA0,ETA9 DOUBLE PRECISION A,B,C,GAM,POM,DEN,MXWDOT INTEGER K,L,KA,NB,INEG LOGICAL L1,L3 IF (MET.LE.0) GO TO 22 L1=MET1.GE.3.OR.MET1.EQ.2.AND.NIT.EQ.KIT L3=.NOT.L1 NB=0 INEG=0 DO 21 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K * * DETERMINATION OF THE PARAMETERS B, C * B=MXWDOT(L,JAG(K),AGO(K),XO,2) IF (MET.EQ.1) THEN IF (B.LE.1.0D 0/ETA9) GO TO 20 ELSE IF (ABS(B).LE.1.0D 0/ETA9) GO TO 20 END IF A=0.0D 0 CALL MXBSBM(L,AH(NB+1),JAG(K),XO,S,1) C=MXWDOT(L,JAG(K),XO,S,1) IF (ABS(C).LE.1.0D 0/ETA9) GO TO 20 IF (L1) THEN * * DETERMINATION OF THE PARAMETER GAM (SELF SCALING) * GAM=C/B IF (L3) THEN GAM=1.0D 0 END IF ELSE GAM=1.0D 0 END IF IF (MET.EQ.1) THEN * * BFGS UPDATE * POM=0.0D 0 CALL MXBSBU(L,AH(NB+1),JAG(K),GAM/B,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/C,S,1) ELSE IF (B.LT.0.0D 0) INEG=INEG+1 IF (ICOR.GT.0) THEN * * RANK ONE UPDATE * DEN=GAM*B-C IF (ABS(DEN).GT.ETA0*ABS(C)) THEN POM=GAM*B/DEN CALL MXWDIR(L,JAG(K),-GAM,AGO(K),S,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K), 1.0D 0/DEN,AGO(K),2) ELSE GO TO 20 END IF ELSE IF (B.LT.0.0D 0) THEN GO TO 20 ELSE * * BFGS UPDATE * POM=0.0D 0 CALL MXBSBU(L,AH(NB+1),JAG(K),GAM/B,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/C,S,1) END IF END IF ITERH=0 IF (GAM.NE.1.0D 0) THEN CALL MXDSMS(L,AH(NB+1),1.0D 0/GAM) END IF 20 CONTINUE NB=NB+L*(L+1)/2 21 CONTINUE IF (INEG.GE.NA/2) ICOR=1 22 CONTINUE RETURN END * SUBROUTINE PUBBM2 ALL SYSTEMS 97/12/01 * PURPOSE : * PARTITIONED VARIABLE METRIC UPDATE. * * PARAMETERS : * II NA NUMBER OF BLOCKS OF THE MATRIX H. * RU AH(MB) APPROXIMATION OF THE PARTITIONED HESSIAN MATRIX. * RI IAG(NA+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RA S(NF) AUXILIARY VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI AGO(MA) GRADIENTS DIFFERENCE. * RI ETA0 MACHINE PRECISION. * RI ETA9 MAXIMUM MACHINE NUMBER. * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET VARIABLE METRIC UPDATE. MET=1-THE BFGS UPDATE. MET=2-THE * DFP UPDATE. MET=3-THE HOSHINO UPDATE. MET=4-THE RANK ONE * UPDATE. * II MET1 SELECTION OF SELF SCALING. MET1=1-SELF SCALING SUPPRESSED. * MET1=2 SELF SCALING IN THE FIRST ITERATION AFTER RESTART. * MET1=3-CONTROLLED SELF SCALING. * II MET3 CORRECTION OF THE UPDATE. MET3=1-CORRECTION IS SUPPRESSED. * MET3=2-THE POWELL UPDATE. * * SUBPROGRAMS USED : * S MXBSBM MULTIPLICATION OF A PARTITIONED MATRIX BY A VECTOR. * S MXBSBU UPDATE OF A PARTITIONED MATRIX. * S MXDSMS SCALING OF A DENSE SYMMETRIC MATRIX. * S MXWDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXWDOT DOT PRODUCT OF TWO SPARSE VECTORS. * SUBROUTINE PUBBM2(NA,AH,IAG,JAG,S,XO,AGO,ETA0,ETA9,NIT,KIT,ITERH, & MET,MET1,MET3) INTEGER NA,IAG(*),JAG(*),NIT,KIT,ITERH,MET,MET1,MET3 DOUBLE PRECISION AH(*),S(*),XO(*),AGO(*),ETA0,ETA9 DOUBLE PRECISION A,B,C,GAM,POM,DEN,DIS,MXWDOT INTEGER K,L,KA,NB LOGICAL L1,L3 DOUBLE PRECISION CON,CON1,CON2 PARAMETER (CON=0.1D 0,CON1=0.5D 0,CON2=4.0D 0) L1=MET1.GE.3.OR.MET1.EQ.2.AND.NIT.EQ.KIT L3=.NOT.L1 NB=0 DO 21 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K * * DETERMINATION OF THE PARAMETERS B, C * B=MXWDOT(L,JAG(K),AGO(K),XO,2) IF (MET3.EQ.1) THEN IF (B.LE.1.0D 0/ETA9) GO TO 20 ELSE IF (ABS(B).LE.1.0D 0/ETA9) GO TO 20 END IF A=0.0D 0 CALL MXBSBM(L,AH(NB+1),JAG(K),XO,S,1) C=MXWDOT(L,JAG(K),XO,S,1) IF (MET3.EQ.3) THEN IF (ABS(C).LE.1.0D 0/ETA9) GO TO 20 ELSE IF (C.LE.1.0D 0/ETA9) GO TO 20 END IF IF (MET3.EQ.2) THEN IF (B.LE.0.0D 0) THEN * * POWELL'S CORRECTION * DIS=(1.0D 0-CON)*C/(C-B) CALL MXWDIR(L,JAG(K),-1.0D 0,AGO(K),S,AGO(K),2) CALL MXWDIR(L,JAG(K),-DIS,AGO(K),S,AGO(K),2) B=C+DIS*(B-C) END IF END IF IF (L1) THEN * * DETERMINATION OF THE PARAMETER GAM (SELF SCALING) * GAM=C/B IF (MET1.EQ.3) THEN IF (NIT.NE.KIT) THEN L3=GAM.LT.CON1.OR.GAM.GT.CON2 END IF ELSE IF (MET1.EQ.4) THEN GAM=MAX(1.0D 0,GAM) END IF IF (L3) THEN GAM=1.0D 0 END IF ELSE GAM=1.0D 0 END IF IF (MET.EQ.1) THEN GO TO 18 ELSE IF (MET.EQ.2) THEN * * DFP UPDATE * DEN=GAM*B+C DIS=GAM+C/B POM=1.0D 0 CALL MXWDIR(L,JAG(K),-DIS,AGO(K),S,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),1.0D 0/DEN,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/DEN,S,1) GO TO 19 ELSE IF (MET.EQ.3) THEN * * HOSHINO UPDATE * DEN=GAM*B+C DIS=0.5D 0*B POM=GAM*B/DEN CALL MXBSBU(L,AH(NB+1),JAG(K),GAM/DIS,AGO(K),2) CALL MXWDIR(L,JAG(K),GAM,AGO(K),S,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/DEN,AGO(K),2) GO TO 19 ELSE IF (MET.EQ.4) THEN * * RANK ONE UPDATE * DEN=GAM*B-C IF (MET3.EQ.3) THEN IF (ABS(DEN).LE.ETA0*ABS(C)) GO TO 18 ELSE IF (DEN.LE.ETA0*C) GO TO 18 END IF POM=GAM*B/DEN CALL MXWDIR(L,JAG(K),-GAM,AGO(K),S,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K), 1.0D 0/DEN,AGO(K),2) GO TO 19 END IF 18 CONTINUE * * BFGS UPDATE * POM=0.0D 0 CALL MXBSBU(L,AH(NB+1),JAG(K),GAM/B,AGO(K),2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/C,S,1) 19 CONTINUE ITERH=0 IF (GAM.NE.1.0D 0) THEN CALL MXDSMS(L,AH(NB+1),1.0D 0/GAM) END IF 20 CONTINUE NB=NB+L*(L+1)/2 21 CONTINUE RETURN END * SUBROUTINE PUBVI2 ALL SYSTEMS 04/12/01 * PURPOSE : * NONSMOOTH VARIABLE METRIC UPDATE OF THE INVERSE HESSIAN MATRIX. * * PARAMETERS : * II NF ACTUAL NUMBER OF VARIABLES. * II NA NUMBER OF APPROXIMATED FUNCTIONS. * II MA NUMBER OF ELEMENTS IN THE FIELD AG. * II MB NUMBER OF NONZERO ELEMENTS OF THE PARTITIONED HESSIAN MATRIX. * RU AH(MB) NUMERICAL VALUES OF ELEMENTS OF THE PARTITIONED HESSIAN * MATRIX. * II IAG(NA+1) POINTERS OF THE JACOBIAN MATRIX. * RI JAG(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * RI AG(NF) NEW GENERALIZED JACOBIAN MATRIX. * RI AGO(NF) OLD GENERALIZED JACOBIAN MATRIX. * RI XO(N) VECTOR OF VARIABLES DIFFERENCE. * RO S(NF) AUXILIARY VECTOR. * RO U(NF) AUXILIARY VECTOR. * RI ETA9 MAXIMUM MACHINE NUMBER. * II NNK CONSECUTIVE NULL STEPS COUNTER. * II NIT ACTUAL NUMBER OF ITERATIONS. * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * * SUBPROGRAMS USED : * S MXBSBM MULTIPLICATION OF A DENSE SYMMETRIC MATRIX BY A VECTOR. * S MXBSBU UPDATE OF A PARTITIONED SYMMETRIC MATRIX. * S MXDSMS SCALING OF A DENSE SYMMETRIC MATRIX. * S MXVDIF DIFFERENCE OF TWO VECTORS. * S MXWDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXWDOT DOT PRODUCT OF VECTORS. * SUBROUTINE PUBVI2(NA,AH,IAG,JAG,AG,AGO,XO,S,U,ETA9,NNK,NIT,ITERH) INTEGER NA,IAG(*),JAG(*),NNK,NIT,ITERH DOUBLE PRECISION AH(*),AG(*),AGO(*),XO(*),S(*),U(*),ETA9 DOUBLE PRECISION GAM,A,B,C,Q,DEN,POM,MXWDOT INTEGER KA,K,L,NB,INEG LOGICAL LB,LR NB=0 INEG=0 DO 21 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K CALL MXVDIF(L,AG(K),AGO(K),U) * * DETERMINATION OF THE PARAMETERS B, C * B=MXWDOT(L,JAG(K),U,XO,2) IF (ABS(B).LE.1.0D 0/ETA9) GO TO 20 A=0.0D 0 CALL MXBSBM(L,AH(NB+1),JAG(K),XO,S,1) C=MXWDOT(L,JAG(K),XO,S,1) IF (ABS(C).LE.1.0D 0/ETA9) GO TO 20 GAM=1.0D 0 IF (NIT.EQ.1) THEN Q=1.0D 0 IF (C.NE.0.0D 0) Q=C/B IF ((Q-2.5D-1)*(Q-3.0D 0).GT.0.0D 0) GAM=MIN(3.0D 0, & MAX(2.0D-2,Q)) END IF IF (B.LT.0.0D 0) INEG=INEG+1 LB=NNK.EQ.0 LR=NNK.NE.0.AND.C.LT.GAM*B IF (LB)THEN IF (B.LT.0.0D 0) GO TO 20 * * BFGS UPDATE * POM=0.0D 0 CALL MXBSBU(L,AH(NB+1),JAG(K),GAM/B,U,2) CALL MXBSBU(L,AH(NB+1),JAG(K),-1.0D 0/C,S,1) ITERH=0 IF (GAM.NE.1.0D 0) THEN CALL MXDSMS(L,AH(NB+1),1.0D 0/GAM) END IF ELSE IF (LR) THEN DEN=GAM*B-C POM=GAM*B/DEN CALL MXWDIR(L,JAG(K),-GAM,U,S,U,2) CALL MXBSBU(L,AH(NB+1),JAG(K), 1.0D 0/DEN,U,2) END IF 20 CONTINUE NB=NB+L*(L+1)/2 21 CONTINUE RETURN END * SUBROUTINE PULCI3 ALL SYSTEMS 96/12/01 * PURPOSE : * LIMITED STORAGE INVERSE COLUMN UPDATE METHODS. * * PARAMETERS : * II N NUMBER OF VARIABLES. * RI A(IAG(N+1)-1) SPARSE RECTANGULAR MATRIX WHICH IS USED FOR THE * DIRECTION VECTOR DETERMINATION. * II IA(N+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD AG. * II JA(MA) COLUMN INDICES OF ELEMENTS IN THE FIELD AG. * IU IP(N) PERMUTATION VECTOR. * IU ID(N) POSITION OF THE DIAGONAL ELEMENTS IN THE FIELD AG. * RU XM(N*MF) SET OF VECTORS FOR INVERSE COLUMN UPDATE. * RU GM(MF) SET OF VALUES FOR INVERSE COLUMN UPDATE. * IU IM(MF) SET OF INDICES FOR INVERSE COLUMN UPDATE. * RA XO(N) AUXILIARY VECTOR. * RI AFO(N) GRADIENTS DIFERENCES. * RO S(N) DIRECTION VECTOR. * II MF NUMBER OF VARIABLE METRIC UPDATES. * II NIT NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * IU IREST RESTART INDICATOR. * * SUBPROGRAMS USED : * S MXLIIM MATRIX MULTIPLICATION FOR LIMITED STORAGE INVERSE * COLUMN UPDATE METHOD. * S MXVDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXVMX1 DOT PRODUCT OF VECTORS. * * METHOD : * LIMITED STORAGE VARIABLE METRIC METHODS. * SUBROUTINE PULCI3(N,A,IA,JA,IP,ID,XM,GM,IM,XO,AFO,S,MF,NIT,KIT, + ITERH,IREST) INTEGER IREST,ITERH,NIT,KIT,MF,N DOUBLE PRECISION A(*),AFO(*),GM(*),S(*),XM(*),XO(*) INTEGER IA(*),ID(*),IM(*),IP(*),JA(*) DOUBLE PRECISION TEMP INTEGER II,MA,MM DOUBLE PRECISION MXVMX1 MA = IA(N+1) - 1 MM = MIN(NIT-KIT,MF) IF (MM.GE.MF) THEN ITERH = 1 IREST = 1 ELSE II = N*MM + 1 CALL MXLIIM(N,MM,A(MA+1),IA,JA,IP,ID,XM,GM,IM,AFO,XM(II),S) CALL MXVDIR(N,-1.0D0,XM(II),XO,XM(II)) MM = MM + 1 TEMP = MXVMX1(N,AFO,II) IF (TEMP.LE.0.0D0) THEN ITERH = 2 ELSE IM(MM) = II GM(MM) = AFO(II) ITERH = 0 END IF END IF RETURN END * SUBROUTINE PULSP3 ALL SYSTEMS 02/12/01 * PURPOSE : * LIMITED STORAGE VARIABLE METRIC UPDATE. * * PARAMETERS : * II N NUMBER OF VARIABLES (NUMBER OF ROWS OF XM). * II M NUMBER OF COLUMNS OF XM. * II MF MAXIMUM NUMBER OF COLUMNS OF XM. * RI XM(N*M) RECTANGULAR MATRIX IN THE PRODUCT FORM SHIFTED BROYDEN * METHOD (STORED COLUMNWISE): H-SIGMA*I=XM*TRANS(XM) * RO GR(M) MATRIX TRANS(XM)*GO. * RU XO(N) VECTORS OF VARIABLES DIFFERENCE XO AND VECTOR XO-TILDE. * RU GO(N) GRADIENT DIFFERENCE GO AND VECTOR XM*TRANS(XM)*GO. * RI R STEPSIZE PARAMETER. * RI PO OLD DIRECTIONAL DERIVATIVE (MULTIPLIED BY R) * RU SIG SCALING PARAMETER (ZETA AND SIGMA). * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET3 CHOICE OF SIGMA (1-CONSTANT, 2-QUADRATIC EQUATION). * * SUBPROGRAMS USED : * S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR * MATRIX BY A VECTOR. * S MXDCMU UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. * S MXVDIR VECTOR AUGMENTED BY A SCALED VECTOR. * RF MXVDOT DOT PRODUCT OF VECTORS. * S MXVSCL SCALING OF A VECTOR. * * METHOD : * SHIFTED BFGS METHOD IN THE PRODUCT FORM. * SUBROUTINE PULSP3(N,M,MF,XM,GR,XO,GO,R,PO,SIG,ITERH,MET3) INTEGER N,M,MF,ITERH,MET3 DOUBLE PRECISION XM(*),GR(*),XO(*),GO(*),R,PO,SIG DOUBLE PRECISION DEN,POM,A,B,C,AA,AH,BB,PAR,MXVDOT IF (M.GE.MF) RETURN B=MXVDOT(N,XO,GO) IF (B.LE.0.0D 0) THEN ITERH=2 GO TO 22 END IF CALL MXDRMM(N,M,XM,GO,GR) AH=MXVDOT(N,GO,GO) AA=MXVDOT(M,GR,GR) A=AA+AH*SIG C=-R*PO * * DETERMINATION OF THE PARAMETER SIG (SHIFT) * PAR=1.0D 0 POM=B/AH IF (A.GT.0.0D 0) THEN DEN=MXVDOT(N,XO,XO) IF (MET3.LE.4) THEN SIG=SQRT(MAX(0.0D 0,1.0D 0-AA/A))/(1.0D 0+ & SQRT(MAX(0.0D 0,1.0D 0-B*B/(DEN*AH))))*POM ELSE SIG=SQRT(MAX(0.0D 0,SIG*AH/A))/(1.0D 0+ & SQRT(MAX(0.0D 0,1.0D 0-B*B/(DEN*AH))))*POM END IF SIG=MAX(SIG,2.0D-1*POM) SIG=MIN(SIG,8.0D-1*POM) ELSE SIG=2.5D-1*POM END IF * * COMPUTATION OF SHIFTED XO AND SHIFTED B * BB=B-AH*SIG CALL MXVDIR(N,-SIG,GO,XO,XO) * * BFGS-BASED SHIFTED BFGS UPDATE * POM=1.0D 0 CALL MXDCMU(N,M,XM,-1.0D 0/BB,XO,GR) CALL MXVSCL(N,SQRT(PAR/BB),XO,XM(N*M+1)) M=M+1 22 CONTINUE ITERH=0 RETURN END * SUBROUTINE PULVP3 ALL SYSTEMS 03/12/01 * PURPOSE : * RANK-TWO LIMITED-STORAGE VARIABLE-METRIC METHODS IN THE PRODUCT FORM. * * PARAMETERS : * II N NUMBER OF VARIABLES (NUMBER OF ROWS OF XM). * II M NUMBER OF COLUMNS OF XM. * RI XM(N*M) RECTANGULAR MATRIX IN THE PRODUCT FORM SHIFTED BROYDEN * METHOD (STORED COLUMNWISE): H-SIGMA*I=XM*TRANS(XM) * RO XR(M) VECTOR TRANS(XM)*H**(-1)*XO. * RO GR(M) MATRIX TRANS(XM)*GO. * RA S(N) AUXILIARY VECTORS (H**(-1)*XO AND U). * RA SO(N) AUXILIARY VECTORS ((H-SIGMA*I)*H**(-1)*XO AND V). * RU XO(N) VECTORS OF VARIABLES DIFFERENCE XO AND VECTOR XO-TILDE. * RU GO(N) GRADIENT DIFFERENCE GO AND VECTOR XM*TRANS(XM)*GO. * RI R STEPSIZE PARAMETER. * RI PO OLD DIRECTIONAL DERIVATIVE (MULTIPLIED BY R) * RU SIG SCALING PARAMETER (ZETA AND SIGMA). * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II MET2 CHOICE OF THE CORRECTION PARAMETER (1-THE UNIT VALUE, * 2-THE BALANCING VALUE, 3-THE SQUARE ROOT, 4-THE GEOMETRIC * MEAN). * II MET3 CHOICE OF THE SHIFT PARAMETER (4-THE FIRST FORMULA, * 5-THE SECOND FORMULA). * II MET5 CHOICE OF THE METHOD (1-RANK-ONE METHOD, 2-RANK-TWO * METHOD). * * SUBPROGRAMS USED : * S MXDRMM MULTIPLICATION OF A ROWWISE STORED DENSE RECTANGULAR * MATRIX BY A VECTOR. * S MXDCMU UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. RANK-ONE FORMULA. * S MXDCMV UPDATE OF A COLUMNWISE STORED DENSE RECTANGULAR MATRIX. * WITH CONTROLLING OF POSITIVE DEFINITENESS. RANK-TWO FORMULA. * S MXVDIR VECTOR AUGMENTED BY A SCALED VECTOR. * RF MXVDOT DOT PRODUCT OF VECTORS. * S MXVLIN LINEAR COMBINATION OF TWO VECTORS. * S MXVSCL SCALING OF A VECTOR. * * METHOD : * RANK-ONE LIMITED-STORAGE VARIABLE-METRIC METHOD IN THE PRODUCT FORM. * SUBROUTINE PULVP3(N,M,XM,XR,GR,S,SO,XO,GO,R,PO,SIG,ITERH,MET2, & MET3,MET5) INTEGER N,M,ITERH,MET2,MET3,MET5 DOUBLE PRECISION XM(*),XR(*),GR(*),S(*),SO(*),XO(*),GO(*), & R,PO,SIG DOUBLE PRECISION MXVDOT DOUBLE PRECISION DEN,POM,A,B,C,AA,BB,CC,AH,PAR,ZET ZET=SIG * * COMPUTATION OF B * B=MXVDOT(N,XO,GO) IF (B.LE.0.0D 0) THEN ITERH=2 GO TO 22 END IF * * COMPUTATION OF GR=TRANS(XM)*GO, XR=TRANS(XM)*H**(-1)*XO * AND S=H**(-1)*XO, SO=(H-SIGMA*I)*H**(-1)*XO. COMPUTATION * OF AA=GR*GR, BB=GR*XR, CC=XR*XR. COMPUTATION OF A AND C. * CALL MXDRMM(N,M,XM,GO,GR) CALL MXVSCL(N,R,S,S) CALL MXDRMM(N,M,XM,S,XR) CALL MXVDIR(N,-SIG,S,XO,SO) AH=MXVDOT(N,GO,GO) AA=MXVDOT(M,GR,GR) BB=MXVDOT(M,GR,XR) CC=MXVDOT(M,XR,XR) A=AA+AH*SIG C=-R*PO * * DETERMINATION OF THE PARAMETER SIG (SHIFT) * POM=B/AH IF (A.GT.0.0D 0) THEN DEN=MXVDOT(N,XO,XO) IF (MET3.LE.4) THEN SIG=SQRT(MAX(0.0D 0,1.0D 0-AA/A))/(1.0D 0+ & SQRT(MAX(0.0D 0,1.0D 0-B*B/(DEN*AH))))*POM ELSE SIG=SQRT(MAX(0.0D 0,SIG*AH/A))/(1.0D 0+ & SQRT(MAX(0.0D 0,1.0D 0-B*B/(DEN*AH))))*POM END IF SIG=MAX(SIG,2.0D-1*POM) SIG=MIN(SIG,8.0D-1*POM) ELSE SIG=2.5D-1*POM END IF * * COMPUTATION OF SHIFTED XO AND SHIFTED B * B=B-AH*SIG CALL MXVDIR(N,-SIG,GO,XO,XO) * * COMPUTATION OF THE PARAMETER RHO (CORRECTION) * IF (MET2.LE.1) THEN PAR=1.0D 0 ELSE IF (MET2.EQ.2) THEN PAR=SIG*AH/B ELSE IF (MET2.EQ.3) THEN PAR=SQRT(1.0D 0-AA/A) ELSE IF (MET2.EQ.4) THEN PAR=SQRT(SQRT(1.0D 0-AA/A)*(SIG*AH/B)) ELSE PAR=ZET/(ZET+SIG) END IF * * COMPUTATION OF THE PARAMETER THETA (BFGS) * POM=SIGN(SQRT(PAR*B/CC),BB) * * COMPUTATION OF Q AND P * IF (MET5.EQ.1) THEN * * RANK ONE UPDATE OF XM * CALL MXVDIR(M,POM,XR,GR,XR) CALL MXVLIN(N,PAR,XO,POM,SO,S) CALL MXDCMU(N,M,XM,-1.0D 0/(PAR*B+POM*BB),S,XR) ELSE * * RANK TWO UPDATE OF XM * CALL MXVDIR(N,PAR/POM-BB/B,XO,SO,S) CALL MXDCMV(N,M,XM,-1.0D 0/B,XO,GR,-1.0D 0/CC,S,XR) END IF 22 CONTINUE ITERH=0 RETURN END * SUBROUTINE PUSMM1 ALL SYSTEMS 97/12/01 * PURPOSE : * VARIABLE METRIC UPDATE OF A SPARSE SYMMETRIC POSITIVE DEFINITE MATRIX * USING THE MARWIL PROJECTION. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RU H(M) POSITIVE DEFINITE APPROXIMATION OF THE SPARSE HESSIAN * MATRIX. * II IH(NF) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RA XS(NF) AUXILIARY VECTOR. * RA S(NF) AUXILIARY VECTOR. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI GO(NF) GRADIENTS DIFFERENCE. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RO R VALUE OF THE STEPSIZE PARAMETER. * RI PO INITIAL VALUE OF THE DIRECTIONAL DERIVATIVE. * II NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER LAST RESTART. * II MET1 SELECTION OF SELF SCALING. MET1=1-SELF SCALING SUPPRESSED. * MET1=2-INITIAL SELF SCALING. MET1=3-SELF SCALING IN EACH * ITERATION. * II ITERD CAUSE OF TERMINATION IN THE DIRECTION DETERMINATION. * ITERD<0-BAD DECOMPOSITION. ITERD=0-DESCENT DIRECTION. * ITERD=1-NEWTON LIKE STEP. ITERD=2-INEXACT NEWTON LIKE STEP. * ITERD=3-BOUNDARY STEP. ITERD=4-DIRECTION WITH THE NEGATIVE * CURVATURE. ITERD=5-MARQUARDT STEP. * IO ITERH TERMINATION INDICATOR. ITERH<0-BAD DECOMPOSITION. * ITERH=0-SUCCESSFUL UPDATE. ITERH>0-NONPOSITIVE PARAMETERS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * * SUBPROGRAMS USED : * S MXSSMM MATRIX-VECTOR PRODUCT. * S MXSSMY MARWILL CORRECTION OF A SPARSE SYMMETRIC MATRIX. * S MXUDIF DIFFERENCE OF TWO VECTORS. * S MXUDIR VECTOR AUGMENTED BY THE SCALED VECTOR. * RF MXUDOT DOT PRODUCT OF VECTORS. * S MXVSCL SCALING OF A VECTOR. * SUBROUTINE PUSMM1(NF,H,IH,JH,G,XS,S,XO,GO,IX,R,PO,NIT,KIT, & MET1,ITERD,ITERH,KBF) INTEGER NF,IH(*),JH(*),IX(*),NIT,KIT,MET1,ITERD,ITERH,KBF DOUBLE PRECISION H(*),G(*),S(*),XO(*),GO(*),XS(*),R,PO INTEGER MM DOUBLE PRECISION MXUDOT DOUBLE PRECISION A,B,C,GAM LOGICAL L1 MM=IH(NF+1)-1 * * DETERMINATION OF THE PARAMETER C AND THE VECTOR S * A=0.0D 0 L1=MET1.GE.3.OR.MET1.GE.2.AND.NIT.EQ.KIT IF (ITERD.NE.1) THEN CALL MXSSMM(NF,H,IH,JH,XO,S) IF (L1) C=MXUDOT(NF,XO,S,IX,KBF) ELSE CALL MXUDIF(NF,GO,G,S,IX,KBF) CALL MXVSCL(NF,R,S,S) IF (L1) C=-R*PO END IF GAM=1.0D 0 IF (L1) THEN * * SELF SCALING * B=MXUDOT(NF,XO,GO,IX,KBF) IF (B.GT.0.0D 0.AND.C.GT.0.0D 0) THEN GAM=C/B CALL MXVSCL(MM,1.0D 0/GAM,H,H) CALL MXVSCL(NF,1.0D 0/GAM,S,S) END IF END IF CALL MXUDIR(NF,-1.0D 0,S,GO,S,IX,KBF) * * RANK-ONE UPDATE PROJECTED USING MXSSMY * CALL MXSSMY(NF,H,IH,JH,XS,S,XO) ITERH=0 RETURN END * SUBROUTINE PUSSD5 ALL SYSTEMS 97/12/01 * PURPOSE : * INITIATION OF A DENSE SYMMETRIC POSITIVE DEFINITE MATRIX * * PARAMETERS : * II NA NUMBER OF APPROXIMATED FUNCTIONS. * RI AF(NA) VECTOR CONTAINING VALUES OF THE APPROXIMATED * FUNCTIONS. * RU AH(MB) POSITIVE DEFINITE APPROXIMATION OF THE PARTITIONED * HESSIAN MATRIX. * II IAG(NA+1) POINTERS OF THE SPARSE JACOBIAN MATRIX. * II JAG(MA) COLUMN INDICES OF THE SPARSE JACOBIAN MATRIX. * RU H(M) POSITIVE DEFINITE APPROXIMATION OF THE SPARSE HESSIAN * MATRIX * II IH(NF+1) POINTERS OF THE DIAGONAL ELEMENTS OF THE SPARSE * HESSIAN MATRIX. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF THE SPARSE HESSIAN * MATRIX IN THE PACKED ROW FORM. * * SUBPROGRAMS USED : * S PASSH2 COMPUTATION OF THE SPARSE HESSIAN MATRIX FROM THE * PARTITIONED HESSIAN MATRIX. * SUBROUTINE PUSSD5(NA,AF,AH,IAG,JAG,H,IH,JH) INTEGER NA,IAG(*),JAG(*),IH(*),JH(*) DOUBLE PRECISION AF(*),AH(*),H(*) INTEGER K,KA,L,LL,NB NB=0 DO 2 KA=1,NA K=IAG(KA) L=IAG(KA+1)-K LL=L*(L+1)/2 CALL PASSH2(H,IH,JH,AH(NB+1),IAG,JAG,KA,AF(KA)) NB=NB+LL 2 CONTINUE RETURN END * SUBROUTINE PYABU1 ALL SYSTEMS 04/12/01 * PURPOSE : * SUBGRADIENT AGGREGATION FOR NONSMOOTH VARIABLE METRIC METHOD. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI H(M) POSITIVE DEFINITE APPROXIMATION OF THE SPARSE HESSIAN * MATRIX. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * II PSL(NF+1) POINTER ARRAY OF THE FACTORIZED SPARSE MATRIX * II PERM(NF) PERMUTATION VECTOR * RI G(NF) NEW SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RI GO(NF) OLD SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RU GV(NF) AGGREGATED SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RI S(NF) DIRECTION VECTOR. * RA U(NF) AUXILIARY VECTOR. * RA V(NF) AUXILIARY VECTOR. * RO ALF LINEARIZATION TERM. * RU ALFV AGGREGATED LINEARIZATION TERM. * RI RHO CORRECTION PARAMETER. * II JC CORRECTION INDICATOR. * * SUBPROGRAMS USED : * S MXSPCB BACK SUBSTITUTION USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * RF MXVDOT DOT PRODUCT OF TWO VECTORS. * S MXVSBP INVERSE PERMUTATION OF A VECTOR * S MXVSFP PERMUTATION OF A VECTOR. * SUBROUTINE PYABU1(NF,H,JH,PSL,PERM,G,GO,GV,S,U,V,ALF,ALFV,RHO, & JC) INTEGER NF,JH(*),PSL(*),PERM(*),JC DOUBLE PRECISION H(*),G(*),GO(*),GV(*),S(*),U(*),V(*),ALF,ALFV, & RHO DOUBLE PRECISION A,B,ALFM,LAM1,LAM2,PQ,PR,PRQR,QQP,QR,RR,RRP,RRQ, & W,W1 INTEGER I DOUBLE PRECISION ZERO,ONE,MXVDOT PARAMETER (ZERO=0.0D 0,ONE=1.0D 0) ALFM=ZERO * * General routine - here always input parameter ALFM=0 * RR=ALFV+ALFV RRP=ALFV-ALFM RRQ=ALFV-ALF DO 1 I=1,NF A=S(I) U(I)=GO(I)-GV(I) S(I)=G(I)-GV(I) RR=RR-A*GV(I) RRP=RRP+A*U(I) RRQ=RRQ+A*S(I) 1 CONTINUE PQ=ZERO PR=ZERO QR=ZERO PRQR=ZERO QQP=ZERO IF (JC.GE.1) THEN DO 2 I=1,NF PQ=PQ+RHO*(S(I)-U(I))**2 PR=PR+RHO*U(I)**2 QR=QR+RHO*S(I)**2 PRQR=PRQR+RHO*U(I)*S(I) QQP=QQP+RHO+G(I)*(S(I)-U(I)) 2 CONTINUE END IF QQP=QQP+ALF-ALFM CALL MXVSFP(NF,PERM,U,V) CALL MXSPCB(NF,H,PSL,JH,U,1) CALL MXVSFP(NF,PERM,S,V) CALL MXSPCB(NF,H,PSL,JH,S,1) DO 4 I=1,NF W1=ONE/H(PSL(I)+I-1) PQ=PQ+W1*(S(I)-U(I))**2 PR=PR+W1*U(I)**2 QR=QR+W1*S(I)**2 PRQR=PRQR+W1*U(I)*S(I) S(I)=W1*(S(I)-U(I)) 4 CONTINUE CALL MXSPCB(NF,H,PSL,JH,S,-1) CALL MXVSBP(NF,PERM,S,V) QQP=QQP+MXVDOT(NF,G,S) IF (PR.LE.ZERO.OR.QR.LE.ZERO) GO TO 10 A=RRQ/QR B=PRQR/QR W=PRQR*B-PR IF (W.EQ.ZERO) GO TO 10 LAM1=(A*PRQR-RRP)/W LAM2=A-LAM1*B IF (LAM1*(LAM1-ONE).LT.ZERO.AND.LAM2*(LAM1+LAM2-ONE).LT.ZERO) & GO TO 40 * * MINIMUM ON THE BOUNDARY * 10 LAM1=ZERO LAM2=ZERO IF (ALF.LE.ALFV) LAM2=ONE IF (QR.GT.ZERO) LAM2=MIN(ONE,MAX(ZERO,RRQ/QR)) W=(LAM2*QR-RRQ-RRQ)*LAM2 A=ZERO IF (ALFM.LE.ALFV) A=ONE IF (PR.GT.ZERO) A=MIN(ONE,MAX(ZERO,RRP/PR)) B=(A*PR-RRP-RRP)*A IF (B.LT.W)THEN W=B LAM1=A LAM2=ZERO END IF IF (QQP*(QQP-PQ).GE.ZERO) GO TO 40 IF (QR-RRQ-RRQ-QQP*QQP/PQ.GE.W) GO TO 40 LAM1=QQP/PQ LAM2=ONE-LAM1 40 IF (LAM1.EQ.ZERO.AND.LAM2*(LAM2-ONE).LT.ZERO.AND.RRP-LAM2*PRQR & .GT.ZERO.AND.PR.GT.ZERO) LAM1=MIN(ONE-LAM2,(RRP-LAM2*PRQR)/PR) A=ONE-LAM1-LAM2 ALFV=LAM1*ALFM+LAM2*ALF+A*ALFV DO 5 I=1,NF GV(I)=LAM1*GO(I)+LAM2*G(I)+A*GV(I) 5 CONTINUE RETURN END * SUBROUTINE PYABU2 ALL SYSTEMS 04/12/01 * PURPOSE : * SIMPLIFIED AGGREGATION FOR NONSMOOTH VARIABLE METRIC METHOD. * * PARAMETERS : * II NF NUMBER OF VARIABLES. * RI H(M) POSITIVE DEFINITE APPROXIMATION OF THE SPARSE HESSIAN * MATRIX. * IO JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * II PSL(NF+1) POINTER ARRAY OF THE FACTORIZED SPARSE MATRIX * II PERM(NF) PERMUTATION VECTOR * RI G(NF) ACTUAL SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RU GV(NF) AGGREGATED SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RA S(NF) DIRECTION VECTOR. * RA V(NF) AUXILIARY VECTOR. * RO ALF LINEARIZATION TERM. * RU ALFV AGGREGATED LINEARIZATION TERM. * RI RHO CORRECTION PARAMETER. * II JC CORRECTION INDICATOR. * * SUBPROGRAMS USED : * S MXSPCB BACK SUBSTITUTION USING THE SPARSE DECOMPOSITION * OBTAINED BY MXSPCF. * S MXVSFP PERMUTATION OF A VECTOR. * SUBROUTINE PYABU2(NF,H,JH,PSL,PERM,G,GV,S,V,ALF,ALFV,RHO,JC) INTEGER NF,JH(*),PSL(*),PERM(NF),JC DOUBLE PRECISION H(*),G(*),GV(*),S(*),V(*),ALF,ALFV,RHO DOUBLE PRECISION P,Q,W,LAM INTEGER I DOUBLE PRECISION ZERO,ONE PARAMETER (ZERO=0.0D 0,ONE=1.0D 0) P=ALFV-ALF DO 1 I=1,NF W=S(I) P=P+W*S(I) S(I)=G(I)-GV(I) 1 CONTINUE Q=ZERO IF (JC.GE.1) THEN DO 2 I=1,NF Q=Q+RHO*S(I)**2 2 CONTINUE END IF CALL MXVSFP(NF,PERM,S,V) CALL MXSPCB(NF,H,PSL,JH,S,1) DO 4 I=1,NF W=ONE/H(PSL(I)+I-1) Q=Q+W*S(I)**2 4 CONTINUE LAM=0.5D 0+SIGN(0.5D 0,P) IF (Q.GT.ZERO) LAM=MIN(ONE,MAX(ZERO,P/Q)) P=ONE-LAM ALFV=LAM*ALF+P*ALFV DO 5 I=1,NF GV(I)=LAM*G(I)+P*GV(I) 5 CONTINUE RETURN END * SUBROUTINE PYADC0 ALL SYSTEMS 98/12/01 * PURPOSE : * NEW SIMPLE BOUNDS ARE ADDED TO THE ACTIVE SET. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N REDUCED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * IO INEW NUMBER OF ACTIVE CONSTRAINTS. * SUBROUTINE PYADC0(NF,N,X,IX,XL,XU,INEW) INTEGER NF,N,IX(NF),INEW DOUBLE PRECISION X(*),XL(*),XU(*) INTEGER I,II,IXI N=NF INEW=0 DO 1 I=1,NF II=IX(I) IXI=ABS(II) IF (IXI.GE.5) THEN IX(I)=-IXI ELSE IF ((IXI.EQ.1.OR.IXI.EQ.3.OR.IXI.EQ.4).AND.X(I).LE.XL(I)) & THEN X(I)=XL(I) IF (IXI.EQ.4) THEN IX(I)=-3 ELSE IX(I)=-IXI END IF N=N-1 IF (II.GT.0) INEW=INEW+1 ELSE IF ((IXI.EQ.2.OR.IXI.EQ.3.OR.IXI.EQ.4).AND.X(I).GE.XU(I)) & THEN X(I)=XU(I) IF (IXI.EQ.3) THEN IX(I)=-4 ELSE IX(I)=-IXI END IF N=N-1 IF (II.GT.0) INEW=INEW+1 END IF 1 CONTINUE RETURN END * SUBROUTINE PYBUN1 ALL SYSTEMS 97/12/01 * PURPOSE : * BUNDLE UPDATING. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * II MB DECLARED NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * II NB CURRENT NUMBER OF LINEAR APPROXIMATED FUNCTIONS. * RU X(N) VECTOR OF VARIABLES. * RO G(N) SUBGRADIENT OF THE OBJECTIVE FUNCTION. * RO F VALUE OF THE OBJECTIVE FUNCTION. * RI AY(N*MB) MATRIX WHOSE COLUMNS ARE VARIABLE VECTORS. * RI AG(N*MB) MATRIX WHOSE COLUMNS ARE BUNDLE SUBGRADIENTS. * RI AF(4*MB) VECTOR OF BUNDLE FUNCTIONS VALUES. * IO ITERS NULL STEP INDICATOR. ITERS=0-NULL STEP. ITERS=1-DESCENT * STEP. * * SUBPROGRAMS USED : * S MXVCOP COPYING OF A VECTOR. * SUBROUTINE PYBUN1(N,MB,NB,X,G,F,AY,AG,AF,ITERS) INTEGER N,MB,NB,ITERS DOUBLE PRECISION X(*),G(*),F,AY(*),AG(*),AF(*) INTEGER I,IND,K,KN,L L=0 IF (ITERS.EQ.0) L=1 * * BUNDLE REDUCTION * KN=0 IF (NB.GE.MB) THEN DO 2 K=1,NB-1 KN=K*N-N DO 1 I=1,N IF (G(I).NE.AG(KN+I)) GO TO 2 1 CONTINUE IND=K GO TO 3 2 CONTINUE IND=1 3 DO 4 K=IND,NB-1 AF(K)=AF(K+1) AF(K+MB*3)=AF(K+1+MB*3) KN=K*N+1 CALL MXVCOP(N,AG(KN),AG(KN-N)) CALL MXVCOP(N,AY(KN),AY(KN-N)) 4 CONTINUE NB=NB-1 END IF * * BUNDLE COMPLETION * IF (L.GT.0.AND.KN.EQ.0) THEN AF(NB+1)=AF(NB) AF(3*MB+NB+1)=AF(3*MB+NB) KN=NB*N+1 CALL MXVCOP(N,AG(KN-N),AG(KN)) CALL MXVCOP(N,AY(KN-N),AY(KN)) END IF NB=NB+1 KN=NB-L AF(KN)=F AF(KN+MB*3)=L K=(KN-1)*N+1 CALL MXVCOP(N,G,AG(K)) CALL MXVCOP(N,X,AY(K)) RETURN END * SUBROUTINE PYCSER ALL SYSTEMS 98/12/01 * PURPOSE : * GROUP OF THE SAME COLOUR FOR THE POWELL-TOINT ALGORITHM FOR SPARSE * HESSIANS APPROXIMATIONS IS CREATED. * * PARAMETERS : * IU IH(MCOLS+1) POINTER VECTOR OF SPARSE HESSIAN MATRIX. * IU JH(M) INDEX VECTOR OF THE HESSIAN MATRIX. * IA WN02(MCOLS) AUXILIARY VECTOR. * RA WN03(MCOLS) AUXILIARY VECTOR. * RI DEG(MCOLS) DEGREES OF THE ADJACENCY GRAPH. * IA WN01(NF) AUXILIARY VECTOR USED FOR INDICES OF THE COLUMNS * THAT HAVE NOT BEEN COLOURED YET. * II COL(NF) VECTOR DISCERNING GROUPS OF THE HESSIAN COLUMN OF THE * SAME COLOUR. * IU NCOL NUMBER OF COLOURS USED SO FAR. * IU CNM NUMBER OF COLUMNS THAT HAVE NOT BEEN COLOURED SO FAR. * SUBROUTINE PYCSER(JH,IH,WN02,WN03,DEG,WN01,COL,NCOL,CNM) INTEGER JH(*),IH(*),COL(*) INTEGER WN01(*),WN02(*) DOUBLE PRECISION WN03(*),DEG(*) INTEGER NCOL,CNM,I,J,K,L,IP * * DEFINITION OF THE INCIDENCE ARRAY A * L=WN01(1) * * ELEMENT WAS MARKED THAT IT IS INSERTED * DO 100 I=IH(L),IH(L+1)-1 K=JH(I) * * COLUMN OF THIS NUMBER HAS APPEARED IN ONE OF THE PREVIOUS GROUPS * IF (COL(K).LT.NCOL) GO TO 100 DEG(K)=DEG(K)-1 WN02(K)=NCOL 100 CONTINUE * * COLUMN IS INSERTED * COL(L)=NCOL * * THE CYCLE OF COMPARING COLUMN WITH THE ARRAY A * A2 IS AN HELP ARRAY CONTAINING COLUMNS THAT ARE * BEEING EXAMINED BUT THAT WERE NOT YET ACCEPTED * P IS ITS POINTER * IF (CNM.EQ.1) GO TO 250 DO 200 I=2,CNM * * TRANSFORMATION OF THE EXAMINED COLUMN I IS * IP=1 L=WN01(I) DO 300 J=IH(L),IH(L+1)-1 K=JH(J) IF (COL(K).LT.NCOL) GO TO 300 IF (WN02(K).GE.NCOL) GO TO 200 WN03(IP)=K IP=IP+1 300 CONTINUE IF (IP.NE.1) THEN * * COPY OF THE WN03 ARRAY INTO WN02 FOR THE COLUMN WAS ACCEPTED * DO 400 K=1,IP-1 WN02(INT(WN03(K)))=NCOL DEG(INT(WN03(K)))=DEG(INT(WN03(K)))-1 400 CONTINUE END IF * * INSERT THE COLUMN INTO THE PROCESSED GROUP * COL(L)=NCOL * * END OF THE MAIN CYCLE * 200 CONTINUE * * JUMP LABEL * 250 CONTINUE * * INVP SHIFT * K=1 DO 500 I=1,CNM L=WN01(I) IF (COL(L).EQ.NCOL) THEN ELSE WN01(K)=L K=K+1 END IF 500 CONTINUE * * CNM UPDATE * CNM=K-1 RETURN END * SUBROUTINE PYFUT1 ALL SYSTEMS 98/12/01 * PURPOSE : * TERMINATION CRITERIA AND TEST ON RESTART. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * RI F NEW VALUE OF THE OBJECTIVE FUNCTION. * RI FO OLD VALUE OF THE OBJECTIVE FUNCTION. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RO GMAX NORM OF THE TRANSFORMED GRADIENT. * RI DMAX MAXIMUM RELATIVE DIFFERENCE OF VARIABLES. * RI TOLX LOWER BOUND FOR STEPLENGTH. * RI TOLF LOWER BOUND FOR FUNCTION DECREASE. * RI TOLB LOWER BOUND FOR FUNCTION VALUE. * RI TOLG LOWER BOUND FOR GRADIENT. * II KD DEGREE OF REQUIRED DERIVATIVES. * IU NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER RESTART. * II MIT MAXIMUM NUMBER OF ITERATIONS. * IU NFV ACTUAL NUMBER OF COMPUTED FUNCTION VALUES. * II MFV MAXIMUM NUMBER OF COMPUTED FUNCTION VALUES. * IU NFG ACTUAL NUMBER OF COMPUTED GRADIENT VALUES. * II MFG MAXIMUM NUMBER OF COMPUTED GRADIENT VALUES. * IU NTESX ACTUAL NUMBER OF TESTS ON STEPLENGTH. * II MTESX MAXIMUM NUMBER OF TESTS ON STEPLENGTH. * IU NTESF ACTUAL NUMBER OF TESTS ON FUNCTION DECREASE. * II MTESF MAXIMUM NUMBER OF TESTS ON FUNCTION DECREASE. * II IRES1 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * II IRES2 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * IU IREST RESTART INDICATOR. RESTART IS PERFORMED IF IREST>0. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * IO ITERM TERMINATION INDICATOR. ITERM=1-TERMINATION AFTER MTESX * UNSUFFICIENT STEPLENGTHS. ITERM=2-TERMINATION AFTER MTESF * UNSUFFICIENT FUNCTION DECREASES. ITERM=3-TERMINATION ON LOWER * BOUND FOR FUNCTION VALUE. ITERM=4-TERMINATION ON LOWER BOUND * FOR GRADIENT. ITERM=11-TERMINATION AFTER MAXIMUM NUMBER OF * ITERATIONS. ITERM=12-TERMINATION AFTER MAXIMUM NUMBER OF * COMPUTED FUNCTION VALUES. * SUBROUTINE PYFUT1(N,F,FO,UMAX,GMAX,DMAX,TOLX,TOLF,TOLB,TOLG,KD, & NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF,ITES,IRES1, & IRES2,IREST,ITERS,ITERM) INTEGER N,KD,NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF, & ITES,IRES1,IRES2,IREST,ITERS,ITERM DOUBLE PRECISION F,FO,UMAX,GMAX,DMAX,TOLX,TOLF,TOLG,TOLB DOUBLE PRECISION TEMP IF (ITERM.LT.0) RETURN IF (ITES .LE.0) GO TO 1 IF (ITERS.EQ.0) GO TO 1 IF (NIT.LE.0) FO=F+MIN(SQRT(ABS(F)),ABS(F)/1.0D 1) IF (F.LE.TOLB) THEN ITERM = 3 RETURN END IF IF (KD.GT.0) THEN IF (GMAX.LE.TOLG.AND.UMAX.LE.TOLG) THEN ITERM = 4 RETURN END IF END IF IF (NIT.LE.0) THEN NTESX = 0 NTESF = 0 END IF IF (DMAX.LE.TOLX) THEN ITERM = 1 NTESX = NTESX+1 IF (NTESX.GE.MTESX) RETURN ELSE NTESX = 0 END IF TEMP=ABS(FO-F)/MAX(ABS(F),1.0D 0) IF (TEMP.LE.TOLF) THEN ITERM = 2 NTESF = NTESF+1 IF (NTESF.GE.MTESF) RETURN ELSE NTESF = 0 END IF 1 IF (NIT.GE.MIT) THEN ITERM = 11 RETURN END IF IF (NFV.GE.MFV) THEN ITERM = 12 RETURN END IF IF (NFG.GE.MFG) THEN ITERM = 13 RETURN END IF ITERM = 0 IF (N.GT.0.AND.NIT-KIT.GE.IRES1*N+IRES2) THEN IREST=MAX(IREST,1) END IF NIT = NIT + 1 RETURN END * SUBROUTINE PYFUT8 ALL SYSTEMS 98/12/01 * PURPOSE : * TERMINATION CRITERIA AND TEST ON RESTART. * * PARAMETERS : * II N ACTUAL NUMBER OF VARIABLES. * RI F NEW VALUE OF THE OBJECTIVE FUNCTION. * RI FO OLD VALUE OF THE OBJECTIVE FUNCTION. * RO GMAX NORM OF THE TRANSFORMED GRADIENT. * RI DMAX MAXIMUM RELATIVE DIFFERENCE OF VARIABLES. * RI RPF3 VALUE OF THE BARRIER PARAMETER. * RI TOLX LOWER BOUND FOR STEPLENGTH. * RI TOLF LOWER BOUND FOR FUNCTION DECREASE. * RI TOLB LOWER BOUND FOR FUNCTION VALUE. * RI TOLG LOWER BOUND FOR GRADIENT. * RI TOLP LOWER BOUND FOR BARRIER PARAMETER. * II KD DEGREE OF REQUIRED DERIVATIVES. * IU NIT ACTUAL NUMBER OF ITERATIONS. * II KIT NUMBER OF THE ITERATION AFTER RESTART. * II MIT MAXIMUM NUMBER OF ITERATIONS. * IU NFV ACTUAL NUMBER OF COMPUTED FUNCTION VALUES. * II MFV MAXIMUM NUMBER OF COMPUTED FUNCTION VALUES. * IU NFG ACTUAL NUMBER OF COMPUTED GRADIENT VALUES. * II MFG MAXIMUM NUMBER OF COMPUTED GRADIENT VALUES. * IU NTESX ACTUAL NUMBER OF TESTS ON STEPLENGTH. * II MTESX MAXIMUM NUMBER OF TESTS ON STEPLENGTH. * IU NTESF ACTUAL NUMBER OF TESTS ON FUNCTION DECREASE. * II MTESF MAXIMUM NUMBER OF TESTS ON FUNCTION DECREASE. * II IRES1 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * II IRES2 RESTART SPECIFICATION. RESTART IS PERFORMED AFTER * IRES1*N+IRES2 ITERATIONS. * IU IREST RESTART INDICATOR. RESTART IS PERFORMED IF IREST>0. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * IO ITERM TERMINATION INDICATOR. ITERM=1-TERMINATION AFTER MTESX * UNSUFFICIENT STEPLENGTHS. ITERM=2-TERMINATION AFTER MTESF * UNSUFFICIENT FUNCTION DECREASES. ITERM=3-TERMINATION ON LOWER * BOUND FOR FUNCTION VALUE. ITERM=4-TERMINATION ON LOWER BOUND * FOR GRADIENT. ITERM=11-TERMINATION AFTER MAXIMUM NUMBER OF * ITERATIONS. ITERM=12-TERMINATION AFTER MAXIMUM NUMBER OF * COMPUTED FUNCTION VALUES. * SUBROUTINE PYFUT8(N,F,FO,GMAX,DMAX,RPF3,TOLX,TOLF,TOLB,TOLG,TOLP, & KD,NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF,IRES1, & IRES2,IREST,ITERS,ITERM) INTEGER N,KD,NIT,KIT,MIT,NFV,MFV,NFG,MFG,NTESX,MTESX,NTESF,MTESF, & IRES1,IRES2,IREST,ITERS,ITERM DOUBLE PRECISION F,FO,RPF3,GMAX,DMAX,TOLX,TOLF,TOLG,TOLB,TOLP DOUBLE PRECISION TEMP IF (ITERM.LT.0) RETURN IF (ITERS.EQ.0) GO TO 1 IF (NIT.LE.0) FO=F+MIN(SQRT(ABS(F)),ABS(F)/1.0D 1) IF (F.LE.TOLB) THEN ITERM = 3 RETURN END IF IF (RPF3.GT.TOLP) GO TO 1 IF (KD.GT.0) THEN IF (GMAX.LE.TOLG) THEN ITERM = 4 RETURN END IF END IF IF (NIT.LE.0) THEN NTESX = 0 NTESF = 0 END IF IF (DMAX.LE.TOLX) THEN ITERM = 1 NTESX = NTESX+1 IF (NTESX.GE.MTESX) RETURN ELSE NTESX = 0 END IF TEMP=ABS(FO-F)/MAX(ABS(F),1.0D 0) IF (TEMP.LE.TOLF) THEN ITERM = 2 NTESF = NTESF+1 IF (NTESF.GE.MTESF) RETURN ELSE NTESF = 0 END IF 1 IF (NIT.GE.MIT) THEN ITERM = 11 RETURN END IF IF (NFV.GE.MFV) THEN ITERM = 12 RETURN END IF IF (NFG.GE.MFG) THEN ITERM = 13 RETURN END IF ITERM = 0 IF (N.GT.0.AND.NIT-KIT.GE.IRES1*N+IRES2) THEN IREST=MAX(IREST,1) END IF NIT = NIT + 1 RETURN END * SUBROUTINE PYPTSH ALL SYSTEMS 98/12/01 * PURPOSE : * POWELL-TOINT GRAPH COLORING ALGORITHM FOR GROUPING COLUMNS OF THE * HESSIAN MATRIX BEFORE NUMERICAL DIFFERENTIATION. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II MMAX MAXIMUM NUMBER OF NONZERO ELEMENTS. * II IH(NF+1) POINTER VECTOR OF SPARSE HESSIAN MATRIX. * II JH(MMAX) INDEX VECTOR OF THE HESSIAN MATRIX. * IO COL(NF) VECTOR DISCERNING GROUPS OF THE HESSIAN COLUMN OF THE * SAME COLOUR. * RA DEG(NF) DEGREES OF THE ADJACENCY GRAPH. * RA ORD(NF) AUXILIARY ARRAY. * RA RADIX(NF+1) AUXILIARY ARRAY. * IA WN11(NF) AUXILIARY VECTOR USED FOR INDICES OF THE COLUMNS * THAT HAVE NOT BEEN COLOURED YET. * IA WN12(NF) AUXILIARY VECTOR. * RA XS(NF) AUXILIARY VECTOR. * IO ITERM TERMINATION INDICATOR. * * SUBPROGRAMS USED : * S PYCSER GROUPING COLUMNS OF THE SPARSE SYMMETRIC MATRIX. * S MXSTG1 WIDTHEN THE STRUCTURE. * S MXSTL1 SHRINK THE STRUCTURE. * S MXVSR2 SORT. * SUBROUTINE PYPTSH(NF,MMAX,IH,JH,COL,DEG,ORD,RADIX,WN11,WN12,XS, & ITERM) INTEGER NF,MMAX,IH(*),JH(*),COL(*) INTEGER WN11(*),WN12(*),ITERM DOUBLE PRECISION RADIX(*),ORD(*) DOUBLE PRECISION XS(*),DEG(*) INTEGER NCOL,CNM,I,ML,MM,J,K1,L * * SAVE SYMBOLIC STRUCTURE OF FACTOR * MM=IH(NF+1)-1 IF (2*MM-NF+2.GE.MMAX) THEN ITERM=-45 RETURN END IF * * WIDTHEN THE STRUCTURE * CALL MXSTG1(NF,ML,IH,JH,WN12,WN11) DO 100 I=1,NF COL(I)=NF WN12(I)=0 WN11(I)=I 100 CONTINUE * * NUMBER OF THE FREE COLUMNS * CNM=NF * * NUMBER OF USED COLOURS * NCOL=1 * * DEGREE RECOUNT * K1=1 DO 110 I=1,NF L=IH(I+1) DEG(I)=L-K1 K1=L 110 CONTINUE * * COLUMN RESORT * 200 CALL MXVSR2(NF,DEG,ORD,RADIX,WN11,CNM) * * ORD REWRITE INTO THE ARRAY INVP * DO 250 I=1,CNM WN11(I)=ORD(I) 250 CONTINUE * * COLUMNS OF THE NEW COLOUR NCOL * CALL PYCSER(JH,IH,WN12,XS,DEG,WN11,COL,NCOL,CNM) * * STOP TEST * IF (CNM.GE.1) THEN NCOL=NCOL+1 GO TO 200 END IF * * SHRINK THE STRUCTURE * CALL MXSTL1(NF,ML,IH,JH,WN12) * * INTO COL GIVE INDICES OF THE INDIVIDUAL GROUPS ONE AFTER ANOTHER, * END OF THE GROUP IS MARKED BY THE NEGATIVE INDEX VALUE. * * * READ COL * DO 300 I=1,NF WN11(I)=0 300 CONTINUE DO 400 I=1,NF J=COL(I) WN11(J)=WN11(J)+1 400 CONTINUE WN12(1)=1 L=1 DO 500 I=2,NF L=L+WN11(I-1) WN12(I)=L IF (WN11(I).EQ.0) GO TO 550 500 CONTINUE 550 CONTINUE * * CHANGE COL * DO 600 I=1,NF J=COL(I) WN11(I)=J 600 CONTINUE DO 700 I=1,NF J=WN11(I) COL(WN12(J))=I WN12(J)=WN12(J)+1 700 CONTINUE DO 800 I=1,NCOL L=WN12(I)-1 IF (L.GT.NF) GO TO 900 COL(L)=-COL(L) 800 CONTINUE 900 CONTINUE RETURN END * SUBROUTINE PYRMC0 ALL SYSTEMS 98/12/01 * PURPOSE : * OLD SIMPLE BOUND IS REMOVED FROM THE ACTIVE SET. TRANSFORMED * GRADIENT OF THE OBJECTIVE FUNCTION IS UPDATED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N REDUCED NUMBER OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI EPS8 TOLERANCE FOR CONSTRAINT TO BE REMOVED. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RI GMAX NORM OF THE TRANSFORMED GRADIENT. * RO RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * II IOLD NUMBER OF REMOVED CONSTRAINTS. * IU IREST RESTART INDICATOR. * SUBROUTINE PYRMC0(NF,N,IX,G,EPS8,UMAX,GMAX,RMAX,IOLD,IREST) INTEGER NF,N,IX(*),IOLD,IREST DOUBLE PRECISION G(*),EPS8,UMAX,GMAX,RMAX INTEGER I,IXI IF (N.EQ.0.OR.RMAX.GT.0.0D 0) THEN IF (UMAX.GT.EPS8*GMAX) THEN IOLD=0 DO 1 I=1,NF IXI=IX(I) IF (IXI.GE.0) THEN ELSE IF (IXI.LE.-5) THEN ELSE IF ((IXI.EQ.-1.OR.IXI.EQ.-3).AND.-G(I).LE.0.0D 0) THEN ELSE IF ((IXI.EQ.-2.OR.IXI.EQ.-4).AND. G(I).LE.0.0D 0) THEN ELSE IOLD=IOLD+1 IX(I)=MIN(ABS(IX(I)),3) IF (RMAX.EQ.0) GO TO 2 END IF 1 CONTINUE 2 IF (IOLD.GT.1) IREST=MAX(IREST,1) END IF END IF RETURN END * SUBROUTINE PYTCAB ALL SYSTEMS 06/12/01 * PURPOSE : * VECTORS OF VARIABLES DIFFERENCE AND GRADIENTS DIFFERENCE ARE COMPUTED * AND SCALED. TEST VALUE DMAX IS DETERMINED. * * PARAMETERS : * II NC NUMBER OF APPROXIMATED FUNCTIONS. * II MC NUMBER OF NONZERO ELEMENTS IN THE FIELD CG. * RI CG(MC) JACOBIAN MATRIX OF THE APPROXIMATED FUNCTIONS. * RO CGO(MC) SAVED JACOBIAN MATRIX OF THE APPROXIMATED FUNCTIONS. * RI ICG(NC+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD CG. * RI CZ(NC) VECTOR CONTAINING LAGRANGE MULTIPLIERS FOR CONSTRAINTS. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * II JOB SUBJECTS OF UPDATES. JOB=0-CONSTRAINT FUNCTIONS. * JOB=1-CONSTRAINT FUNCTIONS MULTIPLIED BY SIGNS OF THE * LAGRANGIAN MULTIPLIERS. JOB-2-TERMS OF THE LAGRANGIAN * FUNCTION. * * SUBPROGRAMS USED : * S MXVDIF DIFFERENCE OF TWO VECTORS. * S MXVSAV DIFFERENCE OF TWO VECTORS WITH COPYING AND SAVING THE * SUBSTRACTED ONE. * SUBROUTINE PYTCAB(NC,MC,CG,CGO,ICG,CZ,ITERS,JOB) INTEGER NC,MC,ICG(*),ITERS,JOB DOUBLE PRECISION CG(*),CGO(*),CZ(*) INTEGER J,K,KC,L,M DOUBLE PRECISION TEMP IF (ITERS.GT.0) THEN CALL MXVDIF(MC,CG,CGO,CGO) ELSE CALL MXVSAV(MC,CG,CGO) END IF DO 4 KC=1,NC M=ICG(KC) L=ICG(KC+1)-M IF (JOB.GT.0) THEN TEMP=CZ(KC) IF (JOB.EQ.1) TEMP=SIGN(1.0D 0,TEMP) K=M DO 2 J=1,L CGO(K)=CGO(K)*TEMP K=K+1 2 CONTINUE END IF 4 CONTINUE RETURN END * SUBROUTINE PYTCUB ALL SYSTEMS 06/12/01 * PURPOSE : * VECTORS OF VARIABLES DIFFERENCE AND GRADIENTS DIFFERENCE ARE COMPUTED * AND SCALED. TEST VALUE DMAX IS DETERMINED. * * PARAMETERS : * II NC NUMBER OF APPROXIMATED FUNCTIONS. * II MC NUMBER OF NONZERO ELEMENTS IN THE FIELD CG. * RI CG(MC) JACOBIAN MATRIX OF THE APPROXIMATED FUNCTIONS. * RO CGO(MC) SAVED JACOBIAN MATRIX OF THE APPROXIMATED FUNCTIONS. * RI ICG(NC+1) POSITION OF THE FIRST ROWS ELEMENTS IN THE FIELD CG. * II IC(NC) VECTOR CONTAINING TYPES OF CONSTRAINTS. * RI CZL(NC) VECTOR CONTAINING LOWER MULTIPLIERS FOR CONSTRAINTS. * RI CZU(NC) VECTOR CONTAINING UPPER MULTIPLIERS FOR CONSTRAINTS. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * II JOB SUBJECTS OF UPDATES. JOB=0-CONSTRAINT FUNCTIONS. * JOB=1-CONSTRAINT FUNCTIONS MULTIPLIED BY SIGNS OF THE * LAGRANGIAN MULTIPLIERS. JOB-2-TERMS OF THE LAGRANGIAN * FUNCTION. * * SUBPROGRAMS USED : * S MXVDIF DIFFERENCE OF TWO VECTORS. * S MXVSAV DIFFERENCE OF TWO VECTORS WITH COPYING AND SAVING THE * SUBSTRACTED ONE. * SUBROUTINE PYTCUB(NC,MC,CG,CGO,ICG,IC,CZL,CZU,ITERS,JOB) INTEGER NC,MC,ICG(NC+1),IC(NC),ITERS,JOB DOUBLE PRECISION CG(*),CGO(*),CZL(*),CZU(*) INTEGER J,K,KC,KK,L,M DOUBLE PRECISION TEMP IF (ITERS.GT.0) THEN CALL MXVDIF(MC,CG,CGO,CGO) ELSE CALL MXVSAV(MC,CG,CGO) END IF DO 4 KC=1,NC M=ICG(KC) L=ICG(KC+1)-M IF (JOB.GT.0) THEN KK=ABS(IC(KC)) IF (KK.EQ.3.OR.KK.EQ.4) THEN TEMP= CZU(KC)-CZL(KC) ELSE IF (KK.EQ.1) THEN TEMP=-CZL(KC) ELSE IF (KK.EQ.2) THEN TEMP= CZU(KC) ELSE IF (KK.EQ.5) THEN TEMP= CZL(KC) END IF IF (JOB.EQ.1) TEMP=SIGN(1.0D 0,TEMP) K=M DO 2 J=1,L CGO(K)=CGO(K)*TEMP K=K+1 2 CONTINUE END IF 4 CONTINUE RETURN END * SUBROUTINE PYTRCD ALL SYSTEMS 98/12/01 * PURPOSE : * VECTORS OF VARIABLES DIFFERENCE AND GRADIENTS DIFFERENCE ARE COMPUTED * AND SCALED AND REDUCED. TEST VALUE DMAX IS DETERMINED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RU XO(NF) VECTORS OF VARIABLES DIFFERENCE. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RU GO(NF) GRADIENTS DIFFERENCE. * RO R VALUE OF THE STEPSIZE PARAMETER. * RO F NEW VALUE OF THE OBJECTIVE FUNCTION. * RI FO OLD VALUE OF THE OBJECTIVE FUNCTION. * RO P NEW VALUE OF THE DIRECTIONAL DERIVATIVE. * RI PO OLD VALUE OF THE DIRECTIONAL DERIVATIVE. * RO DMAX MAXIMUM RELATIVE DIFFERENCE OF VARIABLES. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * IO KD DEGREE OF REQUIRED DERIVATIVES. * IO LD DEGREE OF COMPUTED DERIVATIVES. * II ITERS TERMINATION INDICATOR FOR STEPLENGTH DETERMINATION. * ITERS=0 FOR ZERO STEP. * * SUBPROGRAMS USED : * S MXVDIF DIFFERENCE OF TWO VECTORS. * S MXVSAV DIFFERENCE OF TWO VECTORS WITH COPYING AND SAVING THE * SUBSTRACTED ONE. * SUBROUTINE PYTRCD(NF,X,IX,XO,G,GO,R,F,FO,P,PO,DMAX,KBF,KD,LD, & ITERS) INTEGER NF,IX(*),KBF,KD,LD,ITERS DOUBLE PRECISION X(*),XO(*),G(*),GO(*),R,F,FO,P,PO,DMAX INTEGER I IF (ITERS.GT.0) THEN CALL MXVDIF(NF,X,XO,XO) CALL MXVDIF(NF,G,GO,GO) PO=R*PO P=R*P ELSE F = FO P = PO CALL MXVSAV(NF,X,XO) CALL MXVSAV(NF,G,GO) LD=KD END IF DMAX = 0.0D 0 DO 1 I=1,NF IF (KBF.GT.0) THEN IF (IX(I).LT.0) THEN XO(I)=0.0D 0 GO(I)=0.0D 0 GO TO 1 END IF END IF DMAX=MAX(DMAX,ABS(XO(I))/MAX(ABS(X(I)),1.0D 0)) 1 CONTINUE RETURN END * SUBROUTINE PYTRCG ALL SYSTEMS 99/12/01 * PURPOSE : * GRADIENT OF THE OBJECTIVE FUNCTION IS SCALED AND REDUCED. TEST VALUES * GMAX AND UMAX ARE COMPUTED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II N ACTUAL NUMBER OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RI UMAX MAXIMUM ABSOLUTE VALUE OF THE NEGATIVE LAGRANGE MULTIPLIER. * RI GMAX NORM OF THE TRANSFORMED GRADIENT. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * II IOLD INDEX OF THE REMOVED CONSTRAINT. * * SUBPROGRAMS USED : * RF MXVMAX L-INFINITY NORM OF A VECTOR. * SUBROUTINE PYTRCG(NF,N,IX,G,UMAX,GMAX,KBF,IOLD) INTEGER NF,N,IX(*),KBF,IOLD DOUBLE PRECISION G(*),UMAX,GMAX DOUBLE PRECISION TEMP,MXVMAX INTEGER I IF (KBF.GT.0) THEN GMAX = 0.0D 0 UMAX = 0.0D 0 IOLD=0 DO 1 I=1,NF TEMP=G(I) IF ( IX(I) .GE. 0) THEN GMAX=MAX(GMAX,ABS(TEMP)) ELSE IF (IX(I).LE.-5) THEN ELSE IF (( IX(I) .EQ. -1 .OR. IX(I) .EQ. -3) & .AND. UMAX+TEMP .GE. 0.0D 0) THEN ELSE IF (( IX(I) .EQ. -2 .OR. IX(I) .EQ. -4) & .AND. UMAX-TEMP .GE. 0.0D 0) THEN ELSE IOLD=I UMAX=ABS(TEMP) END IF 1 CONTINUE ELSE UMAX=0.0D 0 GMAX=MXVMAX(NF,G) END IF N=NF RETURN END * SUBROUTINE PYTRCS ALL SYSTEMS 98/12/01 * PURPOSE : * SCALED AND REDUCED DIRECTION VECTOR IS BACK TRANSFORMED. VECTORS * X,G AND VALUES F,P ARE SAVED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * RI X(NF) VECTOR OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RO XO(NF) SAVED VECTOR OF VARIABLES. * RI XL(NF) VECTOR CONTAINING LOWER BOUNDS FOR VARIABLES. * RI XU(NF) VECTOR CONTAINING UPPER BOUNDS FOR VARIABLES. * RI G(NF) GRADIENT OF THE OBJECTIVE FUNCTION. * RO GO(NF) SAVED GRADIENT OF THE OBJECTIVE FUNCTION. * RO S(NF) DIRECTION VECTOR. * RO RO SAVED VALUE OF THE STEPSIZE PARAMETER. * RO FP PREVIOUS VALUE OF THE OBJECTIVE FUNCTION. * RU FO SAVED VALUE OF THE OBJECTIVE FUNCTION. * RI F VALUE OF THE OBJECTIVE FUNCTION. * RO PO SAVED VALUE OF THE DIRECTIONAL DERIVATIVE. * RI P VALUE OF THE DIRECTIONAL DERIVATIVE. * RO RMAX MAXIMUM VALUE OF THE STEPSIZE PARAMETER. * RI ETA9 MAXIMUM FOR REAL NUMBERS. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * * SUBPROGRAMS USED : * S MXVCOP COPYING OF A VECTOR. * SUBROUTINE PYTRCS(NF,X,IX,XO,XL,XU,G,GO,S,RO,FP,FO,F,PO,P,RMAX, & ETA9,KBF) INTEGER NF,IX(*),KBF DOUBLE PRECISION X(*),XO(*),XL(*),XU(*),G(*),GO(*),S(*),RO,FP,FO, & F,PO,P,RMAX,ETA9 INTEGER I FP = FO RO = 0.0D 0 FO = F PO = P CALL MXVCOP(NF,X,XO) CALL MXVCOP(NF,G,GO) IF (KBF.GT.0) THEN DO 1 I=1,NF IF (IX(I).LT.0) THEN S(I)=0.0D 0 ELSE IF (IX(I).EQ.1.OR.IX(I).GE.3) THEN IF (S(I).LT.-1.0D 0/ETA9) RMAX=MIN(RMAX,(XL(I)-X(I))/S(I)) END IF IF (IX(I).EQ.2.OR.IX(I).GE.3) THEN IF (S(I).GT. 1.0D 0/ETA9) RMAX=MIN(RMAX,(XU(I)-X(I))/S(I)) END IF END IF 1 CONTINUE END IF RETURN END * SUBROUTINE PYTSCH ALL SYSTEMS 99/12/01 * PURPOSE : * HESSIAN MATRIX OF THE OBJECTIVE FUNCTION OR ITS APPROXIMATION * IS SCALED. * * PARAMETERS : * II NF DECLARED NUMBER OF VARIABLES. * II IX(NF) VECTOR CONTAINING TYPES OF BOUNDS. * RU H(M) HESSIAN MATRIX OR ITS APPROXIMATION. * II IH(N+1) POINTERS OF THE DIAGONAL ELEMENTS OF H. * II JH(M) INDICES OF THE NONZERO ELEMENTS OF H. * II KBF SPECIFICATION OF SIMPLE BOUNDS. KBF=0-NO SIMPLE BOUNDS. * KBF=1-ONE SIDED SIMPLE BOUNDS. KBF=2=TWO SIDED SIMPLE BOUNDS. * SUBROUTINE PYTSCH(NF,IX,H,IH,JH,KBF) INTEGER NF,IX(*),IH(*),JH(*),KBF DOUBLE PRECISION H(*) INTEGER I,J,K,JSTRT,JSTOP IF (KBF.GT.0) THEN JSTOP=0 DO 3 I=1,NF JSTRT=JSTOP+1 JSTOP=IH(I+1)-1 IF (IX(I).GE.0) THEN DO 1 J=JSTRT,JSTOP K=JH(J) IF (K.LT.0) THEN H(J)=0.0D 0 END IF 1 CONTINUE ELSE H(JSTRT)=1.0D 0 DO 2 J=JSTRT+1,JSTOP H(J)=0.0D 0 2 CONTINUE END IF 3 CONTINUE END IF RETURN END nlopt-2.6.1/src/algs/luksan/v999-07.pdf000066400000000000000000014553071345435414600173550ustar00rootroot00000000000000%PDF-1.4 %쏢 5 0 obj <> stream x}I&quXMk2"cIE3Hh:tl؈isL ef?oi>9iYﯭ6O8ޟ{OOs?5u9Q/Ox=˳G{~|ў>_$z&4'A试82bΓщ+ѩ!O$)('3]_;Fyԋ$';K}Mi-׌'zW/tzJS׃kNBs94LҌ @_'~R's " 3"OxЉ]̫ItdjhIkɗ_W&OYBy򖡝:<5Q' V!ʙѧ: 4'U6wl,=Z2,CfPi'><щru֦hPJ$q#]'WtG2CB%VNH`|lNpueD5ƞf;ΦҞq D ~zur=dç D>Sm*sP ֏e'ͅ6k;l$9 2S$ =).4q);jzct jpVuI0,>'〦8lY}te./u:~` :fqi8Ne,L-O]8#N;zYh`s;'e(`5чq Gݸŗ>F-C'؟1`ƑxdNVUU rLXS'QǔqL K~p2 ,,DC5I%4pgV>,q+'N)#;0Cvؤ5*褽H>W;)Wuc^7=&ҙdu +|0^e_ 33?"2 &:(9^~'Nζ)1A 3?%zTs uE-OX ޔxTxRl"%1)@{kP xF"ewia6)=S̅]eO?[##^\S *rH(DYǃ_͓TDy" &b)׬^z,;]uq\Nk=d1UL7Ojj )[ykhϭ c-fꇜsʞt2ܗGф^t"߳ ]Dz\_*X5*V~y(e" CE Z:qFϤӦo' D|u=TX+(Ҥdm{\澨<|xekZލ(ia}kC驒= 90T1siv֍+0hIpugɘvmHq1K n҅2]P˚]kBg*iWAu~NTĬ *6^zErNi22FB롪>[˲\+7lԖ\3@ #ԉHvTN[:̡ f&b:Z!2>bN8&&tqoV[/0&{C D&t0>84iخ7{Q6͠XN!഻ ~/":9re >9rB@V!o+;rGN󜘗"W³Zڝ1/׷znJ 9/NZtܲ+zg[}]\ x:s: pq|>7D/'ZX3?QbKӚtf{ I-u'ڊBif1d mu'UB ' _v97ɞ ֝.H*>%9&r[r,w@*q2X!$hu~ک eEq׬|>Q T[I؀P&*CtkK{aEk.-*oК[Žqn3ƍ^v_ vbyd dRԲUsXVjMYU/-"[pnz-bT%RTG1,-!]G7#QNk1B.jۮ^u|7`N0*[Yc5 gPԭ26 Ws( V rZb4zadE,B;b+<{앮AΈ @.Hg0*O?IgIU3@PD'i Xs"'+1r~Sv6iYEϢ'x6Ī' oUhʉ8JsNeo|%<.eRU9͊E<V:AII*HU%2 K+REh o<ۛT开q!Z%~x:4JԂE)-Oh  7*q u#O`f[.\Ҋ0XYh8KYբTcf*Z!?Qo-q~x.uPKkYiT~5ٺb *Ml-+y&Ib$:pEbH֠ ',:iqnɪ8w87p487xI^8\I1zݠ|L1`(4Y j`6;Dt^[']iPhf͂E809\qoySl=UفQ+OʚX3U/)DVVoѪ@9]%:NfSe[iߴ5A)bleoCPt([;-KV η?!X}{qTus5>1.m58Ih&Y@c弤4\g ⤵:ۙR`Ju6ԒJZ  ´2a:l+cY.;3dqh!,բ^@s*Xee/(G(|VSD#RF|ZɒBDtBEi~"\@ie8ox ztBCoȸ3'4ID'juR0t@u-ּXVO.'_\Ԩ-7Pư&/b6ؒx֢{HD m>vAwg$bgtt1gEہ8\O^‡]R0%ޜU"͒FpWK5ajP$E%,2Ή3dYVjpnE8uwՃ]OdSlg, ԙ=%/ 4i3[^6 7˖HmIpҼWSWdz4\6IlbkH=)z7 `0 5y1(V=#ĤWOOZ%ؔ UHۨ,˾ Q(1ih4|)LϪiIhIU UPVԺ֐F/`Gt^VX rZ.{4oJ/̇WR 2M\=p!QɝnNhH7 KA2C#6o$Z%,m(m• ]/͸7}iphaQf9mWaE"nNV.-9W.iQJUaaՏ]M(wί;x pBI_ 8/Om2wM[/iPO mqGt=L9NڭAwoKS9ϗ8$j%AkC݋TM*#yvgWžN`j,'}V"o8ᦅ#K[i ; _ZapYduvxf4jvjmaή(Ӷc֒*#v [eĘ + [Or;=G^B<>u  !@HYuCd -D^8Ϭ S) q\7=3@ \*Y:\aMgR]IxV' %ZU%S1jbkzmCozmDM[( #Pm8!s|knWVt34]ݢ`Co.o-!߄'2/yvE|펿]"^ @Ų6CH+0m>av\~zV{%~Fٰh)P&\2,;ob>=8ra"L6,6Dv(v6mmx\+yEbX%PflEiT-®E`mvpv\s;<{uo.b/E _0N`|3x"PvxxL~ID\!#hcua#0;h>)7ʀo_n@3l g} zPUL#R78wV#  ꠯vxvroD)D7j3 -2VmjŦwըOOZ墪+wm1*ͨ]Tިo:sTҽ]A0v͓~ M0#fc}ylhm;&hdfh0T!ԍp0wsz3AL)ѭ5=g#x>cdwDJtΙྉ".N膊nNJ]e:Ӣmタ.v_p Fbt;tetlF\ݯA7xs"G7spCo~ݑݛ+<7Wl|{ BaHE h<yc"!bETb%db&tbgm!RڃNT Z=kWmqW a=0Bhom>d P>a g >@jnqGq0a-C!c0;ĺ`x`n-`cK 1QjB] [CLؒ'􊐀4%lY"1$l(!SeKdS]B.LLٓiBMLySz?{JЖ4NR:iI1m(iOU{ULЊ \{WH)bif1 QZd n{*ܖ,rdn }oRI$kaLL y[bcL}R#w+c%A3p )!I4n9[jLRXCkLSec2mLqcn~cJpSc='yYޒc%N=:f={K{B~~`fX‚vg€L`x |zz'~-}4_П[য়%) E7v/_NG3K87X&T x 8N4ne%yZT'sN=3\ f:ppifBb 3ApqCK-8¬ Z!dр߸<RxB0 x,?1us Yd5:sV0k("9210U!=qqHhYFq۩8}\֖"xCrV8p TeyŇAotv"fϙѩ0I mZLYmy®17SYc1|%Uj(bƼYG7dx+ZV? gEۑ!0ȗ鞪KӁ?sxi-N#Zens$s.ПunwϠ'K@5Jd(޳/#摪BƨḢ1jWcS֛^W}hval@w?\WdCdٰLF#(;sgH F\2 KĢݿ W DB!fq aHb/n bĻWVE%f"UKvɤBY;ҞTeF:uh !?TEi:L+iulY4ւ&r-vQX"]lp/#i7޾CN#~l 9$ܑG޾{Ɇ#l*ceGa8-ˆ`"V&f"gnn8osn:_P 'l?;2PBЇ'r(` E(Jg)0HM1 *EE4 o*"RĪjC XPVDqrWDڡ"6X6OCc-"EK.E4xu."=ċyUo |_؀;z`  #a8#qPP#ci|ÂtȈ'&78W,w;fD|y `:#gA7Ѐ)FT҈ZF\F; X= ֠k#}܈7bF 7GH8" G$8G9"&G@ q9b2o;s}#tĞЩ|u@w;apG ;|G)^AmkmEBPAX'.֑+ZtVV.VbXOoW5%[MP3p*ƪ{P0=*#ډV|^1n|P1V!ꑡd?W5,c˽ V'^FsU⌕:Z^-4FT$ 5KcMӽiM+ګ6Vuʿ|l.՟j ׵EpEV|,}(o+n~c5X,x& zı`qhU/H,glM ؜֣t(-U#pj >#@"H3 .Z 0OL25qҖjrHKiw5A=Jje>nvH0zn6UyF-z\G}s+;5\%bt5d? .ӂ蘹u+.SVjVA\gCL\ӓ,]AV7!'wSirdN90XP]9[ݢ56EuHm׬-S yނ_|M~[JvƸ@0 Š5əNH.'E< u2N`74Gɼ0".»X6}.\fFRY4 ;1r/J)H ]hX0sF-E1Kj4gI`ᨐ\C$N@/s@d란? ]7%^/=: d!,s,bx*Psc&+=!j'sT]Zfn7MP? 9Ȫ}}HҞ=Jv_OShT.ˉb>F/Cf&Uz \ vc2,%n2 94nP^@j'~eiq>ndhtK{ʚ5os$3$s1\lZ6}X.1-uVqc D/$U tޢkqz `pL+&Gjd6UV U 9aj!Jx,)n2 .2%opmvto@0Li y62Lv5,ʵdKҁ9<(fw فI: o \p2^Ⱥj9:v2ną$2r.}:,<| q`_\dY7drY9v%l vfEr@`ccxO/IrulxHvC5j|dKC ;gia#-cV#ҖgIvKO Ja 9rv{j>vn~n6Dz-v[UECC>W-k؊#ڍ~/Ǝ; ڽpg4;?3~tk)˃bI"-.7:6)EeX$SA妛Dzو(Xs RMҪ$ Yae o?xr<\ w\Zׇn׋=.C5\+nÍ?GXe<`Y]ΛM݇{3Kq^_ۼž[܋uK>g8)+<ӼAveL):58(?05T҉1~:5܆?ơ9F6XG'VvOee}H|5xoP?mK`5'N !j>.ZoIUrƨ|q̫//ZU;&Z{۷Oo_>r%?oW?ж<󋧄Kt,/_1zV_~zGTzWYz{㇏rg|}|ُiG@Ms{5s`/#:y?'wY:ب>_7w2Ob/ohZ+f]=]ZR\X'uZlD Qۧo_L/3U?AF6?Ki-KIltAqΗ/<aj A FLBR>@g1])0yRf;:G Η%cW)KXߠ['O<#}y?TiЮzw$wKG~yzGفdˈ.gKFٺ<}ht|~70=d]č7ǯ?-鼝z;]cbesמ?É ]޿$ũ7h7Ұ37Dx0m\WԚvW~'/:j/~ pV_•r}zo3?w^/=_4_;1nДU\;M۸yј$t̤ԋcX>/i8<4)iz1t2:7OW+Occm;n%s_^#E'X_yX֕'O&+ZtMN @ :eH~yNO_5ߏ/?_W_?]pq_TdQAm+ݽhi Od8_b/CvG~YfmX~ce&[a=1A0ٛYsugZ?}Hظ;D?c~][4biXr qYΏ)dI,}.ҍ5 a+1)4~\`SC:TD#qQ^m =(áá5A d5*z[~ $Sji,̺05q/*m ECv?-[+06VevGm<ҡ0\>"g7@uD_2u{ yAq-#2^d*,Njŗ[5N ϯMo>K'1?ѿҨt/endstream endobj 6 0 obj 14003 endobj 15 0 obj <> stream x}ٓ.Iu;~Џ 3@fK~f5a̕.ϞY'0D0yw~<'}ys_xaQ{]8㹵xGz #Sc]~ю-=eFϽC;=^+EH8z=x"FE uh/tz")D ߐp. ߐ h"v\C6ߘs'.<چ1d:FS1_Y#:'H/EHKׅ՞g q)ZOi] &4Q\酞Ds&\ :!!+Zn[ڿ!J@*(H{ҖBV`~3 ŕFW2SWО!C6 N-`-H>Tp)D3ɚE.\%27(K:hBE:7|Ntrl_[,C*,@%D?c)3F/F]nА 8¹̞tE?->aQ3۱ XB#sWq5hכk#rIⱌ؆ M9#3o2{/ 7` 9N3Xy˘s%ߺ9þ+[Ԃkx< ($OЊL1QDphpZq95=.]I5kKk[[{CJM\e8$a8K_զd+-3M-6Z2& ZAn#'@syHBd0 R&HoW8e j`7#%E ?8b :B/(.l1TZ t=7AqK_dQ6P0Y8|fЅ/YVHAb)"`4J%]k/@)_ ,pFp&3'L4RLL s]I_&M pjH& NtʚY"Iq.^n bk4M{")Z52SCک1\]~#k9κL A Rf:"!D#E]->H ' UzXm\ϳ vyAAG]{CrwhF"\b tZhqqZ"N++mz@{[bH>t7W#,yWYkDȕ)"U=|z&i/\awZ u\@"A;mD=kY<Гx/*K0 DmLVp.xt^C#f41D^G5:xUHB-m@ڦ'oD3wk7 HJL o*Qba@g@mh1YW@Y2,0W6U8L"W DdihL ]w_FN6* 4*.`ߓkϴ\"+3lؖ"#v#!BC(*'7-WSqtrNZzz~S1!!2J8P_Qc\<mW ;QaZ2ғٲea=b5!&W]z8ELleñQԘZ|SQ[:miֈ$b$Lխ755vbO<[4CiږXsu EicQNK6OW![= **eLS\)ơj)拑i6rhG0c%!O^Yh1o3B`Vqζp#nO7Hm0s%LPzBQmխ7iL9cA8 `bk0>Gr!` 3s"VRfGd 8{X6SX5 ,Bj1pL9f@a)6Why<&!7$zcD>= uӪ(Jf hsLyƱ7&ynIiBlhvhȩ-܏D&P\L'03ᗘ.^aF,ǘYh 3F\̺fM(3cU9wb^'y.šFSYl]2FLlh1V M83ɪ u0Ȑ%pOȦŹ1',q93Sܘ…4ܘEADB=qdAdj%QAizXK<L⠴4=A)5&]$/v}"1-1j ,elՊK>YݛmVm]&:NK$em# blyoPt(=MUKfo{$ۻ _1XZQяIvtH˜PݐIrǢ`qJc1#fF3%y0.LҺMط1҅ S*#XDLȵ/T+#RxLMR@ݜ}L!F#>֨0{؋8",@YZgK2B/gq۲Sl[qvImb./Ww$֜x$Vԥ<0o̬%|qW5&7` /=[շQ/ۨ$Nz$MȵM}t! ~ 2Gc̚E_]D!9QM9" .EGoBF"@{HAA"/'j g(M^"7h( 5)csss]4+͖/.rC[ QƄ^QIiӬ6%1h~G;&B> )i~iod0"`9v6p0%$N⊬͍C"UFp+W phLUC9P KX!Aa̘Ig7ġ2!gYԡz0KXֶ0DTEv:j r >q ^D| JQ]hMyp=mEMSB $t8qޫS%j/0hܭlJ&NJD^[NYOg3%!]Qg[-J JL%ĖW Or+Zm4 R(%vEKa|VUKnPRTJA|2UBYć(VI6}uKa-X 2R\z4rՔ^10X7U g8$Ju2'l)WD KA4#VnZE,ېWՕˆ{1տƽzsZpށzPMep* Q[#{fjցWjQꙑ;fNT`rd?v 7×$w~Y{$ܺ\-m8ǷݙKn[Lo2lđ\>\_]#NA=L:[C9s(\/rH6s z8Jps/\,L%sj̳Lpyҩ{zC7]S!sWi{߭`99_dz~C`f? 2A#99r0dgM3 VB0漩҃UQ=Z3ʂR0AЕEBhӽXYzaDI! [tFkdcO @\ WY(Z[/Y.%Vd9Ug=Br> 9Sc-wꐓ4 [:/z!_(6',Hn6N,Lmd= ,V(̟X9oU19pn@ y qP+ ?DDfxA~"#X0#JMUj5[#(Q6cV+#z k eD * C6z{ <!y.8dL BRl*P;,IYm/)TZYy\7MQ@ L*F\a )w^ɪ\k_th*y|`M4v-Ʒ~_f@T8QYbE]q5׫/3[t*|s;E X^wׄ|O+wॼ̠hVִзt6ejYd́8|^mcTv~s2// Ux◚f6D+OovHV.D#F—`IrԐ$1N-„WD\YvUXl{A4W9l+j hmE4O&Ѵ{iX !03WbMe4.e.z#3rvtCkv&ח26x Uj^h(֎]!) d TK(T84jAk`LaxY(,%iW|cӬ(Mea9[mf D̒֋Yat`| xmOy/w;8 C nh7N0n ԳҶq+5'ޏ@tZ0q*V ,o90H&iRrPKɃ99 aE9$ i!Qyʃ]y0 .imp[p^ma;:@6Բ3= 5L$F7( az ånp7V= ބt5W z`Y$c6.#>[Dh t:G|"_..\\ͅs=}p0#>@ytAN@nqX=Gq0a-C.}0ź``n-`}K Ή>*5.̆-'Gl{zK { Oؒ@,FLD%..Ƨ4.Ƨ\$sϞ% H*YG>-ɧ-^Rܨw{Oӯ|O3\ OH";4D5T-Yv>ϧ^.RIong SКv]S=yFzO\4] HuI.t1ݒP}]}"*i}햎v}>S]R쓎9[쓞-q%V>7ۥn[K=Kj@VJ3,w5 '>$,HHrrlw3+^ bSچ6o`io[ w._q CE 24#aNTn!Nfmqڨ9ږQQ ֡iTƢXd 8 \cbBl pH)OO ẂB Y5JJ+5CPD4se"ю3GmPH@Fv 7:im1RJ*7d*Ӎ-DV*:-d'l[;("jϩ0I$EuYTYq]+~XUR vrZ"CԘWCoE]JOxl_YpZTTB,{.N v6..X 9 RiizPr3$uζ?WO>n_>!Nb) Эyg xg"* =3KQER[;^ ڼC1ƣƛ W/wӳ'eReĪlTϝ:#9$q_J, %E(Eqr60HbƉ/ }1+NJũH-TRܜiOTKKqi0֮C?홗eo]U ~Lcɴ:֏j疀qnm'G6X£]lp/i7^^䠓0Gq"g䑗װI$wo7Ov Ca(,eqِ^<NJd،Ǣ@qx6rsyww@y6@;c ]'2a y %qv&t `Ay(&MyD*XcZmW5jyԭ!wydc9]lsd;~C8h;DPk;Ci(n8o #XrmΣ]9D;xwQ<p)Jy( :bb QMrUYBU9jNϚkxT<4)nR ,2Eo^&нC4SQ`22LzFj(iiɚ#Zl&bv]Мђ-IG "ߗ%g.Kp\ #U͸XN𡟔eLנřܯYA%yCj~-W5V/HXo^QHl4z,%Iz^K'PB.{RAM 5Ǔ|dM瓬v0O”"5cP (E5NJT\I+(9s•|T 1(fKHԎ0rr`Ax"X@UNFGtceGY"[Bh6~()ӃI"5Z\.*n,t SE)EX$S AMWfpb1m+ AZ$vWaTM1S 陂'Yt/wrм>t^Dwbȴ*sʵun}·DeuN'?Lr FLAFGZm2ahnReƧR5M>G8)3=CAztA288&NQ|`p өhcepMـ.cY<`Ga+t g">`짭A'ikQf)oIU*tE02QZW^уJa'1 2̲S NJz@#1ϓzo};y._v l#.)M:>@=+? RnᏏO|'0KQSjK{L 'w]+,s}tc`~|VGo^Ɠ@/'?U?ѨN?A,H:ԜKxQgE}W-|)Z^g*?I 6 6^=q}T\8pJ b(0R0PЯy[K:`?zʍ/%cWB-oV-?yCpDT`h/rS-OoN9yQlK&]?H?]|3  2G˺@gC GTJEzTD/5 j-=j%6;D9r&E |O2_.o" /3Z'KZnzAhZ+/:.GLO S^>Zitmx-?ljn`%Asj GBf +.>yr7噷Љv.+%<^k-1cw}>v//~m޿4'Ħ -ʿòU)/t. ~q|S(G e ˇEuD: (NxB &Uы%;+@I:}*fx|*5e=nFBnxѳH(e@0lMfe( Ԃ\mjr9 sy@>Q}w! .v\obT)^ _W2HKm9bhv!,.<@Ie *nY%F$1nJ*`Tv=aq*#2*w3:b%B~29y~zΦ.^0HK3]诩+yn7y@~Eu.]gEShFr;Ã8vp-YhYUl꼀L7fQGYIx5Q]ZYoΗŜA0 a3 y5ݢ4QДaUy@6U@!q9*j2\+RFnc |N86``v *@G<1.xruϼ4sG7W#ޅψb~ O51\%"u?;<+s6KlL`1O+0Sq!7G]J;GmG{ONF1zRjL$r͟p0i%!,M}qbd[!۪N~6uo{7PrF. j<-7IFzz o^x%韗8ǩ%UOb#σϬ-jprl6i_U\pQu :$͐]c4]罩9yuk*o8*ݶxC]{V6/b5ѱrro '4Zy޺15!Pݨ'Rr/MZL1m]hbѦoSYTڦh)߃N;'Vg\xιy5Q;]/# x1hKWÁ `pkG0?DQWh0T|qexSU Q_8GR1D-:"%0&Dt'=>a⩸=uR]ŏ".XqA61‰vct)g^׭0Kw$6XwJw,79PIzB`J UK~$^9v8wh7O'DG"i9§Wjmqc,>:NlObhױG|'~ӒQ^Y,wN$/NIAK|#,p2)ZOf\z/eY Bl_h3GJ%qsC,sLCx- x^K+M'~mxuJh9+o9-E/i1CGjj-VU+kO61Ȣ.N zY#L_ kʫ[TL}I!eq6-4"{RLV==?g_&ޓ4r"_?&[dt,7Niȧ=w5|]Kng_'Gqr 0ؔjTs`Iϋ D#W\qq%_kX_FPQ_wf,|GR% ;>5N/K=ۼL^E]JF}ye9u03I9 ڧEe1e|(>o&@ S'|קޥiIŵryL}mMpjMщKyx5wGBKD6ɪ% hU=#EC*yj٧2-tuF0HpW^-H?-<%_/ǫ֭,'Ƨ^%јF hwZq@sչnt9|Pզ==WirP?%sY[F2_^薒y䮧2NsɆ_}yϚg"x!0)IE9'͠';Y36x9I'2H,iWFiTQ&zi;}Ե@؅ڟ(w>u N'K+N-t7wݻo~/~woo7;߽M@+VaeEBՕP  hn!([ƻ)JU`2RsA}hʃD-{#i#Ae$usyA<@ٟ#OG`"u]P&PD3]f[?P&Gm" c[<˙;.zz~t0?™nSAPnmB>p~#Ft3a/'|i-b$Ft_b=љzBt'*g|=nP"Xv=X7gauv.(@ig8ԽmPɒ7F=mrGu>;7f]wWZ5o<&dҹ y(J1Bob*"/) W@ukusz;eǀ ~h?[Ar@3;8N4b:.endstream endobj 16 0 obj 17914 endobj 26 0 obj <> stream x]YErp}qٌ F#@H30ygVUWe-}]4CA\^~?+{E? ֻ.p;n']>੽cfl߉_襝;69/19ݿ:-jpdTq8 5YQlu '|_9@N(S` ra`w_\?z+]\QVj8 #G&na髴|y,Obg6}fp1lF8kx,*NSap>q&ę{"ήPiX--_q|4u +fSj?ۑRN1.K>^HXwekdJCzZRLJ+@;ra5"R q@ޗ}׃_tHaZ n:Y-?-QMN i 9 .p]L{KöȲ ='C;S;r5xri0913||J'ui*, |7 WpCe7?='ǻ?$>ff Y$])ה }FrgZw+'R Pxjq23W؝3ᷰ&a_{[viP99v0T KC<\1@w7m(΁P>+MP3WOSUwoSjY]x95pϏ+4XVB&l9[{JPP@>f|/2̝}jNX绡̡:* < ,"--QKi[lh(= |U+V;gba|h A^1$5|G(-Qr vFS V)`Mki꫔ s(ѦEYRV0_10&K<أL!A.@/G\ZJXiZIjK9D;%A#{hcH$q?)XkTдFY$bαߩ */b[|ӹ:0_Lݱ86rŕ[v"\)E>Kb\d( $cʼnzQ y`nE߳qϲiPڗf]ҚϋbM1l5UҠ< +~m֓5\#р. ;۽۵,}M;S:,@Q0w+UZrHUz*JtE4b\]z~ u_ZOۦdŃM᪨]|-@5P4k(¤I \Tvݬ#}>k[a%pjr2-8TC f^gm=_3vDN(0_efMƱI{C{Vmu4e[b!n z*82mթ&MF`#@+!&32 3N^G L7f0Dw>Au>,\+@ HPn"KY@N8JS0`Ns/3Ya-f,3(L# z:f$PD"M =Bd;:[9ʴ:[\uS"y~.|Sh ÂyJauX[M؃uuɯUQ^,zEic ɷkӞL'&0rKd3ʃEka?@_g(Ϸ?\[HSжrT,%|8Tu 4N=_v&׮)A4Er?཭~nzp݄k⪀ZopBm0ov]P'=HTɃcmpIX+(K 5%go]"J0$W'1#^8%H/ohʓ. ᄖ7uƩ`)99]Qz3Gw%jxU;w0 L:C ӪRpPL b(1oj iyZ:H&NX,-:/ӆ\ hFz r O =z1h޻r8"ڽny` I75q$.lY&qv #T\Snc\HÌqxp,F%dkmb lBi>8lǨW@uȑP HEjsfP, J3 m"fÀ"Ϭ`FV+z!4څ8;_c[ $UCaB=Qq ? =|д.%]D0Ͱepb‰b|thM`}FdE-^v9u 4VcZj!u4=vW5*s[m"Rjx}<'8?l&]<*Nf)dg#T^"Z&³Zw$aiJ>zL1^FT)3Hq =Cevd@2 )/L-(!Tl(j0c|rIPZ;.GN 4|0&s@ƨѸ>qq#J=sx"<ܚv' =f{/`)TA тC5Z pֱSΥ&^SQu[aU kI>@K| (8W7@o9eLJ( 3-WK ΂'Tf-8kgG-4KMD]6F՜M_k'(dRb!wX,^3`[;xhy>R'KnfY4{!ĕh_BlBgL7Z:yWe)U>< ]g\ -!;tumBͪ'-l $*~WXX!JؘiĞP ^_s _ [јcv>T"u@"XQW*rwDqx끂dMj#KC.RGNbnR䕑Vz< j,nǶ^=kZ9PMHt[<:F)>HMG/{: ^iBx1\*% ANc61ȿ1.,ѡ0o5jԦ9bHI8P~Ʊ9#\C+Dk*{T`k-A@4>_9 i`Q<͚&_͸ LJz+)`fAAA>EQAVUx/XP%HT懗D!]5Ӫ3*  VT%*Q^_7U /\މQ-~3 ȫVB)&c+B3χ+ӮVlzFsq+=;2r`%ǝv C_wXj'@VŇw{~|O\x?̃sX_ƜRPN=#XtNBN,CǼ"T3)4$/ ,%GKl;.gVI}#W3_W݂:5Huu=? #۫hm[fE3!_d sYQ40ݭ&^:#%mLI @-MWҕd>]^)6v|22T<=)YX /7XG]SJ=dNI!(FsIJ%w|`Z D)̭_҃pK>6uf R e.Atʤ4e/–kW8 ᜘m#R)=TRSW13U JwN?뢿?_iFY2N7YT&.X"ro)oPUɺ> stream x]K yc~䔙T#.dvlK*U>Hrmɖld{fvg%Y>@`o]|ޮ釓Ox KWB oӇ'DVÞ<ݐH0Rǥ&eGttk{!~Y d3Ch˝8$ vf@.nU9edOg`a־ׅ`d fl[ Xbf 2"qL%VyyPq|[;HPuE8!Mii$㏸֦6$H癰cQ"-r+PQkÆz{6p`%,mCIΕz %.Ҕ_|a²(f4^qxc{4x/uzt@0/ gtEoɖEbZw%xlp *W/x=s=.S: ;`]yo5=l V?7|MKsy(x-PBm]bFY%ر_Q Nt5 b5.%2P] QqA9ƅ SԲ@XEqX,O3C 0X q 8~kTK4}LeKTy?60C:v@)~%AP5@pt KM~Qq!VŅ$)@ Ϧ3M#Kg暠%vGx}HX^M{}<RzDY=ohozŨ[өo)͠%OUǛ-t@W d,u28)r)202 NI+yʼn7v~\ќt7I)-zP{) H?dy|3 ;!YU`P衒{Ѹ\x62ӍKz݋I[|cCJBQ9όXQu!nbǺ~8:[>Rd5I:|н]' ^=0TzcWps\=Wpۃ{@+ ywtGi:Qp{xz#F-㋎e}n-> S߼GSOô״7r{ӂq ?D]k`?AOD dsBg` 1-jT!'A8y`p"v@{ղ )r[+^6Gv8ZUU)j9 RjZM}9I7ֲ/hiЂDN{Cםxcsǭ>2+}vTs-b8\Ҹv=7$`v@2'$A˂$3s@Po/;t [ <$0+سxfz/<Z#q[< | ]W)xV<3} kDBgD;1,?X*8F`5YW,RH@RVu*b;9/"#8b̫Z(uuPxQ[j3SA b_M21Q{AP SO#O8Å`FPhȁѤ(̃h ¾^[EۊVf4Ɏj%9sھ#৾PZ(~U\u$fօ* Cܱ~Z D:y-Qxvr8bК J g|4#܃RZ )ĸku?מkRp ˀa+S bnr0 ԁ^2 wQ\Lp`t.VF ma&V؊1 Lh֣@q/D!8#@lffM-`%=$27]װP8rk::too`u0%W8AVTҹ7n66gZjr%su"$|bNjxcX0;ZYu @K~z/y,; vWrCv;{C>O0CY ;v%Ȯ.9&V}һ(gYk˥U^_P6 6pq.(>kCgEEDQJ` sCj#<^Ɏ4_ Ǿk$?j+&~.mELx_E td@sc"MQX Dϸ.Ft_w}kl"+J ;$(r{1xƯ/4P.CQůzq3$0*_-ͫDV{aCn|ˤ !㝯tӫ[VRRG"i2v uUX-*zȔ;Žk` v5En9c<Sq#Iu:fݭR*E`/i' pX{AوWH,R>97e}sGULeOԂVͭ~] _Ǥ5WKǟ؅Dv4隘SBUaxӻ/ʽdZQj{^c7pf۳q|"EM9jo[[%aOqΘ]7j",g_`k0'VvU jrlZHSvRiz[jq}1[>N 0Y4fXH3d~#)%zn~ Iĩ w!)=^nɅ㹥^nn/2;旺LR2.jvn[GvfZ=ҠRx[4eD4'5sEiT?ODQܝ >8 ΊfUISA;$.aCYUXH眓/͠y2U& f:ٷ1]ԌSE 3Z8~AIh~0lOr= ye.sF̕Du >*%]WfrM<ߵ%̊IDR8SRA}(E0'J O6.=@r*%t_2A Ģ%j= y`d!ƨEzDVI Z6 9+ Ć[g|ƀ75R1^e ~zo*dkb*ݻ\_ߝ?qɓu,o{^Yֽf{q* & G?9~=&y͝m_:yp@AcARc]ɗŐendstream endobj 48 0 obj 4665 endobj 54 0 obj <> stream x]mKU~~b]opv&8w|6` >f4+*n=;;jO?ji~\u:/}ÿՋ._Ǖ0/|p}DŽ+{:Ň޽}Ň_kw~zB˫oq W8_pX~ef֭n_] S''.|{QVj{j-0"݉7#7|wձފNo$Fjۿ\@I:2Zr= `|Gu O10p^}}F^I9%nڡ98Ad}}:qH0_~LGMev#*KL>3L31!&;Vќ7B]k)IJ$VP@v18*+P? + - OUe,Fk-%;r kb;"P BS@uK`ѸwZ@K8g^ :+!BQ¶1<6˹c--FD=ѸwlmK6Jh-T3DJ4XۡFk9B΃)PCFA{w h.q"Gk%D J <cR~CI_k##"!6B"}\"G<$"%v|{D|/R(Mۭ6aZh "ΟO;rZ)RūTS/,c.cg4`-V5VH( 94k-q("j[G[%4|&4kܿE@Z#,HVs1E<jVY'bUsZ"elpgk 3{d)Xǁ e5VJĴG1aZkCH|~j_ΌtmAMa4A9^=\wH' St8FBYCѼ:1h1ܬ3xdj jz,/u?Z!O(}}kC @_ceFhsWk-g>"B_c%D#J8ZK|,ՙ|:Iݾ“آ}-;X H_H8az#DDF(v\|jY;grG1w'nqA#/zm%GzKxHՉUH~PD21k:nVJNSel"{jZ ,Iik(]H\(5٦?{OYE={n^~> jZ壅pz>s|\ &!za3xleܘ e+ gFBq S:Mt-a߅Lu~aS0{O.1`' Ls{=ꇯNaN|"w0 5tw~z Z{{˖;hAotGwTrZ"\ c^MZq1:v1Sqd`8GIږCԻk3Y}Ol@}\P]Q|8_[{9]l3e=;=fΘxAIFf'\a9" ib}V"+v:>-@ Wj;;9\U*{x=.B )Lr!@Km “RD8k[GHty˅p?M({PZg6/&: 6\Q*tڑՉu1lxe SWgD$|Ou#q ysx+4oMᇡf3$}L) ((0NVrNA9ϯ=| ^| g@jo-.2 L`8av0̪R=$t`{愨v 0j'fp8NN5YJP*Vq\iVR&8I]s!eX8)cb7qyeA̺R#=I>bpJҺqeJ9B >剥b}ܩj!wSгDsoL%8"Hz lZ[7^EV≙15Υ(3@E>ob~$~BΫ Dd׹.@{ #;2UYFy_Z T"F&r}q YyRܐ؇  U|$EZ CnJUנERwB`ϣ16ZMBz`MY ೀ@8" .q ,I};<$',Dl^bWr(CH9RgVs|\d le5Fjq)PBj@ #G+K % F2!kV7z5J*KUYTu+A㤦4Deq|ʆϘC 2;-ş$v8NGSEH} ~bontP#y/LiTxhGշ,ܬ' Cm)N.ʣ4[IZb hcZ.UuL(d'HUUu}L)!%]"ciRiz "jͳV $I?Ճ7CK0 N9u"PF5B1g5FZګ^J2R]X7o}$~MU_iDNtO'e1DR?6,0mPJlkڧV%2 G!#luYN@o{jD4b_%-tA>DBAa""ΈgJWًt)i 뜙TB SΖ`Y-rUj)LP;e\˹42C'q .o^-gNyϊm,'VMs o0Z()x 3:ҜJ ݋,Ψaex7hM뱖<>|?,|+`IR@L hNd> ,O}-2A͞2N-ԏuo^ c%Vֶ̲6 L;:azTϚJ@E^X2h4G> stream x]ٳy'ׯI΍9ޗ`\e JbQbW@ˆI,Yz{^CR2Gsgzź-_*\=_,}x< _pW<آ"/>>~-bOObFw'͢<>a$rg|kx+6af-0ǔWs"# a,nޚ"o`\^&yr-Œ5`ޏ\G>G5s\Rř2U8$J*2'dGy20fBr߯@2~ؗuBF|N·S„׼`er|-ҷPr^-.1֯r嵿/|c=) DNڥ/f\{7_! R-u6Q-©+O&.8?SڣB膛L*BNOviHR =,N:*&aCWg8iZV5zQŸ&ORmrmMa褔- `XՑ{p~XD;P&3њucz|CEf\,LP_*f'[A`1RW\|ތǁLdח?[9/Uª-WeuPsgYem O=N b HZZ#*ij6)]w(ħ#0HKa bI$#ł>E|^__wZw_Srʯ__Է F-a1I__Oʍ 8˯8CMpmޠV#ރ?P&3D $]2 PܫH?R9%V _I5z_1ڢ42vx1^Vr/|n ]`\.,~:wa}V8dEO@"޴"Bˈ`\c@ƛާ @Am 류90%~|j N@}hus3b"6ق }`Z܀*]}מ$zYPND]\6g}6éW~Uoݽ|m2dRE-☒cd1tT5)ie'SLzޢfb, kX!Y b4VV=in " nSXh>L(kJ'Դ_;ԈndĥfL@}$ `JLLA%CĽ`B7@K.<? X(2ç3 U+*Ό8 ![^[#!>,)$F)rMw7b5@K=$7,S+[_@yRõdDn^t܏ ($ -.`t[O1^ʎk@Fu\CjC=^ K= km8E/0އBbC=퉴mtE%6Б*r^%Dy!W6 +x8 .:ܠA% ށߠ30}er)oyh5Y`͗}; Pu ٞ_,!_>*$4"jke!u.@ %Ɵ tnɑ%b1gA.-'b^% `rCV.|Zdi Z- |X®ke蹃PTJ7x6κy5Q탼XAP%c> t (h|ͬh^vlKmf+I+3Z9wa ķpc J+.{ob48gT k,aжRިf(ᚂ(!TtVa\FH{VXYPD$= ȬsdMf -4T \ VK*?oW\rziMju?=ơfX:||Bmr: k]@#Qv:"cOgjL ژKU.J l:ݞQ]ԊL bVQDpխc.{FSwSm9SrFF_&TcM - ^TƳA0HHn݊Sz]nQ,I 9u^4%+-o77}nJVRX  !nAOߗ5Y?e <*oCoN:YV نTl_7&p-Wi,5Ð'8_+{qkj ZG=)5 o͇15- $1:۞`nf/䆥+-2ucγ,5ڑG5OO`ziWR$fq_]k3#˵B6\L?a_X_dsqPj췘N D K>tW}r m0h}DWsc6"^of7`84Q%'cCaVORtj '4ķPT!it&Ihm> ZL NSdRd甇c4g8SGݮ@D6.p(7fi*xd/ǀ@}r4b^WJ>;Ej) ś҈Vg#W)ڡSq.xq7h1\O"%66ڗfߨܬ(w#ȋp#^5X9`n@~2 kYjP}h,9~?w-FףvdM jR,iTudO8>2dHT~Km^\%ʧӥvD8,lV `}9/äAv$@*`t^?rS 9'THL3Z~ -^FKnNlR(66}l26N/+Aer4 UKPL-& a%hn{D\ Si&CÊm$$wo")[#AW7|n/㤒&sye 3痖_0twwuHJbݶuzUGu1삪͉EiEq92blNu6gG$8<#FN\n\,D'zI9PpL-o p\ s﹬˟:B5GדK9q2]*FoϟKuWlNcY߽[CEYr2/NnHaBqk\c(v,T~#Ҧ#Dmyc$謳nBoS؛~! G7V[+ \kr'>mkN7=IAec,iTzk6yW5-HګQuH1-^g)mUX%S}Q zQ =)$5SQ]_e ]r8Sdk9=aibdv/)~\M;/N)kQrFػumS)ʦW )I[(X-UgI/d iiQx1J6͠-CǐWHAuF4SULH@X\TW.;K+zhܘ,H>Ϊc2 irT%!ju6mi$\L\ֻf-kM!zI:T9tK&:%c*y,UN:b FV{ӰhV\B$Y𔊶p9 VoB걶;%Q^9^ (]̳"sMD>EsCjƁ-PpΥ|}֯%ڪ6PYX(?ֈ~vQ: jճl&:n(¨D+)7`"11 8,-5NV5(7iC/.nm Z~IU@OJLZ-Pii_0ԺJBo[fF.V_hŎd{`ꁆ‡9%6jA%}zDrl#kPYPm$6$=nThڥ LOSڠLjr Wfl䜗xD 6}k4ITSmEeyO3D#Х>t1fEJqm6>n0%VEFo)a B:R$s 6|;x# FƽÞuI 6_0H5q'7Z,xT'u+&/OpHkS(Xɺ3^@\3ݰއ X{s} ;7V9ڟɶG>{TW؉ޫUV ʱcxM}J8ҩz"PA>f Xk-T :3B#jߗj-(iT[1Bp,H)1M:l#v9V"E+Đ:FLˣXbx OTg/T,1{xZ W=:>]'QP nt9n ]S_P}H[9vFUwwQ ;n-'E tJȕRdo~Jz$:z/qs9mz t«ܢG9MFk#ib[!/ ăMrJS&ۙE}rZVq%HZj!f)$,'#^h)җoEY#"۵1RKۨ $}i^X6|aVUN6=vUo+7'}|arA *=]n{zq6B\XÈU8'Ď{%F(fF11SX* Y%VKQ (\ _U;;\Ƶ<'cܖ(| E9P=#rToPp5u88ٻTCSJ_tFF *M/NB_Ԧo57o Guo1tAΩ"#MBW9ϟk +Yl^֛?aIA;ZèeDŽAXd2n(D˚R_K2ʔ_ HOPk˾q:IJ C̍SRYUJ]~m- lE s{:;3 h]}h6:펆m[A)s=]P\>$w)+fUᔠ$*} H›%l͵6c.o~go3EʐɃjWYk`RJƫaوI&rq_r)"vdi`[¹@L5 }O>y_6֧PR0f BV=XS~G_v ʪ6_xAEnsLKf}T S*sRr7m3J113JbGm;*_Ssj;fO1jݨpԹendstream endobj 60 0 obj 7547 endobj 64 0 obj <> stream x]IuV8ҾbЖ%h[:H FȢ~/ʬe{rX]^>~_/n^?$}1< 7dڃzb˛_=JuMLqv|s{"Kj<= Sx>,ܩ;MGb2N[}y'f1)",Iý J#U+Bq;@v8ݞ-VJ,6_Y /?٣cӼޚ`{&M e?Ln ~F^x2p=q2t(ZDr"Nɳz).< WYx` W!6,l8B iMV%#5i/.+J[3 ӂud]whUg-!ASЇBKA"U;m9n޳ج`)Cp vݍ2O*dvnWP^wTp?E~PݝOore$7zV @-`}LɃ+aw8@*9nguUtOvls g¨T< n9I8L@o[aɏfiWέ03u6~5r:|xl:їX){gj ߤH@Z0DL/q$H! 3/ap{|I„gS0(R|b47ǷEb+n쾼-nOʄ y5 #q R[qEv- 3 %vxˁP֮L8c,gPo Ռu٘I\fԠ|HT⯧xDv28pJk<@_E2q(MD!$]N5b=TǟdaB=f<0e.h;ϲXx|$Sԯ1 ѓ<.JoO?R XrcffDS;|Uc橕lW A.N p!;]g`ZO7& gW5-0I,Bg3f c,soBmye#)@g-|!G=wDa~ RIJtd_@ԊOtE?6N9\PiQrgee{ Ä/29_܂m,~7qV<*B)iJN͟;!=Nd ;Z3KQTjT4L^JrѯQ&b\@'NetD9Q 3. AN2w 2#62Nja, =i vٶǍ v~3Ȟ ,vjgv;:Pb4D% 3YV[m~*  &/{Dmۄb˷a?ۊP[UyeY-u3Ӎ(69Q8\+ XGUs25z9CMtkew{W)&Ժ iDg,'}=ƠӹvsMZC%IVL*qq8%,t?@缲 E]CvCk4aTԵǵtLtg.4KG҄DHA1f#tT-l1&yWGXZg#MUM!86!*Z%FZ>9zWt$S[0ol`)5`3(AB_ϓ#ZF`97802\yw0'E춅y&7*2a7e,aa1 |1hv5; 4dpʡutiZ+D<0X]{ndxԊc| ~ĵi=J *"X;R,\K*t-C}mk-\{ĭ;m 溶6z56 1k,P+ UQ<<@렡Z|A1ZVtucx{W/TS|nl9evt=㦢qS˪KM\%IWæRy+{x/v+H _h GR'a @e4wgj.^-kܣr))SjSesC8 C8*ҮUohtWɼ%, U ZuH\ABmW֮5{;i8B8p52W*yʪIղ('s5sq#Z5^n$" 'RKXTt38n ^h{35 REjQJXJOЭMRtV#% X"Af* Nn};nwG/T;@JEchiwD D J]=^`UFѮY x-9&3,_vP ޅ]/'vb,p_A蔓B\Xwjhtw}#+QnaE]O %1~KeJqQ`ouFÛPł)H崦zB@Cc(5p\Z |R 8.7Lb)P] 5JJE|K^2=U TNW cQgccqb wjty QI:zˠ noEŤ|,3!Rظ*œ%UiY 2z'! AxCO+N='GH3[_5Zt%΄Q%zAZ,5p)GZ$Al4l"QᅧPW>Z`; TȲ"y7&Nٳ5~'u͚|mPS ,RL䑦rdErܗbcܲC)óW\uft^AAi-JMi6yG1N0I*_yM j q \N$U_d & ȡ%brіۓՆm<bg'Z iSVH#Tb\~L*sKtxI&%Cr#$h@$\k_<cscV?3{np׮;#8#½ƌBEbh!G'|£Ԭo?F[/$O.FmUSӽW6R\VjQIgԏd$\\i~?d$ NѮң4p5\VLYޯ^js-eܠ-,sx8VN(8?h+Ԇz8Mn o/zLOtH7+yz,RU%&H5Y_u"m}j 8JRO=M5v=2Eܮ{j" w[wh$UĻ}ԐИaKp a^ l-_Ow1C]r L/<*U#lă*`ħ!x+pIN߃.nXqv=Ya*hV0.vDGMgU> stream x]Iuɇ Î}hٗ]}[dl$2A .:\_fe-=P"LUV.oޒOlM~Ãoo姯^Xz}xAo_^c|}->)e&5K5Y/=?~q-'mA'kmz]0mo"/;~~r&ILP}? P&kY+7S~s-&c_O3{~Lƿ@ 5)xi:-=N &nk %]\<.Ni1I:rǿ,|V691?gENJIqNL('ӝ_/ivq}3V F6"΄Niz٥gdȟpR@~dN Yȍ, OI)%s+ZgyH1'T8H˦;J0j8I鼌[& 5Iˑ`M'+[;)PT4-_M@hH8)lS&|)PybD >Qg&I'DC>zRш%*PZ3!n2$1D#1ZqU–) ǿ_|#$cPgGZ"~R61GaRV^$(f S'vt_ B9WwK  ^ǟDC cC.0dzjf#8|L--l<ܳ-qD]>, ͵@F@mᥝՅzVڂ6sPf!]xe^[3ya3a#}<Kc"WG⨐~b.H)0"pUƍx|<Wp`J24NH3ܛsx96 %vɣv#G)nb.Z1΃T.;I ߹Ӄ/X X9ć޺w={}Woކᕫw>ZƊ+ 6E5egj)p v~1lLc:1ń<X8M༢JXJ|0KYp/C;b|s/$0:-O hrt6 uj^{xkɆFu"Ňl}dߢZѠԐ5Fv̴^@i%^5Xv *4 HڒBrι{juVuDQ^}vEpE kLT;a:|w7 rZ>$ÊZI`gڃŽ& Y(plY0_We!h}'j*{#.o !Jm&DG& &2pQA: f)81a+60!9SE&-lb"f iRo tPbgea/lY!@on2 :" OiGڸRo715GD9 i*c\ae?V"ĺ5_X5"̍c=ߴ[n a5]"(aMb@JCe,9h'~a2Qb5Q.-<3 POIi6rDQb/6k36,[|ZΠ<I:[ FT 8@ G7 !ZmA;ZV3PCeO6qx)M&aŊGfmXi;ktJOQ4&}bSLխB ʅ ½RRpV"KSe"کl,L))7_QC{D$R="Ne'dC5K"؇JAJ]!Y "@%{ Yb58 J^e_'=RhBxzBF"&xXx]SfEx 0n^>:|K()O_tM]Ɗ%.`(B~< Ɲ.Q升}EEmP{.0ť-gލrE|&p3؉ o˘Q}KG{Ov560f, X)y!keY2SqiD63YH:ԲL<~| X5q{H 3.M(FNv27֡ tdFIR5E6amNu `4fuHxzX7EįpϰLE:o´,-w 1NU,c">- ŧ7@fnpdo`d[,l#W3''R22WﭴËW J'  Xd+xKZ:'a{@+)w\Jt.k¸R0V`A%q[l`劸R BIp\ Mn6jr"VyBA|>ٞ/MS?y ˹3n4­e9_AoV{Wi햐әJ\@ FIby଀~uPrb^:0ߋR_ɖ̔el_h-7bkJ>y\R](-u[(u]fPT6,nO*"R1t`EYV4rBC1_g`YX6AUJUa!\ /v2C?AE0da}Xfy]?hVY*ǐB-AY KȱE. k '}cQYOepZS T\oڣU2èJ_ $eG `#~n`F 3gY;M5akøb;r#5Whit0D`r\jeD]rs$QdUV.=yлaDyeb%(d|36VdGKY6hXoyg /)D" ve.H)A_bHďtYY6Mًr\Œyi@EfpN^yJ <{W|ւO&{^jZo>3S/5W-wGd'ģ*,` oql=d]IE٠M)XPXt8EIYk57d9d5zf>cLqM!i04ZVɯ B^_SnT`6^U܋pjl:mZT{npp%yYZIs%493 &jH`qE BQ ^ -$F xaދ!Ԑc*&#|?-^)V{XAH"'AۣaGbvۿ>KVRӱ6tjY#]Q.9!TRekhzm;"{Q 9j":)vI[fnJg aB Y<eDuJ2? {}1:$!\0Òu7 b|snKAHa _.JoK"i&kH ?lw+c^]1{NB)fE 9[n!qp"s}h: X4}E,އzR'EBO돗6iH7dU(eX!Tq NŢSjWH3+냱"k(7Ph RkR./)o7{.lg|RU9 tV[-*95­Iv]VZO+NZPoS JJ.|-`4;?<V&w ׆U/8`saiQƟcein-+|/g̔ &-PYO1l<3b6H{igo z\ )evrnO}1v(I9zھaCT^kQ!yp44vi1Xp=,Ri\Vtz$<ʚĨf؟n:HѮ@? n5 e&R{ ʭܼ%ąlYu?O⌳@K6:̊  ^u8]…8Pq#^:( F k&ku 4Ev k,ΌKb^ λkF͚KaݝyJdX@~nTF140~uRg qB%$ќpu"pdzN(1E,zI}%B9` 9лo{8e=Y!.Xqn}7SUM{f1>l%19H@CyЫ"FQ?,d=m#[*uK{F \Cϻ5HQHNWNs{ODkCp3M;g1\qg0lm-t9 ~$Cc 6B ־IJզOx,;bu3߄19eWl͙ͮ8%j?;Ub0z5>>hc,۳2JMd^Pւ_W?Nmjƾ(y)Zں~8c*TuAg3@3v/JY Bd3[o;BxrlT^Vi!tt!3Vfw>p.I N*w-ej͒=M@ eȒ9Vdt,Sܥ5-DkɝȆo 6;-'Xk3!qd*V#VPLIP'?\” f>{z&NHlgMȘW%3*pQy&S DXЊcu>7r]R1 mR'mۼdʰ(hrp]A٨-%c_ C'ĵH);y˵y8]iDq3k1[Vع%,cҍs;FW&:.C;5b?|/T:][q#9#|Vtǡ=jwl3htvWX8@-]x}a)bNj{j; yQ0\<6"owl%}0nk) GWk,endstream endobj 70 0 obj 7126 endobj 74 0 obj <> stream x]KqyPAa>HfilR:H:A3gvvXr]]/3ىASw*]M=J{+r֪W`e;owtvi_cf 9 pGؿWkv~^HA 1nJhnᨼ4>ꛝ3p#.Hi {޽>z;yG>~tݧgRO*;xQ˰lj  {0:Jsy(gz`B @Eq o0cMLb̞z}0{2380Li4jwfi,/LؼD d;9 }s&əIIPpiX,^dʍwjEIENM/qg˂0:Yۥdt3XҳtTt {Yr}ѤYHLBed=w&3؀#$YηCś*/(}v\yc[,Kڦ h eR|5V*EG u&".StJcnR\qb*OS.fKePG%f9jm~w][{Ǝ:G+59sy6aӛt+fJG 8J`SmVf7܊"HzEOmP{ .4z n1EGyur3jĪŰ 䮝o,n?{ /ꯧƑGc1Y]Hy )d$I(), 9ƹSC[hiH^ጜ) Z>+DSZ<ѱ`tPjoxjI2!Nksk` @jxDB&uusa,5rJWhP\vZ=dp/`3-b K/-c&[a1$:(2 2/&?*Z\%5}[qV;2E(WzPĠ#tal ?+F.T Ȅ",Ht h{Z_MfQ\\A q g;O4Z /C$i/F?졳^&7gbVhvpjຉ56,.kh p#+agʼn_[0fMj7ynI8oHtU7*L+5^w-Ij% Z_#0!qkX6=II, nSNMe5@,aR@1RmBo6mYOAh ..ߡ>h 4[uRP 5 e鰥 @κP[B5AKRM!N+ֆ`sҢOcs**tߎۅi G7Mҍzح<‐I#WC_ެH/hE1($ )&x5`fa!ҿa6JD-ۡ@F B5KQ˶($-cnUͦipAs1EgM)jcrrjA~(EsI$4YKN-9B{GC ;/u(SOE}F;KIQvj&xЮz!_?XpÍ3O݁!8C(שtȪ4TBA\窪V~{4b #H6/"Ia~Ag `D[g!.LK漳2yOŔe sMNd@@X Ψ_ZfL\4w[Ղ*pؓYZ׼ ч¨[Pt^cn'-JcǁunBє%i5{hmYVtR /aH,!##r@mk,"]|,T,(]z97Y o0pM ŷ8փfdW$α!=. V=os]d-[٩>kR9ZE~: 6F+ї*YX!yޑS ̉ELsb2+x(S&FO{O( jI9S^6`baBt ezؿaiTI$;S*yi9ܳQ=e0AeLؼ`iL%dfa:vT26t@`A>Uk54VA Nm*T/\k"BW!0M%M! |gBM2fYEuMLbrW6gE5Ҥ ^ӌxU>->$z}„ۃbzϓ8ܾ*ZS]^E[NIyPx]jRSLWAF'V(vU|”2̨Je:;zރg' SwT6{HzQ\3jO))5F[ڃ 쌶0FY" 'tIVKٰ&ns4)A3)99RRa3̐L ;:Lia ,ޓ %›גb`EooR!` 1d)|`;h kxjUU`zU ?RAgd>7r^vNt/I+r4:톄v:ywl)n8 )2cTn]]נHznkB&  ;c> 0(Ȧ9@(c /t[, q]&d ԗ }E R2ԣAlE:L&m !}tVڥ`/K,Vg`)]}¥\`XX̆ON|IH%I %MxP쇙OOɄϦkj5Z63WH`E/j!>A"ć?K 7Vm\L7NJ.(uxEŀy?6hEsƘݒ33-+= ^Z湉48U { 9$" ^Lﳱ-κfN/DU'8zb/yn$=,y&ZA&cQS x4O8B<06coDGxqԵzߥ^PE '?0O>w*NhYj rv)!QzV^BN0Ux Rl`UaoiʈE ,,& "6iHV_k=X"N 6_v,|9WիCWҫG !dLN&Z6 a-j ۭb:3KER\ PLVԔZG U& 7\m=(u '0@.F1 F\Lyu3F/!>4sLg3'?njQsoIЩKn%9H@}pZ%#pȍ97MGe‚yMKR?rO{Ҥ@лc&'TA5LM6#<WK,Վ=b-" fkMGwy^vY G7pS'OPWܑ`ڔn猻EFBHS8NX>`L[=%+^jQq]9M}8j1UnB[I;5B!ȱ*cY눛7s'{R7;[\ù|%b}u f]ۍ'pu9@3ehwl;iX۟59ݱ!N^H"oh\&mqK߿$A4\l ߝ^wTH5aK?e9ntҡ"31@ flH!Yp '|p"$vluǺ/Z/n݃3'UDl{P~ᙹЖ> stream x]˓qי)omWI⼪9%JDRtcИo[eL;ݍ~͕}/̓땼__>G䧯>}/fƩ= &+cO ߟ6Q3 c?ͤ9}r( '~VӷB~RwOgO'gZ¯8@p>7ZmþVA[Z[eɟSy`O?¿ЧhPJN1=Qfr?;{g$']eX[ yrtu!P_`4ڴq zoOtiav`O+qn'vi/aHfQG\ō voaG[EXWBW&>Z?FGCp0G`nbfb*T_}Z,+Mh/P10ex| $i8y3(hszUfW\5xrDȠ]k֑?w,EEOA鎼&"2G9?̿"]!?ԉ I^K>S%/w uɃk/ HBP'J}(=˜t"M&GC6vΨ廖 Udo$o~e~ ~f '[Kx=#t?$j+RTa 3~_qNE)7 BSv(yb5VYBHUaut]s;e bDlx5%jY?8nӘ?A8) 9%¶P,I2I;h<Lz=w#͟_ yx8璞RnAoH88R)ͧ:]=(#ElHmM]_qׄ{2%3qG6_1l퀽psJɓed K}2G˫C5@TpȠL{䤺kxM.'Y"fu`A+ ,,-գsQH^j<S~hS6Y p,e ;d֗7& ZTQoϥIi)4*b[vLh%5<ͦr8X,m#ڕMhTcxBEJc%7AȤMV$|B^jD \VriեP]pn >%ޞt@30yvb9gX#E]E>3p~O_$H=rd9۞S(s8(tl澎v 뜆O8 ^Hϑp]cAw~˹ "蟜g;9 ݂c_7?)0/@d[jff.!kľ?"A[cP'$ rrrf^Dm!^eC <ڱ's/`P-طJH!1 rf=8SaKZG)94@?&~,$Λ;aQ\3_WMByF`PHkb˶7:G$zj礧&| yOݵN x!Cx@Ogs.ڳaW'`,ALlhf%>BvL~EV^P'5{{'QfёtyxM6h!c\9)2 [CϹ-Pt'0A(c85&a~ WhѢ1Vvb 'x2*3J=uY*,C46_w*(=r9 Ì _ шU \T]_BqA/Zk7(S"^^_> , X }dUkce1ih,4 Xu\GP cDL:_P2I@}i@`@ aS9h߇BP6q@ā (ަ6Xf{90CDN,z v:t莲RV@K9*KusUY|hw8"Qq1$e^"ۛ[Zru|aP#evn *I$=j\:v6 #xa+RSlqa‰d]Z_\sIDrieʭaL %Sc=W9ʊm2Ռ{e894$Ҋowl \O$nXpIKfZIʨ4)Au}ā+/G53IԋhsM5wj/u[ ;)ϫ,2TcGdD _ vPo jjO|Ic,BƏ*wI)(* k}&W/31TYUgU|Q;h .Yp`S¿]zg_aԷ*9Y2Ϊ:DbӔbt׏uO'63բ׿||mn(,}2d鳋[Q'|0 }z'E7KأO )lO$xBYd$/X$'f(c}g1'J|'IEjuwȃGkP?j"6MP==3y-;Mȍ}ōZ/Z *{Kj BT&Cjv9gHB>YmqR3RźxFEQUU"׀'eZxT/_AJ>>ftanH3ENZ>js~E@eJ XRLV3%f> pl_$|6ǀ9?Os5*S3Vi j.F!>nYX.F|=0ԍ?5:L"6Uc!E AI&kD)' )'iy*Uԥ`y/as,_P@Rg4= XS<6T4aaDͧhjjVR=ޭ T݃:]J"TRVj,G-*@;l/oC:[jxifS}XMq@>‰~Wi^/ٚ%*1$Ȝ͠٧Q7vN-G[mNE}yNVgOA8 ,|=#w~Y0~US[B|I sκtdBMc礋Y.aNTpt g \OjisXkEcmy E3DFL\TPx] f( J9(nS4Ka}E&8-_#Wk Y7H5&ȿ%j0 =hu>|#T5,@kL7pfHLޙ?EJ'aݻP|==ֱ98n_YtXw"،79I WlKu ZK\3&!ZRIz 0zI qlka/MBk3d 5C]}^iG 6>|)GDl+e=ckd/g5*D'mzevi76v}n /m:6o_gfYw0z;Xjr 16n`K՜NDmN<.m{FA ~0n핀 qt/aRmF;(׺ ﴓC:[,IU\a_ji U5+0Ҵ--h-:΄/^u^d&7`S2QcG%ZPeݨ}aC.k-z 4V)W[fXu928-ּE_Y q䨳V^Syb$w J.]]EIxڴ'@ƶ\!A+5W[kcȗ{85QIV!,l}eh[ _<09%Ց>|}Dv[ +_X;b[{F -k0\Sէ|nGTL GzV]("q;;q=EeWdP3'lVD4DR*6:,/:L^UX}rEg( gXo}TFnՅ)7 u)[2"K =UjMٕr֛@~fRҝ6'3äz>/ۥ_6XGegKM% PQ[ EL# /шspl\ ^:XX탶nR.&λ`+CȓqO_p6W"] Jvb?_Ñ]/z4U3h |>зHgNvPo'e= Jlr:]ВnK&srN0o~^7 ssSxZaHIo%L™t<͓zyLuY[{X|IJBNKu榱Tٹ읱TODZVj#WMF jd1 H\f 8xD#=jpI ZV_3Q }OۧLS6aۡb7,hudӓB$M_-qXdm8RJK"<;t:#i 5w#|M|pgjGz;aq 9'1qT1=0yhc3,ιY,U?/< -.P_(i9aAn@Q6M3/$hd1pw\s;=V2҃c$aa2F{9F/q*5]Z`cGЌD罋=t0f UԱbt_TJkt% q;AwۅâSwM]M2kno.%r9}J0ಜ(jO!ʪJO?P?=,\+hOF+}a򗒚Qx9Il&i5љc#kPn$^?| kj/Wgr =pLt/1L@O6`zkKrۍ^u0}BWl^.VjKca`HI3홑#v#G q/ Nkg\Scή50Q)4h,Z*q!.^ˈlt*ٞk ޗYFM$> stream x=ɲqu{r6cc/IQi:H< $HY]KVuv{-[=UV۝N?\=*֧?D{|፜jw+1Y?)*LʰpOᣞVrw3?>)z%~g޸Wp3^[O'Aq8㗇#N%&xֶ0)/ɈJ/p X*s e Ų*PxS ! ,"C=cpu2K2ۧ$< VzB8eP#YAg>R1LG{T?eI.Mܤ-;!OjhC=MTC n@u 4LSซ$*5;Ȕr; B燣dp'jtBZ;HyJ@DϏrRAȝ$?~ƒ L8R(@ApBq4@*uW@cDFOVկxdP!b}@Spͤi;<5 Q(7݀F<]>_d!YʆE_w*+N"L@:fLS@rPS9[P7T889+y)_1pJQ\ϯmN;IbjqV{[hmqƀbrPBmIξƃuJ5MӃF"a5=8y9(k,2:--NG!A$ZB#v[1b|% iMEnоϫ!9ATkFPaϑ()2.Tp!kIF͌l]~Lto.l}L'1d\[*\=h&O ʗ݀jCQ Je!OD2yh=qA 0ҝsyK8l`Etu\#8p:+-jRdd0KFL?1*ٌZ0Hkm.$!% n6Rt"+:ضRp]}|΃cg,Hp؎X@ozw/_[w]w{V` x3gaՒ:F 4swSVH D1hi|[!'U @J=%Cg YEEGKnF&1ˤx/ %;hBkͥ)ܓgMkBp 猙U"D6w.:ȷGZp_JֿFZǘ Ny|llQF|LKc}6xu z ;=Y~s!mleGQ:Q_I>u]o~ʍnnXg 24nzpy` ^M͆BM2;7Bu'Gf} xP+Po,Q9;DW Z0)c|* cpȩEcւyO)$]/;3pCрc)qxBQD|6 ̻#S` cs 3}7^,p-.cX&r[h.VJn.,+;׺57U[$i>A8X+= %3 l9qsuuJ,|MT\?e=]W^>F&2?b!4Td-oQ3/eذz95X9Mes Gr8ڴ;q4Kxmqo? q i9[d̗ġI&z˘3bv%/KFd8/%SΑL:!X05o L۴apMv&};2fRoL.cq%/KK Q.nK3u޸4c2ҋTITIKɉSܦ\Hˀ6% GQ3KJ7!`Kt ˤL)[dh+] Qj)ۺG $ބ42hNH$ .HkGcDՔ&xOXI-Ȧry#VH6@ ^(~y9rAi1_BNq|F);_KWlFp eiٜD"&+Wt1ǾO@Y(>3rW8uI؟Lj RS+ Ag&TA @hQ R4ă6EL3IFɐ 1Y_%ֶ^^΢&\X~ND;݁$J Ac$3~U;{gT+gwT!'Qa)9 #SUpZ\%-C Z$d!PY-QH$t Cʰ-"Y#)r],ߝ $-,|Z˅2de\֣Qid"%Ч"cR-@ԑlI6LkRf7չfteKj՚qH6%C>9qpx{GZ䢂Cu)Jꋹhq#bbyPOl2H!O,h!؇zⶽliD QIM]~<!&vи @GF_G^ʕLXe? |lacIqP-:i0tCK3m"l<ў^U)CՏ:`ҞkJ}MB*谰z&Wx1՜ˢ\]ThZf$GRڂiͣ\%[ZջJ(@p Z# ׄB Y2٫!֜ee]I_)T~'r>DoT^{v=,?Q)\0$w( p˿"I91"=7:5fĥb&gL _ʹz*ƖQsEjł+FEg$y穲ZI;FûM? 틥>Ky`,4-:иAv_"}äLŮM12Zؾ>B "N~t;>>9Em_υ*Z+[zCN_U-ʾ~xln߷-m$BYn+PhzA$v($C*9@`-"drx  u-͒UGvm>4\JcO6.6T 1X x"] ₑ mM dkiFe_~Ƴ[7|gb*QkZ57YѺF;{tI: ofkMyheh=hyDWX)#~4C܅FOW;()/hb$!ײCȴ"<ꋴ:10P*E1IJqs>a7hALP|͑kNH.T'_n堫Q{'`0pݿ?koqC_;ԗdYhGeX*߯ufH+sb.|0T qf]!t{u$BW\{ gh2 ; oPE`ghsg>s.><--بBiw_P}e*~L݁k]~jhz2p9LufE8]]Gz (^Sa\8RB.7 d;O̊wM؛<(ѵWvzQK;t_򒇏Wg2٭Y0-ZoڠxfhauYošjFD(*OK`>-81\Aӂ:'Q8~>+ &72xeup~%ݓxǰ)`svdWM`pUJ c∭zA7TA [ЩSħJ?hu4_5gښ!7U*r׻C.ȲIw7%_7$!QV Fυs*q )ӣ.=0Pb:kTgEFM{Q { ׬U#ҐbKoZ.Wb`Zd#U^)+6Υ"'kf='tXی#SnZ;̟(L2kse὘[.o mqIKx( ERa[V-(N9ڂF;w 홇3oj&VE v 9NA^I,TZH_=~C^M' z Leϝ\z‡:WTYӖ-S0q-M3^iOH>e×?2q!ԕ*\%MuzW3]#ʕab*+HyYJ[+"#|pzc:.EmU4)FZw6.l#o=+kSJ'QJR02c," < oX=APX,z < b+5\!7cҧKo u^1⡀1AcԶL;fƚ4 H3;OeZbigY,JP52;>]#dPyt `)At6umcrc' |[r΄w /w;|D}Mn;y,~ooo1nj߇Հ9l`?.ڨ_E+nh #P5ޔy;oH[FL‰[7sSW .rSZpsj+7U|0f vjhWFfxocan?̨9zFLwm~.t,5{vYFhC.5ϝ*Bu0$x Cl1CW.SdRgúrc3ya^)ˇ3]d+b YS+/~3*" ?V<%%\?/|^id2,֟@{+-vZTex ⥖ySvV[ V/^W) 4 ksFR56dI֘e6aM(b42.Pn0 0Lwnrv 5K~ˉN4n+.[Y20vU3[ZeJ^o;͌ꆾ0| Rrto[ hx$Ӣhh/aүz",ܹfd52͔@lZKW=g ?g@F\0X,O_'? sÿF# cW$LL|']L$ժu)ۍuTO؆#_f.$'}lʴB?7 R4)vnB㫿#endstream endobj 85 0 obj 6100 endobj 89 0 obj <> stream x][q_EyټVxF_(U2KLVULII$Eetcf13sVR|hCۃAOzU ?}u한!ևwCV?Sh7 ៑ կ|fNjҒtJ0(< 7h i c _* pLqX흚Z%e-c٧i|ZHBqKI0 < fi!3ׅ~K-Pq`$Zb+iTtͤ#m@G"7.[>]!X+7٣B7{SWT$j\&"/ȎNOJ<8q:1x㎿& )d qJAiڈ T})%6 CEX!Ϳrn_x kyVi ?K‚ܦ/s||λ4CM#P9oFTE.<@x8Mt~IyY; Bp㖦SnQ#B Kje7X':iEF:I4aSq  p@o#)A5ZC_c;DzannVzvޜvc'g(U4˚{k;mCR[l~qV0b 8OC`,_Kd+;Ψ} ‘e7HBt9ٰZ00Q;5dW\}{ ]2`C5ݫ~xًϯz|.'W=|re9K5YK"A$Rj8r$Woz~)^;U-ƴj:$̛_m 2W$<( ePޝR$4S/9-F)-ό["'}VԿ]>3٥e٧+oF7Qv{ke;OIL.VYvl*)g ї`xY9V^Jw:8H 4&ǓI_r W9YVQ̂i9LcQ{ c`>XkZq0ҵ;gCE85Ӳk#G9%cm>(`](z?}/q,o]ӺW_n߽|O!gu{lQh!,2!(4_&q 61YYӈ4Ӎ^עaZF9X[\02(ы`#yVil-X5+f+`–7)&'zd=J0W~T4H/3IQH07px%m_ H n%B"pm &ws0ٔΠjM^nveBY-IR@wg"Hhnr|m?V(6[Am,? F}I:=6 cͱ Ii0s9H4φf̂\5p?il%ύfC93& *D')aśD5l=x@5KTzfGWx}U1r6}uEF*< lb3z1ﬥ( WӪ.0hwsT]:v)EPC|БC$@_| 9)5j[E&$A X_Y|T5AϿ5)4C" 8%;لI!t"pg 4 .Ry>eyx[n[PQ) .JPo62񑙌8>k1ž\_^I#Y-C̀?,:ENXd1{ eϠ]ցq7i 'sЌUk36i% wGd<0>x.,BSCы[[ cny ,3M9 ›Ea0*JuW"&=LԠ(H˪yX/XG) OYg@tuq{? 3F!!N+Wk ЦbxKgOj3<ƾd*a:EnҒ t}^ SePl1!p<@^k }Cg={gnd_AIVg6k퇲S1"eU/2$.ڄp7<ņU}(U2Uî>v}v#E%R[WթdPj%2Hv%Te<Œ7\K[l`G[-LN_s-\2$5rAh-kF; a_VTT кN>a 2qAG^drk t43f!3LjNeCxÚȩm~j5._@ B9=r1Nti~rTUj(?iC(R C;ܩv&3oCޛ@y`,]< \ Qzsz6R 9;Lہ3 r:D~ Ioځǡret_; A`y؞)irK*(,k_YTf1 XfN%VIu: ȥ zhaPq€ 4.?-S҄NUYb+r e-p¬rR#ݨfeDSgiKۮX'9:Kt+gPIhǧԘK|WCo}q@~A MPp$Bok#i}e4nYF$'̾y9b{ loŮ1FDc Ѧ{Jkeav,n||geۋ !`+]7V ӵTz*8Z>Ѕd`Ҍtz#,ݜͬ^Ѩi!x풮HEą rNd?n1 %o;9WgmAa}޲%Ng)ߞ8o0>Ə+="p!JPG^V|A?)T &v\|~a\gR:H`ĔS%p')~GK<^% \:3ح9xfdp<1l8i~RZvN_׬8lBuf.?7N %sIB+jO!qb[ &m&]2dBYhc&k=ː:eCi"3c%h1ei,bm%8'sv:\0ۚ"^ v'oqke~InmW2L+\)rTvfy.pV^5tDf(lLBoԵC,?l'fF F \{ 45l杍DkjTzg۾)%ҽ c'<®4*eU)H0|Plۃyo!²XZ8_܉9V.VKGŠ.ENU#9W; f?>6ռ'Sa\ yOs h|p궈ZY /ZȟOw[*z8 NvOw_~%EK@tT,~)$FucL@unI5,6Um^==q6dv N1jy"D~C0LǫXơoK`R!9V˼11r#+D8ņlCx8xKiBJTL%cjf&d)ÏT.|IGZ\)Ӳ 5.VKW,_Vli*NX/O-".O[1PC/rcRIt.91i?`6\=`Ԉl0Kxt ڻY/1h(՞ >6*Y4L"ESQ[wߌ7"Ժ/<"E0KCF4_iyJV),tUsUˏ,=CuH^cOsFX|buT;̸e{ZXb<.K@o׮qsmhd. ?Zt7s'm n[8BF-$3EM8H#"Mk˷dK0n*4r{%ëHfUEF>!9!dȎ =s1>GjO}zUOm9UHrѲI7 K`5C14q>;Kx8'Rg%'W v endstream endobj 90 0 obj 6449 endobj 94 0 obj <> stream x]dqǯ_Ryq:Am +!]lX`ٵ閎Z:ΙfWy9U_ 7wo|s=->;I*#t4`GytRS#?y&x1B$^L2nO|rR8~|W:9?~ KIIxc 3?e|Exn_ݟS >~bFUL2e|bni&L ]+8L?WL8yt/y8; '7= 3fZy:xu☄@J5/xcpWIt'`J-ОR +Sn28'(_'&T7/v; x\ѽBea5401yIi9\MMa n|I*<ӉpX̧0BoӦ|8rr{y&r'8?<324(\X5$> >LNy^#ȕqNgجM+qaD_*Z3ƛ+QQfB#gdixPzQbT%T/xI4Wg|CM#kX%Yɥᣱ񻸀J51O(T<<HgO/$t2B=_\6 J|&Pb{_2I8?oNbdPT(plYk_)1_k.q.029ӅU\4u@-yx!(Y"hY9VS5.hQ]KxުO2cM`4 /I 鮍׿Έrh=G|e/X9e˅d,{0u] +0h={(åpR{So=e_Ft̔}t|2^B.сZ/aBGxoݽw4 ~X9j`{滿=xݛ87{]YN Hxhvc9͈"E1J8KۡU]@ &y@$ 3n#p7 tZѐ8䋟=*ӝgMc=䖍bHM}R0K?̒Zw`Ԯy߷D62r<>4c]g)_GI5e7n5hin_XlΣΈw8^= t0ƒ~I-WMh'X)`HDizŢ >^hOryiJݭNW/NtpGvoW8뗥X*=ڈ wW31}lP,KBDz_Ѓk5;H+XLb~Y+ c6xrgRk:"x#֮iASV3kQpn|^.؂jr0gGMV>Ӹa?ɿ@y >*E}. *y]Dܰz%\@~z؂]%樰 AbZo* .>tЭ&b5fƫOs@ڊl@aMh5iɻOZ` Q CG~l8X|eU3C%JL@VyMĀf[95%aV&*vV^zYeU\D 2p7k C/N܂EY]\Y*;~kt?i`,v qg"OuribP& $De-4 }x Z~wpH\u".1(4-wf-tIJ*hX]-h;`tm00&E׆<;F4 g`lP 04X Yv(i@/>x2aRN n͇[U ;S|0^'YzpaPgo^{\763)([um s0|;)ΏèC e_P3wkn!/Xh@Us~4_#6I_-MכP 0V6Gz@̮ޔ`/Mzf̷Ar ?}€ik'yԅ԰>LQk)^ H }ņ ab=i|6PMp%`9UoP8e׾Ǜc)μ*9o!ʙT;(X$Ͷw`][(FlQs?FEȥ+t6^P(a5rRJUTfI\ҥzxH}idPDi"Q`"MV6TIM\cv ;v:ZvB||us~ԓφ(|1,ӷ: 2{"DtOlЩCJ:BC+[hjz-4*&IUb$IH1c*+6ٝIcf!pr(Qn|H]@}WhvzW|<oNK 54;L"Ch*@F0TS$۾(L|;)L;/6$;7e;Psh2 LPQK?pTQ, fy85p frfcEtKfn]#viQ1ZfweB^jdž0-NO/`∵4KjdsPWߍda ql*YoN)(+r7 DSn{,Ky{ _h.x#Fv nQp|P.]tѽ d3N*uM)ȡ,9$lIj+n^^]D|_ ѡ`*rۙmVYPK), lw_@#$B62 /{9{;0¸0ie]7'=yMm1=Pb+5cmBnl fal4"vY,亀fI O4[`' &'{갬507<8Fr`a qP`FsyMLǜ=* $L3<]FR5BR`O J_ ]ۚ2͙:㎎*gJ+ MZ#(S*op n :`k9&b|>ƞ 'R: CIs;(:Za_6qZ9E4 쌼ci\*i&E?ac,%YzU3'j+ٚW!J#J+i-GIb"Q|I ~ՠ¤~mxMohxv?a` էĚk(R3΍sm{4?'\cII^7*m)kjr[i-!Bvb)NFEmւ8VY?v9-[리Mt@v{;ӆ5qSD#jV3KbJ5`i7=eG`jNZ[45 ~Γ 6ɈN(mfПP5zB~é!#RՉshFe!I#4'8RQ2R;eyBgk|enx8`-ޤS835hy.` x,01ǖh'>U8JqN ѼvZ'dȰ\ƒf= ?S0!o)ើmZ]}_?O%ܤdȐ*7!|UY^KNyx}@lkYAr[†3[NО7ZapWI_~D04.#ۉ -2bE*lDEܸ%X6&1;24~:n#<^d&Y<,.[oUv0)&%2/mjoK;waN:1A 5|咱EH+`\YUj@.@Hp':sSx_l; VtZGXmTdDLSϝzCS3PJ~ WL ,fQ̀Yg: PzGΈ𒏚-QOɸimCuXg]=&[C@W- 2~Bٌ {>T(;Nf uvtZulONҌ?Ѷ\1c2UUdFcrAYkL;"bMNm);ըJZYHg$Xk=)뾜k"6/<8!(jendstream endobj 95 0 obj 7881 endobj 99 0 obj <> stream x]IqB'6ci/bȴQD @B H !Q֟wf-]YͼhEXZrr/"kG+y?_z#Y(hu%UWO>{$ +c/ G~~s{蟌vB:xsͭ j\ͭXQKTZu߱(,]?.!?%xu^E+D/L)W),XxR#E\xv=nEܢăZ*z5 NBo`^oqA_)PS_oh87mf V.BB} lЋYz4H8s,G:VK3ٞ=Scvʨs{v~,Q:S8Xg Kj1AHzBYRD$}q%Dx}8oS;9EIP=N~}`d-dG֯|q" ϟo&z +J g+7jB a$2i}7cA{2ժP:hd7죏K$=EɠQ~E<+eUZ\G?°}>5+\TL"1^ |8&L"՚la,<"O>q[H,,t@X" t&Vy{Ϥ=,U~E\DZ]i^ۣS䲳ȓ+߽6yjmi6FB@N'VH+ =8=o/'FR-},~~[ g@Lǁ`n†$Rw%P&jy?*U\9{5h;do@y*)zdpv:ANHe}`DqqѕQֱ. .#C8(_Pzf@-^z_(y 4~_w|F>l^snmUM(>o@})wSغn&/.la/?Q67aIJ[ `^#m}4yUc@"Go|Pw)ʼ ٣KY!c}߾BY▎m.hbz${=.}>|T6*\cg>9HőK5G?33 ڛ돜QIJqLƟ5_ԁNܟȀ0T XF=]oTRYlRZ+I6ѽ6]ƕM@r a~n*36Ot 3C;$i^RBdдWoj8Q):7E|U:5֙f/(YtI U՞N3Y76!sLlf;x?L?#0;l&db{kQHI^ɺ`)O9y^%5Kvn=g\< 7v~cʁe'VHث [ VL v_ /o('ȬPQ3=xZP J2􊽡-LKth,̅Eb0mξ0ua+rx/q xsx#}\喒a2:ެ]elU2aW}H봤c,XZК;_zoE2Qa.1ͭ9Nb<srx)H-بBu>eИ +f0b g:Ld8HѴqq "Zl^Z# : J&ÖG[Nj;=CNNgi q=W W SK]v¤ExG3k,vN 3$?[_*nu B=h'E(Eޮw}?7x@s~\9`n%έqz-@}k$oZ!t'o,*oT\$GJ]0ܛQ5p/ ޒS#S$4Dl]7%^+ z)s"qL5;1@0QHtnBd" [8,d@ʴ 6A [OMJC?.~_Hg}jïF kbe/,~ gE^E{k]l|Du ,Zyz/\TH;a$ZxRSͥ[>M):W |f<\IePT4(֡Hajw渲+QڷY'qJI-a"Dtf̹\9}M0fi(X\D k^-apz=Y+M4h@U*Ug6s^g-bVHs ;X6PJY擙FZH?acueqT͌ӷ : 1I(M@"tfviBϳlC`;<R_|- (xs I0_7 XX)a\w*CN/Wv: 2UQk-&@[NKnb46qAw)6N?kCķT)>'Eb&-Ե<˥ݧ:*"jr()TdfȞPv#i؄##KW6M_ϞA#'2l @yeK#M,"-b.Z!y|-WWN|ה@֕ND'K?Ypj[nR"ɺђd^.'-'4;'ɝ:zA:?HRHqDAtܩ M}+ƴqn!P?Nl>;@ûRu2%Su$W:wS89i{7{58s zeBF(ErS-X1QqO8 E Nqᬻ)7`D3dWH{A,z(Ԣu!B8ua2MT@fnCVYIkD71F`{5qt%.2:fִ4R쯼tE=+X z,wFOb"Kt~++(EHHh_! 8f{42ޡr2:n*Mbz^OYb02 a"; 5%r%J@6_۩ <_m'| d_FJq@j ɖWyogYw/Xbh㘝R{fwe5t54+Nh"ˤ/Ԃؒu_͐ƚo&o 53;b@>۞Uw:Rɤk&>GNHl1+6.q"X8i!NVXJp))IO{5zxQ7`t  X (? v9z`0]^pnq, Q74% VD-Ϻ|2D QM-6SE{nn~j +_yLx5Y`p5X/c*/64Pz'$` OlU:.qp !jh=#El;Yg1ɓw)|uZr; h+ Z:Ov(;7߂xuާA/"jA7'ϵl~< ]$ ^!H+pw>T@U䴥E I rݕu dLMjìB]Ϩ& ec3@O}+RWFIW&Z$l(W_yws%_crΣ>2&d8[q["b9vN4P45 t)-F:37_HUV E'R E%HD/\bz_7 .J1~tZF^̑ [e_; K !7ʷ!/bNxVUSSAԕjR{H>1+f'ܼ֗ti@*)?bNr fhLg:n}?g @&L&;PuwԞi:lj@.%]S&s{~,ߗWo1.$yPNyllp9 7ݏe m"%T&1̉xeQqbkFvH[7ۡSCҶ;dƄ׆ M]q;iZ&m3''gH@{rj}%scBڢTF|)`Σ SsmrۅΛ6?:Hsiȭtv9fuaj`AgsV>[CA˞fQwC mH3{Q;<oUc{NS~#U#Kj~(@n8BsE<;4`P#ה`ǰvi- !,u;x˞}\XvK; e˘(X6tɑX65aΆc,G"vONBYy|brP֜A<[{RxQ;5F_p'vR߻7p6˻Lv|T0lAwkRKfMRfh>R] هsI ܒ6;w}qcn;NJ7ʼnF^D>sqG!tvTH/A .9=xyE}Ivb' )F0|paCXܡ$tT!%tobD,.T?AyCćpu2i{ZNgʩ쉝#gGuv;Cx@wO8X:KԠ츚KxACi;;[Vw j*] GT8ǚ@I}]8p(z7l J RZ4bFntxSz*XZHtkҀ؈c0kgIOa@rPVϷ&~H4v&4Nߦ\IX׿Ŀs^ MOP=7Z(yx6YzGc >ZZ0?Dv|J #ed6bٲN׮<蹏Tl\6Py96%T' _pQnmehےFۃvHx "B>Ұ)n=v7hxZ[Eϫ)C <]x^zlDoyu}ʪRSw߉;IX%^!C0Я^u -J8kz0[?`B0h߽5Y_ή4m"{5ڴ:ELv0"F=TS.3K%|/&7 54T^W[Tmk<{pQ6=LI2גvӸ6%w5XYdz!GP^O8I'W8vrsf T;Jݍ(V6Kn αskB@XlTzXoxex#6'}Z?B٨I&u!"1/d߇oeWo+v,qy=w_, 6[ K < -]>L? #MY-Qw&O>f^PmHpϮ .pTBWJ=rf.el9Â1RƂ"6We GOjNd*R3Hxiz Wfmu)g2Y,v ~{-iנ%uv\#GC_?'<qFS_t[S c39VVofQY ~G )pYlKԱkk(pyeʢL ~jK\ ]8C\ 1=ɧQkb/uT&:镋oYz->;rv;R3VƮkx8 ?ʼn N}'ޕ K776nX=J:NZo^#*:~I%J.f7K[ͺlmK Y;4ht&Us ~"ngWw7iZ>Є+ v0%U.IgcgK`]ly&jb̺@R3Tܵ7 ):ύh"錾]POJ_ulLW.).eb%)w %-&9Lx7 `G Xav#ucO f )iSew4QZnD8]+h9'k6%ldw)hcݲU'=@I0hѵk"-`+t|钂m4j*]ʱOV}3O=]jpY>1IVleJrOb;qR0{sbNONt.ERIh%IK/[KrۖE8%vڙ͕?O:^L.=ɺTtC4m"xY.-ZD\ b+*|7O0̍J;H*#=0kbڔODd) Xl4U1V܁d9@o.Nf'uiCae]M0&.LTQY AkA$;$0~9^Qz5ͥ"@KTXf^si8\J.7 9N+.F ߬*v@/Lhig|':aTprޡ?1BNZ)ikXxK~Ixh$6Vή61R?~'-9͒H07;! r[-z| *z?vx9dh^=L<;P|Mj:Fendstream endobj 100 0 obj 8054 endobj 104 0 obj <> stream x]Yq_7f}gmL뮒ME-M~@` @&!b~3ʪ9vudUnnz;{*~_>}sݕ1w<?rٕy2"nWW_AMAAO6!8=IJ)_]ϓRFrnn &?>!B#~[F[?G>&+?[ltX^ v zeV`dn9~댅Gbfi\u3]kwdI(B)2?c![}Oki6avQ<`Bz>RIx[4-0x$YV@xNΓ'| UNĿ{ټ_9\^zs |\EzdY[(ooI9ڗѯ]CԷsP!B82ˢ"g_/ y_q4vby?.$RBMz2WuOYlM9HBѼ"yWR޵bz6e9|Jq|Eyp2VqG"lVyP𔅏,v_oo@fa#Z;nl hϑaf j?s{geq}2@X68wEm 5"3A(+0h[қPvi]ߚ|= MY0qod65u|&e/P9PthyHGX yh`0R,A.H@0?yk`EwA\#Y :YQRGL2!:XI E1𜽝+%LVIRv=Uwx>9H011TwB(*ƵU_])ч[c$dEH؃e1}31* ֏_M9ބRFuE:gWWPO~@Ȕ r{/~Ғ1񤕵Ny[ ӡ…yxu+b* #*Zwhf%<Y΁S7-ȡy3k`1P̓^ KJ%75A{O6H4n`4==7 K hsxJB `a5}vmv6Wb^eB}29 $,$D=>.Ϯ;Pˣɣ>}Wk'%W\+YJ<5>yra-| <3,h@ ?I-ޑ"g^ь j`90Xdx3G!&oNS}/fB25xBok;H'Kj lբߟE-^ܪob9d1t^솲uQA#cuc>*[I⟷)g&wv6Jr4Yq$FT\WQwi!϶8J2(s@'Eak.X-:68G%p@U,m"8hXC>Kmpa dpp2ݍgVI+%[OCÀTL?Nf -;n9&L?akXģ-o9(^{|%0xŢ'u9K2vX&0ԉ1u3 +ItB2hB$`vKLjٶ~'!"#jI'-& בU&]̆M`9 5 ^in)4Zg32*ay1h*W)8ES&6Z X'qDB3= [#:Ю,YdOuYߴ5egG9- -b8A65My(bF,X:h B;Ac.u:KjtHȞ[#s)zٰw8[$)s m.gdĹ!ғg6QPQ/yV,};Hdi7x"gUtDK~<>U T\)X6%,op4[^-@ѺzU!Hnh(xCb1°@aeZh}-gX5 RXƖ$c3ɤqz6 }i㏵ܓzw\!)f! bia=j11k-X2 doE{#b`gU]XMTNɆ6* \T`@8Ֆc$XRRF!t@Zg2'buOJ[%`0zFuTO.ikkoVo{eZ,hi*E 5zONҰ Xy#]֌}r' !2k+%JM=^%4sTkRtZ'n?kRW`Eimm1IAIb,bU3V>CFWQ zC&&j)ō"bP#z}pN%6$]oM R))zng u5B=iɷnBZ /@*_2k]`lg[YDؼKAV]ON vGaVʼnUІటV%ۢ6qla!yQS Пf5r81`Duf:+ZyPheɡ2"^s$3>R^ ?R\]$S DU;Xe"J[*˙PݺfQ}5Q5Qy(Ϋ:xm~usaWg{V ΋dflVGӑ%1ߝ1{EiÊP ڪ qF=h7#9n%[T2"h]Ɉf$%0`AKɗ>_-YS ͦ( EivbiЅ!Tl^ɻP:^ נlݬMGn"M6:mvIT_W{eLNš_Dk'؋'$m!1 .|s_rŬ,1 d-xO@F[{riX'1zuz`+7PW*k.K -L6&O8(;o@rj').1"q huB4; Q†6?hñ:ӍQ_6oܲب[u|X0U~ΟÝ;Xָ#Ux˕G;],!"2SL!_- %7ȹsʬbL L&m M6Fަ7þv63-)Io% w>Ҵ~WH,(;dX.Ұv"R8Zw_z{2+Q}P;x蠰֪m]P]gKrb5Gl6'{aY]\'>x뱊eq a6^|bӳnJ=nnZݪ>^t/L[E3!*[hm=7q|hԶfr+Ou?<Dc>F1` L>94zJa܁k;^-pvqeXYE8ު%O|1uŮ eTۦӣPKgHmaxaks9Xыzcհ:\;]~mK O˳\ phS_q#8Oe˨*p^>+l`zr-^k#%x ;A){ެr>S1\x{;7ʟӃUV#zٕ2讱Jَ_^Ь Y w/3K8˰ŵHlkijj1U>(IFϋɠ9BC}n0G^,6X[wQa V. = kFmǥ!fnUx,]I Sw{Y\Yͥh F !՘DK{[Ţj·8>Ô{y˔4ע1N.@' pjN(hK!KB $َ.Kw-B+Erh\Ғ(Lћ "_o22[lʾ >vh{$^KR9oOjPl:[B-:2 RƠi^lڥSLjm$YiF){_l m]^}4\&&<&z\,hmJG6qGl IqV4>W[ABL?9|m;8.K<G! nʍc[ĔbN-{; pKؔt_j$TfHiic6??,6m]p+_>-U3b%4gORk6(%Ӕ‚-wm9錼R庑ӠǓT}ΙK)J>Cm.wgsݲb$Bו1LGb|0$gXn=0}:`a,lWؽfV u@<ƸcL.c"~N;w7n!FRֱ'nbʹ }u˭3NV$Qx͉^:W#!G0Ww[tS'?ibr rvJޅ"9ֲIqtW, ꅙK-ږ\dc?wMQ,d$ Is)/-j_or@,Y.2bL/&I]W7mvi\dVG.)M&m ȵ3.\@p}%Y>_'Otendstream endobj 105 0 obj 6248 endobj 109 0 obj <> stream x]Y$q̷f>`%QhQ %W<̽]^32+{v^ |`oMUq|ՍX?yo>{ =7~}Co~>PFEIkn~@Xysi;:|C>F Ô殤6C/XDk@]z $JX(`o>5cq#3 V`@Zһ=䮀lNHW_训k-a28E|cG)i"QbC$FZ_> 7>6'vqù,0 Gf)`.ޜbB_ 47:.*Ll<^PT@@Ty; =H J;v MYR:2O4Huٸ2ziW4MvzP]Td@kt46x2HtE6~M}! yMpSѰZN:^ZFyzy-^&qjp\^ioV+MAݠQYg+x*} Զ3\\3hW h3ߡ|kJGG@D}n-+ƒޝbY 1BE[J}SJ60Q'SifDI>돻"XxhF0hl | #*5m(|0M֓]"#]Щ9u!Xj pHI|OmSy*/@Ԇ^\ךn]qDQ$t+}4cVF[ޤd\\L+/߀S8HX@#0b! t0,#Oh%fcV(CٽPg[z˥kr2 uKPc}}v٘jK%bBaJ&YWG8vYdI8頪fXE55Uqmp~Q&)O9&Дawۡ`+Ki6،h3JG& <.Zb}VL[E; iBBHj%x{"~RǓ@ak'{"c꿚nj!=|< w^_jU!;|iF3׋YwYO5zLetB&VʮuvMq6GW{wO!Y7l+PQ:'i4v#ѭtT_f!O7lֳ{k':[I*31W10(=O-@y]7bWn*|X,s]yv_'ZƤt0tɀX2)'YSl*rO4~;qqYE}A?a&ZKFOzY>3)i{5ߴQ5jZiJzZQjI \οE6"{&"LvfF_u̴#6Ff7/~u 7[>JD K~Ά`Xg3 ggn\pi I-~fi)F^ciF]Yh@?LSidi@t p5=.M9OZV>j0H09d02ݢں\y>6;8!y7pV1U/ta` pCfo[ F\WAJd0yZ#bߑ藨K=oK Tu1՘6ԿFj=%ZH#]R&n캵)J=6'FaJEqk9Fbc+O8w߿z3pwjK?'QB">s Iq@7'mvsNs ϋ{{zDfOɿly()' ȦԥCRІJ;KUQͼH a" c?YZ= ;EZDs1f{<@§ۛO`Z2w}uK,&eG^ b `h{ZjXЋV2Kӈdr3 a% ceuB # `Au>D0!ph ; l mD>b܌L}Lݸ&ň<(HX_ $]!VQBtC ^Q40;2 짌eM"'ldta\ /ړMmBГ* - bdHN@fXX/SA&Avt(ʷ W"$OQUdeD@?3[hGjsbN]Z\r=Ixo;j-maSV 6lz9;o6B`fXge 7H)4u,q:U BX⺚=魍Z>k1@2GnYLf DiQ(ml^ދ|n l!HKSt$8]@{ 쪜sh@W-CbcEI|ZLE`=SKؑ)h<0(Cw\%@iuQGDEuybnN;IH!TNX8 xRy.Iopē*%zWt Z.j2~q"KD2iru8ǘϟ 4 av>Gih8U8'h__A *9t]-7P3dތOCc?\E 3A[}jzF^p!ڨNɈѮo6uyͮ]|*@2&>/We@ I0r1[ӻ"=n\x.}Lon4>|ƚ%f'W E>1wn.SO]b/wzS͟[_8\2 0wz#@"j8-'Rq̉.}+#gedU44ݶo9 d%6*URHzh BwixnFzep_6Iͽ&]y}:at1Q7umnř9 blKCX,vkTVY9ڠv=3VU#f&bk?:/{@nWE0z{).Ȳ!B|sCT"m(bc.%^ǝKgxGP&cf Xo]OVz0#Tuci۰fwҥ,tgd@{ cşBm_xi |n_Ƒ !gMu}x>e~]j .%'pY&Fw;b&Ҷu;['ڗ*@90Q0.Pbaۉ=q$g'H5DYp݄i<$d #cnL.=]FpKc(GXJ[ uލ[1."=?]z6BEx:2m,sjaʃzVGIp2QjM`=NHzyD|x`9k;;uS@ݪ<^9ftX&:2g uۘ s]PL.U4+|M+r6FmH[h]_`BL|J~Уל'sLڹ-;pHm o= gVHr.3v6.OAJ ^>6x5T5k"TX $Gg$49x}ӆPz-=wE֊_1NXc̣3/jcN ~(G\b^ s!CyRܨ m n`ٳ*l婖7mID92.G'c'{Y[v;4$:IRyIvx@婃npnpنVz{oHH %"'lY>~jϤ3TZԊ )K|? 7FSc䘽=mq^*/kiY<^8o[.ZH']m Ρ4v|hn)\a֭+/IVت`η}r+}U6%xUO%%nҜVN;FM ={eTt*ʹI$V@z4чĦ!uKnf'rXH> stream x]Y$qX෶z,Na0KEhn5]KY3T!$ggeRHlTP@_ yǟ_WAu՗W(wzh"h:<Õ,X(W9~s k#?3^[|onswqRHukDuO-/?Qrz ^GoE?V~ N818g_%*}ߪ lyCSWs|F >G/i/iy}k iEn0*?l'i6[F߄\]`w k2Neؙv) Z?d]E_Un:PrC $֟;2%z?UZhi)_>Or[;R JYEO+rMٳU|\e7sƱ@_BoPZrDXR/F;Q݊ǤQd[Bf0Sx'ͭt'Ȟ>b}{?eFѕ={~)=5v_&pI)ɵŰ6dс'T2מ-6D^'X{Q2{F"].Fz`jk ̪EȉY?Z/C84g`pYADqbR @5,vxŲ]ev>.5W\o6 qOpFŴ.ÌH2Zkظ߷e~Ē[[-- :Pi=R= : "h ߄P٫lfX aFSIk6ڇ)\#W)`.Yo=nAt ;JFwp5OTpSh@ꔑq #,RUsM(Kŵ_ *Wk=``&GGRBpH2*n~dJrl zСnM<ɷRrИq#'+ij]1Vcgh ^QsPxRbK t:x#M4 ="|XufXdr\h;plZY6K]~J:!)ftdmO4ZZ)ݪVSGY9-[;:i(c{e`Lv@3{dx_#^|-7I gF$~ @UC* de(\w\}pݽ;(:X~{WoW|tƯ_sxɊs$8_Woq3N"Բ⛨Ajk3Y nх"w{%a] !a}v' +$0id5*V0mDX0t9Xoܶ>9Ջ&Sj+8cbWkZ.'$TZ7.]{g~PK=kطk,u09Gڂ:#C4s9$O":F. k#QqS!JUqawL|Vn`\] 3v>F`1[Yb{[y*"qYҡ\H)tr azLLSX8qF9.\)$ ^O[dO:*)>hH#[ܶ^ 2x:-W}o])VxNX;jZ.?E%YގƈSA$!E4k}u4tSLFkcW83/5.^d |@_!boP_9ý7>j-0oAjalp-!NuހiJaQ K ?ͮ(;mH zȞa`N{D b9]%uץms&?A-ך-ґ;FLN19D-7MF0P=LW0UAZ?h^޴0F#3FM OFFvF7l/+m_rkAD:[G Uh@߳uKu4~ 5tMԦkEkM({PGBIhr%~7 "o(ā`(vN6:5p7rS%|X80g&&&`D"w~Nw-KB(uQDNc;!F&eN?qc>;&d§\K`OoIJ6@7+/YT8!quep FBGORb 3?UһiJpZ ̣d[d=r@{Z(ζ5TQDVdIU .foE=vJr`E(pjH;4^1}WLxZ6)NPf4Vz2y%'*j}7_ϪY?װ>UL)* b+̝ #UZab4.<\Dki1k7XуE@ .i*@d3"cJ1hR7Jov;; AY5mA'YK-.u _ʔQ^; 6INCETmǮj~. RV.̧RX5 4fZɽA F.d mRckXP8irvb-7Egoc[9WZa*b@-܂|f_L`97'5O CXӒLK)`v2LLz/i$&gܬGVek@Ϩ6Ys]CM:SbN.Xk1'.|:e,MNqS0[Wy6c讌j]l99fΥUS.VDLi%AfKwQ3x ےz5N|QÝ(*"ƍg|iz*^C!g3w:+$p C5? Z8M$Y5VGz'Nf]N2Zuݼy*m8g͐]Sn&^Bl>^DPk8lC57``<a0!'tG{r3 z2ԟ \Zj.#ŒL,Opgrƃ`H )޴ Y֜}]|lݦAmS1cӲ&8A766ay~3'̶ 楚׶6oښZ`1Hmr,|D&7;ZbM;J;Z O ~S9*+Tj.!#I;P0V}S zhe gZ.l:jҼ޸6GkDYU;pMk1@&$68![nr)4n - `%웶n(`/sNb6Ă;*Wڏ oQfɔW[ Iw0Čw,v]INwF,rؐi NaR\7lg ?#Nis\["K;ebt#'2>j#&CeeMsc;WmeX撬(r(-R>Ƚ(lZݯ)c%T,9kWIVp ny䧻SX$tv-=NwOv5o8gjrךR¡C*8fLʾjIl: .TW{Tny_ :5 zWtJ6wtzZept?ʑ `E?RXփ7WZd}Kص"f5T\yRV>Emv<`[fNiH}3%`kj#WNRx$މbLW_V&7q[ħ[Z o/9L ZXcLY:g5?V2S㙙rR slk>Y͗#@X/ۻꜻ I{J\=KI>fJٍ,~EȻ[x'f9Y;!qā*nmuW1{Lc"wy"@n ~f[}3T_:2T>;y7ڌ!lu`KX\e})ޚx! .i~p; lw *2KyROxak@%uQNNJRV'iv#k)έjazVl.({n*3׫sJC{5}/+j,[njeo^ |"?kJOh$$S–'4 ?P; \|ퟭ|xvWWiFx9ʧ}HN:yNpH{'o%W?T9=%?^DӶn&dJ.鏿"Vz:$1fȻHūEv6yahy௯+).9[1Qj4NE{T.XnLzXǦ:Ŷ^-خ9@U2&9D rbMFXv/%l:P:8NX: 1.1+CȮGGKW'DU9'BM:7Jףf4ߕi|2þv*󳟐|]y>^vHT j)4sۚ3y :!R1DGuTnj t[T!n[FWX ZF!VKӆfRӱ  xiNy0LrP!I9 18}P."K",,z\{Rj~k}skcs]c:2kƀ_6&eڲ-]2wvB+$K~X.ZX |*9uiRvΌ11]MPRG<ǩ׃^*[~A1)E(.I 15;*\<8#@liM"B U8g ѓ{_XH }C/vV:Ƭ,eY$[NI9'A&@5o_Ø1H 1SDMIZK<_/X~ +}i/;0` .MGnɁ5/5cm\81[NhDTN6iwp!!f}ubL\VmҐg(mm8ˠ];݂8uXLeZcu ͙ko7wIW0>ut;jkUq%#NMҝMkK"IS?=Z4m#86a#1XmJ}b|%fۡz<m{^VMb7Exay#74H'8e;jf]']sg]wh:X]uOc]FrO۰a^i74@mZR\{"d+ " hY#m3v% :3:!lrȉD[DnhQ5gOExQw33[9oߜz9b@3 ۺ!MɻERvFHS$ՕFIw׳+x0 ҩ}+_fuS3d2 #AԀ[51Z:o ~q3>cj>Ex{nsžåXϙrZj*]3򢽣.?gj/bYNzmN@ ԌkG@D?0uߙ{xk):m6YkXL/3M^Ԇb|u eAlF W97E"H0"aeڰ.$QJgV!9۫zG?q0' ZNDψq`ji_@n/rzS;m;vMexO`H6./YtLֱMliz\YG[GrAY䭵NvQq-ϊx%PR\LAQojSMiBɞWdkX6qIuU_9 Vˤe$-x&=< WK܉:y9eLTLe3=v?.y0 ٌҝ$gIdTpil9.@OLPN2og4.[p 1:Wz Y v[kF%uz[,\VI~d U3"> stream x]K%GqAᕽauësN]aq +3#4^!-άgVuV9tWWe;f]͊GOO7?_>o~^PX1{OD~ޯ!8 ѓ_~s=NwV/.(}۳\Uwj1Vyz=Eqzu_?}p.۳Z"Wy-LP;6ԋy?EڀCϪL٨ }lx) }fT/ʣIv$QVӬR'ɪۓyu}3 (oH'%= _r6[_oiɤ^_E:%v v.HL²rVҤ2LԢ-FZ (a0E}95~ 6폷JB ?߷LI)pVYߜ"QYoRiÑ.l;un]V2o;s \~~sYZh+ȣ`ۈ@C!BQR'U4Oe,ZgO_0N"Ê#RI /qt\}:B1巴NȈ/xT|UT°xQHV?_YńR f%WxT?=vf5lm  uy_ =J^y0>N*ܩJ:I ?ZGKg xB:%]8@WΏJIPn~DJxD@v֝izSu3u9n5J;.p 5jp [% wK!BV TWNڔ&{Tg**LJߨDcI.nΪVci}BӾ< O㴀V-^M}mܐ$y:š=USjY^Y͍ k} UQ&:I^s_GVRnr^+٦"Q8s΃%L- NFj6yݦr~΃f0EJv?jD*m+n߃B& #FWhT7phZ'2±],q>`Vfw-A$2k3!F_v4.4Ltnc3 ˾$ -75(G !SXgMwvy 2u#=5 bb%D,0nb20?$41o/ ɫN:dW- J!Vҁj:? he|2&/tvDlM71F]Just~:)1gW1Mc'j<9$%>Ɵve7\Cn?!㫍E*&E!NY"Ș퀲͗<9<>LS}[NwhH`ym66Bˣ駙Aԣv\M GFw1#:IpjFYGf܌QO$pRɳ$eģ! ^FzQ1gSt@MoR>!Ek4c QgY.NG ^ z>%ʟd-!/F(ps؜7V"f{!_RH9W U$q'y  |G{]|#zssa [C<0Dm]!$ hiTVWd~Tg{5UEky7$,^G<־MݥG ꣫2_/j,IDQ$Bɷq`AaږɊGiu̺MivUUi.ڼ[:Vr=Wp-C5wJ8AjAL~s]B }U+*vXbe~a(Qc*iJKZ-$%]+ !8kk/tyBCP UQe${A%4 tm,;{f Ȱvgؗiqi̓+靔hE#޲D%67@@tLD)WZPǦ0bEJ^x?JBVKA=3{6  7ٚ#K Wκg0L]s?dW9کVk4.8wV] |M x&.Q}뮤bdZ+|Va6&Ao;1Xi먓^X4~#?~}d戴̅#Ц .+G7拑*_ =ŌB"(IHO_U+eāޱPm*4 8Ud{߫1 b9&&"0R(iKUYW%D43|{4c,8t'DԸg}x"ɀ$iJhHUGKb23qjSh6ք!)fuX |H!PCBB3 .48EIHps})>)!jḴ&{kưmJJ ؖNCP5^t@9!nUQD؇`]klHݣ/P-x7]îy^#Xo֣׿)DßժFs0”6rZhlVVWye~4+P=q MQ0fR8B!4G6+<3%f><-FMgW!R($9 UWC_,QŤ5:g3a" a 8'T5SFF!i/zGKo` шsH~#@*D Y9"w :vR$3Bk̓mN8 ÖR1ДU5۹$,seAΙ|DZEgZt򎫛q¯&*j$Eva;&7BЮ`/{Z"em6hMeL_XN#֤WI[oIwٝ[3?Ϫ:S'a[tvz~65veAmzZacB!;Ank-\<ǷXn6{LEma!%Y]]~SIv6Z_$MC0#pۼJlP}0M2g*ؚ.|nV/s1A! e h}J/'" Kl)ZOu{2AlF9 [/7&x ptgpX:Η<Ώ?N{\؇m݋{ [Tv+|M׃v( O[t0ȼvRE@9'kBCR XEq ~`H4Q׀;Zחe|-OGh)KȟcbaFa!;Z’Z9[4GH: h˻Me,g1~C ,r}xe@^í畃  {Z!McKp%CWo RD9jxuXgNvU}L &tȹ>;Ov 3|',Tc.A߰d@ VUNU:Oe%K<2hn !M"&v7TuՆܩ͉#^߶&Y(}O%'GQWNEaTlꢣaaslpcic͹;USˇU1Hp8 sы0GGcY+ beI݋O( [ g .CD5Yސןڻ~ªLvEbOdЛOiބ`'%T?`:ohkʪbiu_M4? fw5?^t2>`NGK%㯚`> fTK@<ƣ2pY2p >`<+9(, 7%߸vlw`>-w8g9~tWn)|+ lLAfG@Cj^@A<ۣbvB4 |ڶOo1?`(^\j?^ ԫyf5c*˧:|řO] Fs:CKgY^/Kr2}ع^s}WVbMKeᏯGfg׶CwWX?|Կ ᴣwO!'^}Haĕҽ;jAOQ=y}9Y23$j5FJ7I6QT*&i͝r8;E ݙ;8k_@;l{Nn\@(Zrnnf]U|>}+R4a2tGڃwɈr\qgDnkrq2arZ.nJOK 6Tux;: y`3NZZ0"39_z'?UZ´z5fͅ-lA=owݞWFM^BHgW >U%^en1E]ipSs~ͻqh줣Im=}io `4ʷm!St笻{YkC}5jehNKQ̃mK}]#-bw:N}L;|,xnY]/R[7j2`1ZLl `n;oǰbQ*Be- ]xò2o׬+9Fj}> { yӸt{܇Yeڀ|z˭DY,<({$7c26y:10V?['7mqW:2r8k&P3ӇRS#o;E(6]v\܆gzsRǹ{@1ԽA tB־3_D+zG!D;j ),iV e1ރhzS.wvҎ :ע؆CEo*W=wS5}Hڣc[ !uƒAͼAQ ;Xt!"J enOX5?VGsL$e%4UXxf!ͷ*q  0a= ^zÄ$4H׺|wkQgʹK*m` TP9PJ*ބqNYU,>{| N5 aebsGJ9\='$U;}D]zJZQ3ϓ_E1_1kfd[Q}ک_?(|xɼivGP;3I1>?m;T7;<.ގd([:B oe!{/0/6%\wD*=aIo?0ߛ$Jv$"(i5H9H|GD uiԞ']{{D0hD$)6ɚ OLV3)0 x0 HU _'Xf`@֭9I%ϯF%}Uz pozvս"­'.a,萱NKrѫkM,=[}k·@7]W[_"L }ˤ^iO>o?Iendstream endobj 120 0 obj 7904 endobj 124 0 obj <> stream x]I$qGSO&}MM6G68vX"*p!"yow&(Y"4z–˗ķ6'SFvIOtfQ^zd7sN@@L%r_"uZ"!Mw0>,{0/ǯa[I/f@Bk'}^8%Zjq|~qظǑ!kOiQlȌQW F)~T9q|Ȋi?lbVOyX s4:.||̰[%螼%]Jh<Ƭ[ҁr?_7@l8X]|Z*oX{o ꡠM__Cn+jeIl<j$;qI4|6 &Aaukr/V/13 q*&P3o0 /' p)-CaN*Yy7A\L\pǗH%Β*m?C1˴LL& yAʈ[V {^ۋl;CA>ibluf؎&Rq2eϐA5PPK"i'IzZZaem2hqC0;k*ʯpʬ 3+z"/ZVCv:RYR.UG ɤ`|.g8ObDP5GFIneOV+};5PgR̈Kw˭ 7}e}uKhεGy#p^ډ׈1eD]گHP4Fx #:qgaT*|"FA9#)>dRϲl8vT inaY@ݳ2u3{G7p=ݽzz dheSoe\8B˜*vǣ̩,+j) l!]K qC]|WI">On\׽d]A;f:+Dqs:д(]H]"Sl4'BTAy9כ@֤h(]fv:@їggK`۞g]%ȍvyrR{aCflt$5.JLepAIΟs3(3W`D.5}8~" H`  }ׅ``Gb .L(#]O /_kjx8-E|>EWT\jD5Os7yt+\W~k/\|RV/Ժ%#kܰlap^3TS“GBW/x氘 Oǃײ߸UM}Sd !Q{^dx[}kq[٦5qU|l@OInj\0gxi= ZWtfH[nĀ$A(\-!ф cл,Kx!o]I9\|5 >_Egͭ{>O]qVyjvYob,F PK JI7YјW3y&l0Va'E6MKn2\s9G Wd tKpΪ3=Z2D(qETx.!C =E|FݞŷFl}ew4`n"RhD3])t\j]Cww.kҞyVҕgbo÷̋{/N$6餎(/;;q9ӝx|J|ouu :<< ߒ9v@,\Tƀ:8zwdK2eI2_S 14}i kcIMqA,ɚMܴ\ fl;TRwl;5gۉAd 3F(6X`AN] CےN5lIL]VUIѝ-d7iĥs67\D6`)w123f9Ǡ6} 7'39rX1 Ln"A-Q.?@LnDV'cqmJH/&8tU1ؽ:a,ʪ5,GE 'S7,"h`:N4debd7>uV!В/8+~\7  oO/4Q|0~l/Kbӕg4Y ڳI+vǸf)h?l 0-bE6 #fΧ6+Yp݉ %A".ŘK"%g~Ynv%\Y ̳ dE$%PCګ@\V>DYbbxJΚ;QQѳÄ+ ʹN Y$0_9E!+]lamLĵ. GhH-ϴtLW Npm* SAJ3``2%~[|zUjL`UqяqelTiUg9; ѾsotxQ<# Jk 9QT]OU\.ќ҂FfGwNWKfQȆW^[ͱѱy~W{׭=RWgq qC1 ;P=`\‹BDM?L \`zVX+NN)Φ_T>y^{vPg_mRxV_5n۾.}P:f?8/h:{A ׶ӂZcHS =L N|iaK.~p)tݥ%S 7*c.f2L%ۻzT-6E0kn LBz<ܿ"ͮUJ.s\{&U>Z %Js#$"0 O$9juMȧ%OUwV;k IV5c5 E&V䅁Ì16E޴eu2̙DA[A 6/ j&f!Xubb{y/QS:ɯL`QKNkE,DAb%Z*2Ir 4X\mhT©9]f9Ϲ44 cd#|Rވ$@ L (]E^LDIlX OM5|k(%EDcIVܲpAn*1,Xj%q:4~#f[mqB+ZlWх{AΛu=>t/7g^GЋ&m+dkԬ>Q.d-oE )OCD>-&_z;l)]vDyj5s4VhK:u|+!?mm&WYu-YyOck G)@*,xV? PW0vu%`q|kZSrrb^a&O+>Pzk o~&23f܂}0K4I$xA5lasV Xb^գK4~D($7-*U܋KeL>ܼjZ;l|ʥ%@8h> 1GX kªJLs= |,.lD']P׭2%K[„fuM e369{ .l҅BpA)#P> stream x]Y$q'6 iy(X(i2 a/"wI_Ȭr aoUVq|qWȃ[7>U Q+X>^\+>beo_]Z,xm'mgk=~qVrGԋ++8zPLJ;OOzN[EÉ<߉ś_3Od o&q TZ,.毰Dmnϕa`2oreGPfQF2ȿ!E%K&(Vx8pEm}jav[{O@Jn{XD{SKL#wT99x#>Lt.pO!9~Nk/|~Qji͆x|T~Ee@D4аw^"OP^ }0Rٽ$K<~f,mpRf1yTŗ0NXd/CWMNǸz VRI!FPr$b-oÅ@.$}~ ιGNZ/f>S"|SA[YP9Y$d槍V(CIl2a)Ka~qs(rxFuT-R)eL= !|0"@>m^fD )F9`oXUef332c 9dBGܸɔ?~rG"`z 0ץBA~1|XwIrIѭR[FWQ}{eU1}A.i`-'0חTvQ~!s""upxRXt]u`|~ a^EG };2:^8-L$Dw (Si]Qv!sksyjP7R]^Ȓ ߸꬐2BRHݙ$.a.[p(Nr.YZ?ޕ؀Rh^_]el?k1?{ }ndB17j~K'7|Xb0(DM=L{}~`89(Ǧ L=A lfѸ8M-R ?JMq,uܢF^ vdrWw/kHh?9GOfHM=6}/."1W!t8 h5;wk!MMFDo:~V}5Eu~5(&+R 1?sJ1z_cuW.%qS0Dt3XVw^v:Iy҂GCdWE &i,U9w<CW/~J11rTp 8ihVDK$_B uYLGE s}hfD"ժЅkkm4t@1 c|ФŌNj&z3ҟƼt"{:7B5}Kbs)w؄{K9B:ߠ7(:oi#Nb˷m P@BG#ãƦI]ܳh34!vQmQѥ>*-$q$G*s?-yF yNHΔ%EXlslֲQ}G76%dY X+t#]/dQBS m$t*5>oƮTި1#+};L Md$[F9 k.U:#r)oᘇ9ބ[N&SB>JŢf&_X73h8_W35P$ԷPo>ƩNf',Fv!'m\*'0 a`L ⧾lU'U6[>+W Td<' LIΚ}T{A F% P'˵ $47J7L෷wLbWΕlkd;5sSa>1V#Z߽7ʘyڸ' *F%z&3[@p9[d 4|P>IjUpʏyg:Bf"]-; P=eK xw{U&aY D_y7>,\k n,nXT%aM2#8v)Q d٦&Y6 <]qV_P< @[)FJ9]ֆl%5dXVaZ <1KDQ=Z9D#stmMU`nn%{o:c‡-mnn`htR^X~9mEz#EMt*< oI>]r ֜Yz])G Y!g= ]f@48 ,×sz8awxas ]#o>1sHZ.|6|"}1 e(?r=b_Ð D!EA|<4 >) 634ñC8bJ\JQ mM󬭐]]~R$de?1PA%> v6āmRuNϰ }ЙbÈ QLbֱ,X.|K"<~zaͦr@Drƍ $b! y@,L;&I$ ۪ l8f#RK̊gfU$94#o4P,1YKH M!*OP%¤aLxF3_7FV޺r>W`tQ3.2dabXD!p˱B.~9: >Q釃da=cim bP4.ր.ѣoӉ fyôÌ1q|ijdt\IR"ڧ'w0<و,V66'߲Xf8'n4LsDa:+·}w-i;ټ)ќ0 칻l oͯSxEXB݁:oё`;r@grܖD_9Ӄ?m8Vt])}sKPw'RG`kłUhUe[C\-c\oPʦyHz';4lƪdn܇NvfNg Cszm=薺QY2éqf̖ 7qݵJ`tȍ݆ځ⎨d fɃ˺q&QOȵ ԵՉ\,Z}ܧ\z瓒O^%]Xgļ,R r ^ڇypWSֹ@;6\:$WgWow{^;ȫ7~߾ /?z[kGc3ʗּglH%9OȤK:D&.¥qz$iyØM@Bܽ|< zz_<)aƩpt}G[@]yqϓħB60+~ŧϨ\(>y){oOG<3Ƥ.JdY~Λ[GLbFRܻ`s>|Ðw/4۪܊4ku'n ˾if|Ay mmAy)dmqm5SľSt~N|hX8z9D֩\'I Hs |Wٛlz֘O \2-9$ffB@c*_\ڻ͉ \^^>)_Y/9^ >5If?Sn+]ı?wvsJԦzz lUJFZ6|\XHa0"vQ"OiKkpwpoQFd Q} 'Qϕ@Iw._[O_K)}*-᳠ZDMi):~FTGhVwnu@I jlqZ96̔>^k6\ a\!7n4Ԓp7.E@xoZy;)R?9I+Vt"J>.zFp_w$fY_hpKhIX?ИaY`RNˍ=fnAa6%(sn'kA&-.u3muRKPI$]EQG8gSF>7FaNT\%N;4I%k| %䔦sLQ[5ܷDnأQEs1no Xfx Pρ-:8TjӼi2؟Z7}m 9#33/SC-4%b.m$R4E=8;?tҠcG8[$yGn6 f8J-mox[ &FS95 \P .*aYa\guU GLN8r=jryR:i 0ѝڨhhKXW.{EXI)yFe WṬf2RJkyv:6V{Of$.TA*ot-dӬ̳Umy=>8Եl]9,'&^ %SJ7w`"6]bT|},H칄vgMkg  -'hӝU $$T {XOaT ߒ?tt\e˧.4ع)-6*23I􅼣Bا[loRάoҷ^>jۢt߈>m>ξ 9|.GOTs5E)Kwqs(-+)ǝe S@v cN[U゛`_No>iy!6TWR{vmE'mFaz>/-w$]ϘXlknR~'sv+w/ )\kv{[$M;:2UC, w.EWN)(!_2!)H:4 _NK|g[u/2i31P "2vK/|ضrګL}|U-ˍ$= =/Ⱥ9O>y8}Zv3oL?Hg[Ee+K>ߣ&^SsAagϰ\<-6}\2={lֲru~- ?'eiq|̑\r} vgʎBXI}/R뀜 Lr%0)[Nɥ/ț2[{gl>=5vY,AT^%bI8XRj+< KO2e{StikٿZJo_pohgc*;wR>()Tx VhؕU>ébW:_pZWendstream endobj 130 0 obj 7167 endobj 134 0 obj <> stream x]ٳEꣾOˌ0/"LU$`^>_{'DdtYtowl;ytƧvw_iŷ<Kwo݄Zn~qS{ͽYe<5hyw6Ñ FYmV0t Nt.A X۪ec[7ǘb೐JԾ& w: |]` %vTh_bf~|8JS>#9 #3~8U{sAy3Aw-?MJhθDӢa.W5x|b`#|m`a uXfB @8j^ǟoŔ4ݹ3.S KJ  @@?%`p9C0.OwdDrHYG2͒pHQÁ,AE3Ռp7J'w{NZFT2Fd1,M2 +cO +QHg6N~!Q/+NtႸ堐DBgݙf0&0~Ph"W q]b&Nv7 VMKӒk"rx@q[ ɬ=.Bkdg"~GU)J9 ĥNGIEYG_34:nC#k똺h LaӮA"DZJ;X>1ynM*M9Hc\)xV[3( BD@'3| k#=*jT`NXftOYqSM [X+MoxCc|:Ek 4w*ݒAGZ3l"/ӓ Ltm;h,OL![2{&ڻƂs]暜QXAPh՝|#Dn.p HcBzJ@ѧaˬ)FJ {k%o` T?C>E3ԫDڽ>ho<`m'q'3oq oKmo[Öt;HM d2xdxy#Wztm`+DVww:=6,Ti04p|/E h: "ڲq8F8r]+0cRUr7&E%^DB7[ѬFPmn<?='@6 mBkt:^ko-!%LX F +yh칢}e~VX yY~Z:O"Qov$DN M{o7La5哻ޯɧq`|Kҟs|1(fVDb- ZIOX*=R 4hU@, W pD/l8 MD' CY(|al! A1኷F@ ҋeW% ^yg8roIJ2 8@Eڈ I h0#yw2M PT,ɢtv`] .Wt~'JJ{j`ts ٮpIn.$'zJ`2pҍyVpV7w"DIb·H1͍w+zV4(RNnf]lR-Y蠌-Je$/f;\]Fjl/*QVjFBӿ"^{ds2G-S=~D+X`|`n.“j'RDЮg0XuigנK 肚L7n^~@p ;|OI`^EߣIF-cK]4]T ޕͿo6&夃y2sRҞ/~}S}}+6F1ʑm%j# 5UXWqLLl߲)n&>JB" h^^tj=Dw̔ nMLZ csIe"7iB;Ŵ_A ^麁)p0-&LiRа@6(C1'9x? -],{-+X3 30 K.5VVɢ00gn!_U ^rsci8fұH@MiaPFd`Дoti!IY[WSoBv")Z6[KuR&τZǀ  E44^fXll6 |fbI=A9YQ5uBF-PٰVjWVsXP! ֵp%SwA u` >90ymUt+¼\RmimӲ CA{'L#&(Mn\qݳ]َ_>[ g}2&1ݺkMbxB45 ."b$*r+}^ȝ=u5BW^t%U'4@In/)feHN0XSrxL^CԀh.V"%: f+̹ @#Q5cxUE5i?BO tq&Orˊ;߰N"e%%E3QX!sNxINjճ:~`#~6וU.lA7`%,kղZXu=r<4SAy1p_WrAff&ƥZUc&8ףּ[$7puɱ '~yP \T7q*B;8fd (KXelˊ9<^o* &u6sWj NsEA[2܅D) Pp{ItmPzR5`RU +,4?C;A&" [61i zn=N*==ةJ{oUmAGre? jkVaVQWnOһr{jĠKdxyK"A_&n;Lo)G )iR6&=N'%]F}7=023ltH&:M84 6-:sq~Ad6a6zvHWD1&B e K$ BTjƒ:?t^jջEwoCiN<,XzrRXJJ>|h_A"#\frkxWe^4Ph H`X $Gg~ ,HP`q쟭#n s6)Q^3Z9%7F+_aߗ(ᵊF.X18_}KͅK;TO1_.P(NHW9")8.<=젎uɑ59T j>f3cNT]]'vRiɺ>n٥\ykڼc5fOVx\]Jje﫵ᓋ=0cendstream endobj 135 0 obj 5394 endobj 139 0 obj <> stream x][qA?okG}(Pˑm* D@VlKDV_LWst@K]NLr'糯*}?+Y"J{ )Zv?}1_t(&gೊ>k&tkhNLijv~^HMm]r `ui:H Iȸm4^sh$}PSTFQMi/ZO@kEבo^W>?\ O҄~fQH|ǡ\/Bרcܿu8Z"|Ey^ߏ(ar3>-!X/A`}! O;>7#-u UA :gM2u]IX4kr)9 d}aaQ_x:Y[^@ZYvSL[ɭJ"BS{$!UT'~G,4|Eɮ'Mi5 ɣv(&MH߸,G-4X43jYshd(Uc!3c`9)-8)Mi_O#K_&A0+{ajd5g+Z˿,H$REk z@)y&/L56NJ21^BlZjLQjPlTU-醾,e!KPʕ 쒛tTGurU`  d ITji5DK(bPBm+/O|.) Z1]8ty{(NO*Ju cMv4 =<Ӛ5j'X%` ?_W%c()K P4}k[/&aA3Z`-^4\Vf  n~'[@ÆsJw&o.Q/P @%u=',:@#9W:jiY~CgQ ;i1jޭuG!#+\=OAS8.P-*1+ w6LA8W36~IOy?Bxbl^c3OOeK)HA,#/ c-FL1hw߄XQ[s-ƠK99@`]VƟJܧQ4*W"|n2H 52>b(3p1dk\Cϫ=V^_$=ĆކL!H #`@@.P=;|#CAHmIw( =ՠ\k ߂/A|ᳳr5_ _pf(y~H8 0* hzCrzɦgIw"BIZ-B;7N,jPQA6VsiƬg񍡐7][>=+{$/"[Ph%jHA,:&@&m9,`1)!|gXa쉟yi <mzA>f@ʐ|oMӾfT_dLf40CaNux}?œox7>B9]V"PT2^)֮>K<]gN4ҡy\]aJ/ ߡ+?<.4 JV4=%u97gBG0PTYkPj݈k&\NFŹqhUEtDW ָ^\D+xZf {O-/1mٱTsv]RRHη/HlkbJ\`(%*gzέ@'ľfP /MWzЅ aKȡ FlQ-D^O(dؐW9O⥢&`QzHl/ϖ8֐7Lp^Qr^L&,EJ87D^X',UbfQ #S}`h rzFvN=I3EuoXEV FAջsAX50I7D!eRQR$APļy{GT]e"[+9H6TJYʀ S\s痣'y4]EhK+!$u|nNww6hn)bG0[bq1(|Cuex.,C8SIQɵOHH7]zm$# }1,KF68_r6`(`Q>tPC9phL1DdY?wo@p v7hA bW3WHJabTqd%Ͳ:,yXÚn-Q4Go;OTl-퀭Kn 7\8aEajrtݘ|v55HiKʴ?O t4Kq+QJE6s1G>> KF{|}d}W KZav*t6UkBxi{~W__;y}ѿ~qhΠ\sèO|.jlZ1Z(:x3 $֦pLh(7ZIH~d*M6ң>!~ "R $o]IϤ+n|6#w\r][\Z.N5;P,vEK%[)1ׂDbc'_Tͪ %c}v^׵jydO(ͺ1'ӵ7 ' LꅾhLbW,{aBeP`UYLAGV> eDV-_!yٺFdd]{C1{D~|aE}Avam|&(K5*47+,<| aӡȱԤD s_ϦתO/6Y %YURwQv%z㳩g.r`@w+ĂX݊-X:[Kqm0x HGiZH,%"{vEdu+ i"MjnED@"#ل٭=xiETkE~b_f:gZ%<–{|{ǧje"YaO09e޲E~80>d`cMH[O.ihU߷t4N|YvҸ?H`NrvM%/5jʒۅ&D5fSl+)Kgb9*0w^wy= LJǨ\i1Kc]X5e}r),) Jvjq6T!&jh9l<6ƕo c1>+j|Lir^K.*:,ȉ$ʗ|ꍗ}@,> stream x][Gu6ہ9ϸT`LLP%d IJ$[2`۳V߻glcQUem=ӽ.ߺ'?_퉟| էw R8_t Z/ܜ>\]EroT'x8w׸Gp;nI9z1r.bڦE3b?_Ejn=5Yu/˷ \wL"01\< 7"{jz=)'/ ZyI?mX\S7ѳ/ڳ8gφaM{)d y9x^.vIUO/f8 +$t ?*k Y&+ 21wn0ӏ>*^{_bvAWG25d=I^Xtܝ4\nz0YhapDHzTAXZVI좢$^ZZwk` 0! \~{x7N:R¢I-.- '{@~+I_s33\Rd˙]~ 7 l,f0'vSs;1Ae ^,̻˧us>o墸:fH^ˏ2Pi6݋4Õ p 8` Y /4VȠi'wf@`r6WA))`Nk /ju~.5iCpYG,[|<#qR"K/9Y9Ԭ@/s `fJm.Ԡ8УVT0*!p?3^+Gg@C6gif՞D'Yf2bgѷT!"u*|}`&Rft-V:5jP`E٭k6P^hEZt=1n:"b @3 a>cXf<~eJ=pI] %y/VBg8gvΖzK s#=2Gz}#'*<)^[2T4hmd{ }ROKE$"iqAiGzvèfՂٕfQ_ qB׷~)õa"{4^yk&FK4|pj\L !{ղK[>mk}$f4wNt<$c3}9`FfMS™Z]QKKwY\Y@@O? lq4Ϗ!~]fFW`;{e';_D6 ؇n-[CfgC i M{C"XMQmRW' E=(~ǂbLTtn,wJ]I%b˝CPId}&>`pҞMF!4R`RBo~msEt 06,aF~4k!TXĆBґQ`,ݲamoBK]+(R=[ocxpY)>U. 9+Et*0L'Ay ;KgWRMk\Uw}Y$kcrUTQOFm4m@jtz5|«ʠBO9@t^Wa]y{[aʖ$A4T\72dJ C<3(5xPoa3X)ZXv>(CD*)ZjM!]8?80m`&ߝPϊ"maWuc+Ϸ(Vr$ cXoE, )ۇEgXx RpHt5L1Ǯulc8a |/| Tws?TcmVɴ-U^{QvΚF&g!\)w/=dKo2_-92^0$. *MԊ佬+ʢ+^X+ 79ɵr*;Qc8z *&2Xu"2L7%A 2 P@Dia_+rzKYDٰ@l;@,Ú0۽Ji w{4GpuF򙋯y:@5te9Zcс^Mc":5,07C46ш6F;s3`?D%e,&2',e'G4d]G!nˋ$re:{oB2n|~ů/8y #/$Ѱ' {;w]uӋ/[yo鍋w~=/駞z2S'Xֳ'nf K2DVs}r7Ht)B GY0 bi3U~3^6x3J WH@zy&!<1锊k:]3Jk-۽L2D2>/D\X4XK BDa:m9˄mⷳxG%0QpH qEGz)C q,sԩHpSBi7;b3k.3ݙCV~1!Pi +!`,!F#%)Iʽfb{D2I8=c9 \=Ah3@3Rro2nF1Vicɪ|a]etN ) J ux$]"^xqC B\=3Y5f6~EvV"#Nk}w.l9W-I0 K1>MA'OImߥ[Wi ˜}z>E8Cٯ%4$Äp8\L)*=qtpIvb'V)rU48 :mZvj>&d1a_Eo~Ϝs3OLAN9Y*NY l>Q(i}+io+rNJ$J 'Ήx~5\HqW_yjP ]L ],p$c&hMѦF;+5ٔ~Gav= 1%[ʕ$FbH!ɦl\Jb?AϓD\ v&} x4zlkk'ugU>؉0bיye(hz#g:5FyF!W!B-P9XCIPQj'URxS M~bͬ``j]qEgS9T"{6m۽ *FݑE%ΆbzA3 57t#iљ^8u l\e3+ lgXn"IQj T2FH% m'(u_h-K"R뙄k fGحog-mP0WUt,0" HU]v0DipefMöLuT*ٖySP ,Lpm-Z/Fu=<;~JEjxZXq-l*BtEtjiMS:%m֕աJ}UUlhq _kĜl>{F-āHS;N")ƕg"ujS\8ӤH4»EtL҉|jPb{>Wv7]3brj!ιѐ}۾pL,TMØEn6P{L ـ vp<а AIun76|a`Ž}5!@b'e%GӍ?ౢL̝@-U8q=\8[ &$֣Q311A.b8v1Q!;Ō_ 8Q }Cn6,_VER|ԛ֠Fdmh]ũCEFFJOʷd5?lnщ: B 7~Ղ*ضFv)K!﬙/`oc/4_CA m6̞M{iW7M*j[ 3Þi:R]KEZ]rDz]֦0gY' 覻~7 &QTS?!;M%1e?+_;ݱ:pߗ[ðZƎN{MԀ`C  psj< :-EFh|_}?]M0xme0,mP,0 TiY"H1{(xD,l]a{[+a{cG'6$s a$IchvHniv4ziN(*m U=i bV&vx '.UNQ]O9Iz2 b;anڸ{:qc@_Kf~4}Y\P6qtس!im5 :}{QKwlh,`+'z5S|dz۳_L0xxB VMZY{Z%ar=0L?0:]yywؤDv;Y,=Xt=0n{ѳl C&=ɞ4ij.| "yt[Mց[+rl O1IyԜ={l.c(]zMj,|;8̓a]zdzSi=t[سcwB?w[jV7`Aq7T)l r|9@ڱBD4_'.!Jɢޮ-粺]s'j0;MrtP߉Ieɘ0:̗u8;cǥ9{Hm=gUb>JJ~&/f`E ABwia%ze9NQPFTA!t3ʇ鴼:@~MbV!ҵF}ˊճQ?5#6JԍGd%WLWc HCѮtiV,J+H!>` kW[`# =n[QԂ TВT`IwoB.I}{6AX&{d 0mcXeΘ}FWORtI}b"y:ԹG(bm}q[ ܅:06vc۸gȁ΂eLeuhVY6'ڵ ھ2}jBjoA}!HB^c ?9E -cdj$W0%Wcj-p jz3uog^SfβX|p7eN\$ueJG2Zvsbydw Qq|}K% vuxJN|pMt:(,骲}3wQM ̏ݓ֛'=wa`yFp2HhG dB hB&/? \=v\gyYM& ð5uE*GN/'ܽp֮gw%St@~` j:lj'\RdV$ teKw|V?5 ǺάPCsup7HxDW@;'!F$l4dF3l^_]dl}]*vj#As+uI6qKMߨ:ܽ?2xz-ы煜.}//endstream endobj 145 0 obj 7441 endobj 149 0 obj <> stream x]Y$qoAMYR$>, %sw_3+knOOq|qdG.>}"|ߕOwXj:v\ ;6i*]>^)Jۿ:$V3l-WVbN p\MYs8[ 6NgqߋӜc qcR'n乗b¦٬8b2Bv nfN07 AMX˗qz2Zyv _^~ ro1[yXWj Z`[CFzbTF ''u]*ykI7Lpwz ;)tMR/gS; %`N_Ԥ&v* 5eX3mp¯6E+p3[?*f i 1OXiKC|gxq>/E2h !|J;HG9eHnH} hIN`7@w%L'cܢAPY %4=O3%.@u ԉ\Yr-QKɌm쳃_ukND:ݞӸ @IpR2ƻsY+2IQ"AڠsWaRAOG`L8 H m:q+KC*7p`ڐy Zf)| uU"h,A%( jd_dT zXV|1ЕK# ^1`m(+p GʎhFL|#+V 7 GN4 dfPNK$RĜWhvx`dXV\n qļmfA4 S3xDt#|+{S* Fa.)| 6MceBx*mP8OZ++-#!d zHozX:se (ˀFb:mh Bifq (k22U#oW=:G۫klowPw'Aoo'H!DPse3RCF_oz1,͜ 4RZtIsYi Ʋ@>%cDx A)zѫ'_sb:S9,#9W  0K $ fG$?`L">JP~?Ca!iKA~Dܵ nq6+˽d$_M^sy3Ғ7qpjMvQUaà1echa[i٬(ң9G͌:\wuWs@o)ۈ"€EeAJ9Q Ŋ \4ii̸Bp E/}K?2t@2FW#FGGH^؅sW mϔ)  *JX+: tf7_ǓMcdk1m=HSEt5o 5kb{ 4:LMd]pN!!lGHYu1@'y)ꌂ_VkZ"0΁!''-LL$%2f&}W9 A!Y1Sf V@CZ\{-g1R,$Xrf&ʑKTG@ܾ( $%m38?[I,I $GpGNܼEoa;x (zkRp$nfuŠOP/Va,&kf.t>E 892"Ю4Q/eQ1tNjJ7 pP[Z?xԸJVv#Ը!T&gcM ᧃbAɣߦXSQ)trp]CՐa G)0 w0ntӪ1p*b9DJiyN86s2 `S0K[K~͎YP(K^~)oł{1;H7(7U偖> 0 ٿ[>l[E|3ixJ\Q 79%}wo R u|yshB4"=uO:,Db٘\ _hɃrmz~f݄L2&Ӧ^57Ŕ+}tpLx_v"C=O͗ۿGe۫%iL+qc `kYCWM faIcs *w.o0(T{Ŝ=f3v:\F3t}|K*|k|&,bLc{&eiHYL+;K;C*\z|MYT +}Ssy"jqW9—띵ᯫ:8 5ȜxrV2w@}QH0٩GY"9yW(-^[C>[c v;W: G]{t^EZb"/HECE,=w7b\-;1~yMaOUr<3O8wX'Ő:))kxx LYN.-Yaӆ "&M,7;6 H\с NEJxm͈޾^^;N&gVm}E^v!K| /,zKvK ?n-28Cz+\A~KaǮaO86sq~%T͓*W[le w(!Srݟ:m9WBz)0^gOV 8Ƈ.Jl\\rΪf`w^.2DC0;+l-hT#18GX6GvϬCCuS?pHzo?{8w 7} 6{7!.,b}ZˮxUh&_6?Ӛ_ mJ]Xj6L@emLx$s[E"|qQW4jeIe˥wzV#W1+_JiFCԽmy}g/v~mz:в}trΛu6:%+zC,@o1wÝ%U7YU`ը z.k՚an`+]俒P? * }.Xeթ؀M!} c5\^ayΣ9 s:GlbZ/lP%:HwKic2OmgL!լ')OM1n5<3˂Ū\k, Xs*a{&a+ٸDla;übwlɁĩ&=ms|imiʾw-r}peհJqUUR7/ ~ovߨe"鏻]$Mc6v'f(AIHUQYU-HRvn,QauWPk~.." Hzr_)\)endstream endobj 150 0 obj 5160 endobj 154 0 obj <> stream x]I%Guf>[yA% aa`Dj#}N'NսoB^UVgP_\E^ 7/?"]~=B˷Z]JDkO.d_isu\_^b:{$}^HOEQ.CxGWn 2z/1»'CV vlX#(<3qxmP:Bgˤ $'xU/FzHXgd`y">J=K4#Mp 48ܫ2A!Q ﮰ^& (\ywx"dЧ66/Ws,=E?KF~Pq;ʑ ^Ѓ#> ^ҫBCY1>4Ws5D87;Û޺L0{Ŧ nf@cCc@P9n\#haocq?X-n+.4bA#i_a#¶}5Yvzyi>O mdH.@`3_.]{b]#B֑33Ӭ&'7!ԧz6Xi/ c]E6 L uD}O;;[*|D b /rP([YM:xq%Q=C^_tb'Y!$[ƵѸϯ(wȒ3Ak0@` Dv@%I&}㋲ےn {/!S9u⎹s+ez-ʂi^'g)I'tFdI'^8.h,TC@'t=҆5)jL kQGBg"Jr#׆a< " ľ۳e3|t9fڍPK]ecfa9eoj sx @z(QA)ν.Jh5rK'A_߽x/z7R^+3׻?;^~w's]!P3~Tޫ¬36q8.\3W;#PB$82$w}=`&vwk\nG-[9 kqг_|EguDC<^Fǽ-xj摘mvA3 Z$5[O:;_?|v]..^I0~Nvԍ'7p TDRZ/{fC=oꖺXϮ`O FK4'\a1Wdr6f}l=[h6Ip $$ߔx8PM14:JDZPFޑ`voEFڪFcuB  Vnm&lW1Y|̟o V~) IIP#h*h PҐDlԿk0yCNsw8qLv` ǗQRoۓFA0^vAOD1kO eU>'>?>s]?i 07irq (iN,u <Пbrxx222p (f%kyU#+STU{^ل?=mU!DS #bfBI0@^ŏ ^u gB`C#Km"1& Ý07F6 YohV'h6 U}řA > ~0y;L:aMy^JyuuʽuĻ+9UҀKUgK'+̐넫y2X "&j8v== e"h3dïAk]i 5d+۰2,5WN,3-¯csdCCShXLl;i7o<"\))(#lRS h;4RNOx?'pKɰdTbUVɜÊ=6G.zq9j29CDFN Aؙs$P^%:N=UEz=3ObtHK C֡ts Id[41aF9uD=6 ի'}[/29hn/xecق |sMw1{5?рrC s}tC$B?Xa>u 06DA5רe޹bZ(޹NsgN!H}o嬛uPd|ڨvk-(+^I dauM #s3.Ly>"& *>ظBG_SּӰ~sV\[vGmBNUC!Pb=1T 3`aP]DV.[uS"x#7v1|SXstH6H T) H4`ʊE^Sjb؜cVW$۴ Ho'v@٩rsRdC(l6٠ =^V|{7@䱋5^~ԌB rFqVe5F%iY߷kkR B{6 ;> G0wl>-8Ijw7$9K5)}Aa4lT7HHh\7Ri=d7\7sf3ubn[fmbmQEu[@E\En0zD3]lVN4Aa?|dܒS׊u.OOAfK9Zb񩣁S]ƞ%OIdR*U$ ٿmffWVdM XX{*{ORy|LpWtA5v1!87rj35dh`W[uKK9U֡Pw dRܑɷr%'fPyլЍn{6x ,> rÕwNrSXd>rFx.$<Ӊ Xq9#bVwT8ߜNC l8nY{Qt)|1lhoY[9P65( 5Oq qd U>a<lUܬoR6xzZVim-O+<2j>K,3|&#H&U`bڒ?kq$KR~ymZT_^_>e9%;UyZʔF!#.O=[jZg:b8e>y-U t)v^kvi*4+rR(B='v,|EC9J `PR_7G= ; Mo'ɀY*;U$FHZن䊭b:rWƕi/\ 6n`q,Oy`:t`+4<ܦm2%/P$ Zij)>Ȱ `KF&8Vl#Poo0WN [ZMM}rXj1};37vdLpy&*z\O0[OVG} dIr/Iެu(%N"lضoZ5Jco; Fߎ5=#Fa5ΰV(~YMF(I`K7F^+jkC}k C$>}B8I2 9Wت\Y[fHL5fZRArȉm*:fh &L5'1r~^dQu|s.6DpG6pWSIzk{[$l4ѻ's|K~R jr7_ #.sP-6I.pehfY(2ydA_VuWWNVk *d%\[FZIzmL1%[iDIJ&a` i킆FL2P5.`cy"d&qp,=OocJVN䯺=SQF/D \ۼ֛*\{znTy`s|%VJ+̊ _]Nezjp1n$ )N)x? څ鰯rʳg1HSޱWK-_U䫐\?Whendstream endobj 155 0 obj 7233 endobj 159 0 obj <> stream x=ɶ$uXZֶU=C%1s 6&Bb!$AOtc2^UttqS޸Gc ܻ{Vsv8ǷLÉ> ۟tS{v:CÖ=|e!}[yŦ%-M8UOB† rD,o@?81i"EDf) 4ЕbBY/ ok`. , Pr`[<9;դ7_[id,<"X\5LcDU/ʟ8g怳H5#!l6aH̳~3F W%]Ip_TH\KMis11_݊ %UW`uxsIieәy?%ʡo>G27;E}xGPuth}аb_nOfT"|v<:R7WޞZqX;=) =SwOcôZ6gǾ 2Sc R70ꩨv-(Я"3O*O xNc{2?@Z6+yϩ$`L꛰U Chc301ŁY +$yp!Vɣ-yD9Kbq>jZnir59&s;7A C'd0pRě'A0*v$u-Ud@ֈNn.mM` Y~ BOWrazxJDӱ!un.1XpL9.N0lA[/M@OՖ:qF;(@,˟ϵA^ἀLE fSrQ =?m< )4또zL=Z,ofo=0;k'a (@KA%i3q͕p( _!qҺYZF4'K/O!"=5aX `@EhrxUrHH5@*Z&vU(OI&KcC`rBzy+<`9DMUtY<˛t$LoE,}EiU7`'@іSpwg Z>Ln?r-xf#(V Q$CIzВL8WPB Bҳ^7a $hd+xV2hKB-o,O"9O6b Hӳ51fiY FK Uvsua!iU41%Jhr@,,p6B"銹Ѷ Q VH;!'pEnqK><|}̧4P(kЛVHHҼƙ/iO(E 9Bl>nR(.P1נw$SaZH [V=~D$e#iB|1Z\N,Dpq7XUn 2Xª Y IabnhVٴ&L`C щQcq[Y_'~j[iD, ?hf=eKNScԗ2qUA* b1f#YdHbd7oh5A_vS&z4z,LN!z'jwCfӭ p9f`DtMyѰ" iAϊzBOv#bծ!'U6T;L>5 &0>x=g1b.{N 9vbx/`RB뢚oޕ jS\ZV*TPb#*48a9O[+tn bMpkI;ʶtQ8Y($B1ݢt}}'CjPUN~V̶~%:y]np`3%6/;!uJm`>LBg\Ê mEr`  4`],D~fGBL D9D校iIʔ^l-8q{l-7lu */~%y= j";2M8⢌-mn#d;\taɰNwQA Q5u)8L"]&i|~YD^ԒxcTZBCKE0:.mT&م ]8/l+*|U 9K2sZdB6B> Tخ/2K2 hcdl I7,z?-2CZ] >//[vZjQ13m r$o"NGǭV 6y_I +UэͿlU`XB:\5Ec}LxG^&Bm?][A+da򇒕y2V"?wq@ƂxoXRX3Xxg/ 77"66ɬ;m DNRD Y1*0޶[D[Y#wdlTY'T@*PwIl?1EbKѥZYEa.R oaS/V-bE*ۥJ-6@P[U4?4eϢ&84[ÏDSOT$~Z摛9y@" iW~8{Zc`* e.c?*Q2ha "dneG5,fn[L@/[UFPQXVVinh@¯ԡMb;y/c]jT$T[{פ'S])JzOyJb݋@gр+/eNJ`40WAڀ)9ɬF !.QDʔ E* L*JNaqz]>Axu#&T-` \sgK0县+m3!.#2֦% ]DClJ+Xa26'76T[y>.ۓsDlJ5쳢MQ.wHn-d@e>oUJt O`.\wJ P@L@&>wj,a0ts͓VmCȚ4oiT:)8C@k|Rmvy]&ϠVݲ2nER@A z&d9g h":嵢'|% [,v-bi+i&fgC·+FV@DjwB7ƫsSs@5]uktΥy,[ DJ;|2q8MeϢ٫l o9)Tך%nR>6{zU`Y7K#|V[O1XesT QUs2 |0rgWVy>/#{U֖qKޘwv\p'ܖF ~|%/xxy[JR+xNAL%۳ 6Q z6'W1mT 0sW^TZ xgUyU*BNjM5<ҩ'CEٞ8/;,H w1k2dlGU ;۪lx'=Hn.̃Oݤ蹍'4Z/Z+뭹k=DNhŷ>аX h+=tңs-&5Wu '_F;`vzM@}g֚Sܗo:넶x}zv舗^Wa-L*dG fvteevtжXEҌK.{_77"ql-z߰A1 0=L2УK.f)VRh"Ю܂>Xg8 Ntc3nK=b\3~:$Ds)QDXX: f@vyCXH@m9 C ~]tzxKwX)ء;\Ԭ6uQk p_#7) 56?Ƶx{ۊl;S`C&ݜ:غӪkE/QNhЌ{9 m3х3PFڬ4hmgјyjĚ앍=vuy_q¢貋ګNl6q~o\ x`Vj_/k>#l[ҀeF&pJ| tFK5m۔;MvsBQ.BHmkz!tmЄ'P+FÒj*շ;M**go3~/Vy};>]*ՌXdnD7_eدT }?JR%M& 59)@DdrC}k[ -wHT>t4!.h>_^aK͋7(7Ls}X]jk.+tS'Wvn爺{ (邺|u Cx/ˠw8 ǥmK[sWE\]U?L:4MBxe`€ 0&GowfT U`(ŢY!-[·ebG >#yX})Дj] Eڕi@Wر,Ww.-Hˀ q)ATD0vqcVfbT'{\TDjdNJ6Q[[/K m¿uۆ|h=&WЇ3ncJa{߯KP1sQMwIͻtcW)9E2ᮍG-7n?vM\{=8ܲ+z01Y˸fӇ/!\wL]lR>ř,vi'k*}(TP'z$YBqn%a=9i>R^צz;[IC&Y1cXKqy"bgR 8;ޥ)BwYܡ!n>hDG0Tp88R\x[`~7:5 06asLTрٯ9'bȼ!Ժշ=W7/K];՟M D&Ҥ$E:G7Mfendstream endobj 160 0 obj 7885 endobj 166 0 obj <> stream x]Ky6'>%aekw֊dH'Iʿ~3Qx$PY=33Z (ǗDNLr'g\?~W۝wի+!r46N~%s &+cy'|s>\z?]$~/ћIIt}Rb2{V>O[K;Y<7|&D){]8%}5~ 2*w&PA+C0 r3;g*O.O$`@3oRK3jH sU<~ǿRk =~7is3A̰I9՚D9l@11Eu0Ć+,aR '\CNO Uz"CSM"(X4%X0EhoQ)KN? 8*υ4l}{$D:NL5y)+JèlG[5(.^!>kT4LAgeXguл2rpGIP> rDY{ L&T:::_)eRLu;?o_RX$5ttEN)|8݃&<9veyYZɁ=h';3燵VnIڀ\">F8dOܑǮ$o*=ShbVwKH34 67<=T`t^ӑ?iB,K 2:)K-yr|9+bK俓"|h<|uP`D"km&Oa.T)ĥ4\LVSSQ&4;[ɃE;hsVjNhUNsj2DNq{U>okun%xM6F'OdImk8ʀ9;%ҖUT@KjLmG)E2TPŗPȊ$ҳVMmX&UfaPyDnvi@ĹAUu<јܜ)|T$BYA"k: Zj&znz}_ ?FS(5CiZi>.əO%T0]К}]7>z;y7ף~vǫ~@7ieaݦ2X7q.¿UY9۰[P1P8VB^MٰNF\Q>[P-ﯱ(GC kbѠRW8Iͥ@ Tv*DldYX@e|ati܀KT LY'_@H Qf7!oK_еNAĻV-6VqׅMo*31 M Ɓ 3xf8P!X䣜o^q)+cR7gJuźQsp:p8?}*E<@i0% :16h\1BS `d:’pƷ=F8Ida_[FSZ~ǨSdK$;35ʫ5CpFw[q4^F2nL~XIBvV2c*#(`;z3u3c K6XylPz'Ҫc >Xu0&u䒈W2w ]I#*g3H9(MsSOt}}Ku|cgo@q[Eo ,OX 6p7䃪;_A^G%LEUVSh@(ą]}OSC:w40&ά9J?joJg*-S _Q@[ I,ssDN#W[!2y])mZkTUyDkGPPvGyDqr]ПfY*A*KMyD=y0nnӌ =^l HO<%tʫy91H N :g?Kbt2ȌfԗLNKwFY$6Xޜrcrb("LԪKI>aQ1k4V'vɯ[57HuXcĤ$)Mnw<`ih6ev=ql(|-G@Vㄸ=Bdw$4 ]H9occWLRŤ=Uvm#OX UAi67 !):([*zςhW#H>) jӲsQwԜ/Yn +CJsu-h{sKͼ.YwhFsQq68Öͅ#!Pjyfr` 3L9@qƅdiV6"t"Z\DcdD\90k: 9c?f0ӹ<Ե X SIՕaOB@] sC"F1sZVm% v][&ޚ亶7̵e6% đ@5Y$ƜOcO 7u$dӘMs\FxoBUzЭi{1?ˊ;;?&!h Qa,*4XK ކk?#\s^P'jVf$N#El.O>s+2%YZ:g.pa D:^SԪN3ˎ3p]-n^S-.ǵgxv)]=ipN5cdY{o V,)S/C(lTz|m>@Ν!z8ZL. >) 5To%F˲N3'漠`#2*)wp"b2jLo[  Hk]?oHCln[" , MtmAvд .W/a-KTs*ácށ$y[MJcQ Yrʳг' L }>`T*l$׏ '#V9T8eKn5R t#DLl̂q|&dqaQb{HYLi+@+sUbŰې$PO0DFJT1V0j^%-P"֏9"?" 1伸EdG~t&1Pn;y?tOvس&wY6u r3 P O]$.8fRkU)e?sR4$?U~٣Wѵkgiw&%YbstqSy5?d~ eB"RTJ$$mdT #c\c2BP@^6Lgrg%9Fxݓ/X:Prij#LF+#>J;83C19X'xA\hѕ!bIQre=TAɹ\ZYy߁Qn sv i%=0%~VMcuLtϝyn 'cp .V8,T)-NgV]7Hդ)wbjSOS j8znx,nA$ ѯ[EC6+B"1 w%9xfZdM3$ iﻕλOQ5d£xѽݠ\F|߫2SX'M; @8YIuL!<,TD-=iϿE[A>7gQl#&U4T\"קԴ5dSP:ixg\.vR뎚f#]$>s\nrq$sÎ:;-{Pl F7;9Wѧ@*\> ,N丆hYlTIy7ݐAJAxgMUnSݜwJ:JE=g4_teEϐl g6o1@K= =׃3473G6#ÃFR#,q9]3PxciuƲsft[qXguP.^ 'aR$d#4P{1.#ȘD&_R K>N',13IV9m˛Q!.{U#r1j f`+܊у*Zpa<^ca`}ahX:+qၲ˨a+epp4hKO ߎ٤Tۨ96A~ˤ%%4 &xhK*9sIv}[5E s]:+|GI042z2g όemK]ۛ^9WwOggs ~(䷼F9֧s"(߮e@[& + +u{[P[O"yڀ^+m;fw%b1_ G!W3i]!<s*GQ {_).ʕ$ B::T$7}@MHhȫ\4מ*r-/:7AU/{v; 9&ٓ-r~` +dھ[QeTr> stream x]Kq`ou`~x ARK2A@ђ#۝YUU3X=חޗ_ngz㍟o1}@3'%9b23o:׻xOݭs9i o잞I:v?佒AzpN.3|MF)'b0|pOIj[~7=ػ]G:7^q=B^Nz9y,ٓ@^ei ..[eңv]-ˣ%l4F;ઋK`"2<==TTm;۔1=)ذ N^|z-p]w>1A陵Lx#fF AU|u@M!tE$UB .;P >X!l\4IV[fmm=NHEn =k%IGL2L^}o'W6-Q\5&I!4]MF[e2ҨVp%4l Ҧ(j++vL44Sˊ06jYqHWUWvVy!6^(~מԔ{NLbCTfG6("ۜiRxId Z7Y*!dVxܞS!T~ F`F5-JRqn8 S/X?8sK7XF#ں?ޮ.^nth+e WerC6jBu0oC6hXqe^󎔼.[z0}PĈ_ݑEvrōnosf0 'ji\y] qЗnҒ]qQ#͟+yL (0LKB%6S}j\ȼџ,Pd(%KPK܆CA0=uW霮5plٱ]STU#? P nؙQW58Sh.sϖ΋⟉ bGև?ݵ"?ɬhsW:Y_=ڿ(@d67aуDF^^hyܓ<YtdݲfzwOǫO投nȞ(n .?zuO+ֽӃ2ʷynZ4/VK$xZTO{^CUI^XVD[{%ufg;Bhwa#8쨷Zx&Q]j~_}S(&6ʔK'$BO>0u2ZڲjhqR ?8OpGmS678Sq/ WIDmc;.Β B9Pzql?vE \=`2(o1:) 6x (6u<)[qLP2" nba=s'NmIrDOf#ClpD=54Q+Ql3Y~,t^vd+wDvFgQ;B [l? ad6AMMM_oީ:b3޻RB(V'-kDl]gbzOs6ŽQ X.&;eXui1@d_y<;g}#Y3A|KWaN 8S;9Nj6ti3qt@ TW}[ FkMLG*+Zi0Ԯ&f:v!@F˕ r+*pʛ`yҌNA["7[Y]6ԋ,w"\3r4 P5*z $w*NJz8,)^q 3ipSAN{„$SJ T+7n:Y8ϩr$P.fב{quE Gi!i-Wf8%q|~HYGX6hjrT+7|[U>݄Y gw ֵW2nQӕ#6:&"]4i5`^]WNfacpr҄VmdaL#9WKaK:ONF h><@>¼rgۧj '^̷q"&",yruht8XhJB+@I۶om%7.`% .?Zے,sP0ĜWm摒mbv[9w%ADѮ,}К*:&a"˔L3-^>^ܻW[K|իMٳ|~|KH'-jk>^Ur9; 1# 4R9Q'w>-Ktzī9(ה[Q o ;?l\'oΛܐDQ_]]4K~Z FsQԿg ZF /(+>tW$xR!;TUDݬ\iM[EO>nrAi^&kO*^ iM\n,Ӻ.aHWǓ9\n#D^a6\s4OlE=?Za;ԥI/ #.ŁВnDCVV\ˬJD=1L%߯d'T[`SHm Sm0XLC6ϕ`j,3}9>3Ҕ#_Q0|56Y5X29:W|xx],~->= oTۜ]?AN@JX</dfL%Hb[dO@Inf8*{?c:#;Yմi!9&{](rvue&5FBQ['NI$WqJR^ l=Et% J)v&3Cf"jCB%t49Ss΄,LKYU ~)+\:=xuqzGa5-GSeÑ8 nL "E *R#ݽ^cfSURtu_{vd=}>ٷ7l tfP`p,({uU`&>֟zXzնp&!s.,u4Ple#uU㪿^H.bFK|ŝ?,b8)v:S)d-ٳ5#Sr췌dըf J*^@ )že~D 1͊^ 梅JJy.׍; (=0_Ɣ%{S=4*#)_+fL'3݆y ^X(]"ơBoDZ7,NOYQsƭq p%a#_%mP`!qZf3d]uĻ T0h&X+r̽BMlb^Fy0-z,D]SKgIW.k GuVȿ3cJʴg2~MʿQ|`J+(ׄi8 J;vHs:k@\~oOi``b3z0ﮊ pJTLgCŌB8ej 8{Zud/.I<KX$ XnՆLmqof o/[#:_o`2bi[kcq8HzeǭMKy{q7vY6qQ|RFj +{r`t 9e "q4ֈ|\dՕ\HUrgF~dhvBV]@DNՈ/L cf ]: B1Kܐm"I4GqLZM)֫^h8EWj=ӽR~+g\;S5Ց JĠW\ピ_E !m_ʶsjtQRCYokUԤ-Y1%k&[UHZH'%X|9i?t"9]5ч!}!F`'t \U H48LMgP&/k*Y=dҒW{/̃Dл.9ō/`endstream endobj 172 0 obj 5981 endobj 176 0 obj <> stream x]K6Ίgynף#U,0  d&X#ٖzؖϜ8cdkݟZ72 >՗}0^\!r`c̅RMb.ZR=(ó./B?p彇//Ŀۇo7T_`S:קL R]w/~#^||rLuB(MwD\ܟ4]~o>qyF(P%GeLK$FY&қGVQ{}J?˲0-!pj>YQr9\Y3||4B뇩T%ˢqmAEfzlaB>>0Bh׿D#`A'{kv* 3~?hkƙ!b\a,C *|MvT'z5ޕɽ$(cUKBnj`-sMcv90܌vN 'i7d\ҋV+Mlz4ӣ*x^e,, _y95EF=CB$XX$ vzOM@"­LB\3mj;[l|dӣ"9$u(OEF[/\غ_1Xsݷ3U^dF OKGAyuCy>C8!.tlN._7KTu%vAMer.]B[ K梌 5ჵI2\䢛pc3Y<'7˨0X|I~R=J K3Ub(IIdhB6ڑǕփbe6[zLW>"ǖx6ZlˮG8:5[K[sGtJnTh;BJmp}D*qrpZ=&ӂ&!M(?#DPbꪎy3/J ~0*hkRCulyF2, 4Snt/dnq] ܦ*H{Ss>L4#抌<x4Cd!M=|^R>H<>ʅt*ii!u{ǕR0d6i.tn2XYM'Stz/20zidc0֩CeKߠNRrPq̝ >V/|]Z5K5{{d@MD4ITK4Xz$Nm%fB$GOAI;D";UhXX{R^@dG2i=x]h+N@wZ Tl ,M?׭bVQWL#%4܇WMA+Zu[qa2aZƲ. 0m@#Aú4vA ZXq9* [A;빌jZlkv6 j@0Y3ŀfON7#YzЬFlTAmYAo0ӢÚ87⛹ HzÚ<0d<@hCo)ڑb=v^cbŎ,.c&XnW5}o02^%ދ9ޥn Hp[E k2̷͚#ۊF֨, !>nă3~D'+DϖͲ5C<)&=z~$ؐ1JaYkbzo/+GuH@l׏쀌Q #3%-NrybG!go8uǿeZ=CPI1u`@$ "nUpJc8$A4)TʧȡHo)Tձgc#<dpenVC"$yP5~QO1qKF1ny^R+ŗJ¨~ ?+@݄90Gu9 {zmxh2qM H5 <@&FA30Jg9VH,+1=Oxff# H <`9A:fJ HAvSdA:%}䀡Տ*9vRh9̠ϴFt'h֐1mqcJ'5duZQҚ:F 0Qg &YUbLc7d8gF\XLN=vC30J't#nZ݀"-md1ٵ._4'o@fW"DWoCsyj0۩٧^-s`pRYh"3`6bJpCe30(WUS:q 05K[Zb‰l8TxBZY`D3Q'I>[$;h}'cd2<6¿bqM=aI$GbBl#̸9@d@CR!Zlzo&>ҿI~=ᯯϏhNB 7&As| ԡ2*hf),Mx)KߚXo $C6/'DE= 4D-[ձ&j-Zݔ=:! 3&nkOnbO [okmFǖcU԰#U󛘵MĬ#"knfZsۂO:3+֊5=p2BڿjB2O V;^qԚ[pN!(Žg> 9}W# O9Y=+']ﲲ@ K؈KΫSV#@a>w{YlF~Ϫٶ?s!,ظ~גDGXq~dmpEf_l[sD+ԋbZ.6?^l8FsP%B1Pw"ps ѓ/5~\$?FsO9{Çwtbq/e x~u^`%F}~2cRtN3 Ԛ"~gH$9jh_"4ֵ#rk6n@Ǜ5,pgo Vx5qS(] -7C[Hl؀ :k *T{ cv_4],eCYMOϛON; !M1'waendstream endobj 177 0 obj 4798 endobj 185 0 obj <> stream x\Kܶ)s9 hUMIITk$(dAl]hJYP _h^tr/_޺_{=~eg(KTg}ˇë6Wv7M{?G|t Vž'V|Qv'-ǣ괶N_ko>xp65wݛ~vqZR`?9H]7LnyJiN. F^҉Pvr\6vdx56>dYg:um6?B|qfuu{hIBf{ZE7_CB3he'L [օRw 傌JTNZFUSwOAWAJsS#~-=M٘zSL*7:QЦ}7i|AsI %Nh\oqJ_Iؗe(OyI ~D(NXUxJmpV642SR6P`32.-@-:@:It!\9EJJiu!j&$`d ƟrPQr^QO 2BZTfN{OՂ I? ^>RM*sQ? /#EHMDJjr9Hi-Zq@ SfWq[jM%pT4:V !p1TzʇB\3p|mЖ/`E{$~ADp]Ў-]'h*ehm#vnT, "*11CM#4 9@MY3v&,Lr&ߡp|tp j0 0jg=*ÔPh0lD2P.:dMfdi1\K24˜tpKCi.*jc#y8 +:XNjx6q\F<ǾmحؘV<籆)>yMƆ LTDZp~-Cut;:tn"B hgLuthPqEBZzUY#Sm?WblN$k$g 7't>sA%UZNOBtp[pk@z֘dLiSm܌+EvԛA=Ruym qcSyOTmɡ Ճml& 4`Bi[f %E!g Q͚3 /!Ay:A>y9j!ƆB^cfQp DSB09/u_/l?hgۏ"m?4l<'K1f"d)JP zyQB5R H1$K)2E`.i4CȺ MIeꎦ `=L6l܉`۶nW4hp4S%cXjYhoϕf$b02 H#SDz4KHXkҊ6h\p3V(>OЀjDc1)V)]b/0ɬ\KP?MoĮꐳN3 e3V0pm@]SK4:3JV4ծP@E:ދ̂Rzy U7-΢ra+*F 7R̰^QFE\ܘQc9 Eϱy2g.M%QIkT ׾֟dY0A|y}Mgmc~NMsjѢc`gU,})?d sbV6~ZMQz~(-g"&7?cEq fPׅi)Z iflAfd[z1y`3Ƀ-ɾy/$4]dUƾv-j0mJvyr+,|tX#$ 8;nh Yskвn1#RL/XCB/R/t+BE&l*ďLK:q̆؊$ClW p-TYl#[2K.sܧ92bGLxlqĤF zǓ@zK6ȟ19˼bϝISOw4TQ0=DU>7Z OK"-6H}@9jG)qUNΨJ0(A0& lٰF{>_@V#rI@AAV}t@TX I^ / .zmA`≏U؂M] DwrAM*/|> /[i V̻??9 xr+.2]v,$M9q0`hnHܘ^Mcz:)%7S%_]vH$Lc$ov9ICendstream endobj 186 0 obj 3007 endobj 190 0 obj <> stream x]K6Ίgynף#U,! 0T&L‚bHȃdѲd[>sc }}݅ B¿g R b,xPnEKe_}٫ח~w~?^\>xx&{o˩*74}|R`!ƻ4 Z0ɠ}ܕ=5ߧ;kL5B5l*jݱ ( |w夯Gt̊;Eڌ;(n ^x]˸9k(䄙&'=ZLYq$Pe QRNF_cjGT8=i)]O50d(pLdFR v k>d~ROXzr|p35<"$i\x*KEFO6Df|UXhFײܩZv0M|0LX?.N΁ 5Zc쾗uWo_Ǜ/w}V3ix@<ɏLwr&/좜JVr,ys}NibGtY&p8 OXl<:pDlF6R2F!F>p泥؀6ɖږ~Ete]M4ߨq|5XVOvi);;j֪5ia@=YgZa#V ą90g}o p0l9 TUd.KKVj˼8ļLAH5'! +&1]4odѼk&?uӼx54$ŲovK[N '>1D;mqRy hNG:mkyY5y$ `]8i MLn:uдF5JF#G4uE#4 7ģ2l@pGӤ6&^Q61UUF^/ዓ! N9YifznK]9~btE9Ij>ȡ4]e._ 5ƓO2.'dcR ${BEff+b Q(Q=G[{sxAf8- NyIJ?s5)[3;LO0Ml<4pVVV` myLr&'7M((:dȀ<\qīS=#]r|9~sNI/[9mUvlFn k` cDLrOYi-I> *ZV"|mФu")Mm6U̵єO|JXq:q}b3ӖS&(($JH'@Eab &F Be隀$ N-֭nI+耂uJ։ (X'ӌ .iv4`J82QMPWBG)*6!D/M f @ XEdRFc 1Mĭ`HܱX,]ʯ\"ID+ >IxIX /+UVOk`\SbM06%Ӛ#JRxhEUj&dMB"CFT:-T.o ןYYl!w~"鷌i奙JI^kbzeW*[p1xKFR( }Ť{Qrjl,a˜̱R/ fXg΢ 'haMsB7'!;wNcGRI&(j.˝UvY.}cC\ u7BnԎb#;E n~K?g qVЍ,VݱNp"nZ~` py[Sb_3'w9dAl z܈:N=%^E[afҚ{/*6qk}>(X_k#C&yQ^zW}D®-!^?5]Uԩr0ݮ:~i'Ef>pϮDQ4kD*COݿzX&IN HMx HUp"X8OX5's|ߝOܞ􋂂gLl HUL+"ݐܖZdď)ruYk(CRUx=ՑT :Be%k{װhhm E:fAnɴ%d:"lW,#xΨ(6C@S9NZ6g)HB”( \" ~S6 ;9̝RF S:9%Y'wr:9;ƜbNYA.RJYQ֐#Z]i첆\Q@}ecqQ|E#2-b8tڱ2Aj6V,ƪ< Ψ(%~`8vӹ8=h즻%cbB|D/Y9 uS9縚 vj& 9iBr>< %c%&[^tM4[{OR> >Hq l}$9GHVVU:]4tyQER=ܨt,+d݋GƱ Qkt f|OqبZ߉p-sߘp<060M9*ttKWyYOR%48{xO̻ 7 wMVeSd0Tja?eQ[ZGƽ*NҭT討-tLf-w=FX  ؄ƮL|%_]:^.攞`c'ӟ$?DL QLgMSV,gG*.5;Mgپu&@3s3yfk+Vޛffb/ df#s\%8Bh*{~q6AE%, #s81rwXnGgȧgʛn~ߞ8 6T89 8WvmD}WLsM.e#vUh~8CSM " w ޓ2!"P<>/9֛Bٌ2syuE<}ӟʈk1ju$OHGTz&Eb@DN=gLҩ%ZʲBz6g[A=Dtj޷^4ŶcsϣKĉZwYO*NF~ujvogǮnum %KGɢN]oQTsYM\`jʪM{m{P[5=[DuVVzZWܮ9# IYoQSMΔqXΦ#3Μ~M4`LVww(0yMhsel1<DjO /a7&R"Cܢ$̇SEwc"8ȼOMDW9gVi5Gt\Ny[}oʛƦ3t\j6穎zY7u[ݖuctŢB8%Q}YR=ɑg%3(D;S{wI! Qp=7Ψz=Q<+iיlQ[IG>U^O7K_̡3>( ?s5c z$33$9WFnaЊlB &bm]B73j-G+3f6vt0ȷ&ΙAB770rOdN“a.-dzm^{u|Oɒa˓ԹϜŹm;]k?dhʸ*7$/wNXV6e5#r<3Ҏݓ]~jGQ [ǃ}eo~~W ͥu|!T\pp~v`Zo]VT[Μ$x}>ū&"}BXpIƟ&vZ/wVoEKHOh%aMMghΈTь"w'C^O ?!~M<K>-endstream endobj 191 0 obj 4522 endobj 195 0 obj <> stream x]KFa~E{F[#8ػe%l@?TIȒRI %m˯z}wb?O޽̞xO$6o|QKztJ3wYa j*I5,P1NVAɬO=8U%\: V -`E^+#{j:cOvz$p+/)Xt#+ⱜZ*&b`*Z+/ _k.=K%{"@/YK;]:8:_ 77= wnvTLbDD`)PL^Mެ7ڛxjKtSÃjuibt! 8`Ǎ/KFB9f|/.jaeyX % ! +C 6"v̶7/y;SOmOPcJ)EtBkn+CHj=zdPf -GzFnFſČ6A1ˌј.l1kɌGn;p(G))U?)مF͖ d%AA(-%FKOKb-=sPۆd^wQ^&3b"dzYMXJzwOPB*+Zgє4lK X3U3O#8e0SG*Ԭ^M>I _E\L(Px"\J2d1QbQӋ߈[EmPjQ,֥bA 9b2Ah\pNJ:O:v!]dԛh8vE'ڠD: 1t? JC_}U㮚{/Bӗ}DVOVai:/荾7{JmP"+jҘA%{,eMnI4}fjv28S`t\ѳ6h Ș94RUȡݚWd/}y<'b6 J5e.i/5%9di4O4C!  UgAx64pl)6(U4b4@6NOCF u&؃Y T!$-w@л`,D;<=8r$0cy_ @mlȚpG?\ۅ#[cv0ZKmPb/jP]8S`u󼓽'z4so̽Ya.ic |@9EB =ecA-Zv$qS ޗ_GVpJNQ}/4Q؞̳jO_ugCIZ bMoL]moA={=;՟'59L<2l^ӶOi7sͻ ĤCz JmP"(0tjB9CD J E [g8?NNΊMkT|^tS؉ة[ ^vgB^@0|ŬԐL3 "ҰT2 ͊NӂoNh6)47"b078[y2$߽f+u"ZA>'ڨ )R,my^EI?~[V Ir6N/"1v~PV$b mAZ obdem7i]:rz]_cBm3Xj,j йqU ,K-kP-[8+[J$("59ԃ9b_|&MQCYx[OE~p>Ag5LݮqI-#,ȵHg%T@?+pޝQ=dF$4ij@ `CKc2bl;#ᮋ`ex31]U cq.4Y|.Q3[AĂN@KL dVbd91ikŜY_cE-@դ5T&pc^w{81j?MaϢ)Uh C`-j5bs! X(D,ICk;\1G?ˑ{ȑ]*כD4ĦiQob@,]K/m?v,}x搎QcEiܤO1"(ɂH5fO"HȂa)t+>qW:dMzʬIqu!1Kgy<@ޝAܽ,+[t aMK#-uo@BN_!YaG$foȾR#+&@fѭ/s{Hsg|L{9Āfi19^%x!3KCc2F׵P|m0 3߄xe$B^ߑ\ā,KHmM솧EЇ(j͈MBD?r},$#'{9 3 vmcG8o|Ù ξć+xc? Vp2a6ewvөe 3+жEjzo{)ۇKdm 4kCl1+K ]" Q;H65٣I^!AP㙤a hpԩ 3 CК/;`IPiOVO<hw` C`?_K포OqK4Udgqܐ"MҴȮ+m7Y?T&4C)|ȗp˖9O3vH֧G)tRG'bd}鈫CU&/KOv\$[jdiZz䙤i閡*jdiesHS4J4I[ǧa^g85"-ĀfiY"ꚵ&E01|Ї|Ի3HӍXğ"_E(N{L,d2qF b@X,u+}S81Y.]_8Cy6vBV{0uRY1K c`Ώkn5.`@E *law5EҕdC0Xxy9I2ѹpѢ[ {xxfmpaVQKh'uNعfu{J F1тvj0Tf?vSkhuQa= z-Cʉo&#E0όDopA {5hJ@^(ʿe}}^Squ!*TC'#[1\$g=xVpL_{06XJV : Cί&;%'4 )4|Q>:^P+sX7(\aE{lb:AK EdԅO,Tendstream endobj 196 0 obj 4386 endobj 200 0 obj <> stream x]K7ΊYTqz?b`$Nb ;@%cM链O%#=Cȏ<|:n1m;)+1ó?g:ó߇yէ?9xy|=>O=>_;oQw_#xӫ3RΟޟR(fN?ewX9󝀇:&Nu߷-.ugq~Fι kw W>ݟT"_7bg3QRvؗp|wC_j۬/F2U3/s.~~9EJ2qo:} 6S(t::t~;;1LD':>²Ns |.ϻQ<Qx4es8s w1um7~1?^Ǹ@W9\!f\iT'|2Bu<2f˛^[ /pt^?*<o *a.%=0ay|<|-CZ?:VsyPUBW@EF+kz/1-KA͢bPQረբE@R̠'jhjjb,vVQnTh [ Ix /TJ#XRS ]0 S) EBJ*͂1k+"+=.."fG.K*_L'0 `J`j L"s'>V, PڈWǀZ^$qQĞI̦$6jiٟU y:}y608I`]y^u+vBʀlk 'K_ 4*]zNR݇981C}g6}>AK@m׶ƅ@ _q2%~_ɵώ, mɷa,Uz]9c{|^退k)vp u A$h:PHlpsՁ:̀<;u'+>5L-"x.)`<%$:9j_%*0@K$چh ZLJE!jRU^%j t(5>* [hL[T D :EW냃7*٠ ZE6cCA/LͽaK|a@"ba[:60ش-EJD_'"~6V "b$h D$B(R> : ӊΉH@D"L})"TD܎ "S.)Zb)B"8DIj%1WIx(IijLW׮qq].]yW0%i{ *;[i*nJD,b<2F b1=Kw]j t]Z^59A;p~VG@6"3LCv.$ΎN\ *`, *~*#*m0h1։292Km ]kۥ/FJ^b$g{Z,x@%:@K *چ( ZQ)BsR;f\GQ4RK6OZ5`K !=UaWB!®Bb \bէ F!VׅH%ЅFbnH˸VУ*,.EVJ:cQ@q"X9)RN;SrjbӐIˆ-Dh+m丨}B_:. ^m U5ŮDjZt~ܫ.VJͨA^@("-+!;RfC"DPgFPl!w H΂ ;JWAqt\=)gEǦ[D rRAE\˧.1#趘Ԏ͈@*Čnj!ẖ2G%H> $I &OTL<&&x\5.Dp[bXU_DI#X4,onB- ٦ -DhР-ZyIK@(F0"V*eR)C%-5 ҂RoϠK HKQT@Kh*ZG$- ^i,ƢBe g]]Jb ҎJZY'-Dϯ%m#[gg#,7nS" HKw2m57]K\IeשQLPu|>xBBù4gpC+[8l Tv&B_U *N{ͽ "'v,_ tU1{Q;aUI$ةMO(PGQMRu\?5>\N'*|`7C-kLJ|qܙNRx`x.&rR{xh@O_b_7[e^T/(Ⱥ#1~ Mp01%̱x~5H#5ͽA mUݤd4aStc2?saOْzmR/ƻ[NbAWt|y!PkFyM 2e83Iw42[ qӵ9+}4'_11%H`K;˂ڣ:@C;z4Bs{z KOߞæj'N }pmgL!oH)Yw:-aqUR= :γp\g^WodUXJ#:؏[PD?_ oKx…fBam"ۋ/Õ圧F}=rHšvm8 =rS54#^6yendstream endobj 201 0 obj 3754 endobj 205 0 obj <> stream x]˲* }RUlLI<.:Yc;IǏHT %cxoƋÁ?X'7Gy#:>}{^|rqsRwNzz}P7  2 _+:}cP?^> W6q5NP*: .|Q^|&ZO/feQ)uqJu u(/:Sڨ/s^;qo:};mv":ULϗY.p輗F:; 82r=UxS e9fUnKvJ|pӝ3'|@&JHar}K_}Y,C'? 5FlFN^#7utrpuLb얮{ 5)&\_~ طl #< (wDH5) |MĠ}lyPl8{eD/%˺=sȼ\uV8Sfǧ9>ʙtn]ۍ'dބX\`l&,+ƪd Ga1[Ftn5<_O M|Hj:J#ZM/5+N  XXN5شpg_4Ps2^)GRA]4M-]Ѿe}op_bw$@ fDe0S\'xî ZhȚŞ&͠sx$KKJBG+&0\ ԻN6Y{*w.YflT>ذ@91 C'K !ԵyC!t& `%EeյY7>j I$l5&HNE$?H0rM5ZXM$ b"i #B0do")nz$t $;C$Ht&t7"z|S'5EIA%4TE ;=*kl #yD[ZhNjGanBo$L (#bZiEڂ4́aۙ}W΁R(ӂ$#!@x!0C"F腸BtZo.!'=n #΂*v[c.Gtg䷬iLm4'[7_;1 nf&-N  & 1DHlPI kΤpɀ.)Dt:@'H6 1)"g L{}AMeP+"`;ϕF, bbĂ&F3T@[%K@,"pQ˶ mĺ| +.B0 _ <-z߯\ v\,Tfl<$$ 9"Y:;th2`&hfXJ& )L7U(OE\Z@"-ܘ_9?;DpuPBݐ75B33S%4 dWyRfTjixP[Xqvbane023K7F (0G&y%g$i2p 5HJW)¡$%I2jP!!L@ =VTsT8xVFH0B&F9! zC8ArcFC3RJps R`n3#C<'$HJOByţ{/Wѝ!tL9XD*=;i_Jͨ8ES iCѢD9l7a,TNE>Պs&N#ܶ?v2u67Bl&KJIhihZ6Y[F, bC Uѝ -4:fAբ"U[eu2fsb8o}}JJcJ & qsih~M,=UXѝ!pub+w\+͌O xsJ1fa,C3B(D@-e3 ]ScH 1KKM؊Yڙ()34K?awlL9+IntKrGxIoX,C[ӄ-8*;tczzj,ͭ(8y{wSbjmpqlA`$# bs,ݐ; -._Gt.mc\B3S A Oyέ20D!"8C\m2: =lH"K]sQ \fwݩ$ D?0pʝ #B\GN, DIx]2q o\&4IP^LQpF3S)CiS]e- &)0WpFA8)HpF%UR%œT)мc9m|~N!n.8WU5/.8'-[rckZb8I2*Ⱞs"koEnQlN^ܦHzp7spEqo2z `;S9AEuLm~1FBPzfU$xnycS% G*(GJͳQsk5T-p)U|aD\WD~ @ אָW\=vab2qAH˂)xxhOL~/5 Qw*w#܂za,cazf'm?6`[F3& SΔ@&Uys.f[)5x(}9niq>uM쵢u͊U_{jtUC[aC_ ՞\ٛqRd1i-0aRNVOapc%~IB ֢7x t+.\363hnO_0Wg- oMjL̓3~ͤf;}|Vw*;\폡K4J0bOp%t>ŕC kosW ;ڜB=,ODz/TPJ֍m '+ﮠrwe OpP3 è\s-<ЛeGأ]Nt |b<_oendstream endobj 206 0 obj 3726 endobj 210 0 obj <> stream x[[sγoM.7,`優< `ӭѥ5Y{r9-XQJ}6lw{7{~t&OO}_0{rsp'4)9Yc6971?yX-L?Rr|-i%*KMwtӓٜ5p6cfZ]X :k6|f^fZL?J3}QHH!ٶk1O3NgaZjdA"cp5epnz4BM@[>6$yޞlqA%h(-aZˢ " hH!Zh [478Afp[hFF dL6 ` QZ('秨cvN;@Mc8DyLE;Pj[&AsnQ/j J>,Ť>vjV /d5|:X)8!qt{lڻCpOd@槣3;3W^58 1Gky?=-itƞħ:.x=mF4\ߔ2U u[RF*ڄq{Ǿ;(W$$JilmRA9,>Bۺ[ tt!4v;=m W5ޥ(w!u[7!~Կ ߍ@Cԭ]W=Npk~a_'%wΞ3})짱[qu{з2-Y( ߍ~"?}Qiy?P:ʫVBNoC="mAouPP xE؁%]mlf9? BWP}E¢(0X@{R}AZֈnPEW:ySt3Wej %eS aΙmdhYЕY4f~H_敮`Qw-&Pʝ<8w%:+Jf??Y(jFDBݮ:ӘHirkEPpYqqq MZ+(XjAA#5 #ثnxxi2A Z^H dXw%/to#E˱kv'[o4K͖NhSCrX,a-ͥl1ˀ}E3>+Z\rkbqJPH^LՂ2#m.Ը:=X?oNYظhc-Wcu Q]f Rgͥq&-bϓUihqx!<-E B9\#}Jb? |6oE'0]:1+I+HVGMZX."aof]]`Fan3sL!k G$k3J7@ARaU@bmZwm-g}ʻ|VBLd5KyT*#VeYբ%#c$&cn-mCJT{ x.&<XaU`RN^N6#9PZ=+2`OJ~|'|&&u,*2TqGi]|` SOBUsLk\id^*",o"sހe "/cY,\Ob+inq"7PD4[-㬽Dž,dg>6w>슌&J:H RgsxcAEJƹ?AkI#kBW0kx7V/1aD/N :ـ`4o.,Ģa {=38kyg3HP[ |^sg:X=}"C燷S7PmNvۯ7{7GOg/ncn7oۓ,&Fo2XV* ZMXpn8Kcb?55CjѩA$5D$wx{^5Yw$t՝up<guF!(80M^M]d<21k#sqGX$rJ; O V3, Y:c `Z;SNCNNYL^|q"OĉKN&b^TU5K q+H]r/|/ t+&益oj2+T6Zk^̄}zV? z;-Ue4.* C#v&U:NyQ$CS8%BB%%47}]PJُCJ3H4 Io=f O:F^ɒYka90ck6Px Eq\Ă $K b{^is=}w<)Q`VO;3V4?ȅdEHW5D*| Ҋaڜa3˂ۙ6N+]VΫ2}]jڟּn_ֲPz[^~,5, ,kƏk>h|VD>KaoS9\1U_I|DCSByQ[=!AkHX2Dr= {B%]'*'"5peij„-[;saWD΅\]eqʃZ~]q'@WGubq'mG,0MqkKe5_; 0-,{! _ĩۈ5ūpA/ޯőq**5ޫBZki#NeŋU)@[ dEyjwJ_A;;gs^& 9۝2ی9l]SvӬ* @> stream x\KsyDፁrm"#I%s%YNd[~קr%QKU h%kg-n/Y^Z/?mVˋ{e-ˋ\}>CskS}>s >?wϭ39L' smkVx]=ɏ-^)]*TJw77oWц0`\Gӽ0w~"R4a.Nµ6ԋûdžO Rd>N#;m"5̓Oz: /.:+عM臘g!yFkΖO]6Vd㘶qTjCߡldl{W(5%!X%g(0J:jIM! @5L ~j}lddgިTd U{>#*q t;t+Э-6q P4!AqajhPlyTBmCr가k\UsNfp t sZCYk ) 0<^y}^,bj 5݇^̀@mɶѪF-~aC-b| l2̬^BV~R5RӵƟ~K&k@NW?eӶVՏ#Aqhty;bZ9s yϥϿq"nu 6N?]\`U[x^?FH @D&^Kpp4W7.٭õT5LQTUr`9\X`p`J~[Fa]\q.nXZrŽ̋F6̀B(mAg8;GK%b@v2¶K,oLO,͋,=g?,/y֭ sF9SHD֘@B"$1ve`TPkٯ|a@j>m_ (eJԻ8qQ e0M+Vɒ{,ͽ6^5S+xH5D=Hi#g||}E]ʒz5\|#jR*c"YGoYI jP㝒AA,y:OiF~̢;5qA0c7db05%؞޵B8h xb(*fZ(5b.yVуUCN (J=׺-#ΌL!ha_:^_X=k0\Eb 砩$`;:q*a}N'{ܒVO3,@ODg8 n´_ ~h qC7:VMXXN>R7bHy%fTlm_(`ݏJެdo2U]0ZYW%e*ri$2Ԥ]z+E8FB:PF`ϩD2~4}Y9 Qtzgt̖wH?sBꮍ&"4>BB@]t=`u},w*bNVBHƗsdXȵkޓC9E=§ 5v6m8a Un#U΅SB@!+|lU hʸܛz L8^ಔq"732Y3:=42e Rϱ x'FD5ȧV`IMѷ p {Qʳz(KAڋR ;N" l9R3e/3^1϶Y BZ99f/.̵yb!L9/{6HRӸd7B' +^~uK%{G#fcGFrvI/s>ÂaeX>Gl`0!h}t|DЩe@ ÉZv{7`sVTg_p{!{FGk742lX&[Q#qd+座c緺 Xk9ƻM0|it(#O~J›Op|<e\-|$>7aCb72#Y/$ jyX;())~u#-G">OW|6;qYk@[m9&JEZ'L\i.w# |ni"u13otEI0NIy5kNJtw@$zc1XW ֍YcңGz26IHH(:D7$#b?\53jʃlw\h nnC O^)``@.ִB6pF:1cdց nƶ˪Y*RNABZٹX"ŁW*nU Bs:p{ M\ y:UlװkݜY[SŚd&Sp3?`)Q?RR{4C|t(G^ˆAX:PdHuofW+uou N7-9UB{sPQي*ވ zF\V+lq"tH:IQy2_\ Deb E@ F*OjVtbbqi_{P3?IJکb!~W-â_ :e-A MA[`ʮB֔R;S, 0D gzMDq~4bAI[#7wn<1Jucu(P⴩9}"j~%\#`ٛW+"uE8-BU4oˍW]dOtALY%ĒrT|`ޤ71R,pޔ1C5vAk͝\9=(o,5L5D8,f-cn;;Wn|ՏlÏd1ko[!/mTwXM~.g+Bsw5IzC}\ >5Ӂw,e\ljGyİ.wO+~O!f_|7 6.n,n^4FZfy4@0ځ"o` 5!127VٱPKy4h;"6A(@}r?ަJ[Eny.9ʷ 䛔(]`SE㹠xί(D4MepآА6p5;1H139aOV`d½17d,qC{noS :݂lUM b]4hmwCIK\BJ{|)n P wLȉL9aBQ' wy'xB'xa8F\_k.k$ٞ28 UR[M|PdvՉ?txf&lM0.6Zv1ߺt>iNVfi;|"ABl| h'Z\ %4_U=Uԕ* ɖf>%vH\0¸J 7endstream endobj 218 0 obj 4163 endobj 222 0 obj <> stream x\Yy13U#B1@ iH\ޙuteUW*$ BTבǗg ܺo7< n'Nxћ<|s O86h*39rݩŸ>|Nn>?EN1Xi081gW;5(Ņ~` !ݩ_vjR8T x BRs?J Z)HWW 3h; ~Y6N ZI;dsiH&JELS l3Rk)γDe|d҂Q=\h Ȇ J:aA];qVmn OCv|\OqSO;pr\k]v !/@?>8qOE7y첔H`8;(wGĥ]81DuRa-~lBUA5*JEOD![)] t',< gr\ZAEcV"[nW0q5nk`H`NF|iY.8S،@P$7B,pW#W#yC B_>8XCZP]>@:hWd`ҁ  RPSieUN~"kD9 K/K bgLWmxt/`QMpF]';x,u%I\ZoZT6kИ$Z:qYꢀ)Pue:jwR}U16rUEɬikO))3a[98_K<sc憉U,_?JS:s2Z޶535Z$òLp-Q"_NCk#1_ޔFtpW㯄~?b|>.M^2Deθ@u097Aw"ŒF[DjB+ز2{8<1JE`# 4L( Shi!Ńj*PUB-ԋ㬣Jx0k-l|g4]xV ht2h8% Fu4@Eq8D뉁Rř fR0fJ-Kƕl^,E\V41 •xR \7tQk1sԎqt5o~˝;şw*`Gk)KZlT Qܺ&kq&7fj:8+J>Nf# _SPD,=GqL9Yt"-Eg_L!=! iQ Rc] r `6BˠLFDVgBT* [5TMSj:I+]TstM2-℺{I&%P`;4ntBFdP $!xZ_"?MB8N7@7ZK5uAj~A!=kkCd B5]:̣>XV>0dL@g:Ԧmj REh5,[ꢉJ&̭r)`)DjVcUP,xAHncT!R \,w;Jo=0Wxc̑_Xs0$$$5=.SP]^է5#^^ٍ 름z __ &vIv5Bbӻk 7$' P˖v#&XQ)( FP iWɏG~Q~֏#@f^MeRb jzɞt'GeaӒӚP8fy(Z#"~Ҹ.K*}y-N7gB>9;1+M#\auӈS>摕궇 [y4UoL-p)GY&f/80ɹO{ !\D.3x%plԵ~zuw^S.Lcu|k]* ̖]~-[>)gw/Q3U9c„OKnݹPOu7O~U0E/lq^(gE,rWrrk)q?.W*ܙzʱP)ߗ I]ؘj76f%_q: NdФ:X'S3{_*@-%,ĸ0d aOJDN5EOw;qɣD.5&m@>]W6uۋ=UbQ9tc,\?N;.g+!ϦS4pboE"l&`ODqn,Dg x^S$ڃ R3T[|<~N!O[vv Ѣ%ںxv ;#܍{љC] %VeheR/?= *2<OhρHHneu*pKHGx!:c̢R w|ОqdtrJ,|VA84>N79-H| AvbyYHYMEJvR0un UŻ{xQoޚbj}Ty?xД6OѺ3}DܺiV7 |u_qS;RDq3n fUcG|$`1NO(ԣٷzߧR(Qn78CV`X)ww k1i\?S#!&GW7Fq MwBLnU6ƨtpee̱ =~ɳ 6bX/UNnn 'm>Bn;rS^;r$ @zCUTC-%TbvLA=_]MNFWZUi'Z7#36] E7i1ȍtu*sB}aW.OUoCU;þsXzߙ߅ޱ\O\jա|i%;݁Wx%Ւ.2/aWT΀c;q^ʂ Aq{'9 #L=ƈS7N&JO=e3WHIB09c LRuD@vulR01-y 1i61KwI!wI+M[Km{K  @Ha2D # 1?endstream endobj 223 0 obj 3927 endobj 227 0 obj <> stream x\Y$?bgM! CMvG@Y-Ò|HaϧnVwYmC)EW'9|_v݇U]J9~ݩ­nms8ruzOW_⏓ǧzο~^ On`in׾Fv#3VTɻտ6l^lwpi%4y/7ﶢjyqh*f6PXN;毫|εYsa9wr[a8}дv|zmwVX1L8K(ўMMghOk&̛=@(K{_4yۥfCO< >O[6C_|/6I!Cm<1+P< jڼz݆Ad,EFc*.DߖFthG_ƬЧi)xlJT-k'Hڀ^zB+_o g'py %efR2-2zS5|[ox"L}$ V[UX/Gzs<0kH$$I2 QD'rb*ws_ RJMCY)7n#ء1wtpJ'(2@¯¯ ɔo HyBU[Ҍ%p"%|J+1;4J'dpJ Of[VTpao+O q!K*ѿuvH81ju+rlk"2!bq~AG`OZ`^ZK*|P͟GY$q|GV0y^!}qBp Ȁq 'k!$0+D )9<&Yeʖ{rl{h(v.y<{w%tWrmӒ$J `w@08v0-$(abv9|Twf7!>ɃŒ*hb|*} ! B]X` <t !1rM!,)CCg2V2z>JV{u±/Vk9zQ#H[oJF h|es/[ˀW x:4҃@'jv WUZIyJ؈@ "`B WMu>"|9A/0a/[SFG+|a>|LUZ_P2JVZdWHZ{&ՠL.U=x5 "͜7[ҵbr `;]`{l+ܯx2p1>OM%#hh<i}tZuWsi U `/hb~*] MQpo?(i{Lw1*TR[6$ ۼMY4GPHB%>8+!ﺡF0b.M 7ĆVڑkEh%As I6K[j#,Eb?kF]ۚdlooކ;)B%Bga~_612Vu5XҀOw˲(G✊9)39>xI{ \#Ͳ]`\L.(VRoyP&Q{IMH4,Ȅ0>,P<ٶ|=(IP6%:NK!YșF0x@C( r#t+v# uto 1.n=;zW1Ғ|!ܰR%8SM5kMRzN9Ԫ,) Ns귤j҂7J!uI n,K.I.CN?ڴQj_»rی+ÔsOKhz|UxjF;`_pMmYɤ0Ia8 k0W=t o604U-7jQDEpLV*K軦MoI/H]'tk̤]+h GC|#iL~i;6۔һii?8i;it*G7sÌK CV;Vi=e¯pF9s܅SSw/Zf!Q[VDƣ6IoRRܱuا ;N{@myeԼ=8E=$ iE iz.Q!!?~ػ n$w ￳ /oK^Y#(O^:ǩfl}iyjW}]m=,oݪ__rd[CC5ųHx>y/T>P`g\y/2-z1 J A R%Ȼf/+Fi\6yv#\E)X&:xr,'vz *&c^`~^,UtC'?Qendstream endobj 228 0 obj 3578 endobj 232 0 obj <> stream x\ݶ+Tޤ@:AZ7m{8i|pҤ|gHQJ]Z1I}.y.{?Ż/wgߟѵ>}/HwV3ٵ6(u~N7>H7lw1 JX+7[cMk7/vV5{ - Vk?/$inL WY)7w;մm.Moh H^V7^y|]v'aEީ2Ojs kM}F-l$z75.,B y tIظo陥tQDKU*T%֚n HL> \OLkQ仭ܼ҄H2l+\>8smʚ7ᯇav %ۈd 8g\&Tj((/:MƽGU鎣OLF5 V-\fX( YxBz:@/FUok zj?2:Iq].f82[3AU!(WΗR0]Hںr@ayqNM#lck" g/T}+;vߒF%+E}Vo̥XFP]}ʹ& Ay;xlS r {cvb㝬Y|u)CM#hJ[7p9?k0Vs`F8pa%Ҽy(X2(ѳ`?u3[dt>}N[Ne@JDS!N # @w/aEZixrآA!SIGeU8ըgsQKB <.@'DԮo Z+EԘ]{xꂋ dOeot <&4#u&z7AnPW>;W#l2ʁ@} eAMɈ \D__ `|~;db^Lmi3ۦcm41y W0:vrcx+ӝ;B4e*zb['ybh ;ͶQ[KY\E~0 AM%>5!q&|ȿ”S̹ ִ-"u*tG [-a콣6C9>TeW Y gD:X"JryʧTĭ`{MȈ)ľ; 46X 2{PhzdA2 Y9p)C#Q$}q 3X'9A҅.$ɩN _+Hn JwrnEJ-Jss48N 1,)L1ڏŜa$saL)0Y2xc̣eڝ+ #y61T\sܾe@,Lr^4R}.Di uJvgmr̾τբ3:+ Y/QəB?|P v(tiAL[ ;FV]֎ur0z^@jl&Hf?{Teܫb"Hf#m˿vOKg&H7a~RU\N±>ļ3"H_z7wWwWM׽&ꦫ{V!EEL+6xb =Ո+k >+`"~ql`Fpm4žit9| EXu Q@ M0}`\kdZ Χ$9JXoqXvyN5ճA(RBsք,*~>a4 }N(3-3l9uF  /4HyO}T>N~;Ƿ] =춘Av7J2/z>"1bIH2"NKlca 0n[aԬEhZh'9rc,{xVH{G rmEe.9Il76,Mڸ+F(rg';>i};S&cye^o'ϣq%mZkj$=B>9h.SPlm ς$˜C"& 7LOгl; ; >v !g0{h SPH}TƤ1{ĪxK6{(#d䌥2e@K~lִlLLL0i{\rI@ߢR%B|FI+\BwSŢ f%zN,pdA8uB;;:ɸ DsUE0hW`"gV#JV2pX/Q.+G#> stream x][N^yI1Ryu< c1TsԒ==ZёtO3?XW 7N_}} ԫ;W[:<_]}} u{tF^m}!ygWTs wfuw&v+1 < zަ!^a4!:OM##EZ9뇙tz;ݘ0[h*zO8{yۑG#!M Tew&P Za`}FBǪXh_'g ɭz@>dJLE18Qڦu[ˊQf х^}-M(DRH:z*@a08^BB%434-@4GM] 씱KF,FGlT*(rg5Y b{#i Sp=A㢾y"S L>ipf@%=8sho'ӝAPv,;#Wlv_`eY1x7X«YtIeJ,iw$?#JEC S*Il':@<bߡ /}J/hzKU $8VrNAn*W1ݺP{oRv |p6 0n;%M9Jjr\2mÕ \=hMe]䤌jej jߪ;K_ ,2/@oxs< ⿓5G'6Lr׾@^ '8Q_RZ54LV-sԇ3? iQeS/;  sĶKx((tky(-B5'nT _S>+)1i*})|q; OdM>eM=z\8N1qa']jkPP$>a1`` '1aL'&3é`dwTEf La瘟?ZR frKY6=&GR@&ݚvڿD )q<^hg-4 (QyB<8tNL(YfTV=K`EWPE^kDKǛ2;Fj †E!w/}(*=:==NYeNv>)}må_7]eAo$4HLxHu* Wrr ܯmIf ̒ڄ F!d]7bջƽi1ԇq gt'hv‰"8 @ 1"kQmU13-Yhda_`Ք,yFc~8gT^5+oԲ78`b;8mgtXdm*)jbkR9SzlOU3"Q1<(79cqW8R{Us@"d)b.pX 'b8=kc0CbLrс~[&Pۋyڨ'X/Ҡ`,iak&G,`Ň2 NOY*Mft: ®Z;z;<٠7>t[uKvڊ܆hwKR4{oi]ɣW0[CQs+p$<{qr䃳Oy]\ޅ[ \|ez=ijo:Ոj[X6g:1cM:"+ʇZ{(LPc5+b9\.*Vw̆}ojtx*P5ռ_d<*oV2lg&ر=R+>/ﬨ}߶kSp!/:3r p 裍g{UH%uؑDDxwZ3,1LVث ʸq`6&Wyx:q%1ӒfaZ&W3[ov*oH-rc-ay}|3wOr ۣ0:4Yʶgiir͛椎iPZi oV"U:emcxEZXy狂 -ϝlaJ<3ήMzLR6y8sB=rwq*A%"]lW]ԉ(LUri7\d…Ű;op't4sl8}s Kv2 y’e[vmUҌ.SyXϝ掷KpEew[Ҟ>mE-=P>V4㱢\脿kХNz)O,R˽ x)̵3*% 3!H҆D4ɹK16^M-7U>lYG=-s^Ď5Օ\a:t'up] 4ɒ$~8k]n"//S \ɟ'[T%KR6N / Zv:8W9|޴G8əPRޫ4: v0mz玿%>np j\䤤wGz@HQ!8`Nf:.̖'j}nVIڛ}Wm$wr0!MNYV\~̫NMHendstream endobj 238 0 obj 4581 endobj 244 0 obj <> stream xɒU }vhGx"Ba`b vY*zã:+o.X {vq ]w׃G/n›3Ox?ޱNsVN˃ǫC94_>]N)/ j)t8~(7Ϸ<}K?pq˜B}$oo½VS1ybGe48\K_$|W-?lp)~nØO…H蚆 \!;Tp_Z^_ Jmī׏T<] ! &|{pc=/ C]L2B WӃoe`dq(Kn\;xۇ'~\k?7N?7_|{Fu8@) y/O@d໳x˕D5h VpRHvX Znȕ2=a s()%o#H 7!.^$QpF`[JQZ_\:++Y~ݓi3pztr3fs;뗽Ԩk8+2x\gF 4pЎ(*TK:;.ךpQ%q6+6p- A[[qrUopDv>^x m ]*{@"X^,IH'KHYE[)aSpp;kq{5,]E J\}ѷF$`e9 $۴<{P @F/ Cpntg\ԟ<_!V;Y@Ptfnu;^EvI[$e6Z]C.X|M1ҡi,d atf5NR9ʚ<c ̵xxV [~2^̃pu"xӦ8ؾhw( nuy46=y'=ަGQ, ]ϥK#iuQ60Wy9aVm=` 񲑈@i(_(:ʞ5;dGY-5ʺ{s&tRfPifC"nO!6VKDeˠrbHMݳZ MpG>K<F7632k87*<BxED ld1M{ҤvFuZ!ߗl~.Y$q+ᡊ/ /8E " =D+M]sքpӬۆ`iV| afWї=ѕӧǣxcnh~v\%ne 7&1zL"$]hNJSˉn6Fm?=ƕb{>}s/| 3G#-sC PCC5"Tȉ`vM}g ) &;^FNlA̤{2`&>g*&WfV >#v~~H h> ՙCۆC\ccJI }'ջl5`'&#I gі >K,?Bni"7,eO2'o§~wFz>6ϵH+'=30~ {P>ڇ ;%'B{>Ѿ-w: z{P'-+2_~o.u76[=WmyymBmх1?8|nv>oɱJXҟmcG #CU42쑬Uо|Gcc( j"ح+빡6?70HC;j*W\~ A)\dzGZ[XG,Fk7ۥRtfv.VrJY%+>SErۃ7~ (49v+6ɝ>㒖A_@Z$Y9VmS;bgMՠVG:}ixv´w-F[UH`\S˂ wԺиZLoo&TOrw|`|4y{Mz fi)zeږ=J\]^_qDS;C e{˻uYugáuEa,R)4T*z.FbܿtjmpQ[\1˪[-GbY41;d%qS T/~޸ф1.T`G%Ym t_tvÄNmg[[  #k)y_€ WN#!`A?~_"*D J ZV9*vraoŠM.֮J0e5RSԒZ?46$<8*U&p*6rБN L%U_EJk8jIV@]'15ɩ2FVh=WU hŇWBBD5oJ m@\5* &Z9h +k$\~Sj:(o- +z!'PkjY)UDK`4yyԻoe7{d͸'hZyIGJ, [AȚGnƟ @"N-I-rnMBH(T]hA?MbJhKQDBx hĦ"}yٕ/gw'3?]+?7|Q^~/m~^WXX6:{K)U ?Ǘa"+K %)]stjaυZ&7u^dY!rEn\v~ \nZ- ~dsC*!P2j5l>L#_'_քˑ s^j(G`,i^$F4#>zbt K>j]8$Kacjؖ|۹%GU`c`M$7fm+Cae2)"9;l?zqT9 IpY=_~H˶(½ !p=6aY!uN)MսBYJ*CK2 MBh! p5dR;Ff][7ړN㺬16Xxf4G;ă@K֎itFW$[D[JM]g":4\ @ϚA}Cd%5Qytu#b@N~JWXD!Z|ə[Bw= ;f'8)7])ֻMD콈JcxotƆ؂|ԃ1@4)]F@HwH-^Kܡbvdn <!,[tGJ<0Ϗq2endstream endobj 245 0 obj 4657 endobj 249 0 obj <> stream x]K6ΊE /j_*6\ Tfr"!!Ef,mӲnޡ+Yy| ky_ޚ]kÛ7kk86\JJx ?YÇ9<ᇇ_^}s[{x?X?r qӠesi1¶yzwY?Ϊ=~]Z *&DdcI/NH7*,C^J ^KA?FLt=qZTpXdc qw֪d Bdq8қc M=4Tm ;%Z| wl8NčSokFLjԨ3fiul^[QF\iOMAԦ,jj?^I$d`7Ջ_er?Qt OZY(S,~AAt;B dAMЧ5G<`bZ38g~o0QKhO2K2sOZOYPO=>a͙X2 _4 4~G TAA}IUb| G F. gT%%&ĖaG/8¾ 2fced݈ĸL}jXP$ O:lmzK>2[νQM̡6u琙hAϾ%MzdFq8d:g-/[窕bip)!huJs/l[A8!wCA@T'pzj%9՘9B.% yH3w-=s`0 K|ܐΛvVsB9(z}_e?@69 Q$3_s@dV}ɽB .;Wx)1dgߒ~i@TԜl",; ϐlVt4pG 0 :R DjFʕmLg(2eyƱ\+k)VUC毥}v25s[fgrd`8}|$ia,1bae2񂞅Ќ^*4NoaBy0]6Lm)fj#JcJ221W9f^\{3A$W2$#|E,!w n0]OMw˼cRۍp1bܩԇ3hkCҺő~^WRS,gtA鍙,H;bĞ|l01S"3y>BseU)C H/W='{|*)wkk++Ei$>1P#j.rt/5C}P>s ^ʛ%zeŭA#gҶxls5oʍ?AhrXNtϕPocl(6PLZͨ%ġ$T"RY:FjTPbi!Wǒf{`Iud9^ͪ2v@!pP۲4٫݁SI ۞Rph&)^G-BHEI GSz7f[IO16‡_6'lHN#cxwlFlޟELezvp]s`SB7(endstream endobj 250 0 obj 3337 endobj 254 0 obj <> stream x]K6ΊE /W:z53\`AHHHQ0$ =ݶ:oפ+U,%Oa-oX_ߙwֆ7}h(±ARVH[SvO_4?|_{MWo~}x|'tPK5.gCk(cGc<ə9?JMhKMJ4 ׆[!t?2-׈GCa$C.pA5Z]!pO>L nM#2_@h+\X\8 Bt%ʣ(ND9B!!WQym!JKxOBKtl% Jʋ'KcS;5}B3,C4iHC.敗weU^yrXU F舤 $!CPB!P{ u*)$ѧ%>R&MqqFGDèqq^ ԍ$GJ qlq0m!.vTU-?]1>84!17/1/y93GL'N98c/]}KN_vLؘk~CZRh&T5Cy/~:(~ [$S_ jT _?`GU~ׅٱ9a2%hU }2Rsī_?M ^AO6 /&J} m## 'uΓ RD~\*|2h.dChvi35BS22TD2ٔ#v2#ptl!&s6V*6#uˋjgr>(K+fYI+A+c6v#07U'ɕ 0GFYcR}Dϼ_VZWa-jpާjxgYIx$7"LU˲FX!]//TʳJX,F,/p}/S#%O9!! zN`硧|!ayZI>G~r\_zP1LJ+-f sf`̐ohMWfR* m[ByDu0˂ј@_w:TGv3c{^e XODF\_D4`5b gQ*]D7F8?`3t?:6~uq׃/N87iyd:b E Yz@C?^= 7ݕ4UvNaXmI’]ogI8'F3殺N,aa\z0On Id T'`As.$7Rle Li %g< h:s'j3۳)!k, m+z਽a~OR]S;uyH2WqF, !.%8d]3VcghdQL3헥odOMœ(߽%:YՍ Æ@6d6}:/?)%? x PJHVY?y[r܍ӄ4#nev`&g,&o%L:٦jnQ>[եN ҏRDc!IIeX9_1b$apa9`Ex;_~W,0rS%I`:qbo<<&wшg I0ʓO0,ܕe m`*gEWy"1h[ 6e'h&[F&IFq R:q$I-; iP>(FEn'3̐F @}5E MMd–gAʺ(94A܁;1'N `䈹;1 S'f糡 ;+N ^e=o zv\ҀKSI+#)%9%K#s 1;u#`;1xb0r3# &~gWg#~8kI]CɄ?S3P !kΞr}p.W^m&5IV9%7>֩}*`2Xj7aOk(-A ,} ;+z04yPI2c3,3o%tr(M]h )bps@N`H$[ P3N*iZY#<|Hq P]QjN)p9ҿ9K FOI\,?TNnكD\! vr'endstream endobj 255 0 obj 3075 endobj 259 0 obj <> stream x]Kܶ)69jݒT ? qv9<{m<[;B{f wN(̸*/pg/?~zwg_u_]t? =LJ y  BJlw;ø8;isw|輗oN):ęU :?7 ou~=!5R[mxr{Q>?{:8|a"x%v0Z3:-fdhj&}h;ixRulljMp%R0טD1sOP!c6o/ ·^\l8o1`S=uha|j"VM0a0af< 0UQ}1:#܅lFPY3w@ 䢿Q d,)<ѭq 4I$% G<Oo=sbU*g w!wB.$[C r0mھ2 2 .ɔ @Hh B*v'\eR 8wطB͡V5'Mo妭 OTE($N+/n3u-'>٬4>B'N:}_G`r2oNT9IU?wq>3l paKmH%wͰFP 3*}Y+HaY}X+XmI9k[胰>13fxl7ictS{a7=Lm +u[^t } 3M-LWh ej<<IPkaۢ8x^]xNxA%i%R\%i22v gޔ'Q7*ېv((ffvJ,w6_"'# sVfsU [{FD-zFJe5q%q25;wiUX$HO+5 t((g]¥.o+ cq~S|l2|#ek+2k:OM:qR8ʴ%8fݼmŸY18HfjEĬOR.>!kQ@v "r2񜕃62|Hx0cYuFS$mPU'\83HpУ<3 MJ@ʜYi$gkI AOYp΅:A--vaiTiׯwm?eI4k wݓ^z?>caSW7aLr{|:zq>\gױ<Ȩt}٨_bۇGG(*QukS-GdtT2*):+mQw.1s_OZѵw\QvSW;iJNrx\>_B;Y.A@KԫJ>$9[YJcvzAc7˔YvpB.=WIU/BRz$8Ȱx[*InQ7/y*Kd*Ӵv}T=Qs]Q+%ō^+rzGZ]JUs7x=;[9sj BJtH&Ϧ eND% (>|eٯAh `PDW -ezZa_+M5ot5SmQs|_|&]`lB/+aL@{d΁,R+FoʁE9M>e/ o}>>Dd.B, LT >9sQU2MzIfQ/2 Lznjl"gh)uD;e&;sVQ T!Vٙ^0ynq3[r3r3Ky;nJ'pޫZV?endstream endobj 260 0 obj 3117 endobj 264 0 obj <> stream xK%7dzbq>YfJ.@, !Sj3Q)ӷnׯUe;ߞ9g={=K!8SGYhasg`Y/_^w?~uz8M??9tzfNߞ|\سgހQ秿xКi8[=?;0.5s7`i=pfhzxւ{eoONo!ÃO(f,gt/uQ\2kG{[U:n>aL_?g65nZ0Ȱra1 7R{{?&]ɉ<ޢI:,v v!(fЇbfRclLo5SBw0u6 PIHp zinމ[gJw|CQgiLn.^ o/ޢҎBjMK웏Y_eކNpm(Σ )|/ZgiXX mf컰7 0px-vGrO4{+ɍS@J-yx D 9h8AYrn^+Bh\ B)@ a8I]|/ŝ.'(\?WfR#2)6揧w/Gϊ j2!4#hq\FEO2ouڢĸ9lɃn]=b{!W{#]w h^A9#;Q]Y,ehgb_GۈxpYf]F ($ *2P8}q>ƖVVM?Fch吳z9&OyV8̽'%@^o|m?zzaL >6}p,̖zbXo;i|9T{M$v(%k*wkw&EY+)`9孠GB;|!VXZF}pq0 .d`(3@y3Db|flnz5vx! :p CKH}aX;ߖ!HN̬@jR݅Lq3&"T0,5S<&k_m]X3~f "k wX#V>c"ƬJKxVmufmE^dceM >B ٤k,GC{5s1|w@$wJ1sW-hoNٛ"AbJey_X&U,tD 9F7*x"Tvr(|_;g~8`s|ъ`{9 jm=y^'5,%==- x5<:^u13&$`|dz‘&n~6A`˽xD0Pzp1\^sP9!#]x mc7[E?bc=oehBXwSK9%4ޟի=(91SYQ"zyUe> [Vaڷ\ν0kR+= )w5aix^򔑽0T#)I)+Ra]vdY0?{ \UhT+N*f"<_]bdd@ "iI1#bl2'WA UXntttt[k|N 8p8r*M"i r7;'{$ Xr;ibbh"y7V*w&GL4 M+A2U_FSs3V37<_v٪o䏕3WJFQ~}=[8X=`k!ޮ 号MX+#Ң.,%oaԌDYy@ Cȏ['e dv慄V2TC,ޞ  jgJ@')d m}MXc= HKM$37Ց 6I UikWMYA5K i5V+dl<jTj Gm~K^[|/p-$VTM`CC{o&Trye-Tg~("W%jA Jɛ" &o?![!!s>z"GnM ޛ9endstream endobj 265 0 obj 3383 endobj 269 0 obj <> stream xK}a~g,, "GI@lC;F(dbnp$olǪbș8o٣8(Lu'sGe w={qx|û9<~y߅=3O__MOA ÛϞ=:> LJ/qqzw~]w輗SNsu3@77g##_~xtx>B!53Ge<|3߸e4Y~zN/6_H/M<"\<poЂaF[ͤg%wexRxt6EN-b`b}(&*D,݇yRN;B9{(ay?^'+tAuzxN)Jl[wϛ驶œhЉ5J+(nƾ$%p j;v(Ci6>Mf)8F6Z㫰ypPA 6NXgx$Fӎ\S*\ _P!$HŔM0IQ+ņ  $[T+g!}ʽB5eѢp?6$.q>'nb:\Qv)i3xu%aދT JPUChA F`<)ihE6P-JtQoky0Màt=NkF23WF㲊/f';)O S'!}\8Lei \Qw $"t:+Qs,}D>JJ큙u(#`VĭsWi@  j8DEg4>:h%Ug-icCz+VR1ߌ6 3UO9͋v#Qqj_HPD|=a G'b% ̃rrI@F0t_/5/WO‚^ A 6PG=`(Nub H$ &&)[F :ʺ85 ʢFI|hKP|dLVІ&q<\j-,VQ6\,;F㵗 Ly'ӿ4S,472#1xa2( n¯SO\8Z2^mY dIX Y 'ղr.잚 Y˳)1+̅El"k1am]X3~b "kr:kɯdf&uqxc*RNx}Y>-r TFL+!ʤViMD#u{ ,.$(M ƹөIX{u$TTNf[V'aCZ Z&DGFe5y٥{ !#'~Jm0 DmF>;*]i .ڴ [2-K.S¶CoFVS\ҵw!6YjT6JY&cɯ]tR֯iL_\E#wȤeR&[9oԌ`)>WRQ5]t2 yT.T9MPuQ~wn&zLU&$˕`DJ%4-Ś/#\J~X99uURŊu/Q{^xx~,[№D1{Qm@~{I7XXBBU,{!VpxVmtORO*>+rOA3s_!-(p(4#OdM˩]ID@}|eh0]vÑsKِ k6p)`^:Lt> $?(ȧ3?}HtCGmzh %f$cOQ3ӗar%&qvxA \a2.`jUzWxi|ס5$vEB;.yzopH~nTWWAɑA r@CInqȍGϻ#%=:_S3hBkvaNgSM3sqRipy2{Ccٔw$*B*Nx(^⮜aJ 8i 1qX(Q",# y,Ko|iHTV):h Fn6yXEY1/,P=yБG1>2Ʉ2d4fJGLJG+Rj{*U6p'|-p2x>5Gnց$S:{ej{"q/GItYzD{VYQ ۫PS^\=,|NO6/I Sq1 K`VQPd<4l#Y"$\ڤqqMtXyI!Vruwy`vB(ԅ6́WX *@G̿aAIEg]UJ4Vn؂2C{B x'Ra}wxqg ,])qF Q uxbWrEׇA5A~w:yx8C_CV!Ako<ۋLUgnC̠T=&z=!T&=8Y D31))-VW]de@GScu@^/9Z-j2H j&Ԧq }śn9Qxa&6j5 8{oa@f0FcܼAcAj2H "F(mB.7 lnX|'nNbH1EY3܄֬BhEm+Z溿_NcEU~l^]yarsqP`(b2'l6!6 J$ ER,X0= 6cYq髫8/t~\cjB>\"h\ޛE$h(Ov1(ũUn }ܒR6>Y9_z(xW+ylV M^Dn[MdlvM5To(BۀP0/2`die}<9g!WcN,i\IqErdKk9mEMҡr{9gv 2ϛrN/I1e1bRzA_cCޫha*endstream endobj 270 0 obj 3480 endobj 274 0 obj <> stream x]K)}T#6ƛd8'!#H6ή}ݒHQ%Xpk)JXOn/eݱu߃';@Wx{|?~{v{ůgOv/__wOpp EOANyOowm84ozb'za = AhȾQm!]F_,NaǼW-pRQǎ$CeWKs0i]-Fg/NGHAjd[Q%@ EJ.ʄ\ zEsWzv٣!;A"ByCb WV:8[{jHQyO#e dp J2/%/ʼn .Raee`!j'Y1imϰ\X'`Y૸3XPN*\9ryUN,Nz68\г伄T.Ǣ,02cDo9Y'c'jD6Zc&w t!&N6(ܱ*St#굊Oҏ5v)ttNm::s:Gr:G΃ UkLbW4ݝ5^:wڹzYwm%$ 7C--]m]H(̝_#{ad6>K=5#yx$\rf,R[ EbqVX||'3+cw@R|\h V"e Mޞ1&ufxȉ":umFeq`z{j]K99b{Iӣ5K,SVMR!c3h1m%ZM&EA>l%ܬ6٘RQyγ gg +燰҄u:׳ pVl'G}2.(Қ=hYĨ2䣠Ƴ2Rˍg;&Q7EYt= ˗e!˓ꓯƹM ̢5ܢܢߒ&gxY&D6 [ԦiV΄̻)`cwS/)->(bP+X*@U\wO@j!As]VOY Z݄a+LVoǸ: O ^7JU˥P5㖱2* yXy, Fo"úXnM$;Ap8,cY j 8nXluC_dS&z80qC%?ϲLနee묔vB-232FZA D%,  \ !`wjE"ZC\j->cỤeg*uӏlzv hq$8#TpzLV,6YZ|L# Ds $2^qp~qxx0ʰH]7-Hᥔ=P%cr_:rρ,LN rZ֐!qAZ*ƣy(\ګ>=^J>AX244oP.z""*@hZZEk$ҏG[HxSH=zñ'ҡL D(Li?hoo$Rn~kĒ4>8F]z@?W`uM:?Di6?}vߦöGP#0VC.X:LJ|<9O][ x亞M˚T!VʶMjyms~vIEBY3{&#Mken#Ǜ1oro/6,`M%WdE-3)zlWzi;{>N4y~1X$bclc*@6+_'QY2DQ"c7Hwj~'BY+Dih)knKbcʳҪ$wՔ29\rrtac'JM@ߌ8E(d~^:2T^9 &Уn gPDzzFNeZrv$Dv]2UI7\Y9)\VaNJjG߁;BL'/҉?l 8SY)ˬfU(pU XicX@iw]>fa'8=Vɨ/ZRnE=l5~;z2AVC+0rVEtϓtlU낈 k(hLzFS\湨sfuNXIPw!B?1-ȪH>=M5h.k|]^tTf9;a+lҠCh[U9Um; ~j -s~Gb/-*\yu EvFS=10XFflNe.&E[\e[,e =hrm v5a׻@4Eendstream endobj 275 0 obj 3118 endobj 279 0 obj <> stream x\M8u Fpbgaa efw{R.p-W=CDLeٖOK=ߋ"~nwaזaj nT6Р W޿ow7W_~A?߿tWp{xF>hh[xi>otPw=t_(:(P 0wG##_~{ؽ /־!Hݘ=xmՂw &.yyjCTl(` Bk&k<|50Ղ+ݑN4Z[sܾ%kE57P|v]ݼSmkö" ɆҰS4.i3fZ5F4\~ 0H8]EtY(T}!dh=s$(<^ӫhHC<Q%gTY\]1q<FΨqӠcGD %gML@gt3Ӳ!s=zf3L(Nwob5gG(j׺Ppz359n%nԪ8rLĕJ1gD*ֆJ\ ]0AD M޾t2 c$Aqϟ 9Sy웸*k[ 䎢zrP7Cv z@;%G*ugϏäOT?% Z)C5v&{LtTd9f#j F{٠)Ut`M^E6hr͠9l!*!;>ad{yԓu@K(10 ډ[\0њ 4F;AUgM}`ʢXL LUOjk73Vsq]@h%5)˘>.%G&U[ q)`mw䓦HWMG%bR2! 6`U+ZM4;W-f'2`A UdO]U#^\sZkgC|iTMfJgNOňGLzX_]l4ϝ<d&[ICǢ9KkՊA(pvkݘv5>s&~80x!a%怔p ekk;>=EoE\@mka02UctYުD̺-!f-!0fY6꣣=_eTSʫMP􀪙 es;8qfذnd] ip$Xag$g.%?=>ft$ʊz:n8?;PKhYTf:e;IҼݧ!#!{8D|l,dM4)$(ȕHth@CzL 8l#p*fBoǦ}BcC;"sjǏ6x)Mu>_I|8r- IuPy8FΓHicPR4C^KLҘQ5֣@_PH6ӵ72~0*u<U >n$5vyOɇӿ] / AQhѣ=}jxw*CO {j8k4}Y xĺW'>$x*q]S>9$w"OiiTE<&IMi0yYKˉ<՜y~q,v/$͢fOARw?*FkG4'TdOztLJVH4ٍ!9Ar,8Q& SrdZڂI6ZKrm[߮#C^fT6E:r:r֌X19H[]<+HʠoJl jI[dHmWVE7*InԁP~5' Ա"$s=ly坂h&٭fui&%-ԺRرD7I&\Iդg;E%ů1g0U`끫r L('TTEsWTgɧ #^1J^}sEPSRicT1,+* [ cˋr3A{&k)*u5/Iu$`|0Apӻwz <>vtzEC}S= Fld|(3\dI) g5Y` 6Vz?ZI*Yji*nʒJf ; ̼#Ee*Ҝ8ʈ(%{J@礨{"I%yI m_SߐѡcM%:DNSyf6wn,9YxRMeg\ISZ\4BU<礦C#/5_Ҧ7OۍX[{:oX$endstream endobj 280 0 obj 3141 endobj 284 0 obj <> stream x͛I4sпG5{ZS%0@%@B{ܶ%Kj[==I*bm&mÙhfs4oF4n6(vFH2Z_fsuO\}{ yionv#?xrhO 84h߈Fi>4})fs=Zu+-gFv'}z(o  A5:2?Fx|d44e4'[fgMxSRLWǥ_#c}vӶJ)<>S)<ʉnHa¸A1P8^zCG5C5FcbToWl8B66c vx9lt?]Uj\=G='%ٿy+ iu_t:&qa`82UTFiaz5E(/AkCEx&^JNmZoaGZʊa AS'F]˥~W3LGD ^L= GCgL(%(  JʩHsKK #J2Ia^gNc, Þ9YHq10Gs`NƳ8൜807jĠ٦bP 4^ޖ1)9K@tʐKrF‚ȟSAN!$$PV. ɇri^0z&9$&:(1iKLP]Yq|LҏqPT)k:=j}ϡh);tFĩVcN|ZCb,Ldo 1FzBҰ b9η>h'9ֵ٢K="I^\Rz&\>LCqc}xeCNJ,ȑxI9@ x?$Ma(58 wq+'%MA6LA6q!,U2lim"NJusU".C"%HAI ߸fnJ/)CQ At~v1:$;۟SG<~7 +L⧔ԢN;*q6S83/2"7gb}_ *N㖙🲔S.s0rѦ5T󼤁ZE\%n;Ty=juxK8$]"]e$Tf{2'!^NVuysʅk(C?8l?> stream x]K6ΊE^vu=z?Rł!CPIb`3I۶$m\RTʶt>۽^?{{ݮo?woZhՙta/u {oL?鮗w/^_^y/w/~z^6>w;y8y^.>v)gsic_\'vA !F}(;0E獲Fp7GEWN>vq}d -=1,OSwŗH}z|K';-.:)stK΅4ԪOt2cϧOl /D[ABtx۩Ws4rCP|4)`tt?6ҕWsԕzJY9=cc7 wߝ=2F5^:-Uzar>Mh %i͝S{ 5^ipbspV%aet0NW6t&Ꮦ- EĄ[E7׹Ruz\5H(#U4Nc OMpvr.:&G Nq!NH75eA* NˈS軸#/ C6\p @QB 3@d>z:z&t=q4F1p:/`?Si* NY])ET@(yS)dIJZ Հ+[R)3)?(JM,Y,&d-Mh6Zksχ퍖՝P+BsH0D,he\Z?[BHs>Gz Q]~iN*jH/w/wӳ3]{D~A^S"Ee˜@ f3AZx }(]y)C<sDH3DqNdi?=R&LnHSlo'ELCoJHS#RŞ U#jzm[y~>zeUדf@(K0η& !8?baDǔ%t!Ӝ:}d\2=lCKYc8 {qQYc'I\XRq/δ)>ZV0YVd|@vr7qI~GX gVZNPQkqƁ&~IH" @ᗂh# h-s@@ NFW '*ˊe專gX&Z-0%㈩{Qa|Y=4MA`׊ zB7Q۷S:N~lW5] <^MPTB=ӧB6]َkmCT4j3])Cn|BƔ>& :;``&mX\o*ea5lf7>_؂]\OHϗ -}ʅ8Ӵ*au0=(`OOjq2> |n "S9?p "$+.2f.wUbO6>p]̬2f0hqbc a35ҷ%AxSZ5fM(erYsjw1k0`hYxR̲-o(+;h e~R)UUI5r]+gP1z#-ӊJ%$1":#rk4-9ΆF=0=, ,n HI%{tNTS+6Y$ۨOWŊЉn&`6QKF* 99zq>[_*?KgFaԿC/},Kwh=8=`F뙜t-N_Ҫy`Q/-(Pf*';O a2EӚXNQ28|$--ԍ@D z O^q|q`|\fyέ-&0HK!EҁA1,xsmIeN-)%Uh7% 3_ChBAb5zffn lJyqjermm!m2}<Fm cQ00^l_CF;}endstream endobj 290 0 obj 3135 endobj 294 0 obj <> stream x]MFC MUf}:k%166kOVPvz .IWY/:N}cov]Www: WzwNOïv/]{݋Gzǿ^jߣ,vowz3;;=:qAi<*аpG%Ƞv/w%ËPM't zGgwH{T99Szc^34S4h A^Ɔ&~2VwKn?a#2fC=4aɈM88ylĎ(1kP.v.D$D-=I6+44Ohd,ygjV¦M E+EpbYP=Sy ,#.Lv[X3r3 uȡFe-63=-s9r6g1ω{/**8SAKF"dslt P( ^5BO8An0YvBKSdsX We VFd؃N\!oV8:MLiYf;ѱ׳mxK}c*RRk;:wk (lDD."bfyD%؇W-*@aburNaj9q 9PIޤnq6}k_cs3s;Ѭ4=g- e`HXnlp!i7A TRZsKUPL3pK0{Ҩ9\A;y+qAF͎8%lPV gIŶw7rAIJ@ji] @z*}ѧqOB+$F0F.Yr{ul\%uuSZMGëgłcYjł<ց~ۋ,̵FlP: 7iQw#Yx¯ ~ ~&Z' H'k•W iys ˑ@QG֪_Yxْ㠝RV6 1s\#| bqJA&:ߔ]Aն[ʊ ;*2TO0TڏKj,3I2kա.N1c MקeD_d.Lb\CVx-e p_L胰qNҔ᠟J^M]KC\/{k0n̉$p6\q6 agGHyфnkq|$n@^zd %%H~+<裮[a%tȟ@6~_aQ^#]6 ;zp~C !0u ylm>Ro^M=v_cB)뢓_hf O%%d[#'k4vȲ+,䶙iظ{\U%6c:l« JnDօiوZ3*jѬ\MY(dIqi> =;U0n/TB^?Gw6J 6VU֤).8)u޾oXaTOPH \dˀ2t*$qZ}} SҧD;ݱ ൠUٰ*$[i:/UUDH,V8, `()Gj =mf:m/Ȃߦ_|%k>V8Mp\Vض|햪kv nyb(F؃YXV|٭yƿVz{yrJopa?ߐЀ𮂃:F,_~[~?N:7iͤS cڀ- hVn!˖F1r$_4@saym y4kz>.m.i"Kjǖl8q0.N3 zY9R7I2`[i%]:,6b&O /Hliԓd&0S$ٺVYN/U}XX]^WpI&Ez2 +*H=LAk AC!WeIn*s y}"l5}Yًt3H/2/{_]T]V)9S3k玲cGt8A?]endstream endobj 295 0 obj 3213 endobj 299 0 obj <> stream xI$G}пB^%`dzs ^Nug{OtJKinz=?A?^do!ph^h/$ `<@k HqONo#݇ _HUG=qhk~o/V[)o4*s^Kw=+ 5S.hsrbL/B_/Ar%qч(^Bsayޠyrlgqêʝ RII)?^}wi3]w i"ca B?_ȰO+7N9NQ:_/ ``KYwI DQh 㭬 #=7 '4e=Hpf@_Z ~g lRt%vK8N M :eSde6iǎcSmxoTۘQ PÁb,yMI J T '#mrX 0eR Lg.=e5ki*L)0xl'8Ւ@F»^h<zsm,ɹݠժ>waB#!AHBfP%ưN*(vT !_NCSbNS|.4tJ]QwE&Im/ :}ڋ.T|@P?@Lg0](vtO0tA) +B+HAiyT*H.JAUɗ•.5$1]V8\v;mu`ʘ¸/b^ōFXj+]'"ׇPlY8qGfx5`.m!)&=`jLCTp`4Wjk?l P. $Kx "ɱ3'$a\oh?Tѡb@tb}Hr}b޵.%?P!ˀEt9z: JNrO*I`#aBbZ;jRPӷ I7r'JDƓ:kjZCUcLQ)CXfG%rDÌr)yu4ߓϞB '̈ N.JM 'G"*U`@Q  8HjE?hZ-Ƽ<y+1@'3oGtCEX*J/x8y TER-4.Ӆ.L69ʾ=> 9(V.*]=^H;-1TrRUw 6C-pe<@}3r7kQ3sjwN%}ؠÇ vAga=C@t!Q+ܸLw}:pOFk͝F-R<gho%pud M"npըPjaJQ9S 6pҫX6901=*?9@K >pF;U_R]-LLJQ~|ۿACe p4s=I4@<|8҄4\GH5^ 0@s"rG4[9KR dGֲ Sj25cM;5aPZ3"4C m]wNE6\`T4 '}4ߌP@8yYzsPxmҋX9r ,q1{ܳ mqk$iV"mqVBdBt{<MbIcyRdWs|h2eyRTR>{)*/cP4ƭBJց/_ LnAwMnL-=+fj&\ܫeBD qQ"TH'i 4l me#:smosS<[OIۚ 1 ;ӂO>KPO,QY^~b\!UkrOg"ʂEaIQjUVi51!ZdSՠ$XJ*CG528F~jhףtϣ v ;O=눺T1IK5` ` h 3LYXqx'㈚T9qLxM"0-~#"m-],aEچL9}M8E7uYh=y5A#̲C4<29`Jݏ˧YBUbP;4լkrT&S!mwRl") ^hxL`>UQ^xjyBBƛkĥ1b zs'kY\8Ae,$'SdzOmD78Ж.9"q:L5# /$+Wvi섧WƔGMv Ϥ(ִX]Wc+}̈́hKˤ`B;0DQԫhMK Gc8~p7+8[{g@Eͣm a.0Gdv. nmXSGLyVV@"l[6ʦ]z6**|%#e;1%2:QB9Pr:vN)ry!2yhS`"Sٚ> stream x͜ͳ59q_1G`=K 쾥ER^8P,i#͸mؙy.xy>ZO4:Uh~cՖ6u¶`*6(/=q_?iϾ<~|zؼtݗg; MRɃft侮ƪޮ]zfT2do4hl@o7$?xz[J抵54)߀TG_yO,rU׿7)$r# dM}6@PÉZAYK=bRmiBektq*/ҪORb4*aZe#KSܷA'1f]j+ EAR tZ =tguW*2X {̂ jB G]HT!UC~(9̽ϸST6Lj>qv)>퓐Qr4t+GE3u7q+G3-j,0J2:y=.7dyccgJ- tP')@V벢ȥj| N7tZ:U68{3<ABZ> u]3'+vD\Hצ<*O/ $e!WV2V- t؎ G7+5AG"O.Lou|V \WpYP3̼v]p Z7t\!Րҡ3S>/N &/.|BE/'q;X0Xpx=2E/Zu'%Xmv@QjA0Ҧ6IuLJJp(hӟm΄kjӞ,0B{\ '>>\~B`mOQYzR?&YAMޯyHz$&Э4G^_=Z>&˟OAzQ^_y_岻#Y§&'T? %uʇUЖ!]Cet6~JO~߿qӣr7֒>endstream endobj 305 0 obj 2279 endobj 309 0 obj <> stream x͜K}AG x*u6$ٔwKqkE #55KU.GBu27;}oT݇ G#B90:ū^=t?}W=>՗_t^?voqaݫ>\.ϝWbc;}ptBъRaQ~P+?) G%t6;a{L{-:>>ݳ@u _>G?ʮP ~z8z9xڦVgL8}k4Bix1׹]n}3$%J!?lO 1Tx*I fx%NML)MGb:-#st)v3QoQU7;G?QMx<(EʞOYL35*jib,QN#+ e@N4ʵ9hϠY# 4O&)l9m@Aи,&Ik *Bͧ 4m ;zl 2]1~XgN6 8ifPj}lή3R޵e#UKÆbl駌!45miWOE)s#W3lM[&VZP-ӎjvM@C ̳Z T1nrdLcZRy ZƷm(G؆䂖)+Mdر,\:3iSЄ64 #igh ,IMckE⮟%-MZsBCk9j;JʁNm;9L 3d-j A53qF@ +(i:}@ǀj6+ 7]T JΤYpue%7#2]P×WrIFŷ ypwMKOq)m]͗LɐG+3}:~8: a{r%|#,{^+<~vXfJaLiW5?$Mv ̏u c䶨 JNÄ,4zs K7l%b QÕȅځe&KKi5 `HQSMuHI˝@`(4y.%F&/*ɵUځG9ƆEu0Ҷ`NG727ebyZS\:6N ^'sdhhk]*ฬI2yuqBoMx$0rYbSr+' !C.քKs͖d+:ual63˰;VF.I?#R1+ZŬ 6n@ic-gMsj%t7lnxS-t*C(ӂ<~j@[3˛Z{`dudk,Y[p/RS&i7A7G6”ʾR J$u)xVr@^*'N=`ȺpvJQ.9W[_: /55TrylL,EV#? %?Z_ Rꎟ26N .u/GI $^ œ#M?5QQPlj%c{ ߸XmMޕ_q?76 :(gf.jv#?1i;lfS}. y tNБ YC5\O]p~ pʉS`TbK)K*vQdYԆO~ue%0qS  ^ïG%(-Il%o BL׆r?6%: EQ8|DU8ņ\_6J^Fj38>!.).I{"w{3VEI Z8!(YE/"T]RMRmΫ4%0bO69RU~ 7&@'] K~߶~ҙ? Ih5^qQ<#zP3_Je?WngD ϗh"=?4CIx?RU/c۠gzp^ҏʡηL)Jendstream endobj 310 0 obj 2320 endobj 314 0 obj <> stream x\[s~knZv3IRJl ק{={ΑdRI(\2~'ObvW?;,ɫc݇Ё3gJο;a'Ŝ Ǔ'ߎĭpVߍlRRK7Z ?B:e$}b䓵֘<$Oo?1sHMrw$KW01F lT7sãӻQLBpG,Sh?㩰|Z Sz^|+ 5F+[VJ^ꄀ aZli#w\uuiA;|907EnXi\~O9hgą$ @K;\p>BIi Ha0; ~m<_nH?0KӞYQvApƽM`>}兌9mWtsf2Ù+gç+;WFƉcpmRҾK|8e :7â"qrxAlȶ݌ˤ~)7 7dA9H7X{OHvB#G Cs}9LL0M9"0!`"`{x_PH;`ۀ CߋI/;X峭Ffڿ<4A$0gihJr@xV6/ɜJAP _óud.Vvw@V`vy=(UI7_LJ6H}QeJ!XicCJ +qWq02 2Ƅw`P8d^h',֏E^3x-QhnxQ"YA 4Oz?$uɚ,1bV+ß`V&KGՅE4"QRgyw MhH7b(zyR]Y=ȕ~2Bb'uL9 %,I,jFZ &IqŃ~*9},JK>dg\y*$MJu^G 2X`&E$q6 ,MËJxힽO8Ue~- gңY?\EEpS>@gP$x>|]ቔd4J^{6C6*>j%OyylVsBMs{?%O zVm#|MmG Z< #|? 4Wۜkn:uMJMٹbbdOqIO8k=,_n J&o+"?)oGRAҦa\ Xcؤ<UkO^i4*稚 S%jtr6|HzqiBSVc~ A%&6{6Up8㑌:UOhn ̓IP^\g{e^}r Ҿ@= β"`3kġxa^:'~)D9ەj; Mc_Ju9XС<5Mo cX<2%`(LU(cki$ZBpkkT[w0#I8&LRƛQ wH#"63Gӡ2i.DF y{PБ8S~Vv;P=X*DkG7n! BM9g !.ЉiԬ@Pwג| =V<ԟQt" 5q,lBc82]8Z֌wUjd}4>Z]b*&$4J"* RattVCT mXP>8y{FA^<4X]p:fDZ K{½yL).#JV2<.*ŕYfH0k#_'5%~1u_ bofFEVoj`d4zóNp 2!XI0Y(RٶF"1qwkyIy' HjԷ:yC붋sȀ[U-+ ٱ DnVed=ӝ2NX6i18fXӟb ! mȗfp꼎īNKD[eKɗe.FVy;wKX ŝ HSO# ` yD_T~V ?A|QMlٞOl!b2`it'K?nQWa'5B4 𸬱c;7bQ'(-eh}8JI) @з j*BKAWXfǹ*TF-Կ IhD64"(Pw#S,#YdRn߁2@w C@+Mop1-2d^A""3iu1)w4GkzvP-+$B襠g( A`߽g8X1ӽ'# CU%**Ds5F1jKl<ݸݳ_|ޒɦ!^ް mԔ}vh$;:1iA+@f\ܺm.%jTT7!}@ =_q? ?0~r) o/|qW0v+wˆF6εF\w KAjFf`Bp+\N nUa:VNs/t E]QM0@7Дxb=m” & cbw&JϗK1˘M B%"c&OCrfRGTl%J,. qu\'f'|T<"_ a=RcR\N]UH<֭ڍ尻HğCk*V{u49@>05x|g]C0xp_DO BDm  3J)z ޸{E+E{d _!@Hp+-M`ӳ̱}L4{Xqqkj?&yc5jJ+,Rup&$_WTE[ _,D*M^L:E9{ Px1_RS&I4;i6[*$M%ߙə(N*IT(`08B5ۂ3?U?? o 63vj ]9\;7{endstream endobj 315 0 obj 4367 endobj 319 0 obj <> stream x\ɳ^UG T}V]< $`" fx$`37JYOݿpglg {ɕoسϯgzWxKO}x ^y~v+<=تgVU[O|zVw]u/wZ%{UJy{hZv-J{{Ukk6t9WίJ[  \:w]"W笔 G8 rsGj,Ox|RyQwjpj5* SHE1k.\Jzaf#su Xs+t ϮHV|lEa;4MX8}1Nq}g`m!-\|۪ھa2IK%,%g\¬L0Sly~#n(R@0yO3( էN$tWW/*`G>mY9a*/*&?N/Wñi=6+yCD"iVե$ۻ(8RpbEow,s1\v"J`2-EUp=# ~+FY(q*AL qFVQ)%e8 Pq(,}S`$@CFƁC*~B+" qOM ןYSe*E3V'a?xn;b\hZu|5yfYD4@5X@|/P HPEy-$2 2*ܮOW 3lqm@nj-QhLu?Ҡd [ Hb 6a$lrv6\qf)y)9',ݝ-+1uڵW \CbKb<8*I6l%|"1v`knu{,2Ɲ,F 1'U)^޷K!AEB]|ˢ"/;Qa|r]Xk_)АM GtL*wCD;&('6*M@ħe2D^F(NJ_ȵȦ?|A%%- oGu-vмҁ|p!~uM|f)L$2I`Wh&q1́m.K]GǷɉ܉]PG^2j횷C*̷x=`x\ VLfQu2:9HIQ4 ]ne]3#KV, X`w]`bڋzRE#in8u[^=$xr i F̏"WeMg`չθnC%=,pf)(LV"F Ky5[mU> , `i!ކ6u8tSTH߁CJR>`8O$dZ98S BU?ՉQm&-N?:zCrFZ3y(z} 4Lrrw0tCh} [\@o,.!)M}Cꌬ-G֩e'4TI!: g}蝈g-. (51x(ϱ-)@$}Hrv}D,0 ;Wm`,j3G78!8!7H+ohܥgEBj%6tL }leIRH ͮeėm8O@P!mam*=+~ȷ`?) Ht$Jڼ\JA* XK4$$f)J<tX%Qh9x^<2>e ( Ӥ 3*Tӄ* /gA嬘 ޭ-OoU.ELF}r,x&X<.{8ZBBR|4"g_|HWQZyR@EYa$mi9 +}x iP-08:ò:5Ix%iPEY6mĩy=@׳8" ӖhlqY@2 0E P 54 KR{{bQ鎦i *F)W_XFhxVx4aY`MCa3K1:< ٕns,ܜR#:\5S5B:%(m5Wb -t6K\lH_.{~ Z 0ߘJb3DF򭔭e̷59} \S)` B;qFE";]΍TZ'NRP'܏vkilO8僐K_S rq̋(аcfhB“7˒թ$ZIksJE:>Xҁ;-OF%'QwE@rr+\@5m*5MA9"r d91?g-J&3d)V3lje[3fޓo *Uؠx7C*oilc &:&@;t-0WH]P#6M]iIم_Sk VjQQF+`g CBBĐۓtNn*"M`'{0t PѾ"Օ BMa’*CT5ʕ1ioehwU]mtGO.՚:^κv5"Ym ^[K0}&BXmDP[>^Ő-[t߷qcZbE+ar }RB :T6Hp~|d9mM˘+ns\ 5XEx 6o EFu)ã.:{.5I-m~L#*b"'dRF}bW>HťspY46 狡5']јF.cH)B<#e=[L~E ~U#^D P>_dgԸ_u] m8xmĬ+{lfy=b>i=IƾȄ'ЋTX2"m0dj5@p:~pNg> M+=PqJKJN,ʾS?DW?F@7}2,dkX}#ůr}ą((ժK],{"ؤFPoWM` S.Er8L(OFfު)NX\RwT3g/ڔܨ fNJ\\+%:e& "cmܕ@Mg~xFl |(Sc>κ3QJ)#+(^k)yZ7F`U q8qO0ߩA`5HՄ@ָ[ 2ce6&!Ht+v&Ka=,X57 v^nq)HGk '? 0!FٓOOTL`5><Ɍw\,K2f'S:%ɖPeMzr6̡VIDc *xT$V^jjHGf俣)qsE+s4L)dg&rJm GM}Z"`5L+iiKڐ_#jVDO`<0o fLC[Y.du5ܣNj11M9ɭVu'])ě =|[4JAxF͵NMlZ-F1'xHt_~%)G蘕[ 1Iޫ[Mv=*SmC"xr8G_6h}ugH~ҬpN2bsƙkwEbN \4JO4L;yXFmB D|e} 2:BǤ۲h-@d4~tk5'ǫ;g %kEհogQ{noǃct]"x%bbJInjy f*c:W 2<xz,m,1ݑh;8Fƹq27Op~3_dʓnOQW \1.oŅ>TSi%6I'YRTtV_$Gu:-B(Hz&],M$wb=!Myp ܔs bgB kؐ;P)`i_SU/M5{(B:qhIB˯вZ -+Zr~$hus§祚('K )Ɣ5|-EO1ЮWx%L< |,mr"T:Ϳ29mBhWɇq)N I`FTf(rحٓsRZw>X,&xG)u>*M /0(&Z{e|grg84VՓ>3$Й|m}b&F̮٘fli%?m&VEu[(&]VE 5"-WۭN$a2NiKgJ/PX98ԩ)щi9e\֘Fqï1OUOc؟0x<~ݺWendstream endobj 320 0 obj 5017 endobj 324 0 obj <> stream xYKoEu3;DG@pp$F U?gg ktwuUuU )ϯNw_;=8DD Ǜ%(wNdbe;oY-{=NMz:]Vazwv򢞮1cZ MgxfNgi{5$M`~ zmDzSk)tїTe6͢ F6y{E†w^r}v{MR$T23b1i@;װǢkt0\)R4l='qlS\yЇM"KX(\)$Yh6XQvU.uviFx qӌP^N/.lCti䜽fQ԰'g0qy2/؁`w>ƿڦy<#P>gLqӘLJ.ӪmRKo& 9ǜ|9C#L;a YJO"9LHf~p\('aHͦ*b4v1/H᠛t/ K<CI1: 9u=1k@p9&8Q dHt-"FUvOrv-"a%;[Mõ|c+W3@f uHFKRX* .HOeVN!BuJE{mg[|a/.4zccs5l]?ŋ +XZBOxY2h~R ?Yxݧy{2dr,/I9NKJ]fà 6u ω<1k?JFCQqMKI[ Rg>ոQB^.E>PP,,!ɻ՗0"G8Ɣ~*D޽c;(91tju]PSـfUεwG}A$3D{UEw`e05ѨG閫r6!KDYNH!v_nt 6jt:ܵ@c W2`eC1l"KRP?KqVҬu2 drgטVI24q 7Itw67>f`Q`f!+W5AeTykR96EmٿM}F΍K"p ޫtV{z!") r<J8v]xQӀ!%ư{K` <9%u#|åHŞTP2zv|;NH{뀘8?gVeU⢛b ރҗM<ރ4 h UPߓ!>5"u*! *sÙ̔6mE>. NSj% vs,PZYFvKq}[Q\e8|#o GZO;2A*4t$fKJ:F u?y]]]dkY}J ྃnB;m-bj6.߲B}h+Q0~ЁKYɬ1h %3-?2۸z; @VJdAZŒ)#k 2dendstream endobj 325 0 obj 2109 endobj 4 0 obj <> /Contents 5 0 R >> endobj 14 0 obj <> /Contents 15 0 R >> endobj 25 0 obj <> /Contents 26 0 R >> endobj 46 0 obj <> /Contents 47 0 R >> endobj 53 0 obj <> /Contents 54 0 R >> endobj 58 0 obj <> /Contents 59 0 R >> endobj 63 0 obj <> /Contents 64 0 R >> endobj 68 0 obj <> /Contents 69 0 R >> endobj 73 0 obj <> /Contents 74 0 R >> endobj 78 0 obj <> /Contents 79 0 R >> endobj 83 0 obj <> /Contents 84 0 R >> endobj 88 0 obj <> /Contents 89 0 R >> endobj 93 0 obj <> /Contents 94 0 R >> endobj 98 0 obj <> /Contents 99 0 R >> endobj 103 0 obj <> /Contents 104 0 R >> endobj 108 0 obj <> /Contents 109 0 R >> endobj 113 0 obj <> /Contents 114 0 R >> endobj 118 0 obj <> /Contents 119 0 R >> endobj 123 0 obj <> /Contents 124 0 R >> endobj 128 0 obj <> /Contents 129 0 R >> endobj 133 0 obj <> /Contents 134 0 R >> endobj 138 0 obj <> /Contents 139 0 R >> endobj 143 0 obj <> /Contents 144 0 R >> endobj 148 0 obj <> /Contents 149 0 R >> endobj 153 0 obj <> /Contents 154 0 R >> endobj 158 0 obj <> /Contents 159 0 R >> endobj 165 0 obj <> /Contents 166 0 R >> endobj 170 0 obj <> /Contents 171 0 R >> endobj 175 0 obj <> /Contents 176 0 R >> endobj 184 0 obj <> /Contents 185 0 R >> endobj 189 0 obj <> /Contents 190 0 R >> endobj 194 0 obj <> /Contents 195 0 R >> endobj 199 0 obj <> /Contents 200 0 R >> endobj 204 0 obj <> /Contents 205 0 R >> endobj 209 0 obj <> /Contents 210 0 R >> endobj 216 0 obj <> /Contents 217 0 R >> endobj 221 0 obj <> /Contents 222 0 R >> endobj 226 0 obj <> /Contents 227 0 R >> endobj 231 0 obj <> /Contents 232 0 R >> endobj 236 0 obj <> /Contents 237 0 R >> endobj 243 0 obj <> /Contents 244 0 R >> endobj 248 0 obj <> /Contents 249 0 R >> endobj 253 0 obj <> /Contents 254 0 R >> endobj 258 0 obj <> /Contents 259 0 R >> endobj 263 0 obj <> /Contents 264 0 R >> endobj 268 0 obj <> /Contents 269 0 R >> endobj 273 0 obj <> /Contents 274 0 R >> endobj 278 0 obj <> /Contents 279 0 R >> endobj 283 0 obj <> /Contents 284 0 R >> endobj 288 0 obj <> /Contents 289 0 R >> endobj 293 0 obj <> /Contents 294 0 R >> endobj 298 0 obj <> /Contents 299 0 R >> endobj 303 0 obj <> /Contents 304 0 R >> endobj 308 0 obj <> /Contents 309 0 R >> endobj 313 0 obj <> /Contents 314 0 R >> endobj 318 0 obj <> /Contents 319 0 R >> endobj 323 0 obj <> /Contents 324 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 14 0 R 25 0 R 46 0 R 53 0 R 58 0 R 63 0 R 68 0 R 73 0 R 78 0 R 83 0 R 88 0 R 93 0 R 98 0 R 103 0 R 108 0 R 113 0 R 118 0 R 123 0 R 128 0 R 133 0 R 138 0 R 143 0 R 148 0 R 153 0 R 158 0 R 165 0 R 170 0 R 175 0 R 184 0 R 189 0 R 194 0 R 199 0 R 204 0 R 209 0 R 216 0 R 221 0 R 226 0 R 231 0 R 236 0 R 243 0 R 248 0 R 253 0 R 258 0 R 263 0 R 268 0 R 273 0 R 278 0 R 283 0 R 288 0 R 293 0 R 298 0 R 303 0 R 308 0 R 313 0 R 318 0 R 323 0 R ] /Count 57 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 12 0 obj <> endobj 13 0 obj <> endobj 23 0 obj <> endobj 24 0 obj <> endobj 44 0 obj <> endobj 45 0 obj <> endobj 51 0 obj <> endobj 52 0 obj <> endobj 56 0 obj <> endobj 57 0 obj <> endobj 61 0 obj <> endobj 62 0 obj <> endobj 66 0 obj <> endobj 67 0 obj <> endobj 71 0 obj <> endobj 72 0 obj <> endobj 76 0 obj <> endobj 77 0 obj <> endobj 81 0 obj <> endobj 82 0 obj <> endobj 86 0 obj <> endobj 87 0 obj <> endobj 91 0 obj <> endobj 92 0 obj <> endobj 96 0 obj <> endobj 97 0 obj <> endobj 101 0 obj <> endobj 102 0 obj <> endobj 106 0 obj <> endobj 107 0 obj <> endobj 111 0 obj <> endobj 112 0 obj <> endobj 116 0 obj <> endobj 117 0 obj <> endobj 121 0 obj <> endobj 122 0 obj <> endobj 126 0 obj <> endobj 127 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <> endobj 136 0 obj <> endobj 137 0 obj <> endobj 141 0 obj <> endobj 142 0 obj <> endobj 146 0 obj <> endobj 147 0 obj <> endobj 151 0 obj <> endobj 152 0 obj <> endobj 156 0 obj <> endobj 157 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <> endobj 168 0 obj <> endobj 169 0 obj <> endobj 173 0 obj <> endobj 174 0 obj <> endobj 182 0 obj <> endobj 183 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 192 0 obj <> endobj 193 0 obj <> endobj 197 0 obj <> endobj 198 0 obj <> endobj 202 0 obj <> endobj 203 0 obj <> endobj 207 0 obj <> endobj 208 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 224 0 obj <> endobj 225 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <> endobj 241 0 obj <> endobj 242 0 obj <> endobj 246 0 obj <> endobj 247 0 obj <> endobj 251 0 obj <> endobj 252 0 obj <> endobj 256 0 obj <> endobj 257 0 obj <> endobj 261 0 obj <> endobj 262 0 obj <> endobj 266 0 obj <> endobj 267 0 obj <> endobj 271 0 obj <> endobj 272 0 obj <> endobj 276 0 obj <> endobj 277 0 obj <> endobj 281 0 obj <> endobj 282 0 obj <> endobj 286 0 obj <> endobj 287 0 obj <> endobj 291 0 obj <> endobj 292 0 obj <> endobj 296 0 obj <> endobj 297 0 obj <> endobj 301 0 obj <> endobj 302 0 obj <> endobj 306 0 obj <> endobj 307 0 obj <> endobj 311 0 obj <> endobj 312 0 obj <> endobj 316 0 obj <> endobj 317 0 obj <> endobj 321 0 obj <> endobj 322 0 obj <> endobj 326 0 obj <> endobj 327 0 obj <> endobj 347 0 obj <>stream x]10 E"7hHeh0p{00HSqp6adQNXWO*?pyi泚6mǥl3(QC]Á:Άf ,!BX}X`e nTV*^]R(yK]d|(.%>e endstream endobj 40 0 obj <> endobj 348 0 obj <> endobj 38 0 obj <> endobj 239 0 obj <> endobj 349 0 obj <> endobj 350 0 obj <>stream x]n @|pJæipJPM;M;<crˮmyiz" /KVtZ095՜^C.Cg䓭IqMx+!h+_5c\e,xR }LԶ~Gv` ^2X(Xa!dåZ*C;귓TcOҕXH+"> endobj 351 0 obj <> endobj 34 0 obj <> endobj 352 0 obj <> endobj 32 0 obj <> endobj 353 0 obj <> endobj 30 0 obj <> endobj 354 0 obj <> endobj 28 0 obj <> endobj 355 0 obj <> endobj 212 0 obj <> endobj 21 0 obj <> endobj 180 0 obj <> endobj 356 0 obj <> endobj 19 0 obj <> endobj 357 0 obj <> endobj 17 0 obj <> endobj 358 0 obj <> endobj 178 0 obj <> endobj 161 0 obj <> endobj 10 0 obj <> endobj 359 0 obj <> endobj 360 0 obj <>stream x]A EMuaM^ahXH m^Zc\> endobj 361 0 obj <> endobj 8 0 obj <> endobj 42 0 obj <> endobj 362 0 obj <> endobj 41 0 obj <> endobj 328 0 obj <>stream xuTPTww}!@#JVk&D01!H LLX*,Y@XȊMflij1LQc6xU{(fǛ|;|QRJ&#uI_H?LS%Fl`QJzORG)2'L ;H%?4Σ.Y4fTTZK-%6ŒE+fkii!d+1l<(3QQXj>kx̰VΨ65WESB3*+klf!lT`5n46Aa0YV93NFH9VY]S.TTZ]YfVE&y$j*5)饖rGi3.8h6IBȼeK$?n=U SsbꡌziNwvAAwNvM! Jb!MkbbbH1)W*GT+TXqD4;ݢD4+F)qHF3[=_?؝ 9J'{sHD'\_PQ=?k!>^j7.\&o>?|.'VOWA˭}?\Wc4 DX1ŶmąCᱦF<ۂl.iYǰ5LKb(Qjc>a Ɨ}7I?8ݰy߷uE;\WTYDthYo8ؾjd(q0{ 筱7UŰab?n{` [x g^G>v#Uwv: mgTjA!Tp"mOj$Za·M.2p\m.7/?K}.3,y3Uhya܂ݽ=tLW;>Y Y%eq⥏E!Ƽl7E{2')*!GZD1W( D~-14(Re s1xYR8n<&/oprEz٠@<1haRBd~?ˋja nh D1Ά 3l:>*`Ʈ@𸀛\{`CMTp&45&g E]3-,Qub.):vX u.Gr2r/D"=+>-?ʺŹag:\b׳w?܆48v^=tw,w\_fvoHb8X8a۟ X:} ]Cgוr)>٨LJH z|`c3q-.' kmLc/bbjv=jB!܀;R>xwz'V;uZyoo`^O LJgKGHXWF`Ecmrv;[dY LGc՘T),9xS4„o:n&0KR:.NSKJ0!aXsʄzyP?SqY߄#q!^5}#Gq,+!>{%P@:xna8He"ļգFf(rI]"(D? endstream endobj 39 0 obj <> endobj 329 0 obj <>stream x={lSU]BGhG,1G`vee+[Y׻umkok{]Fk;]2` fD#`P3P0v^ށsr|EEK+dw kڢ:p5K?/UP[OO`˟D(N ٨U7/T(ݸu&VUHe ]Ij{DJ3KwV֠{tԬ)RQj)U=ШhG]H%*yFxZ I_E_ oxGV=@H'SxaW(+>xM]*eq]E=nI3|)B  c3zFǂĝNmn)1<6e&|wްuwfrp&y,`ha ?G:n uHG~Iba:1iM#YVeA>;S=Vɕͭi了Qf.],Ok6K4E7~D ?D?ҿc}VO[- ?쁒h-aK ^@.cW O"~+M$Yp97^Xv. .0A7y{0 9@ET(25t~7W\fQ=teK"?=oڽ\ClڼЊY"Iw;xfNzoF6 <6鈅SNGhf;AZ3;#އQ{M.G8zp}S :KF^ ދ`gBk9SFj??Drĺ,jG F. q{Q@ Xg$L-NVs8Cg'YIb|WNA.ΎEloٍuSHhI^ы\FX-d-`uߎYI~]Mj6OncйE[։:4`y(hh(3:]ﬕwඬv]ne?J ]5K-ѕ_v-z]l4B^,i#>NIyb0v'Etͦ|O=$2McWB=Sh,`*!mVRKR\.WՄFV,WoI B8iF endstream endobj 240 0 obj <> endobj 330 0 obj <>stream xcd`ab`ddds 4T~H3a!s<<,s' }7]G;9(3=DAYS\17(391O7$#57QOL-SpQ(VJ-N-*KM[윟[PZZZ3f^;O Dg,^V;ڒ3J_[x*{00YM endstream endobj 37 0 obj <> endobj 331 0 obj <>stream xU{pT7^&*Y ZJbd4Je#l$$>ξِd7`@URG2*HmQ:gZ滛o3͝99CS)Mӂ^Q4=ƒ[ CԾUsBW@gMۊ*TVOG~0~ZIQUQ^R4;'rWKU/KjKTj|Ȳw_gɲwN)UJgȫkUREv~F$*rAD7/M{*ҺzL!?uyF,RL)UɤJ TBWՔWT2iFU#)I2al(eeeDARsTP)|RQy?T<EPS *Jj4Ih7:H05dJLΣ7R,)yxT6u(ms0??&|0-2e;.ҼǥO'uBpޓ vWh8|Zk_Jf+yb#~ET;"{|$@6=x@9iGP> Y,3Oly&x7!sKvh6{F;=l[y|,ً>(0Olt[^[knd5zq,EieW㌻N0; ZxB/ݠv K8쭩Q*kjzCCCl&gŮWUEi$sgp{:;{z ^&d/XUˠNVn0&]B.>ez3xwOU*0a?f;k=#85=&#p|O`M@M"2<*!F|Q_bw. ' m F K'J.ؠw5Է=a:^@-(zIhi[,`ftA^v悓E$op`$20p|Ld\kbp"?/sX #]6Z|n.gbvbǭ!"T 9 b1X\LV *օlN#z bTD EH, A xjK ^B~S?NGi.-㖡h%FG#nR>*(O8摈j;^{.li-AOG a/V5$F,Վ6{D͠Ѹ4N M&i9`[ ͢戶>5KkX[" #Ld"qF0)6h*j8h(QUj6h&܍+~B" dcr$Թꑜ~aq/V_IYm ƾ{/=W.yHSw+?f7bI&Pmݹhwɷ>6onVt}8xeۼ+iqSsuH-^C}u7٫vC "uڹ s=!C4"Yۈ8/\k“?J{?YqmnIY[bǘM`b>~7T{GămUDCS_%D7xtW0Bߢ,a}$#9-\1Zs}g|EJ%HN ="O F;> endobj 332 0 obj <>stream xX tTe}EA"&QQEi {X T*U}W^I*{* -aGvCqvkfWH̜:uN%9w{@ -X:'izVAۅ E)#;n&G&"`[s)$wI^pO=6;}~qd鮼)(}uyREEYoTgUIdyC/(-.I3Js$%9EerJ*r1ْ+I2e-޽๥ˊrs|b򼱷 ~b% 1XH<@L#2Ej!.anbXN:ekcnxlرR\hܒqgtMIs&17O37AbF% k\HM\/!jg*Y1k Dw@U rujlmːC\;Z:Q%jF*>ˤcM*?s?_ $?Id3ڽv7 1uX ^w]l4G:"S5ǎ dO,^$Hk 2Hi7PzotIP4:3u= _12޺g=D,o4xlPcu/-TX5VYʥruUeFH0noApaj3&U-Lܟ$nAYj N8ϟ_ڲS~߅'=C>lfzb&?@#/g c{}v@6!րŢ2`@S5xk%[[lbHo)4?iAvCy6ͬ).䀋a|@:# &:+vC7am r(9] }D2?qЇBv.L" PՌմ:.s%0u"CĜtY}ZkJJVoE: `6*7rlCmI L-<}ǫ+}:nk,zk{/t[=Z-k)su@J Xp&oXNVfGO?v0Ok{&XdSn@<8x{!ū7OÀi茚Gg `Uɏ\ʛQc [w+ 07 ڿީ[Q)9xţ@UY,>pW\ށĜ1L&1 cp5*^(u z݂w 73; Z֢cL[S3OH_|m@NNOmք;.e;6>+o Y ՘Cw:m"4$lX My@c萴3>b<MEwq+7m/.eo.KO:Qw-iZJ쑺z<ݸegez*|ͦ@.VccBōp{>iD3k,G>/9huO{5OWtwYK{c=hOoՎIv7_0F+BQ@_=k9ڲU ` +kUm{oR&..eL~u{b]^>}؉FNO~0#FΠY跀֓h/B#Gx5_+{&"1艶.G`?Z6vxhiL1=cdK3Ks`Tԟ*ք&F\π)kxIZ{2 ֯_oF= z |ݻl Ѱ.ꏣz+VSYbYmF 4rPϣzd-k2TՓRC@\~]"4KRrZxÜNաy ;+-5OBZOZu9iŔ64;F(ja@zjv)]`*8p;#IYJCb8:CG7%-TsE+{|tz,]&V"Q+\i?s/d闰ط3M/IdMզR6w?=M41XmTm wZc?^^ܫX͐2]yAʲX4E&B_'d;stU#U>>l/CN 7*k%ŕ5ʦ>(-lEeB5qoWsobպښ=uNo }MN%^?#O\Až>܆/[J689,1Co ,Q:MyN{z'{^ٹeڍ vh7^QGgN]ƏGn8jlV?mU(XU&kHp\(@y68x?c Dc+Vx7;XIŞ׾x)'*2RZ rΚ!ɟ1= H ȳ,rcuϡh#Oo|v~ j? dħJ R.:ga]\N&@~ORn4YۯZ_vD9w`mrkՕ S]-d ET(./-GVoĪ%,qlVd%e^h^A}w^޺/sJ0 E&EDX{謹7,8&aDtՒ58aT4w7О\CVhP'|al] ָo} T6W/1VZMx~7}F7r}0''),B?X^6 s L6ŲqfȪwWd7<_k h> ʘa:+#ʰXH ~>JE]UeHKܤzYDz1V-;8ȐޯQZz+YՙIgПtH; nlKA 2X5e[pФg!>Ȑ Z7=x EGj3 =KU/@15.<'lތŊk Qo;[AKy>S:z}vՅw4W߰2K(ٜ$ui,O*O֔w]RL T9  o2Nx0@jzta|: %Y0˗ Ju-&whHfJ\$,,z$Ms;?-/O7>ȳѠ˘Z+G>U ~fl u[:>#Ϝj>37"8םTАH,d Tc`)=k526붘$U^ت秥ZpRW47ѸFt+\j]Zciw%,@h$R~q쀢VR@{!bV [(_x-^jLmʼ/I7z-Ӫj5p~?z n9>eL̙B r endstream endobj 33 0 obj <> endobj 333 0 obj <>stream xzxTe C+" q$#z/RU@RA)%6I2$I&=@ -)bAAWt-Mݟ:-2XN&mݯQ5cEݍ.A05^2.>953W f[yUҜ\q~ZJjć>{ԤB̉rv%83sz抂 4'+WP?qUNbR~60~n|fnj| .?I[S/ȍ/LLLKNJJόJHgXW.g/$nY47i y/槬[V Weľ,̌U ;Ǐ;zܤ&uy,,$VdVE|l:2ֳXXXY6Vg=za֫WXOambd=ŚZZz .X,/b6Ml3¶ml;v]l7ܱFeF _4| 26ı;㳑; GŌ:yvto E{pyD~9]QgJ B=)>&JNLj' *R/Xf ȭ^q Ř& Ƣ1h@'+E@Qf4v$FCYd?A!/um0N'3(ĄڪWtlf}=6T:F5Uh9 >[\F93DDf}L[yiY hp6AI|9 )AK^Өgɢw]?L ʃ?5>(@&%m23I V09ũe[7H=@z}F&J6%UibF%G#LOAstݵ љwdzRk؝FBod$j+=ҡyIpJ ҵԭ|,y02;F^J@y&[pKߩ×{}RM)_6֢Vt Y8/iw"bcs棂';p8Mv?ضbRw:i'd@$I-a4Vي@T;DU&H(R"X'-{|64Y֠ho$&A.Qgø7s?edX9-&t/E SEJb{ ]GG[\}{¯Fp,4߿|EOo +5墑@Sxb*=˜}%? "_{} $E8tXmrp%UzJC*(ʃ"9EIy6Kv)Nb7S*[Vczbl܎W6HBUkAFo;inoTJAyQ3ߞBM4h:JvmA"~^A)A -9{!࠴v<J7l4 Ջ z#GB+ :r5vl>4άtЁ=k!I#4B-; bmL"[_@^Ov4З9;wm"d^I\9Ԇ!w~dA30nޞȇ˼vw6:P>R= l4ħpTR*,tm N}M~ $$Ad ݀IGFY:>[tre\󊁐(`B#W`f۪@ n[LN.d{~!~Qm@3ar aM%@c0N>ĀXWBG l# (y2U{z&m+ZPB b .\}C$T1m09M4!cq(bkIH5-Lѱg7/T^\tjƖEx=t!CϢ;&iׯ9C}f-\.N%5n/9EӁxp%4م(4:yS_c2vd</m4VXH oX h>}9@GTYZ%[DzKG9Yٮ;?@N/J-[]ϻ@tiũ^yCSҷ[eEE^Jq y*t>NۢA͐]7S/qQ;6IvD#`HTY8Ʊ7'irIDzbӄE 8`jRjMeQI9bͺ׮~y, FvN]@?mtM1SNž3doΛcnW@tJyisx MS_V!(凔*:[2"zn-E^N 2RJd0_XǡGX,yDBō6$hxi6H0`",zRacLǃA[ &)v6ntw=* +fq@R^}534%]N93%/`mp"9[L7p 9,qD=+"f6*߈_Mk>/Oł2jB$ZU k D^38k9aҟ{Wgx P eW1dou:[{^[`J٪|5)O3TDt!qޒ ^ TMmW'kK@8 ;6H|R^\BIIxXft,<_0ZPO?d\[ߣQti/w\mOޣޣc=Xp9I0àJmUa20tơ=8(x눼};N)3hr"0LP8a^g:,=b`{[〟q`bOmCC@_^ylϿuaʂA֜wgQ g3mhjI Z!-gVѶɻ7qgD Ag+X9xzV ;$^&+`ݳ.owu;)O Ck>>Đ(줶w `rrVLVcT:^ -{TU5=i6k/h FGG83fnpN;?>GƴĿiu4NfseV9#6PʞI k8G.ZN4{,.#S6x Y{jv1>}t7ȮF=;2.+)Pm]g\e5"Y*bj,=^0M6jA uaYUVZN&{vCh (#ᖽCd`Q!'U%"UTNyz}-]q㪇P)#7~9yw\6tYzV~4Zۜd۵?Ϛǰ,MZԝH?m+CGC`?bD TN֊ɂiVJ_4 =2Mv Ek`8/#5se xMO/<6ј 9ľ>90Dӫ̂LSM+44q;-ժv ?&%Rw)#t>d=PR{`Xm)g .97\2ݷ,~"&kgĨ߅վӏz"1_h:|L Zt9hwFt !8O x4u%t^debUcu\{ n⠕y laAAvXnrhs Aݜ<0إxvF%IḀr [Y9;~?zW01+˾r`/m+*(@eTW*"1^`:pv yYtF 6.E1BSx58]\vjgrڜmJwvEI#}i1L 0ko*P,UtAWMI=rN;B, *F0؋L16QJ,shj*Z!T,]16у.VizBOr"jU\3ubxY͙f-~軸B2^.g}dL"K }jkJjlUFg . KD TCi4D$F %Pv)64ZSa3-vQjfm|.suuMge>ew\D9ƻ5ĉ?{+Дsu؋p_T/ R?a4tb-Y3oyy/XHkTtTS7~:ߐO^cAcdD%1fREgSf) RRf2:dVɴ2|KsBC>@3x_`1VZ:~Kw20y4~5 F E.IO9ywy8G\tb!}͡'t9^LXp*=*zVOiJM,vJ@]]YLPg#ovC3 AM8*ٙ* ?8cͷs7Gߓ9}1hu2|h58L{*eFҩ.b_*TU!ynY߲rx{eba<= _^hGm 7]ۍ {/jDDCwy>HnwѳG3>$$S<of{Zwa{P3#E%NxLY9u..aS(j0q50I= ",4UCq۶O i:;Sn2z' ˨uiXvn7('>pOשLUo\h<:g-zZwR줊Ahe?D/ 110HjFc[ڋ "߃&}'UDQnK<~ c[̚sSY6m BVP{TljX#w{J #4~>C#qGG)os}m(M?pSQ)kcw07gPYqURkh4OD-3Ѵq<N0yT# ="JB4+~7e h{h=5d4S_zI&ܑ8y,Y)%^'mBH[3^fc7mVǠo4@ǗKM:!៲"Ko^f}M̉lEԧR/{՝ ezM8s6A} 6j[ԋWD-ofU6' >-]2]H?,AEp4ʎ7~4>; >" ʼ4)ߡ腙[wZRAV+?8ΪRHr Ke)NÇ6GVYSNM@/\B>< NP/'=vY?P3Qzv&Kdqй~/H J6_]c8At LĚSM6c_9b.lUj-!*;8,B)ܪ E!vs]U#/ItpUQX,|J endstream endobj 31 0 obj <> endobj 334 0 obj <>stream xZXT׶>ȜcO4'1`b ػѨ`HW`3f`u }@CT,hh5F1C6} h̽I{{{׿gJ"Ȝ(6RxI" !,Ǚw$@_)Y?tD°Q49DhsPpLpל'Θ1~AO~gv@p!~uOx W;WFx[j<'T' ܓ(W1rNAޮ>+Fߢ~3bǚ%;ݖFxܶnkcƎ{}քAq4yƩ}<}׌>)j NRSR7pj%@VQHj5&5ZC-&QQnRj2@QS:ʅJS)'jrCzS}~Tj5zRPxQ KHͦS-%RvT5zIVXP413I=VF-m,iS(%ʮ hһ϶>6[OvSm6pA __g}^bൃ`j[j{W;.! )r/u|}nwS{9a7d6?{xac7FȔ d:{/M7 ns\= C 8BJ_U)(2r歞L",4I.lz:K PvamA!4~O=PJXhOm| Ez [ 6х1JO-GV$Ej <:/VtAMnMY0|'G1dxh 'ŝDXJ.^k'׶@{%@+\.{`aG{xZCԤIxf x>Ԋ\kG<@ULdY&a\ +ݝhCh9CĢAŒI\U"k\J;w)X06 's(><5SE9[|F* Bql~X6i8~~?IQVD2Siij>dڛxA x#59h◆0=Y1L=i:5X䈝H9{1x"rFkh;~r?B/Mi?Z7g@‹w424 Ar_BL+]i,Jd}% a$xj͸U vx6͚!by'"%З (1M'TxuŃJT5xߑ fag<R'u~bG2UVWHΑ^?_p%yJO}+$P;;E]~/CSl,~Y jur/v J00w.|qurCLGLOSB"K(1 w)텄'xz߼$>!.Fް>4'msf?X, @}Z:n}1Fe^PUWt%Mڡ޾cwR.W 0˩N3uw$MΆ `AoxV5$Z`4{Y{[qi|=.Pf&t2PL}5/DGcքgʥ"e/4&VfCȁqOIms&*!UVȃwfPJ>NݯLiKXRW➨XP`ւ c&oZ_%i"-("fƳnH;xԟE- !:ˌ?~Mfprl0KnߨtW]c {/!E{")B^hK?Q~7ܳ#*h!4$<Z&EE>fÐKL3o9J{\މXC;=ýR2SD ӌ=Y]N*<($"28"PUav.70Os&Nv(]z]#eb|J)-mpt'hz5##=htOvnØCunv-s+_шI6mfSVWesAKP[[*?RsP!EHOz_V0 8xJ|o 6- H;tCx@4,!- G 솷-& 56DCȥB`=Gj `0imHO^Ld񺇡)>wYFInW &FIW4A-D~HWZIJ~q+^mFΜH4W _GC{[}v#=ܞvI|"M $X$G1ץs"'_:י,񔓿9Ӄv[[9ڴZ40*C /ٽӨׅ0w8JIЕ.Uǐ IDKZ HIWŶP 2jL Ro#w>4A:?^Z#;j*VَAib_nWV7T.;@Č|@3%ߡ&p~^ v;ڹOD= UdG8Aj;I9+A2s!Gb4S(E:KqzU8w':nI măf.Z$N4}>$;% 6FV\ę_֘$߶K'%tF3mW;/W4Jӥpvp֏ <pc73Sp0&'# הՈy q>4u ԥw#O^ =U,y#o4g57roRUEY XBO"~CL4q؂-"bKGL1Y0v3tL^'*gqZRz(Җ̧4jH+ZB+%P*JPra͡2s,@J;N c;{O5KWPF'2\G:$-P5}­~׶r.sP;=E0w1Q@m,꾅S ފ;a!IO5ҍ߄+%^8Z'RשpU[ o¼Dh%z8 rhD*H;%y3XEjJb2T}ZV]`͖dOE)j`rFqa|ɑrRNT1O0 ˪u oPJ=IUd"4o *"&В8$KmF(i&혆>f S_C}Dth-f2Ul宔UD0xsUh,?y 1:)@xwM1(I gy`>?pTGڄ nJnOcY<2j'ѡsTATa8BDuE [l "M rhCǺ#YշhDwB䃻h=>XMϛ/qFr~wERHSPX+'q*_/<]y#>Q \ꒋŵÊ"Rwk>s>!ZZWߗ_;xzE \;ldV:u ^ǖOn/*$.! \b+5[Ej}*!$~uFU,M蜔 b60ɐmL-ky\Mˡ6E{Nl֝HX%;ԃl^^!-{&$4&${{z*Р2ql Q2p8LJxoqO! 7}}Brߔ1Ѐ@#"*K-|N-fq0A}$_r17HɣO&Gsѝ_bė训/Q65Ջ#MC"6E{!;:z,\g!Ġ [SiԅF&B73Ð{0?'*Q\ .{e^-`o!Fr@̡ ۂrKo-,#LK 2 `0گ߼߯ըE6k Цk4IJ$ϧ<;X}NnZ:ꘪ؃̛nT3>yrMRArYS")n3 #`Z8ak3C,Y! 8cHȮؐmC 0 =45qGH 'pUeC^B3g̤'s /*0OʷUw_1IvI6H |NOQۿNUԩD.j5&c̤fe|EUm6$5W.cg&]Rq'`}q@qQ*__4lʅ43\7쿉BW!$ϛNgH Mn(NM#3d< ;XS V=Myo2@'KxQj<ɱyJRyM xtA3b'Þ>\L}{r=_ҷE endstream endobj 29 0 obj <> endobj 335 0 obj <>stream xmViTWQJAM75.$Ȣ절"5 ⎊\E ʠ"F(6* (6B21I5y9N{wєE4ka) Qzgz=+Hύ2ÕA$4x]L*.|mXDsX(Cƒ aeffe!7[1]261!4LMQTUtvcL]l5nqk<}6(Θ9˯,gϡ1 ʕQc)?ʍZD}AܩxʃZB͠<)ʋrfQޔ5&Q)eKYR eG SCO SJʄ2FPH(rZi3:~7VOW'1KW_+)]g☳̿ylfr8o `v' 0|ojFQN9ԀbwP(k<ljNR- RgZA672Ẃlz.eZ+xO܅t)9 cyt`Uֽ9hXll4^-(*jUy#˛^>,d[T|YͤyO!U0ෆ'&LY;wW.oW~gl/llDQ3(j ]V' e3:Sغ4'1d*(T4jA[Cd0?iڰA](Ңg2<e9f aAs._%B?a$__P6s`;Ak=nE[ӷ"n~<]f>.)?c}N!oW?@Ƴx{Zk|~JQq)h<2HlSH\D-?鉸vx bAUYI<ڌ6E&mOI@E;ʪΨ$^)=O$ϫʤXD/VPLSЅ_#^&=}CA/LI{{t}Dcɻ\B∇{ eG.ݓ)EM2u]Ş|5n6LI0G0oSe0WҏJ4rUĽxC/}]UkU6R-+?sB5Ig%cO\t룷VKCi0bxTv/fm;k"vOr7 ]2~!^[3Z|ks֐iǐzE. 턈O'"04po<,l9;a #`cl`C<~.Lȴ]}jaϙ&pfJ9NӲ6wmAu);Bgnza>$R k5V 8`(r+$m9/k`d&"n|b:޲Zv /YW[Yxm^'%֊}۰dwܡKY[ %Wq&^]7#_n}WvD*d %o_)ݐ+(ښ9٨}1i)i(oY_-V^zJ5 02h30(x ':=f,btS<, s&"`,ps<# X.Z2ic{l<Ͻ g</j^uD,.~}(d::OL0̓q]L--xome>)k<.h!B%-Pc)RZpgӧcݑ5jO36J]Ƞ?f }p[26ǃH-ɸLd8| a^ ӌ,۱BI2h I>mK7rIG/;q+$ 1c+̅5Uzyo3zg%'*W@v. ΂L ! _3D [jH$Pco`=8qi+.CC-6tI(GteWQ3z6o`sŤXYܤ#I%OE Xd#wsswTpB&\g/롤 b44% m|]<w+͈^ wJ+CkA/|vE#jxm"ŮtK>LIk[3]7;t.u;3`_X"u?JmԀ=#"N^v褍Ke%dW^&|2_٭:yg;D`s_O -#; |;AE4mDxL#zU‘X#/+n@m tadY0kTΦopAO=l~td\qY~z B!($!xCT\4߷Ud83gʪC59<ҵXÙ'Ow8&kdS2#n$o60CJ|cA ,F.%XO*xmaTǽ?z\&*^ dgxʦׂm.?o:ֽ cÖ9ixOҵSTǟOАj#@ +J5^)+ZXwAqnK9Cu/^߉GL֢S1Τr~Vş,Q/]._RTP~Dx:|(.́ b5~2C}UA>##A.i endstream endobj 213 0 obj <> endobj 336 0 obj <>stream xemlSU]{(d-B8R´vzê:nL{n _R&]elv3u6l*j|_L`DcD%Y2o!9_I~`ŅP'}= Me4|Y@c(qU>a$Ӹ L8#:x/Ͼ:mhf)#;lfjIRCi8gy{p5>-E=Q?tJ|\FuCۉ^wx];ݑĝt-ՅJu|@lMLdw?HN ytF* i = ?qZ-ţ0r&=]sJw]V2b,¢w|砻Hpb{^ba,GIE&1f1[hٺhW9 d8[gWT2*dkn_pJK+uU[Tb`K50x$)f: _ˍӪ) ;_X̪*vOP%~^Q uF5=~/~ cFd:|:Vu"S~Ű~j.e9[-7X-#+! endstream endobj 22 0 obj <> endobj 337 0 obj <>stream x5kHSaΩv(Ɏ jaM-C5E7jӶlM32-tKԼ;HfIe&}1PߞQ(D( ڙcRU2JPР y!NZMQ;lRlq BRjV^ :BAotZs: {lVYV؞/f>X$:E̮V`w9EDG!B(4i}"P$bLĠS>U7Gz4ʏv`8wWv'^> i𬙝r3ǡ"jO5^pm#._fec}c27&hK̊ʪ[X[k13 Y< YDµ#CΓgA[E=&ɄV pN_J|:jNv:P_#v& nnj2J,7"u̿{ <2kc7'F݃^wuVy:Wkm'HYB U8lr /Ƒ_ɜMr8qYkUzى#OJ5 bFȒw2YO⁧477 DlgQ%[=%}Dz(~/` =Vȟ1zmzWZ,юs'n{74cC$U_=2y50T(Lv[JΆu{Fxw+zI-\xMMy<~n֫\ G/gd endstream endobj 181 0 obj <> endobj 338 0 obj <>stream xe_L[UmAftmQ-Ddl2pp(K)tm)-nݶ (؂ Li%G)Gr۵ b'9痜99* *7_*m>EddK=W/depT> endobj 339 0 obj <>stream xXTT>cz"sD%vQDT(M00CG`~z 54[b]I`i11yfܟf[a83{GDY[Q"H1e1" + \i@7FB`<DVmv 9s0eΜYI|C\e~{e"a]o,aqp~~(=g; I\CwIC(jqF%1ܖyOvYrYAWʃ=]l;nIN2괄3fϡIԛC9RoQ5Իhj5zBQSLMQ멕tjL?i?vA_Xɫ{T^tba :)RRj.KN6F5|^z|4,2m =,lx, Q/@snæ'aăI=HԡJ~v 6&�+=( D|'lyiQN[:mbHͪ@FC+Lj9AgGRJ¥&7{|p^gHrvwLeAh*B9?@ *a"_E'Lzы~0@A|I;N.eD/ayKo2+ϔ]<2VY!{5\=>B,:h׋Na:AFLK$Rp!Th$knAU\5Jp$1)5EVJYIEO(\+:S, CMa&ǣ`7٬_\/'.rz8?AM&(Ĭ&Tu)#{(QJ_̊ +6vEZTƢüPP%1q'knU] /. DP}h b!D˖huRJ*TFZ:`/.`_a6EXuL:CǤn9L ;-" TZĴ -ߗ7Vx]/jkKba:xJt9H8Ŷxدa0'M VRTtJFΟ'b2Z3_nfi5@=d;Y8UsT>upp;E$H8Gcߩ+ԜXYG+Z>icd#b,Qkr^"wqRnѮ6>7a*L =mΰSyMZCbI, w4Pw)W0L0ZPZ?:5уo};×'aGfT]7\a;t/>.ITrAS,_k% a- w+rvOM~ݠAʝ wtũKIC%(t;w. 1``xns?ԭeꛚe+Ҋ^h:RDVS=4ax  so}ܟ Ȣ C(=WtjB͡QD=@ʀ8K+{#S|(wo-M,`0.kn^^{݄z82@*gucGh7 f~;Ͽ:uol1%D#1$u[cx%v}߱$Ur}̹M]U~,Qf9.CVY47g$xJ8v"ꅧl BQ} 1љI"K _rT*KZymV[E scڂMfW5gp3lnQJD{?bp5v-SZZY(Enf8ViJ5{L\7uGWRt|ݗ;eGcjd; >G38;Rd&EУ ȋf7Y o=rXDZ)ѥ*4@QKՇsGn6qPru"OBo}z\Aܥkgv` H`6G9iեlQ3^r&%îUfWu)߶h$Uަ-8 zD|2M1tLh|.61>}: Smz7(6kUB^t Q,F1~Bc<]ZI/{># ,5,#Cuk =m*&qSfc8U ]le,:.ԥ}ˣw?6TOTPO/jj_ѷNқFCŶm6 "_MV 9iuRU#PfJ֬zof$hWd&FH1 DRb[,5\s^2I57׽A*r[2fp('#CYQLjHP&}m|SnYr㴁g#pyfn<KI?f JC̚G>c? 2dpX/ba5iA\|3ac{*{ #_v5k5y2:"H j,L 6 G2' :i%})@0by%`96 ܏@RK :G,l6 4]a4f (5Q(1{z#kq$(d~e aaozwzLQWR`lrՄ iCǝ0%[Mq?mm%S&,_tѮg8K Iba7:bs5U;dWA[ݱ6̔:)J&( {Wԧ?(&&S (j6K؏ TgyiR][BQYGڬ Q5dP+hٌdlnزݳ`{˿/8NQU_msOQ НE)  IIa^6*f ekWnuDxt kɈ)/_LyBVBt[ӓ/.S$'+I8G!lq J5J`sck '8ݺwLߪF !UbH$Ɣ?= wCk#r22sMa='jG[܌[=2&O 6bƶՄIA{^HEaX6+/+1(e^5窴4}Tyb.l_ |4˫ǁh<]d @3y*a_]2Vayɵ[BbT *N#35N™ĪcG3$2q&7!aXXF@0zB&T3<-mA-( {H[ s̷_C%qWcK~}@=Â鳼VTW䪳'koq^퍮r%]љ6Ⱥ53 %׺NBIf28 k+Qy ć!MN@Čqj=b.57aZ[R8ԚDw f Mҗ0K/=`GyNAJe0x$m,)/;ۧ.ުY{읚Σ6۸7{6ܒqcuG >mܢv޺ZnoX5ǗgRwVr,z.ȚMB(4+$*uq ٦OƒOg"LMwCV=.핏{zHҳ"2T bV& P= h'7 [G80pE׾o endstream endobj 18 0 obj <> endobj 340 0 obj <>stream xZTT־kW@[h5Q Ho#M`){f ,[4_g|jFc{ĜK.kyowbQνWճ%$8N*|7*{b/$++=gÓTOhmCBcwExis;yt=;=8|CNȘ); WD w!AHkBÃ7 r(qCL5bC]mݒ0> ],rr+v8 tߴ*:c'MSK͟>cαqgOLQ%=5Em>>ޣޥFS멥TʑZFMPXj#ALj"I$rۭ~QT GfS5qjej<6fn'-H'4uZBo 4rtzadc@rO֩JPmP.n4\}pk[5%^zY[VX.k)n.-{b~zV^<+HM6bY/ב=XE{1XkȬѤA]er:LB ғ @) "Ԅxe|cU ]bI2CS]%O{bٳDުUnF=.HQ&z6뫠d 8$Ct1ɑffrm-6p,B0?x*MW0JQ4UEb= H`J+ŵ-.@<8Ġ!uoNP'iTJ M2vUb}:E|X#)P[i!(C:m6;Q2KeQ ^iiýPY\Jnilyɇ֊'g!SRAb2q˱`YxvÞh6֢9!br 3A=ZY25YE y$z81. &Y& dZ+_]AEwm_[shq`_p8xze&Ё3=/}~H:99U%>܍kJWYkޫ;*8.G ZI˄Y(5?huOBҜd}jF{`+xF6Llb/0/sP/᨞(׉\rLH Q\F[9m&%&) B]l:8ޝHeѓ{s+̹{',rIVex2=;h%f NCF(4j %9 _Va>/}!nh_ C!C!G<M dx gl̾.M|!ȏ/9Q,bd8zﶨPc:UAp]0Ped/X쏲ǟSϪ<.?3#'gcs@Yf@,AC@L<"!> Ek,z/Zgn4uZG"b"B#G !KT$@8YUUSh,oM#8L o~] wBa!'UqE^Q¢Q_nm~2ZB n@oJYT4FlsbfTonxJ" Ȯrf*PId"p7 H*+Ajc1$8f7H`Q[.o#=bR%SZ=F%Bbm.ȫ q[-D=h,MMN^=ʐ{eʬOD@n4Bv&(VȲʪyc#Ceɉ!bKyzͦ2YAUR'f'yE*=9zw)K~j%K~-QbY|#zxVC-ܦ8F7H@AYAR+;f54>G=aӒ4 il]iXF Chx# xk.qg7A>q1 E.B^Yx!OчZpihut<6te{*}L} 7CBa S]wI\j3ag6_G?,lYSu ]=uzߌtJPvct#EMLj(& b8#i֪H ӌPTCBb6 9{K9iG555SMPgoBM ez<ݞ@NWf֣wI dHwBH3PbKh!GB^_%ZRPKTxV {(Fr!\y$]^03amCwԊy\$vg2yd0C,R>^Duo<࢏&mn$DCFRlqOT'%D>4 y.B2?6#^mI*zuYQէfҮɺxUoNv {(( SߖQЬmּ7GnXU4YUXo|@'fަ<aޟ{W Gxҏ# )s#dC3pH|5;}tn$0I9z,/F8ݭ6)9_D^mec1D3ں?\z#W"-pUu&} &k?Yl]"Eْc!ro9}F9MjTm;թB\-t7A&'!]= NBVʥXz;y4;zgpL#ڷE3]"Ķ{jqBk HHV+5Jc-9  P Votu>>=j0~4?EˑCV_ 0u/8ήbF$$Aܞ=r [tX%ӈA= lHND /3 #Da0:GJ :ZXYDy&ZwR&D+LM&MVđ-'*̷}0ɰlcz Mg]īӶ{Y[uqvܾ#. [tDZ5䆔|(sM?xe)oR$%3z3ijkkNBOcκ5θ;!wǛywwn9{u޵E ~,w: ֭}=K9 E4.hYpʽ+= >u;vz; 3x)%$=.!e!N9q_&PK$ VuOZ?)ZJu2!΄[ȹ֐dؓiȞOEudtҮL/Naɡx@끴h> @40*rϴeXHbilu24C[[ o#ZvJJMiqg ހ%x NH e*#gH1wCb׭sMP3:lVb~2eQh:T/)Ҩ(p=!*( $m4BiAkN&0Ѳ"VƯ Y,S*ZP1)۷})/&4,8(/#+G' ;'E%bTֱpzP%FOxuw6b~e3/MVīQs[@\N[c- bxR;)#_ FcA2uLlJnn5EYwż_}};EaS·aaڴ޻uN_L~ n3_g࣊o | r֩RFvq9`&zLj$Ǡ }̬\cJbJbv+J1ZsMdqb>-}$f $Hu m:q L>:D=M$kFSEg'/HVҍB vcp㯒ݯ1'&-c?!b -b%A){v$ ~%^; ^!ɴ/pl PܐRS闬+T9`x6_!i᥋mP?nE=g्SSu*՝g&Yn9b4sݜF`ZN˧%jևʂTkH֦ha#P(2;(Ӵl<4ma~T1xשOW wVe:Xxw5j䚍jdϢҙ3nЎ nNv#c/hSX~;\F\ZV- 5˪whܵ>|E?L¢>/0-ϗCi>8&4 uzP$U-j9xK)٠!!e@r c SoHrN} '%+G[/Cp s!dؤ /(/Kque1"Ȇ_&57Q6~tqew7>B^OV>v [%[N 4xyr ;wjw=2C1d_1K"7%I|lP|] A畅1mg^<*: k,\lmm ZBNv^~!z 1reˣ*BXY!搠cXm\d#6 [Cw.#̋il%NC.$7R۸'yh!W&~a 8,zk<"KP-=U4R&\=HCm(ʾq (ae̎ÇPwӆY D}f@#*ļ{/GփO4&`BJ28PhC2=o{>ۤ .ַ H9yUmvŎ^q쟛̓g}aJ~G3^Haܐ?, Y}sF!V.VǶ n r\ݥ,xW,ܡwɽ2~O#bt q(NbKD<.(k)YOedg7nyt xBK2@(Kmc0,ޑ\;'x=oۙK+E. f@0WӰ;:j$h>5nDh Ro8 [mȁB?!F pI ~Y(FA_9uBJ7s|.?} 7 IBHi;/_!5𑫷* nڐ $lƔ쿢z"+ٝOVG$J]xU:i :N?k 85KM Uv{VCT`cwV`&^DGXaa??.oH 4I򼸒T?1R ̸JGm}׻c^}@z endstream endobj 179 0 obj <> endobj 341 0 obj <>stream xX TSW1*8 wSZZ**-T*u@E1 !C<d0 (:[i5j[SAiZD?+Yp9wso}EJ$IW0;MxZ$L!8w_ r#'In]3qX$^eELl<<4L1yƊg']e!];'Tv* j]!&/D!!rUn+bdJE|_y4EQ W/޵+i͊+X;>l )}"7v.9=1w =_XPMVRg-ʛRsiT嗦7ˑ1,'ң.~P+TY-ӵ-Ģ EB\rU_R)*ͬʪBը+(:Vڥprq*#]5ƴ]LeOac {p,XӏVZ3J-oҮcXQ@mӖ4>Ů+h7O&5Xz]ag*Q6iRFz {}ܫR$pj䄱P-H\6H TlMQ,b^L2FY' 14̫+hEUExE:6: }fʍ&vI,$:"KIsQ~<}n:;/<Gi g=$>1 .]ض/Jڛ܁3%f&]FхXX X}#Sqt<yvsD%f%dM3b2tL% !Xyf}&h#n X8j~OXՆ68`\Gr}3..k'/vV[;ֿj+i C+6mSC̰gM`_7 jip&BXfbwKO{)HHP2x:rKMg' 7,KyuǠVfkZ-h~?{Ÿۇqi+`dl!7I]A ( 24r!?& igpnp9ͻc^O{y5J3Չ74tW)=>D'z Vr)-ODuaIEg5tOS}P{Ro&*ڈpZlQ[PFLMD 9yE9V#_#L"hgaמP7vy`PalH?.!e3rVQ.DZfZ:Y\W76&9"sYvv@PxQ8IS&uCm9Ӑ[3d$﨨+zC#u}ίGXQf^-53ȤAΛV]ǴӤ#L"es:~ =Ft~<ë%"hӷFԁb *D;/5Fړ"Jx+ߓN3 Ң*0IB6Aއ;T9D(6o @̒W0_nw_Q`ߛTj%CT夅k];3ৱ^+vwv4x%R[(h5/:1'=$dnA\qIq ctrRl0WM 64t̍G\㇊F~й)'S$^ɫ C$)va.WM@8#鵴P 0u@HsFE Ɩ{5E. #3PAEuϬgO:v~{j8@].v  05DSp1K-3((_);"/>C充5ը1Zɻ«7gMrY). ְ/HI/ڝ2|ޯ{`jY2AAXꮩoQ72J:;>goR#6Ԉ*zlh 0%C o~֒p(n@AZ$N67!C!=F  qdee'7_[Z;l~%"&v |YŔ4Եwȩ#M5IJ[X.ɑd)c8dxǓ$ܬYTUX} 8UC,,fuwT_SPXX7̶n_f{d!=q]Z:;VWD BcٲBʙMZIJ.@(=6Ig(.冻&xmzL xv>ԪyD&q[|^%WL?ݼѳx:Gd}0CPjmSSsU>a 9GJxHmئC4Ԛfdf -c1-mGNp}w*iŢdEZDLrmr]eiIiZWr::E:P{]Sv5X2 #nA ]#*:9(]5~@ݶ^p.G9)jZ 2,?Z4BR# ,tlڞd`=d^/`Fi"Rt5+ں4'|_\/u*,c/W8 ~GR[ }ځ<[]=tեO6.Aڢ =?p"88~я_ UK Jɯح,_t;^[gs]eI.pF"+s%sxQװw/ax͹))zFFHk7AZdN{n \݋,D/z K?gq/Tl\zn)b]xlXdŗ@j 8l:ҌY(KJJQ=Ӝd +a<ʱdSbl,Lߛ#Ξ?rS%޼{c uQ e|rQq"nLZxCˤQ&GnCbHi4E/0 endstream endobj 162 0 obj <> endobj 342 0 obj <>stream xECMR6$-  0-*FJYCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMR6Computer Modern2cOf}I|:}OŨ˪16-X~_ȱЋ=:D\BEKmlGv?oa  7 ޜ  endstream endobj 11 0 obj <> endobj 343 0 obj <>stream xW 8Uɥ4fΡDBN%Ȉ"!2E7iJ.*]gHTHdL\{̷vif}=ǃz0i״¿'*"*o*3H]ԇU-Ԇ?GBLAhyMl\r"WLЛ6gULxa!+\BVEDŽ"z^a_Jg)H OO _lؘի\bǯ(*yEإ6qn+#'Dz.Xjo_51~'N8JM}LP:.Kpʎ MIV=I2I%IU$ 5옘ۊ73LD,lݰYҲ[R|[BLַ (.0bgtC)+ ytt. 8PPPsYdWn%!<6%~s yL5`yssŷټ?zr0 .r-> ]hs)J} 5!i<=%a~NdZu 5>7p@KC_G] pwm̜0ABDHTc I;v3*x$#v@~on8L 8%XHj/Ng5и}VZWKĕ2 KěY&_a0b' \ /%AKBykOV%E-U}y?BB!J*ٙ-J`倿h)\&۩DzoQZp|w#,?>)xi9Q 0)`d{%+}(;[ xB醌nL>>P/pɡNd%a(;.mb*Lŗe!*۰Ijj^^ac 6sݚ]6唡b<ؑ_kB#H_s6C ]ϻSY cgx  \0;F8M>"`aؑG+$NΎm=~/]01DOú &pp|/I`oDZ 0~,o/䬜#0?;Ps%Vϡ5(7#5.4bAӟow^ O .X񣹷uJʌM vDi.6M50GXBr+p׿f"ك~8va ˹N8Z }>b9cGyldjoRppqe0|›(!gChsN^N-d4A rG ؙۖv3*Z1%҃Q,k4AES7Y(T:I Fue[wʊҏAlgc'Zø+kkcOJ\ @s*/nA׺' ]P@51)%PwrIA~ Ij͏MpCޒs:쓷 AcɎEojJ?1sQZ>۲C ]*4}]Mq"&ߵ`v]r;_+G;ѿ;}Ҙ)X 8] q+^ʦnžA({p2o/&'X[@) )C_Jr.s8 >u %w\אs0E6![>n]HIrc\ǻm SAڈ021{;REzpd5CNӕ有I?Oܻ SRm8#)'se4LMG3O,̪*J޻EN&s+ݥfdx{DW/.^P(>u¸rtm٨dž[;b1|݆Rn>[ݡmWBJ?PKpRu30C-_?dpC! +kEoNu3S`\ D;["(̆) bzP~ $ݽ0'V\M!*Qjpឈ'݌38x >P/MliHC^oy+Ȫ0Ct"Dg͸ᠴEuٟҖ:LgZPdsuklg` 9ڍc6l_Չ<`>]*B\P}N\F9nKbJk7"s5ֲPɒl$UK#Pt_UFt0CI(!*)n٩8ͲUCT'!gH|?L/d,$fY~/*[LcxGvMwTēX̋M H"^"Rɒ9bSkv1b@,)8*G-#Rӑ|Z:U]`ߵlǐ~֓mBף_NdvCY\Ōj>AZ@M^1Eٕ+>t"boF v}=JQ`ww]S'dOkf*[mrt-JZ&H [bLp7bu2eVQ01+0g 4N7A@߽I2$cq¦۞ċpYzN$#+$-#s" psrYj,>8}d4 㰁`ۨyPsNM8.C La1*z-J 'AkSWHҒQ"WIC_B_}qw%xFHLcH=">\#!y -xRЧaQޤ잕0l>_$GQQ͐ N*ÎWuzh+ 5\|Ev?q®Sc,+c%bʯ}G"~Rsc"^IKF4CKA`+Q#t}G畳5LJʢŘarseaftnoNv`/ۍXsvL wE[9g~l;01>}rZk z‚hOXS޶Ua(ggzip0Kpp}N( _ɕ_m>ӆo.;z6:oZ˺uJ~.mɢf,)IR}Y'Nl5#s pP`JԒKˆ7s`^ .T⛓WO-w qv@\ O~ QE\*A_f%f'Km 6E +e9y Ęp0u`s.+Ȉ3|0&MsdX +W.O  0o{;!B#ZpkLZa9_cm0oíeQ>'=t5FOXDj|{(`%(wŶHXRdH^řNG7LjlIt7v>}Π,>60C;О썚TeTHRc$ů\ƣTb:`@/Udo֯|fzW͞jݒ,5v@I׻mf9ຫn^Zb`)ï9x\xo:7r]<d+H7Ki)c$BN;y*$1 &ʱcMHTHlg/d1wӏo5T?! ԣ`IoUryzl1{mj9UQmgG/Py!Z3d:WF* ,3\͙Ec9w*_VOJXMܾ/VtIp_/3v8Vp%v{ bM\&ʦ~?T)/)CvKjåjLKUջwkP<*} endstream endobj 50 0 obj <> endobj 344 0 obj <>stream xuR[lE*1-Xi*BADiHiRYJ%IdP( xkSǏ:m'iV<~!UAGJH_ Hh#X Μ{=w h1p#Ȯ>2v:GF Gws<h?r' noksjk!3`p䵋v*8e>m^نX }Ž-ώl6eC'^nLXc?w7ì>5`99; n 0gu t (#S7' ܪ si--S{d#_D%f'O.J3fb1A9"X"Y[,Ndd$ISD1GqP\&U,ZNDE1"R((dF,jze%MU\g7ׇW)t Y)͈HtpBZɢt6yc%9Z Qdj&BKsub~"(FMM*B'IkhOb)rH?ݘ2ZEz rŽwUhHf$(.Zk?[YE Ӆi1GS(z%)#e=W?- D QoSmj>q=~DL"NXy9mm UejlDHȂlP61-)霒jO@v_j4m5WFL endstream endobj 9 0 obj <> endobj 345 0 obj <>stream xV TW18jx Vmby(QPC+y'Q{jt"7:HՅRZ2>K&3!eNUxDjDz9x%?1WCȗPCJ{FJw"/JN T\cEz^; .{G(āFcљ h]b,8k<@ֽG{  ztήM|$u.RK) 41쐇Xa/h:lխ,J߽uϦ xKN O_ U7$C5m2شj%ٹ+~}t+M9ml e\yf,.϶nw&g[wFok8 hțr>CW>#y"-V]f:hdK *_ 128ĶSX?t3E tnHn1+7@6 Ż"5o-K;;Kp)^`s/D7߀k̀P .JP("K_bJgwtK- НCEEێvWt15ږQ~ dCaRfZP uxc.>8vHpF!-Gj))G=dFňn ]LWv1=0D+4YI o$[kbEAԌ]WӒz= PQ(Hh,)e@_#\-q|^w9!KNS}+\.E_8h܇P#oPj*DDȨ<}vYK'$u|$jzȥUi 4ִGɞګ՟93mچ .-[r\*)2aR:>7wH=d0e52pkh>XsXyn`(Ԝ+7v>۽TT~J Q0 PL {Vu?M>wѠ_ vAKgqcc*SīxJm#ΤvCzѻ:b? Z[mSNswE1:ܮ0> nUZQ F3~mNa<*dE_A N.-M^/(A"Ĭ7 ' º@V)VZW-mϐ}~d,$(lֽD#^_|$ q \޾qϞw\\g u >@A8p4B[Ț˜ꪃ=@?o9CFҕp8Gd! eROP;78‘Ugck{=yM B6D endstream endobj 43 0 obj <> endobj 346 0 obj <>stream x]SiTSg}qyKVb[ U "E١ aUb5"*(U˱nNghܹwlm(M~XҖA6 Кm2d;ٽq`R M*O\)(F(#JZi`\Z,%|ޓ.}R-q<ڇ)47`r떕yCB1,_L]ҽek7 t|m)Vo?ܱsp}8m̐JkJu27(Yb7Hc7_ޛVɯ˟ƒʤF ]4' (^U}x|zy.2č::ԕHBŠ&K=y{IzY2٥ Y/ endstream endobj 363 0 obj <>stream GPL Ghostscript 8.54 PDF Writer V999-07.dvi endstream endobj 2 0 obj <>endobj xref 0 364 0000000000 65535 f 0000322328 00000 n 0000408826 00000 n 0000321833 00000 n 0000312040 00000 n 0000000015 00000 n 0000014088 00000 n 0000322394 00000 n 0000339037 00000 n 0000402603 00000 n 0000337695 00000 n 0000396134 00000 n 0000322435 00000 n 0000322465 00000 n 0000312208 00000 n 0000014109 00000 n 0000032095 00000 n 0000336405 00000 n 0000381836 00000 n 0000335876 00000 n 0000376535 00000 n 0000335326 00000 n 0000374124 00000 n 0000322506 00000 n 0000322536 00000 n 0000312378 00000 n 0000032117 00000 n 0000037616 00000 n 0000334505 00000 n 0000369035 00000 n 0000333793 00000 n 0000361284 00000 n 0000333076 00000 n 0000352058 00000 n 0000332522 00000 n 0000347116 00000 n 0000331748 00000 n 0000344203 00000 n 0000330933 00000 n 0000342163 00000 n 0000330119 00000 n 0000339834 00000 n 0000339401 00000 n 0000405643 00000 n 0000322610 00000 n 0000322640 00000 n 0000312548 00000 n 0000037637 00000 n 0000042374 00000 n 0000338594 00000 n 0000401343 00000 n 0000322760 00000 n 0000322790 00000 n 0000312710 00000 n 0000042395 00000 n 0000048026 00000 n 0000322910 00000 n 0000322940 00000 n 0000312880 00000 n 0000048047 00000 n 0000055666 00000 n 0000323016 00000 n 0000323046 00000 n 0000313050 00000 n 0000055687 00000 n 0000062299 00000 n 0000323166 00000 n 0000323196 00000 n 0000313220 00000 n 0000062320 00000 n 0000069518 00000 n 0000323316 00000 n 0000323346 00000 n 0000313390 00000 n 0000069539 00000 n 0000075420 00000 n 0000323466 00000 n 0000323496 00000 n 0000313560 00000 n 0000075441 00000 n 0000082253 00000 n 0000323605 00000 n 0000323635 00000 n 0000313722 00000 n 0000082274 00000 n 0000088446 00000 n 0000323733 00000 n 0000323763 00000 n 0000313892 00000 n 0000088467 00000 n 0000094988 00000 n 0000323883 00000 n 0000323913 00000 n 0000314062 00000 n 0000095009 00000 n 0000102962 00000 n 0000324000 00000 n 0000324030 00000 n 0000314232 00000 n 0000102983 00000 n 0000111110 00000 n 0000324139 00000 n 0000324170 00000 n 0000314404 00000 n 0000111132 00000 n 0000117454 00000 n 0000324291 00000 n 0000324322 00000 n 0000314578 00000 n 0000117476 00000 n 0000124004 00000 n 0000324432 00000 n 0000324463 00000 n 0000314744 00000 n 0000124026 00000 n 0000131517 00000 n 0000324595 00000 n 0000324626 00000 n 0000314918 00000 n 0000131539 00000 n 0000139517 00000 n 0000324758 00000 n 0000324789 00000 n 0000315084 00000 n 0000139539 00000 n 0000146493 00000 n 0000324910 00000 n 0000324941 00000 n 0000315258 00000 n 0000146515 00000 n 0000153756 00000 n 0000325073 00000 n 0000325104 00000 n 0000315432 00000 n 0000153778 00000 n 0000159246 00000 n 0000325236 00000 n 0000325267 00000 n 0000315606 00000 n 0000159268 00000 n 0000165036 00000 n 0000325399 00000 n 0000325430 00000 n 0000315780 00000 n 0000165058 00000 n 0000172573 00000 n 0000325562 00000 n 0000325593 00000 n 0000315954 00000 n 0000172595 00000 n 0000177829 00000 n 0000325714 00000 n 0000325745 00000 n 0000316128 00000 n 0000177851 00000 n 0000185158 00000 n 0000325866 00000 n 0000325897 00000 n 0000316302 00000 n 0000185180 00000 n 0000193139 00000 n 0000337540 00000 n 0000395506 00000 n 0000326018 00000 n 0000326049 00000 n 0000316476 00000 n 0000193161 00000 n 0000199601 00000 n 0000326172 00000 n 0000326203 00000 n 0000316650 00000 n 0000199623 00000 n 0000205678 00000 n 0000326324 00000 n 0000326355 00000 n 0000316816 00000 n 0000205700 00000 n 0000210572 00000 n 0000337106 00000 n 0000390348 00000 n 0000335501 00000 n 0000375222 00000 n 0000326432 00000 n 0000326463 00000 n 0000316990 00000 n 0000210594 00000 n 0000213675 00000 n 0000326555 00000 n 0000326586 00000 n 0000317165 00000 n 0000213697 00000 n 0000218293 00000 n 0000326678 00000 n 0000326709 00000 n 0000317339 00000 n 0000218315 00000 n 0000222775 00000 n 0000326801 00000 n 0000326832 00000 n 0000317513 00000 n 0000222797 00000 n 0000226625 00000 n 0000326924 00000 n 0000326955 00000 n 0000317688 00000 n 0000226647 00000 n 0000230447 00000 n 0000327047 00000 n 0000327078 00000 n 0000317863 00000 n 0000230469 00000 n 0000234424 00000 n 0000335046 00000 n 0000372867 00000 n 0000327170 00000 n 0000327201 00000 n 0000318037 00000 n 0000234446 00000 n 0000238683 00000 n 0000327293 00000 n 0000327324 00000 n 0000318211 00000 n 0000238705 00000 n 0000242706 00000 n 0000327392 00000 n 0000327423 00000 n 0000318385 00000 n 0000242728 00000 n 0000246380 00000 n 0000327515 00000 n 0000327546 00000 n 0000318559 00000 n 0000246402 00000 n 0000250337 00000 n 0000327603 00000 n 0000327634 00000 n 0000318725 00000 n 0000250359 00000 n 0000255014 00000 n 0000331170 00000 n 0000343696 00000 n 0000327704 00000 n 0000327735 00000 n 0000318899 00000 n 0000255036 00000 n 0000259767 00000 n 0000327862 00000 n 0000327893 00000 n 0000319073 00000 n 0000259789 00000 n 0000263200 00000 n 0000327996 00000 n 0000328027 00000 n 0000319247 00000 n 0000263222 00000 n 0000266371 00000 n 0000328119 00000 n 0000328150 00000 n 0000319421 00000 n 0000266393 00000 n 0000269584 00000 n 0000328242 00000 n 0000328273 00000 n 0000319595 00000 n 0000269606 00000 n 0000273063 00000 n 0000328365 00000 n 0000328396 00000 n 0000319769 00000 n 0000273085 00000 n 0000276639 00000 n 0000328488 00000 n 0000328519 00000 n 0000319943 00000 n 0000276661 00000 n 0000279853 00000 n 0000328611 00000 n 0000328642 00000 n 0000320117 00000 n 0000279875 00000 n 0000283090 00000 n 0000328734 00000 n 0000328765 00000 n 0000320291 00000 n 0000283112 00000 n 0000285241 00000 n 0000328857 00000 n 0000328888 00000 n 0000320465 00000 n 0000285263 00000 n 0000288472 00000 n 0000328980 00000 n 0000329011 00000 n 0000320639 00000 n 0000288494 00000 n 0000291781 00000 n 0000329103 00000 n 0000329134 00000 n 0000320813 00000 n 0000291803 00000 n 0000295446 00000 n 0000329226 00000 n 0000329257 00000 n 0000320987 00000 n 0000295468 00000 n 0000297821 00000 n 0000329349 00000 n 0000329380 00000 n 0000321161 00000 n 0000297843 00000 n 0000300237 00000 n 0000329472 00000 n 0000329503 00000 n 0000321335 00000 n 0000300259 00000 n 0000304700 00000 n 0000329595 00000 n 0000329626 00000 n 0000321501 00000 n 0000304722 00000 n 0000309813 00000 n 0000329705 00000 n 0000329736 00000 n 0000321667 00000 n 0000309835 00000 n 0000312018 00000 n 0000329780 00000 n 0000329811 00000 n 0000340329 00000 n 0000342385 00000 n 0000343889 00000 n 0000344616 00000 n 0000347425 00000 n 0000352486 00000 n 0000361793 00000 n 0000369369 00000 n 0000373093 00000 n 0000374353 00000 n 0000375460 00000 n 0000376943 00000 n 0000382349 00000 n 0000390768 00000 n 0000395713 00000 n 0000396573 00000 n 0000401605 00000 n 0000402876 00000 n 0000405949 00000 n 0000329855 00000 n 0000330552 00000 n 0000331316 00000 n 0000331403 00000 n 0000332186 00000 n 0000332954 00000 n 0000333574 00000 n 0000334344 00000 n 0000334961 00000 n 0000335787 00000 n 0000336312 00000 n 0000336956 00000 n 0000338199 00000 n 0000338329 00000 n 0000338876 00000 n 0000339745 00000 n 0000407502 00000 n trailer << /Size 364 /Root 1 0 R /Info 2 0 R /ID [<2275F163D31ACCC3B4E288CA3BBECF50><2275F163D31ACCC3B4E288CA3BBECF50>] >> startxref 409018 %%EOF nlopt-2.6.1/src/algs/mlsl/000077500000000000000000000000001345435414600153515ustar00rootroot00000000000000nlopt-2.6.1/src/algs/mlsl/README000066400000000000000000000016631345435414600162370ustar00rootroot00000000000000This is my implementation of the "Multi-Level Single-Linkage" (MLSL) algorithm for global optimization by random local optimizations (a multistart algorithm with "clustering" to avoid repeated detection of the same local minimum), modified to optionally use a Sobol' low-discrepancy sequence (LDS) instead of pseudorandom numbers. See: A. H. G. Rinnooy Kan and G. T. Timmer, "Stochastic global optimization methods," Mathematical Programming, vol. 39, p. 27-78 (1987). [ actually 2 papers -- part I: clustering methods (p. 27), then part II: multilevel methods (p. 57) ] and also: Sergei Kucherenko and Yury Sytsko, "Application of deterministic low-discrepancy sequences in global optimization," Computational Optimization and Applications, vol. 30, p. 297-318 (2005). It is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson September 2007 nlopt-2.6.1/src/algs/mlsl/mlsl.c000066400000000000000000000353531345435414600164750ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* Multi-Level Single-Linkage (MLSL) algorithm for global optimization by random local optimizations (a multistart algorithm with "clustering" to avoid repeated detection of the same local minimum), modified to optionally use a Sobol' low-discrepancy sequence (LDS) instead of pseudorandom numbers. See: A. H. G. Rinnooy Kan and G. T. Timmer, "Stochastic global optimization methods," Mathematical Programming, vol. 39, p. 27-78 (1987). [ actually 2 papers -- part I: clustering methods (p. 27), then part II: multilevel methods (p. 57) ] and also: Sergei Kucherenko and Yury Sytsko, "Application of deterministic low-discrepancy sequences in global optimization," Computational Optimization and Applications, vol. 30, p. 297-318 (2005). Compared to the above papers, I made a couple other modifications to the algorithm besides the use of a LDS. 1) first, the original algorithm suggests discarding points within a *fixed* distance of the boundaries or of previous local minima; I changed this to a distance that decreases with, iteration, proportional to the same threshold radius used for clustering. (In the case of the boundaries, I make the proportionality constant rather small as well.) 2) Kan and Timmer suggest using fancy "spiral-search" algorithms to quickly locate nearest-neighbor points, reducing the overall time for N sample points from O(N^2) to O(N log N) However, recent papers seem to show that such schemes (kd trees, etcetera) become inefficient for high-dimensional spaces (d > 20), and finding a better approach seems to be an open question. Therefore, since I am mainly interested in MLSL for high-dimensional problems (in low dimensions we have DIRECT etc.), I punted on this question for now. In practice, O(N^2) (which does not count the #points evaluated in local searches) does not seem too bad if the objective function is expensive. */ #include #include #include #include "redblack.h" #include "mlsl.h" /* data structure for each random/quasirandom point in the population */ typedef struct { double f; /* function value at x */ int minimized; /* if we have already minimized starting from x */ double closest_pt_d; /* distance^2 to closest pt with smaller f */ double closest_lm_d; /* distance^2 to closest lm with smaller f*/ double x[1]; /* array of length n (K&R struct hack) */ } pt; /* all of the data used by the various mlsl routines...it's not clear in hindsight that we need to put all of this in a data structure since most of the work occurs in a single routine, but it doesn't hurt us */ typedef struct { int n; /* # dimensions */ const double *lb, *ub; nlopt_stopping *stop; /* stopping criteria */ nlopt_func f; void *f_data; rb_tree pts; /* tree of points (k == pt), sorted by f */ rb_tree lms; /* tree of local minimizers, sorted by function value (k = array of length d+1, [0] = f, [1..d] = x) */ nlopt_sobol s; /* sobol data for LDS point generation, or NULL to use pseudo-random numbers */ double R_prefactor, dlm, dbound, gamma; /* parameters of MLSL */ int N; /* number of pts to add per iteration */ } mlsl_data; /* comparison routines to sort the red-black trees by function value */ static int pt_compare(rb_key p1_, rb_key p2_) { pt *p1 = (pt *) p1_; pt *p2 = (pt *) p2_; if (p1->f < p2->f) return -1; if (p1->f > p2->f) return +1; return 0; } static int lm_compare(double *k1, double *k2) { if (*k1 < *k2) return -1; if (*k1 > *k2) return +1; return 0; } /* Euclidean distance |x1 - x2|^2 */ static double distance2(int n, const double *x1, const double *x2) { int i; double d = 0.; for (i = 0; i < n; ++i) { double dx = x1[i] - x2[i]; d += dx * dx; } return d; } /* find the closest pt to p with a smaller function value; this function is called when p is first added to our tree */ static void find_closest_pt(int n, rb_tree *pts, pt *p) { rb_node *node = rb_tree_find_lt(pts, (rb_key) p); double closest_d = HUGE_VAL; while (node) { double d = distance2(n, p->x, ((pt *) node->k)->x); if (d < closest_d) closest_d = d; node = rb_tree_pred(node); } p->closest_pt_d = closest_d; } /* find the closest local minimizer (lm) to p with a smaller function value; this function is called when p is first added to our tree */ static void find_closest_lm(int n, rb_tree *lms, pt *p) { rb_node *node = rb_tree_find_lt(lms, &p->f); double closest_d = HUGE_VAL; while (node) { double d = distance2(n, p->x, node->k+1); if (d < closest_d) closest_d = d; node = rb_tree_pred(node); } p->closest_lm_d = closest_d; } /* given newpt, which presumably has just been added to our tree, update all pts with a greater function value in case newpt is closer to them than their previous closest_pt ... we can ignore already-minimized points since we never do local minimization from the same point twice */ static void pts_update_newpt(int n, rb_tree *pts, pt *newpt) { rb_node *node = rb_tree_find_gt(pts, (rb_key) newpt); while (node) { pt *p = (pt *) node->k; if (!p->minimized) { double d = distance2(n, newpt->x, p->x); if (d < p->closest_pt_d) p->closest_pt_d = d; } node = rb_tree_succ(node); } } /* given newlm, which presumably has just been added to our tree, update all pts with a greater function value in case newlm is closer to them than their previous closest_lm ... we can ignore already-minimized points since we never do local minimization from the same point twice */ static void pts_update_newlm(int n, rb_tree *pts, double *newlm) { pt tmp_pt; rb_node *node; tmp_pt.f = newlm[0]; node = rb_tree_find_gt(pts, (rb_key) &tmp_pt); while (node) { pt *p = (pt *) node->k; if (!p->minimized) { double d = distance2(n, newlm+1, p->x); if (d < p->closest_lm_d) p->closest_lm_d = d; } node = rb_tree_succ(node); } } static int is_potential_minimizer(mlsl_data *mlsl, pt *p, double dpt_min, double dlm_min, double dbound_min) { int i, n = mlsl->n; const double *lb = mlsl->lb; const double *ub = mlsl->ub; const double *x = p->x; if (p->minimized) return 0; if (p->closest_pt_d <= dpt_min*dpt_min) return 0; if (p->closest_lm_d <= dlm_min*dlm_min) return 0; for (i = 0; i < n; ++i) if ((x[i] - lb[i] <= dbound_min || ub[i] - x[i] <= dbound_min) && ub[i] - lb[i] > dbound_min) return 0; return 1; } #define K2PI (6.2831853071795864769252867665590057683943388) /* compute Gamma(1 + n/2)^{1/n} ... this is a constant factor used in MLSL as part of the minimum-distance cutoff*/ static double gam(int n) { /* use Stirling's approximation: Gamma(1 + z) ~ sqrt(2*pi*z) * z^z / exp(z) ... this is more than accurate enough for our purposes (error in gam < 15% for d=1, < 4% for d=2, < 2% for d=3, ...) and avoids overflow problems because we can combine it with the ^{1/n} exponent */ double z = n/2; return sqrt(pow(K2PI * z, 1.0/n) * z) * exp(-0.5); } static pt *alloc_pt(int n) { pt *p = (pt *) malloc(sizeof(pt) + (n-1) * sizeof(double)); if (p) { p->minimized = 0; p->closest_pt_d = HUGE_VAL; p->closest_lm_d = HUGE_VAL; } return p; } /* wrapper around objective function that increments evaluation count */ static double fcount(unsigned n, const double *x, double *grad, void *p_) { mlsl_data *p = (mlsl_data *) p_; ++ *(p->stop->nevals_p); return p->f(n, x, grad, p->f_data); } static void get_minf(mlsl_data *d, double *minf, double *x) { rb_node *node = rb_tree_min(&d->pts); if (node) { *minf = ((pt *) node->k)->f; memcpy(x, ((pt *) node->k)->x, sizeof(double) * d->n); } node = rb_tree_min(&d->lms); if (node && node->k[0] < *minf) { *minf = node->k[0]; memcpy(x, node->k + 1, sizeof(double) * d->n); } } #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MLSL_SIGMA 2. /* MLSL sigma parameter, using value from the papers */ #define MLSL_GAMMA 0.3 /* MLSL gamma parameter (FIXME: what should it be?) */ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt local_opt, int Nsamples, /* #samples/iteration (0=default) */ int lds) /* random or low-discrepancy seq. (lds) */ { nlopt_result ret = NLOPT_SUCCESS; mlsl_data d; int i; pt *p; if (!Nsamples) d.N = 4; /* FIXME: what is good number of samples per iteration? */ else d.N = Nsamples; if (d.N < 1) { nlopt_stop_msg(stop, "population %d is too small", d.N); return NLOPT_INVALID_ARGS; } d.n = n; d.lb = lb; d.ub = ub; d.stop = stop; d.f = f; d.f_data = f_data; rb_tree_init(&d.pts, pt_compare); rb_tree_init(&d.lms, lm_compare); d.s = lds ? nlopt_sobol_create((unsigned) n) : NULL; nlopt_set_min_objective(local_opt, fcount, &d); nlopt_set_lower_bounds(local_opt, lb); nlopt_set_upper_bounds(local_opt, ub); nlopt_set_stopval(local_opt, stop->minf_max); d.gamma = MLSL_GAMMA; d.R_prefactor = sqrt(2./K2PI) * pow(gam(n) * MLSL_SIGMA, 1.0/n); for (i = 0; i < n; ++i) d.R_prefactor *= pow(ub[i] - lb[i], 1.0/n); /* MLSL also suggests setting some minimum distance from points to previous local minimiza and to the boundaries; I don't know how to choose this as a fixed number, so I set it proportional to R; see also the comments at top. dlm and dbound are the proportionality constants. */ d.dlm = 1.0; /* min distance/R to local minima (FIXME: good value?) */ d.dbound = 1e-6; /* min distance/R to ub/lb boundaries (good value?) */ p = alloc_pt(n); if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; } /* FIXME: how many sobol points to skip, if any? */ nlopt_sobol_skip(d.s, (unsigned) (10*n+d.N), p->x); memcpy(p->x, x, n * sizeof(double)); p->f = f(n, x, NULL, f_data); ++ *(stop->nevals_p); if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; while (ret == NLOPT_SUCCESS) { rb_node *node; double R; get_minf(&d, minf, x); /* sampling phase: add random/quasi-random points */ for (i = 0; i < d.N && ret == NLOPT_SUCCESS; ++i) { p = alloc_pt(n); if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; } if (d.s) nlopt_sobol_next(d.s, p->x, lb, ub); else { /* use random points instead of LDS */ int j; for (j = 0; j < n; ++j) p->x[j] = nlopt_urand(lb[j],ub[j]); } p->f = f(n, p->x, NULL, f_data); ++ *(stop->nevals_p); if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else { find_closest_pt(n, &d.pts, p); find_closest_lm(n, &d.lms, p); pts_update_newpt(n, &d.pts, p); } } /* distance threshhold parameter R in MLSL */ R = d.R_prefactor * pow(log((double) d.pts.N) / d.pts.N, 1.0 / n); /* local search phase: do local opt. for promising points */ node = rb_tree_min(&d.pts); for (i = (int) (ceil(d.gamma * d.pts.N) + 0.5); node && i > 0 && ret == NLOPT_SUCCESS; --i) { p = (pt *) node->k; if (is_potential_minimizer(&d, p, R, d.dlm*R, d.dbound*R)) { nlopt_result lret; double *lm; double t = nlopt_seconds(); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; break; } if (nlopt_stop_evals(stop)) { ret = NLOPT_MAXEVAL_REACHED; break; } if (stop->maxtime > 0 && t - stop->start >= stop->maxtime) { ret = NLOPT_MAXTIME_REACHED; break; } lm = (double *) malloc(sizeof(double) * (n+1)); if (!lm) { ret = NLOPT_OUT_OF_MEMORY; goto done; } memcpy(lm+1, p->x, sizeof(double) * n); lret = nlopt_optimize_limited(local_opt, lm+1, lm, stop->maxeval - *(stop->nevals_p), stop->maxtime - (t - stop->start)); p->minimized = 1; if (lret < 0) { free(lm); ret = lret; goto done; } if (!rb_tree_insert(&d.lms, lm)) { free(lm); ret = NLOPT_OUT_OF_MEMORY; } else if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (*lm < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else pts_update_newlm(n, &d.pts, lm); } /* TODO: additional stopping criteria based e.g. on improvement in function values, etc? */ node = rb_tree_succ(node); } } get_minf(&d, minf, x); done: nlopt_sobol_destroy(d.s); rb_tree_destroy_with_keys(&d.lms); rb_tree_destroy_with_keys(&d.pts); return ret; } nlopt-2.6.1/src/algs/mlsl/mlsl.h000066400000000000000000000032721345435414600164750ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef MLSL_H #define MLSL_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt local_opt, int Nsamples, /* #samples/iteration (0=default) */ int lds); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/mma/000077500000000000000000000000001345435414600151545ustar00rootroot00000000000000nlopt-2.6.1/src/algs/mma/README000066400000000000000000000032171345435414600160370ustar00rootroot00000000000000Implementation of the globally-convergent method-of-moving-asymptotes (MMA) algorithm for gradient-based local optimization, as described in: Krister Svanberg, "A class of globally convergent optimization methods based on conservative convex separable approximations," SIAM J. Optim. 12 (2), p. 555-573 (2002). In fact, this algorithm is much more general than most of the other algorithms in NLopt, in that it handles an arbitrary set of nonlinear (differentiable) constraints as well, in a very efficient manner. I've implemented the full nonlinear-constrained MMA algorithm, and it is exported under the nlopt_minimize_constrained API. I also implemented another CCSA algorithm from the same paper: instead of constructing local MMA approximations, it constructs simple quadratic approximations (or rather, affine approximations plus a quadratic penalty term to stay conservative). This is the ccsa_quadratic code. It seems to have similar convergence rates to MMA for most problems, which is not surprising as they are both essentially similar. However, for the quadratic variant I implemented the possibility of preconditioning: including a user-supplied Hessian approximation in the local model. It is easy to incorporate this into the proof in Svanberg's paper, and to show that global convergence is still guaranteed as long as the user's "Hessian" is positive semidefinite, and it practice it can greatly improve convergence if the preconditioner is a good approximation for (at least for the largest eigenvectors) the real Hessian. It is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson July 2008 - July 2012 nlopt-2.6.1/src/algs/mma/ccsa_quadratic.c000066400000000000000000000451471345435414600203010ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* In this file we implement Svanberg's CCSA algorithm with the simple linear approximation + quadratic penalty function. We also allow the user to specify an optional "preconditioner": an approximate Hessian (which must be symmetric & positive semidefinite) that can be added into the approximation. [X. Liang and I went through the convergence proof in Svanberg's paper and it does not seem to be modified by such preconditioning, as long as the preconditioner eigenvalues are bounded above for all x.] For the non-preconditioned case the trust-region subproblem is separable and can be solved by a dual method. For the preconditioned case the subproblem is still convex but in general is non-separable so we solve by calling the same algorithm recursively, under the assumption that the subproblem objective is cheap to evaluate. */ #include #include #include #include #include "mma.h" #include "nlopt-util.h" unsigned ccsa_verbose = 0; /* > 0 for verbose output */ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* magic minimum value for rho in CCSA ... the 2002 paper says it should be a "fixed, strictly positive `small' number, e.g. 1e-5" ... grrr, I hate these magic numbers, which seem like they should depend on the objective function in some way ... in particular, note that rho is dimensionful (= dimensions of objective function) */ #define CCSA_RHOMIN 1e-5 /***********************************************************************/ /* function for CCSA's dual solution of the approximate problem */ typedef struct { int count; /* evaluation count, incremented each call */ unsigned n; /* must be set on input to dimension of x */ const double *x, *lb, *ub, *sigma, *dfdx; /* arrays of length n */ const double *dfcdx; /* m-by-n array of fc gradients */ double fval, rho; /* must be set on input */ const double *fcval, *rhoc; /* arrays of length m */ double *xcur; /* array of length n, output each time */ double gval, wval, *gcval; /* output each time (array length m) */ nlopt_precond pre; void *pre_data; nlopt_precond *prec; void **prec_data; /* length = # constraints */ double *scratch; /* length = 2*n */ } dual_data; static double sqr(double x) { return x * x; } static double dual_func(unsigned m, const double *y, double *grad, void *d_) { dual_data *d = (dual_data *) d_; unsigned n = d->n; const double *x = d->x, *lb = d->lb, *ub = d->ub, *sigma = d->sigma, *dfdx = d->dfdx; const double *dfcdx = d->dfcdx; double rho = d->rho, fval = d->fval; const double *rhoc = d->rhoc, *fcval = d->fcval; double *xcur = d->xcur; double *gcval = d->gcval; unsigned i, j; double val; d->count++; val = d->gval = fval; d->wval = 0; for (i = 0; i < m; ++i) val += y[i] * (gcval[i] = fcval[i]); for (j = 0; j < n; ++j) { double u, v, dx, sigma2, dx2, dx2sig; /* first, compute xcur[j] = x+dx for y. Because this objective is separable, we can minimize over x analytically, and the minimum dx is given by the solution of a linear equation u dx + v sigma^2 = 0, i.e. dx = -sigma^2 v/u where u and v are defined by the sums below. However, we also have to check that |dx| <= sigma and that lb <= x+dx <= ub. */ if (sigma[j] == 0) { /* special case for lb[i] == ub[i] dims, dx=0 */ xcur[j] = x[j]; continue; } u = rho; v = dfdx[j]; for (i = 0; i < m; ++i) { u += rhoc[i] * y[i]; v += dfcdx[i*n + j] * y[i]; } dx = -(sigma2 = sqr(sigma[j])) * v/u; /* if dx is out of bounds, we are guaranteed by convexity that the minimum is at the bound on the side of dx */ if (fabs(dx) > sigma[j]) dx = copysign(sigma[j], dx); xcur[j] = x[j] + dx; if (xcur[j] > ub[j]) xcur[j] = ub[j]; else if (xcur[j] < lb[j]) xcur[j] = lb[j]; dx = xcur[j] - x[j]; /* function value: */ dx2 = dx * dx; val += v * dx + 0.5 * u * dx2 / sigma2; /* update gval, wval, gcval (approximant functions) */ d->gval += dfdx[j] * dx + rho * (dx2sig = 0.5*dx2/sigma2); d->wval += dx2sig; for (i = 0; i < m; ++i) gcval[i] += dfcdx[i*n+j] * dx + rhoc[i] * dx2sig; } /* gradient is easy to compute: since we are at a minimum x (dval/dx=0), we only need the partial derivative with respect to y, and we negate because we are maximizing: */ if (grad) for (i = 0; i < m; ++i) grad[i] = -gcval[i]; return -val; } /***********************************************************************/ /* compute g(x - x0) and its gradient */ static double gfunc(unsigned n, double f, const double *dfdx, double rho, const double *sigma, const double *x0, nlopt_precond pre, void *pre_data, double *scratch, const double *x, double *grad) { double *dx = scratch, *Hdx = scratch + n; double val = f; unsigned j; for (j = 0; j < n; ++j) { double sigma2inv = 1.0 / sqr(sigma[j]); dx[j] = x[j] - x0[j]; val += dfdx[j] * dx[j] + (0.5*rho) * sqr(dx[j]) * sigma2inv; if (grad) grad[j] = dfdx[j] + rho * dx[j] * sigma2inv; } if (pre) { pre(n, x0, dx, Hdx, pre_data); for (j = 0; j < n; ++j) val += 0.5 * dx[j] * Hdx[j]; if (grad) for (j = 0; j < n; ++j) grad[j] += Hdx[j]; } return val; } static double g0(unsigned n, const double *x, double *grad, void *d_) { dual_data *d = (dual_data *) d_; d->count++; return gfunc(n, d->fval, d->dfdx, d->rho, d->sigma, d->x, d->pre, d->pre_data, d->scratch, x, grad); } static void gi(unsigned m, double *result, unsigned n, const double *x, double *grad, void *d_) { dual_data *d = (dual_data *) d_; unsigned i; for (i = 0; i < m; ++i) result[i] = gfunc(n, d->fcval[i], d->dfcdx + i*n, d->rhoc[i], d->sigma, d->x, d->prec ? d->prec[i] : NULL, d->prec_data ? d->prec_data[i] : NULL, d->scratch, x, grad); } /***********************************************************************/ nlopt_result ccsa_quadratic_minimize( unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, nlopt_precond pre, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt dual_opt) { nlopt_result ret = NLOPT_SUCCESS; double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur; double *dfcdx, *dfcdx_cur; double *fcval, *fcval_cur, *rhoc, *gcval, *y, *dual_lb, *dual_ub; double *pre_lb = NULL, *pre_ub = NULL; unsigned i, ifc, j, k = 0; dual_data dd; int feasible; double infeasibility; unsigned mfc; unsigned no_precond; nlopt_opt pre_opt = NULL; m = nlopt_count_constraints(mfc = m, fc); if (nlopt_get_dimension(dual_opt) != m) { nlopt_stop_msg(stop, "dual optimizer has wrong dimension %d != %d", nlopt_get_dimension(dual_opt), m); return NLOPT_INVALID_ARGS; } sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7)); if (!sigma) return NLOPT_OUT_OF_MEMORY; dfdx = sigma + n; dfdx_cur = dfdx + n; xcur = dfdx_cur + n; xprev = xcur + n; xprevprev = xprev + n; fcval = xprevprev + n; fcval_cur = fcval + m; rhoc = fcval_cur + m; gcval = rhoc + m; dual_lb = gcval + m; dual_ub = dual_lb + m; y = dual_ub + m; dfcdx = y + m; dfcdx_cur = dfcdx + m*n; dd.n = n; dd.x = x; dd.lb = lb; dd.ub = ub; dd.sigma = sigma; dd.dfdx = dfdx; dd.dfcdx = dfcdx; dd.fcval = fcval; dd.rhoc = rhoc; dd.xcur = xcur; dd.gcval = gcval; dd.pre = pre; dd.pre_data = f_data; dd.prec = NULL; dd.prec_data = NULL; dd.scratch = NULL; if (m) { dd.prec = (nlopt_precond *) malloc(sizeof(nlopt_precond) * m); dd.prec_data = (void **) malloc(sizeof(void *) * m); if (!dd.prec || !dd.prec_data) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (i = ifc = 0; ifc < mfc; ++ifc) { unsigned inext = i + fc[ifc].m; for (; i < inext; ++i) { dd.prec[i] = fc[ifc].pre; dd.prec_data[i] = fc[ifc].f_data; } } } no_precond = pre == NULL; if (dd.prec) for (i = 0; i < m; ++i) no_precond = no_precond && dd.prec[i] == NULL; if (!no_precond) { dd.scratch = (double*) malloc(sizeof(double) * (4*n)); if (!dd.scratch) { free(sigma); return NLOPT_OUT_OF_MEMORY; } pre_lb = dd.scratch + 2*n; pre_ub = pre_lb + n; pre_opt = nlopt_create(nlopt_get_algorithm(dual_opt), n); if (!pre_opt) { nlopt_stop_msg(stop, "failure creating precond. optimizer"); ret = NLOPT_FAILURE; goto done; } ret = nlopt_set_min_objective(pre_opt, g0, &dd); if (ret < 0) goto done; ret = nlopt_add_inequality_mconstraint(pre_opt, m, gi, &dd, NULL); if (ret < 0) goto done; ret = nlopt_set_ftol_rel(pre_opt, nlopt_get_ftol_rel(dual_opt)); if (ret < 0) goto done; ret = nlopt_set_ftol_abs(pre_opt, nlopt_get_ftol_abs(dual_opt)); if (ret < 0) goto done; ret = nlopt_set_maxeval(pre_opt, nlopt_get_maxeval(dual_opt)); if (ret < 0) goto done; } for (j = 0; j < n; ++j) { if (nlopt_isinf(ub[j]) || nlopt_isinf(lb[j])) sigma[j] = 1.0; /* arbitrary default */ else sigma[j] = 0.5 * (ub[j] - lb[j]); } rho = 1.0; for (i = 0; i < m; ++i) { rhoc[i] = 1.0; dual_lb[i] = y[i] = 0.0; dual_ub[i] = HUGE_VAL; } dd.fval = fcur = *minf = f(n, x, dfdx, f_data); ++ *(stop->nevals_p); memcpy(xcur, x, sizeof(double) * n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible = 1; infeasibility = 0; for (i = ifc = 0; ifc < mfc; ++ifc) { nlopt_eval_constraint(fcval + i, dfcdx + i*n, fc + ifc, n, x); i += fc[ifc].m; if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } } for (i = 0; i < m; ++i) { feasible = feasible && fcval[i] <= 0; if (fcval[i] > infeasibility) infeasibility = fcval[i]; } /* For non-feasible initial points, set a finite (large) upper-bound on the dual variables. What this means is that, if no feasible solution is found from the dual problem, it will minimize the dual objective with the unfeasible constraint weighted by 1e40 -- basically, minimizing the unfeasible constraint until it becomes feasible or until we at least obtain a step towards a feasible point. Svanberg suggested a different approach in his 1987 paper, basically introducing additional penalty variables for unfeasible constraints, but this is easier to implement and at least as efficient. */ if (!feasible) for (i = 0; i < m; ++i) dual_ub[i] = 1e40; nlopt_set_min_objective(dual_opt, dual_func, &dd); nlopt_set_lower_bounds(dual_opt, dual_lb); nlopt_set_upper_bounds(dual_opt, dual_ub); nlopt_set_stopval(dual_opt, -HUGE_VAL); nlopt_remove_inequality_constraints(dual_opt); nlopt_remove_equality_constraints(dual_opt); while (1) { /* outer iterations */ double fprev = fcur; if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n); memcpy(xprev, xcur, sizeof(double) * n); while (1) { /* inner iterations */ double min_dual, infeasibility_cur; int feasible_cur, inner_done; unsigned save_verbose; nlopt_result reti; if (no_precond) { /* solve dual problem */ dd.rho = rho; dd.count = 0; save_verbose = ccsa_verbose; ccsa_verbose = 0; /* no recursive verbosity */ reti = nlopt_optimize_limited(dual_opt, y, &min_dual, 0, stop->maxtime - (nlopt_seconds() - stop->start)); ccsa_verbose = save_verbose; if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) { ret = reti; goto done; } dual_func(m, y, NULL, &dd); /* evaluate final xcur etc. */ } else { double pre_min; for (j = 0; j < n; ++j) { pre_lb[j] = MAX(lb[j], x[j] - sigma[j]); pre_ub[j] = MIN(ub[j], x[j] + sigma[j]); xcur[j] = x[j]; } nlopt_set_lower_bounds(pre_opt, pre_lb); nlopt_set_upper_bounds(pre_opt, pre_ub); dd.rho = rho; dd.count = 0; save_verbose = ccsa_verbose; ccsa_verbose = 0; /* no recursive verbosity */ reti = nlopt_optimize_limited(pre_opt, xcur, &pre_min, 0, stop->maxtime - (nlopt_seconds() - stop->start)); ccsa_verbose = save_verbose; if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) { ret = reti; goto done; } /* evaluate final xcur etc */ dd.gval = g0(n, xcur, NULL, &dd); gi(m, dd.gcval, n, xcur, NULL, &dd); } if (ccsa_verbose) { printf("CCSA dual converged in %d iters to g=%g:\n", dd.count, dd.gval); for (i = 0; i < MIN(ccsa_verbose, m); ++i) printf(" CCSA y[%u]=%g, gc[%u]=%g\n", i, y[i], i, dd.gcval[i]); } fcur = f(n, xcur, dfdx_cur, f_data); ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible_cur = 1; infeasibility_cur = 0; inner_done = dd.gval >= fcur; for (i = ifc = 0; ifc < mfc; ++ifc) { nlopt_eval_constraint(fcval_cur + i, dfcdx_cur + i*n, fc + ifc, n, xcur); i += fc[ifc].m; if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } } for (i = ifc = 0; ifc < mfc; ++ifc) { unsigned i0 = i, inext = i + fc[ifc].m; for (; i < inext; ++i) { feasible_cur = feasible_cur && fcval_cur[i] <= fc[ifc].tol[i-i0]; inner_done = inner_done && (dd.gcval[i] >= fcval_cur[i]); if (fcval_cur[i] > infeasibility_cur) infeasibility_cur = fcval_cur[i]; } } if ((fcur < *minf && (inner_done || feasible_cur || !feasible)) || (!feasible && infeasibility_cur < infeasibility)) { if (ccsa_verbose && !feasible_cur) printf("CCSA - using infeasible point?\n"); dd.fval = *minf = fcur; infeasibility = infeasibility_cur; memcpy(fcval, fcval_cur, sizeof(double)*m); memcpy(x, xcur, sizeof(double)*n); memcpy(dfdx, dfdx_cur, sizeof(double)*n); memcpy(dfcdx, dfcdx_cur, sizeof(double)*n*m); /* once we have reached a feasible solution, the algorithm should never make the solution infeasible again (if inner_done), although the constraints may be violated slightly by rounding errors etc. so we must be a little careful about checking feasibility */ if (infeasibility_cur == 0) { if (!feasible) { /* reset upper bounds to infin. */ for (i = 0; i < m; ++i) dual_ub[i] = HUGE_VAL; nlopt_set_upper_bounds(dual_opt, dual_ub); } feasible = 1; } } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; if (inner_done) break; if (fcur > dd.gval) rho = MIN(10*rho, 1.1 * (rho + (fcur-dd.gval) / dd.wval)); for (i = 0; i < m; ++i) if (fcval_cur[i] > dd.gcval[i]) rhoc[i] = MIN(10*rhoc[i], 1.1 * (rhoc[i] + (fcval_cur[i]-dd.gcval[i]) / dd.wval)); if (ccsa_verbose) printf("CCSA inner iteration: rho -> %g\n", rho); for (i = 0; i < MIN(ccsa_verbose, m); ++i) printf(" CCSA rhoc[%u] -> %g\n", i,rhoc[i]); } if (nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; if (nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; if (ret != NLOPT_SUCCESS) goto done; /* update rho and sigma for iteration k+1 */ rho = MAX(0.1 * rho, CCSA_RHOMIN); if (ccsa_verbose) printf("CCSA outer iteration: rho -> %g\n", rho); for (i = 0; i < m; ++i) rhoc[i] = MAX(0.1 * rhoc[i], CCSA_RHOMIN); for (i = 0; i < MIN(ccsa_verbose, m); ++i) printf(" CCSA rhoc[%u] -> %g\n", i, rhoc[i]); if (k > 1) { for (j = 0; j < n; ++j) { double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]); double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1); sigma[j] *= gam; if (!nlopt_isinf(ub[j]) && !nlopt_isinf(lb[j])) { sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j])); /* use a smaller lower bound than Svanberg's 0.01*(ub-lb), which seems unnecessarily large */ sigma[j] = MAX(sigma[j], 1e-8*(ub[j]-lb[j])); } } for (j = 0; j < MIN(ccsa_verbose, n); ++j) printf(" CCSA sigma[%u] -> %g\n", j, sigma[j]); } } done: nlopt_destroy(pre_opt); if (dd.scratch) free(dd.scratch); if (m) { free(dd.prec_data); free(dd.prec); } free(sigma); return ret; } nlopt-2.6.1/src/algs/mma/mma.c000066400000000000000000000346071345435414600161040ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include "mma.h" #include "nlopt-util.h" unsigned mma_verbose = 0; /* > 0 for verbose output */ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* magic minimum value for rho in MMA ... the 2002 paper says it should be a "fixed, strictly positive `small' number, e.g. 1e-5" ... grrr, I hate these magic numbers, which seem like they should depend on the objective function in some way ... in particular, note that rho is dimensionful (= dimensions of objective function) */ #define MMA_RHOMIN 1e-5 /***********************************************************************/ /* function for MMA's dual solution of the approximate problem */ typedef struct { int count; /* evaluation count, incremented each call */ unsigned n; /* must be set on input to dimension of x */ const double *x, *lb, *ub, *sigma, *dfdx; /* arrays of length n */ const double *dfcdx; /* m-by-n array of fc gradients */ double fval, rho; /* must be set on input */ const double *fcval, *rhoc; /* arrays of length m */ double *xcur; /* array of length n, output each time */ double gval, wval, *gcval; /* output each time (array length m) */ } dual_data; static double sqr(double x) { return x * x; } static double dual_func(unsigned m, const double *y, double *grad, void *d_) { dual_data *d = (dual_data *) d_; unsigned n = d->n; const double *x = d->x, *lb = d->lb, *ub = d->ub, *sigma = d->sigma, *dfdx = d->dfdx; const double *dfcdx = d->dfcdx; double rho = d->rho, fval = d->fval; const double *rhoc = d->rhoc, *fcval = d->fcval; double *xcur = d->xcur; double *gcval = d->gcval; unsigned i, j; double val; d->count++; val = d->gval = fval; d->wval = 0; for (i = 0; i < m; ++i) val += y[i] * (gcval[i] = nlopt_isnan(fcval[i]) ? 0 : fcval[i]); for (j = 0; j < n; ++j) { double u, v, dx, denominv, c, sigma2, dx2; /* first, compute xcur[j] for y. Because this objective is separable, we can minimize over x analytically, and the minimum dx is given by the solution of a quadratic equation: u dx^2 + 2 v sigma^2 dx + u sigma^2 = 0 where u and v are defined by the sums below. Because of the definitions, it is guaranteed that |u/v| <= sigma, and it follows that the only dx solution with |dx| <= sigma is given by: (v/u) sigma^2 (-1 + sqrt(1 - (u / v sigma)^2)) = (u/v) / (-1 - sqrt(1 - (u / v sigma)^2)) (which goes to zero as u -> 0). The latter expression is less susceptible to roundoff error. */ if (sigma[j] == 0) { /* special case for lb[i] == ub[i] dims, dx=0 */ xcur[j] = x[j]; continue; } u = dfdx[j]; v = fabs(dfdx[j]) * sigma[j] + 0.5 * rho; for (i = 0; i < m; ++i) if (!nlopt_isnan(fcval[i])) { u += dfcdx[i*n + j] * y[i]; v += (fabs(dfcdx[i*n + j]) * sigma[j] + 0.5 * rhoc[i]) * y[i]; } u *= (sigma2 = sqr(sigma[j])); dx = (u/v) / (-1 - sqrt(fabs(1 - sqr(u/(v*sigma[j]))))); xcur[j] = x[j] + dx; if (xcur[j] > ub[j]) xcur[j] = ub[j]; else if (xcur[j] < lb[j]) xcur[j] = lb[j]; if (xcur[j] > x[j]+0.9*sigma[j]) xcur[j] = x[j]+0.9*sigma[j]; else if (xcur[j] < x[j]-0.9*sigma[j]) xcur[j] = x[j]-0.9*sigma[j]; dx = xcur[j] - x[j]; /* function value: */ dx2 = dx * dx; denominv = 1.0 / (sigma2 - dx2); val += (u * dx + v * dx2) * denominv; /* update gval, wval, gcval (approximant functions) */ c = sigma2 * dx; d->gval += (dfdx[j] * c + (fabs(dfdx[j])*sigma[j] + 0.5*rho) * dx2) * denominv; d->wval += 0.5 * dx2 * denominv; for (i = 0; i < m; ++i) if (!nlopt_isnan(fcval[i])) gcval[i] += (dfcdx[i*n+j] * c + (fabs(dfcdx[i*n+j])*sigma[j] + 0.5*rhoc[i]) * dx2) * denominv; } /* gradient is easy to compute: since we are at a minimum x (dval/dx=0), we only need the partial derivative with respect to y, and we negate because we are maximizing: */ if (grad) for (i = 0; i < m; ++i) grad[i] = -gcval[i]; return -val; } /***********************************************************************/ /* note that we implement a hidden feature not in the standard nlopt_minimize_constrained interface: whenever the constraint function returns NaN, that constraint becomes inactive. */ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt dual_opt) { nlopt_result ret = NLOPT_SUCCESS; double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur; double *dfcdx, *dfcdx_cur; double *fcval, *fcval_cur, *rhoc, *gcval, *y, *dual_lb, *dual_ub; unsigned i, ifc, j, k = 0; dual_data dd; int feasible; double infeasibility; unsigned mfc; m = nlopt_count_constraints(mfc = m, fc); if (nlopt_get_dimension(dual_opt) != m) { nlopt_stop_msg(stop, "dual optimizer has wrong dimension %d != %d", nlopt_get_dimension(dual_opt), m); return NLOPT_INVALID_ARGS; } sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7)); if (!sigma) return NLOPT_OUT_OF_MEMORY; dfdx = sigma + n; dfdx_cur = dfdx + n; xcur = dfdx_cur + n; xprev = xcur + n; xprevprev = xprev + n; fcval = xprevprev + n; fcval_cur = fcval + m; rhoc = fcval_cur + m; gcval = rhoc + m; dual_lb = gcval + m; dual_ub = dual_lb + m; y = dual_ub + m; dfcdx = y + m; dfcdx_cur = dfcdx + m*n; dd.n = n; dd.x = x; dd.lb = lb; dd.ub = ub; dd.sigma = sigma; dd.dfdx = dfdx; dd.dfcdx = dfcdx; dd.fcval = fcval; dd.rhoc = rhoc; dd.xcur = xcur; dd.gcval = gcval; for (j = 0; j < n; ++j) { if (nlopt_isinf(ub[j]) || nlopt_isinf(lb[j])) sigma[j] = 1.0; /* arbitrary default */ else sigma[j] = 0.5 * (ub[j] - lb[j]); } rho = 1.0; for (i = 0; i < m; ++i) { rhoc[i] = 1.0; dual_lb[i] = y[i] = 0.0; dual_ub[i] = HUGE_VAL; } dd.fval = fcur = *minf = f(n, x, dfdx, f_data); ++ *(stop->nevals_p); memcpy(xcur, x, sizeof(double) * n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible = 1; infeasibility = 0; for (i = ifc = 0; ifc < mfc; ++ifc) { nlopt_eval_constraint(fcval + i, dfcdx + i*n, fc + ifc, n, x); i += fc[ifc].m; if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } } for (i = 0; i < m; ++i) { feasible = feasible && (fcval[i] <= 0 || nlopt_isnan(fcval[i])); if (fcval[i] > infeasibility) infeasibility = fcval[i]; } /* For non-feasible initial points, set a finite (large) upper-bound on the dual variables. What this means is that, if no feasible solution is found from the dual problem, it will minimize the dual objective with the unfeasible constraint weighted by 1e40 -- basically, minimizing the unfeasible constraint until it becomes feasible or until we at least obtain a step towards a feasible point. Svanberg suggested a different approach in his 1987 paper, basically introducing additional penalty variables for unfeasible constraints, but this is easier to implement and at least as efficient. */ if (!feasible) for (i = 0; i < m; ++i) dual_ub[i] = 1e40; nlopt_set_min_objective(dual_opt, dual_func, &dd); nlopt_set_lower_bounds(dual_opt, dual_lb); nlopt_set_upper_bounds(dual_opt, dual_ub); nlopt_set_stopval(dual_opt, -HUGE_VAL); nlopt_remove_inequality_constraints(dual_opt); nlopt_remove_equality_constraints(dual_opt); while (1) { /* outer iterations */ double fprev = fcur; if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n); memcpy(xprev, xcur, sizeof(double) * n); while (1) { /* inner iterations */ double min_dual, infeasibility_cur; int feasible_cur, inner_done; unsigned save_verbose; int new_infeasible_constraint; nlopt_result reti; /* solve dual problem */ dd.rho = rho; dd.count = 0; save_verbose = mma_verbose; mma_verbose = 0; /* no recursive verbosity */ reti = nlopt_optimize_limited(dual_opt, y, &min_dual, 0, stop->maxtime - (nlopt_seconds() - stop->start)); mma_verbose = save_verbose; if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) { ret = reti; goto done; } dual_func(m, y, NULL, &dd); /* evaluate final xcur etc. */ if (mma_verbose) { printf("MMA dual converged in %d iterations to g=%g:\n", dd.count, dd.gval); for (i = 0; i < MIN(mma_verbose, m); ++i) printf(" MMA y[%u]=%g, gc[%u]=%g\n", i, y[i], i, dd.gcval[i]); } fcur = f(n, xcur, dfdx_cur, f_data); ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible_cur = 1; infeasibility_cur = 0; new_infeasible_constraint = 0; inner_done = dd.gval >= fcur; for (i = ifc = 0; ifc < mfc; ++ifc) { nlopt_eval_constraint(fcval_cur + i, dfcdx_cur + i*n, fc + ifc, n, xcur); i += fc[ifc].m; if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } } for (i = ifc = 0; ifc < mfc; ++ifc) { unsigned i0 = i, inext = i + fc[ifc].m; for (; i < inext; ++i) if (!nlopt_isnan(fcval_cur[i])) { feasible_cur = feasible_cur && (fcval_cur[i] <= fc[ifc].tol[i-i0]); if (!nlopt_isnan(fcval[i])) inner_done = inner_done && (dd.gcval[i] >= fcval_cur[i]); else if (fcval_cur[i] > 0) new_infeasible_constraint = 1; if (fcval_cur[i] > infeasibility_cur) infeasibility_cur = fcval_cur[i]; } } if ((fcur < *minf && (inner_done || feasible_cur || !feasible)) || (!feasible && infeasibility_cur < infeasibility)) { if (mma_verbose && !feasible_cur) printf("MMA - using infeasible point?\n"); dd.fval = *minf = fcur; infeasibility = infeasibility_cur; memcpy(fcval, fcval_cur, sizeof(double)*m); memcpy(x, xcur, sizeof(double)*n); memcpy(dfdx, dfdx_cur, sizeof(double)*n); memcpy(dfcdx, dfcdx_cur, sizeof(double)*n*m); /* once we have reached a feasible solution, the algorithm should never make the solution infeasible again (if inner_done), although the constraints may be violated slightly by rounding errors etc. so we must be a little careful about checking feasibility */ if (infeasibility_cur == 0) { if (!feasible) { /* reset upper bounds to infin. */ for (i = 0; i < m; ++i) dual_ub[i] = HUGE_VAL; nlopt_set_upper_bounds(dual_opt, dual_ub); } feasible = 1; } else if (new_infeasible_constraint) feasible = 0; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; if (inner_done) break; if (fcur > dd.gval) rho = MIN(10*rho, 1.1 * (rho + (fcur-dd.gval) / dd.wval)); for (i = 0; i < m; ++i) if (!nlopt_isnan(fcval_cur[i]) && fcval_cur[i] > dd.gcval[i]) rhoc[i] = MIN(10*rhoc[i], 1.1 * (rhoc[i] + (fcval_cur[i]-dd.gcval[i]) / dd.wval)); if (mma_verbose) printf("MMA inner iteration: rho -> %g\n", rho); for (i = 0; i < MIN(mma_verbose, m); ++i) printf(" MMA rhoc[%u] -> %g\n", i,rhoc[i]); } if (nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; if (nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; if (ret != NLOPT_SUCCESS) goto done; /* update rho and sigma for iteration k+1 */ rho = MAX(0.1 * rho, MMA_RHOMIN); if (mma_verbose) printf("MMA outer iteration: rho -> %g\n", rho); for (i = 0; i < m; ++i) rhoc[i] = MAX(0.1 * rhoc[i], MMA_RHOMIN); for (i = 0; i < MIN(mma_verbose, m); ++i) printf(" MMA rhoc[%u] -> %g\n", i, rhoc[i]); if (k > 1) { for (j = 0; j < n; ++j) { double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]); double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1); sigma[j] *= gam; if (!nlopt_isinf(ub[j]) && !nlopt_isinf(lb[j])) { sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j])); sigma[j] = MAX(sigma[j], 0.01*(ub[j]-lb[j])); } } for (j = 0; j < MIN(mma_verbose, n); ++j) printf(" MMA sigma[%u] -> %g\n", j, sigma[j]); } } done: free(sigma); return ret; } nlopt-2.6.1/src/algs/mma/mma.h000066400000000000000000000037241345435414600161050ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef MMA_H #define MMA_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ extern unsigned mma_verbose; nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt dual_opt); nlopt_result ccsa_quadratic_minimize( unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, nlopt_precond pre, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt dual_opt); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/neldermead/000077500000000000000000000000001345435414600165025ustar00rootroot00000000000000nlopt-2.6.1/src/algs/neldermead/README000066400000000000000000000112471345435414600173670ustar00rootroot00000000000000This directory contains Nelder-Mead and variations thereof. Currently, I have implemented two algorithms, described below. The code in this directory is under the same MIT license as the rest of my code in NLopt (see ../COPYRIGHT). Steven G. Johnson November 2008 ----------------------------------------------------------------------- First, (almost) the original Nelder-Mead simplex algorithm (NLOPT_LN_NELDERMEAD), as described in: J. A. Nelder and R. Mead, "A simplex method for function minimization," The Computer Journal 7, p. 308-313 (1965). This method is simple and has demonstrated enduring popularity, despite the later discovery that it fails to converge at all for some functions. Anecdotal evidence suggests that it often performs well even for noisy and/or discontinuous objective functions. I would tend to recommend the Subplex method (below) instead, however. The main variation is that I implemented explicit support for bound constraints, using essentially the method described in: J. A. Richardson and J. L. Kuester, "The complex method for constrained optimization," Commun. ACM 16(8), 487-489 (1973). implementing the method described by: M. J. Box, "A new method of constrained optimization and a comparison with other methods," Computer J. 8 (1), 42-52 (1965). Whenever a new point would lie outside the bound constraints, Box advocates moving it "just inside" the constraints. I couldn't see any advantage to using a fixed distance inside the constraints, especially if the optimum is on the constraint, so instead I move the point exactly onto the constraint in that case. The danger with implementing bound constraints in this way (or by Box's method) is that you may collapse the simplex into a lower-dimensional subspace. I'm not aware of a better way, however. In any case, this collapse of the simplex is ameliorated by restarting, such as when Nelder-Mead is used within the Subplex algorithm below. ----------------------------------------------------------------------- Second, I re-implemented Tom Rowan's "Subplex" algorithm. As Rowan expressed a preference that other implementations of his algorithm use a different name, I called my implementation "Sbplx" (NLOPT_LN_SBPLX). Subplex (a variant of Nelder-Mead that uses Nelder-Mead on a sequence of subspaces) is claimed to be much more efficient and robust than the original Nelder-Mead, while retaining the latter's facility with discontinuous objectives, and in my experience these claims seem to be true. (However, I'm not aware of any proof that Subplex is globally convergent, and may fail for some objectives like Nelder-Mead; YMMV.) I used the description of Rowan's algorithm in his PhD thesis: T. Rowan, "Functional Stability Analysis of Numerical Algorithms", Ph.D. thesis, Department of Computer Sciences, University of Texas at Austin, 1990. I would have preferred to use Rowan's original implementation, posted by him on Netlib: http://www.netlib.org/opt/subplex.tgz Unfortunately, the legality of redistributing or modifying this code is unclear. Rowan didn't include any license statement at all with the original code, which makes it technically illegal to redistribute. I contacted Rowan about getting a clear open-source/free-software license for it, and he was very agreeable, but he said he had to think about the specific license choice and would get back to me. Unfortunately, a year later I still haven't heard from him, and his old email address no longer seems to work, so I don't know how to contact him for permission. Since the algorithm is not too complicated, however, I just rewrote it. There seem to be slight differences between the behavior of my implementation and his (probably due to different choices of initial subspace and other slight variations, where his paper was ambiguous), but the number of iterations to converge on my test problems seems to be quite close (within 10% for most problems). The only major difference between my implementation and Rowan's, as far as I can tell, is that I implemented explicit support for bound constraints (via the method in the Box paper as described above). This seems to be a big improvement in the case where the optimum lies against one of the constraints. ----------------------------------------------------------------------- Future possibilities: C. J. Price, I. D. Coope, and D. Byatt, "A convergent variant of the Nelder-Mead algorithm," J. Optim. Theory Appl. 113 (1), p. 5-19 (2002). A. Burmen, J. Puhan, and T. Tuma, "Grid restrained Nelder-Mead algorithm," Computational Optim. Appl. 34(3), 359-375 (2006). Both of these are provably convergent variations of Nelder-Mead; the latter authors claim that theirs is superior. nlopt-2.6.1/src/algs/neldermead/neldermead.h000066400000000000000000000043561345435414600207630ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef NELDERMEAD_H #define NELDERMEAD_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop); nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x,/* in: initial guess, out: minimizer */ double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop, double psi, double *scratch, double *fdiff); nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep0, /* initial step sizes */ nlopt_stopping *stop); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/neldermead/nldrmd.c000066400000000000000000000250251345435414600201320ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include "neldermead.h" #include "redblack.h" /* Nelder-Mead simplex algorithm, used as a subroutine for the Rowan's subplex algorithm. Modified to handle bound constraints ala Richardson and Kuester (1973), as mentioned below. */ /* heuristic "strategy" constants: */ static const double alpha = 1, beta = 0.5, gamm = 2, delta = 0.5; /* sort order in red-black tree: keys [f(x), x] are sorted by f(x) */ static int simplex_compare(double *k1, double *k2) { if (*k1 < *k2) return -1; if (*k1 > *k2) return +1; return k1 - k2; /* tie-breaker */ } /* return 1 if a and b are approximately equal relative to floating-point precision, 0 otherwise */ static int close(double a, double b) { return (fabs(a - b) <= 1e-13 * (fabs(a) + fabs(b))); } /* Perform the reflection xnew = c + scale * (c - xold), returning 0 if xnew == c or xnew == xold (coincident points), 1 otherwise. The reflected point xnew is "pinned" to the lower and upper bounds (lb and ub), as suggested by J. A. Richardson and J. L. Kuester, "The complex method for constrained optimization," Commun. ACM 16(8), 487-489 (1973). This is probably a suboptimal way to handle bound constraints, but I don't know a better way. The main danger with this is that the simplex might collapse into a lower-dimensional hyperplane; this danger can be ameliorated by restarting (as in subplex), however. */ static int reflectpt(int n, double *xnew, const double *c, double scale, const double *xold, const double *lb, const double *ub) { int equalc = 1, equalold = 1, i; for (i = 0; i < n; ++i) { double newx = c[i] + scale * (c[i] - xold[i]); if (newx < lb[i]) newx = lb[i]; if (newx > ub[i]) newx = ub[i]; equalc = equalc && close(newx, c[i]); equalold = equalold && close(newx, xold[i]); xnew[i] = newx; } return !(equalc || equalold); } #define CHECK_EVAL(xc,fc) \ ++ *(stop->nevals_p); \ if (nlopt_stop_forced(stop)) { ret=NLOPT_FORCED_STOP; goto done; } \ if ((fc) <= *minf) { \ *minf = (fc); memcpy(x, (xc), n * sizeof(double)); \ if (*minf < stop->minf_max) { ret=NLOPT_MINF_MAX_REACHED; goto done; } \ } \ if (nlopt_stop_evals(stop)) { ret=NLOPT_MAXEVAL_REACHED; goto done; } \ if (nlopt_stop_time(stop)) { ret=NLOPT_MAXTIME_REACHED; goto done; } /* Internal version of nldrmd_minimize, intended to be used as a subroutine for the subplex method. Three differences compared to nldrmd_minimize: *minf should contain the value of f(x) (so that we don't have to re-evaluate f at the starting x). if psi > 0, then it *replaces* xtol and ftol in stop with the condition that the simplex diameter |xl - xh| must be reduced by a factor of psi ... this is for when nldrmd is used within the subplex method; for ordinary termination tests, set psi = 0. scratch should contain an array of length >= (n+1)*(n+1) + 2*n, used as scratch workspace. On output, *fdiff will contain the difference between the high and low function values of the last simplex. */ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop, double psi, double *scratch, double *fdiff) { double *pts; /* (n+1) x (n+1) array of n+1 points plus function val [0] */ double *c; /* centroid * n */ double *xcur; /* current point */ rb_tree t; /* red-black tree of simplex, sorted by f(x) */ int i, j; double ninv = 1.0 / n; nlopt_result ret = NLOPT_SUCCESS; double init_diam = 0; pts = scratch; c = scratch + (n+1)*(n+1); xcur = c + n; rb_tree_init(&t, simplex_compare); *fdiff = HUGE_VAL; /* initialize the simplex based on the starting xstep */ memcpy(pts+1, x, sizeof(double)*n); pts[0] = *minf; if (*minf < stop->minf_max) { ret=NLOPT_MINF_MAX_REACHED; goto done; } for (i = 0; i < n; ++i) { double *pt = pts + (i+1)*(n+1); memcpy(pt+1, x, sizeof(double)*n); pt[1+i] += xstep[i]; if (pt[1+i] > ub[i]) { if (ub[i] - x[i] > fabs(xstep[i]) * 0.1) pt[1+i] = ub[i]; else /* ub is too close to pt, go in other direction */ pt[1+i] = x[i] - fabs(xstep[i]); } if (pt[1+i] < lb[i]) { if (x[i] - lb[i] > fabs(xstep[i]) * 0.1) pt[1+i] = lb[i]; else {/* lb is too close to pt, go in other direction */ pt[1+i] = x[i] + fabs(xstep[i]); if (pt[1+i] > ub[i]) /* go towards further of lb, ub */ pt[1+i] = 0.5 * ((ub[i] - x[i] > x[i] - lb[i] ? ub[i] : lb[i]) + x[i]); } } if (close(pt[1+i], x[i])) { nlopt_stop_msg(stop, "starting step size led to simplex that was too small in dimension %d: %g is too close to x[%d]=%g", i, pt[1+i], i, x[i]); ret=NLOPT_FAILURE; goto done; } pt[0] = f(n, pt+1, NULL, f_data); CHECK_EVAL(pt+1, pt[0]); } restart: for (i = 0; i < n + 1; ++i) if (!rb_tree_insert(&t, pts + i*(n+1))) { ret = NLOPT_OUT_OF_MEMORY; goto done; } while (1) { rb_node *low = rb_tree_min(&t); rb_node *high = rb_tree_max(&t); double fl = low->k[0], *xl = low->k + 1; double fh = high->k[0], *xh = high->k + 1; double fr; *fdiff = fh - fl; if (init_diam == 0) /* initialize diam. for psi convergence test */ for (i = 0; i < n; ++i) init_diam += fabs(xl[i] - xh[i]); if (psi <= 0 && nlopt_stop_ftol(stop, fl, fh)) { ret = NLOPT_FTOL_REACHED; goto done; } /* compute centroid ... if we cared about the perfomance of this, we could do it iteratively by updating the centroid on each step, but then we would have to be more careful about accumulation of rounding errors... anyway n is unlikely to be very large for Nelder-Mead in practical cases */ memset(c, 0, sizeof(double)*n); for (i = 0; i < n + 1; ++i) { double *xi = pts + i*(n+1) + 1; if (xi != xh) for (j = 0; j < n; ++j) c[j] += xi[j]; } for (i = 0; i < n; ++i) c[i] *= ninv; /* x convergence check: find xcur = max radius from centroid */ memset(xcur, 0, sizeof(double)*n); for (i = 0; i < n + 1; ++i) { double *xi = pts + i*(n+1) + 1; for (j = 0; j < n; ++j) { double dx = fabs(xi[j] - c[j]); if (dx > xcur[j]) xcur[j] = dx; } } for (i = 0; i < n; ++i) xcur[i] += c[i]; if (psi > 0) { double diam = 0; for (i = 0; i < n; ++i) diam += fabs(xl[i] - xh[i]); if (diam < psi * init_diam) { ret = NLOPT_XTOL_REACHED; goto done; } } else if (nlopt_stop_x(stop, c, xcur)) { ret = NLOPT_XTOL_REACHED; goto done; } /* reflection */ if (!reflectpt(n, xcur, c, alpha, xh, lb, ub)) { ret=NLOPT_XTOL_REACHED; goto done; } fr = f(n, xcur, NULL, f_data); CHECK_EVAL(xcur, fr); if (fr < fl) { /* new best point, expand simplex */ if (!reflectpt(n, xh, c, gamm, xh, lb, ub)) { ret=NLOPT_XTOL_REACHED; goto done; } fh = f(n, xh, NULL, f_data); CHECK_EVAL(xh, fh); if (fh >= fr) { /* expanding didn't improve */ fh = fr; memcpy(xh, xcur, sizeof(double)*n); } } else if (fr < rb_tree_pred(high)->k[0]) { /* accept new point */ memcpy(xh, xcur, sizeof(double)*n); fh = fr; } else { /* new worst point, contract */ double fc; if (!reflectpt(n,xcur,c, fh <= fr ? -beta : beta, xh, lb,ub)) { ret=NLOPT_XTOL_REACHED; goto done; } fc = f(n, xcur, NULL, f_data); CHECK_EVAL(xcur, fc); if (fc < fr && fc < fh) { /* successful contraction */ memcpy(xh, xcur, sizeof(double)*n); fh = fc; } else { /* failed contraction, shrink simplex */ rb_tree_destroy(&t); rb_tree_init(&t, simplex_compare); for (i = 0; i < n+1; ++i) { double *pt = pts + i * (n+1); if (pt+1 != xl) { if (!reflectpt(n,pt+1, xl,-delta,pt+1, lb,ub)) { ret = NLOPT_XTOL_REACHED; goto done; } pt[0] = f(n, pt+1, NULL, f_data); CHECK_EVAL(pt+1, pt[0]); } } goto restart; } } high->k[0] = fh; rb_tree_resort(&t, high); } done: rb_tree_destroy(&t); return ret; } nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop) { nlopt_result ret; double *scratch, fdiff; *minf = f(n, x, NULL, f_data); ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; scratch = (double*) malloc(sizeof(double) * ((n+1)*(n+1) + 2*n)); if (!scratch) return NLOPT_OUT_OF_MEMORY; ret = nldrmd_minimize_(n, f, f_data, lb, ub, x, minf, xstep, stop, 0.0, scratch, &fdiff); free(scratch); return ret; } nlopt-2.6.1/src/algs/neldermead/sbplx.c000066400000000000000000000201131345435414600177730ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include "neldermead.h" /* subplex strategy constants: */ static const double psi = 0.25, omega = 0.1; static const int nsmin = 2, nsmax = 5; int sbplx_verbose = 0; /* for debugging */ /* qsort_r comparison function for sorting indices into delta-x array */ static int p_compare(void *dx_, const void *i_, const void *j_) { const double *dx = (const double *) dx_; int i = *((const int *) i_), j = *((const int *) j_); double dxi = fabs(dx[i]), dxj = fabs(dx[j]); return (dxi > dxj ? -1 : (dxi < dxj ? +1 : 0)); } typedef struct { const int *p; /* subspace index permutation */ int is; /* starting index for this subspace */ int n; /* dimension of underlying space */ double *x; /* current x vector */ nlopt_func f; void *f_data; /* the "actual" underlying function */ } subspace_data; /* wrapper around objective function for subspace optimization */ static double subspace_func(unsigned ns, const double *xs, double *grad, void *data) { subspace_data *d = (subspace_data *) data; int i, is = d->is; const int *p = d->p; double *x = d->x; (void) grad; /* should always be NULL here */ for (i = is; i < is + ((int) ns); ++i) x[p[i]] = xs[i-is]; return d->f(d->n, x, NULL, d->f_data); } nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep0, /* initial step sizes */ nlopt_stopping *stop) { nlopt_result ret = NLOPT_SUCCESS; double *xstep, *xprev, *dx, *xs, *lbs, *ubs, *xsstep, *scratch; int *p; /* permuted indices of x sorted by decreasing magnitude |dx| */ int i; subspace_data sd; *minf = f(n, x, NULL, f_data); ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; xstep = (double*)malloc(sizeof(double) * (n*3 + nsmax*4 + (nsmax+1)*(nsmax+1)+2*nsmax)); if (!xstep) return NLOPT_OUT_OF_MEMORY; xprev = xstep + n; dx = xprev + n; xs = dx + n; xsstep = xs + nsmax; lbs = xsstep + nsmax; ubs = lbs + nsmax; scratch = ubs + nsmax; p = (int *) malloc(sizeof(int) * n); if (!p) { free(xstep); return NLOPT_OUT_OF_MEMORY; } memcpy(xstep, xstep0, n * sizeof(double)); memset(dx, 0, n * sizeof(double)); sd.p = p; sd.n = n; sd.x = x; sd.f = f; sd.f_data = f_data; while (1) { double normi = 0; double normdx = 0; int ns, nsubs = 0; int nevals = *(stop->nevals_p); double fdiff, fdiff_max = 0; memcpy(xprev, x, n * sizeof(double)); /* sort indices into the progress vector dx by decreasing order of magnitude |dx| */ for (i = 0; i < n; ++i) p[i] = i; nlopt_qsort_r(p, (size_t) n, sizeof(int), dx, p_compare); /* find the subspaces, and perform nelder-mead on each one */ for (i = 0; i < n; ++i) normdx += fabs(dx[i]); /* L1 norm */ for (i = 0; i + nsmin < n; i += ns) { /* find subspace starting at index i */ int k, nk; double ns_goodness = -HUGE_VAL, norm = normi; nk = i+nsmax > n ? n : i+nsmax; /* max k for this subspace */ for (k = i; k < i+nsmin-1; ++k) norm += fabs(dx[p[k]]); ns = nsmin; for (k = i+nsmin-1; k < nk; ++k) { double goodness; norm += fabs(dx[p[k]]); /* remaining subspaces must be big enough to partition */ if (n-(k+1) < nsmin) continue; /* maximize figure of merit defined by Rowan thesis: look for sudden drops in average |dx| */ if (k+1 < n) goodness = norm/(k+1) - (normdx-norm)/(n-(k+1)); else goodness = normdx/n; if (goodness > ns_goodness) { ns_goodness = goodness; ns = (k+1)-i; } } for (k = i; k < i+ns; ++k) normi += fabs(dx[p[k]]); /* do nelder-mead on subspace of dimension ns starting w/i */ sd.is = i; for (k = i; k < i+ns; ++k) { xs[k-i] = x[p[k]]; xsstep[k-i] = xstep[p[k]]; lbs[k-i] = lb[p[k]]; ubs[k-i] = ub[p[k]]; } ++nsubs; nevals = *(stop->nevals_p); ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, xsstep, stop, psi, scratch, &fdiff); if (fdiff > fdiff_max) fdiff_max = fdiff; if (sbplx_verbose) printf("%d NM iterations for (%d,%d) subspace\n", *(stop->nevals_p) - nevals, sd.is, ns); for (k = i; k < i+ns; ++k) x[p[k]] = xs[k-i]; if (ret == NLOPT_FAILURE) { ret=NLOPT_XTOL_REACHED; goto done; } if (ret != NLOPT_XTOL_REACHED) goto done; } /* nelder-mead on last subspace */ ns = n - i; sd.is = i; for (; i < n; ++i) { xs[i-sd.is] = x[p[i]]; xsstep[i-sd.is] = xstep[p[i]]; lbs[i-sd.is] = lb[p[i]]; ubs[i-sd.is] = ub[p[i]]; } ++nsubs; nevals = *(stop->nevals_p); ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, xsstep, stop, psi, scratch, &fdiff); if (fdiff > fdiff_max) fdiff_max = fdiff; if (sbplx_verbose) printf("sbplx: %d NM iterations for (%d,%d) subspace\n", *(stop->nevals_p) - nevals, sd.is, ns); for (i = sd.is; i < n; ++i) x[p[i]] = xs[i-sd.is]; if (ret == NLOPT_FAILURE) { ret=NLOPT_XTOL_REACHED; goto done; } if (ret != NLOPT_XTOL_REACHED) goto done; /* termination tests: */ if (nlopt_stop_ftol(stop, *minf, *minf + fdiff_max)) { ret = NLOPT_FTOL_REACHED; goto done; } if (nlopt_stop_x(stop, x, xprev)) { int j; /* as explained in Rowan's thesis, it is important to check |xstep| as well as |x-xprev|, since if the step size is too large (in early iterations), the inner Nelder-Mead may not make much progress */ for (j = 0; j < n; ++j) if (fabs(xstep[j]) * psi > stop->xtol_abs[j] && fabs(xstep[j]) * psi > stop->xtol_rel * fabs(x[j])) break; if (j == n) { ret = NLOPT_XTOL_REACHED; goto done; } } /* compute change in optimal point */ for (i = 0; i < n; ++i) dx[i] = x[i] - xprev[i]; /* setting stepsizes */ { double scale; if (nsubs == 1) scale = psi; else { double stepnorm = 0, dxnorm = 0; for (i = 0; i < n; ++i) { stepnorm += fabs(xstep[i]); dxnorm += fabs(dx[i]); } scale = dxnorm / stepnorm; if (scale < omega) scale = omega; if (scale > 1/omega) scale = 1/omega; } if (sbplx_verbose) printf("sbplx: stepsize scale factor = %g\n", scale); for (i = 0; i < n; ++i) xstep[i] = (dx[i] == 0) ? -(xstep[i] * scale) : copysign(xstep[i] * scale, dx[i]); } } done: free(p); free(xstep); return ret; } nlopt-2.6.1/src/algs/newuoa/000077500000000000000000000000001345435414600157005ustar00rootroot00000000000000nlopt-2.6.1/src/algs/newuoa/COPYRIGHT000066400000000000000000000022661345435414600172010ustar00rootroot00000000000000/* Copyright (c) 2004 M. J. D. Powell (mjdp@cam.ac.uk) * Copyright (c) 2007-2011 Massachusetts Institute of Technology * * 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. */ nlopt-2.6.1/src/algs/newuoa/README000066400000000000000000000031131345435414600165560ustar00rootroot00000000000000This is the NEWUOA software by M. J. D. Powell, which performs derivative-free unconstrained optimization using an iteratively constructred quadratic approximation for the objective function. See: M. J. D. Powell, "The NEWUOA software for unconstrained optimization without derivatives," Proc. 40th Workshop on Large Scale Nonlinear Optimization (Erice, Italy, 2004). The C translation by S. G. Johnson (2008) includes a few minor modifications, mainly to use the NLopt stopping criteria (and to take the objective function as an argument rather than a global). The C translation also includes a variant (NEWUOA_BOUND, when the lb and ub parameters to newuoa are non-NULL) that is substantially modified in order to support bound constraints on the input variables. In the original NEWUOA algorithm, Powell solved the quadratic subproblems (in routines TRSAPP and BIGLAG) in a spherical trust region via a truncated conjugate-gradient algorithm. In the new variant, we use the MMA algorithm for these subproblems to solve them with both bound constraints and a spherical trust region. In principle, we should also change the BIGDEN subroutine in a similar way (since BIGDEN also approximately solves a trust-region subproblem), but instead I just truncated its result to the bounds (which probably gives suboptimal convergence, but BIGDEN is called only very rarely in practice). The original Fortran code was released by Powell with "no restrictions or charges", and the C translation by S. G. Johnson is released in a similar spirit under the MIT License (see the COPYRIGHT file in this directory). nlopt-2.6.1/src/algs/newuoa/README.orig000066400000000000000000000046761345435414600175340ustar00rootroot00000000000000 This is the Fortran version of NEWUOA. Its purpose is to seek the least value of a function F of several variables, when derivatives are not available, where F is specified by the user through a subroutine called CALFUN. The algorithm is intended to change the variables to values that are close to a local minimum of F. The user, however, should assume responsibility for finding out if the calculations are satisfactory, by considering carefully the values of F that occur. The method is described in the report "The NEWUOA software for unconstrained optimization without derivatives", which is available on the web at www.damtp.cam.ac.uk, where you have to click on Numerical Analysis and then on Reports, the number of the report being NA2004/08. Let N be the number of variables. The main new feature of the method is that quadratic models are updated using only about NPT=2N+1 interpolation conditions, the remaining freedom being taken up by minimizing the Frobenius norm of the change to the second derivative matrix of the model. The new software was developed from UOBYQA, which also forms quadratic models from interpolation conditions. That method requires NPT=(N+1)(N+2)/2 conditions, however, because they have to define all the parameters of the model. The least Frobenius norm updating procedure with NPT=2N+1 is usually much more efficient when N is large, because the work of each iteration is much less than before, and in some experiments the number of calculations of the objective function seems to be only of magnitude N. The attachments in sequence are a suitable Makefile, followed by a main program and a CALFUN routine for the Chebyquad problems, in order to provide an example for testing. Then NEWUOA and its five auxiliary routines, namely NEWUOB, BIGDEN, BIGLAG, TRSAPP and UPDATE, are given. Finally, the computed output that the author obtained for the Chebyquad problems is listed. The way of calling NEWUOA should be clear from the Chebyquad example and from the comments of that subroutine. It is hoped that the software will be helpful to much future research and to many applications. There are no restrictions on or charges for its use. If you wish to refer to it, please cite the DAMTP report that is mentioned above, which has been submitted for publication in the proceedings of the 40th Workshop on Large Scale Nonlinear Optimization (Erice, Italy, 2004). December 16th, 2004 M.J.D. Powell (mjdp@cam.ac.uk) nlopt-2.6.1/src/algs/newuoa/newuoa.c000066400000000000000000002064741345435414600173570ustar00rootroot00000000000000/* Copyright (c) 2004 M. J. D. Powell (mjdp@cam.ac.uk) * Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* NEWUOA derivative-free optimization algorithm by M. J. D. Powell. Original Fortran code by Powell (2004). Converted via f2c, cleaned up, and incorporated into NLopt by S. G. Johnson (2008). See README. */ #include #include #include #include #include "newuoa.h" #define MIN2(a,b) ((a) <= (b) ? (a) : (b)) #define MAX2(a,b) ((a) >= (b) ? (a) : (b)) /*************************************************************************/ /* trsapp.f */ typedef struct { int npt; double *xpt, *pq, *hq, *gq, *xopt; double *hd; int iter; } quad_model_data; static double quad_model(unsigned n, const double *x, double *grad, void *data) { quad_model_data *d = (quad_model_data *) data; const double *xpt = d->xpt, *pq = d->pq, *hq = d->hq, *gq = d->gq, *xopt = d->xopt; double *hd = d->hd; int npt = d->npt, k; unsigned i, j; double val = 0; /* first, set hd to be Hessian matrix times x */ memset(hd, 0, sizeof(double) * n); /* implicit Hessian terms (a sum of outer products of xpt vectors) */ for (k = 0; k < npt; ++k) { double temp = 0; for (j = 0; j < n; ++j) temp += xpt[k + j * npt] * (xopt[j] + x[j]); temp *= pq[k]; for (i = 0; i < n; ++i) hd[i] += temp * xpt[k + i * npt]; } /* explicit Hessian terms (stored as compressed lower triangle hq) */ k = 0; for (j = 0; j < n; ++j) { for (i = 0; i < j; ++i) { hd[j] += hq[k] * (xopt[i] + x[i]); hd[i] += hq[k] * (xopt[j] + x[j]); ++k; } hd[j] += hq[k++] * (xopt[j] + x[j]); } for (i = 0; i < n; ++i) { val += (gq[i] + 0.5 * hd[i]) * (xopt[i] + x[i]); if (grad) grad[i] = gq[i] + hd[i]; } d->iter++; return val; } /* constraint function to enforce |x|^2 <= rho*rho */ static double rho_constraint(unsigned n, const double *x, double *grad, void *data) { double rho = *((double *) data); double val = - rho*rho; unsigned i; for (i = 0; i < n; ++i) val += x[i] * x[i]; if (grad) for (i = 0; i < n; ++i) grad[i] = 2*x[i]; return val; } static nlopt_result trsapp_(int *n, int *npt, double *xopt, double *xpt, double *gq, double *hq, double *pq, double *delta, double *step, double *d__, double *g, double *hd, double *hs, double *crvmin, const double *xbase, const double *lb, const double *ub) { /* System generated locals */ int xpt_dim1, xpt_offset, i__1, i__2; double d__1, d__2; /* Local variables */ int i__, j, k; double dd = 0.0, cf, dg, gg = 0.0; int ih; double ds, sg = 0.0; int iu; double ss, dhd, dhs, cth, sgk, shs = 0.0, sth, qadd, half, qbeg, qred = 0.0, qmin, temp, qsav, qnew, zero, ggbeg = 0.0, alpha, angle, reduc; int iterc; double ggsav, delsq, tempa = 0.0, tempb = 0.0; int isave; double bstep = 0.0, ratio, twopi; int itersw; double angtest; int itermax; /* N is the number of variables of a quadratic objective function, Q say. */ /* The arguments NPT, XOPT, XPT, GQ, HQ and PQ have their usual meanings, */ /* in order to define the current quadratic model Q. */ /* DELTA is the trust region radius, and has to be positive. */ /* STEP will be set to the calculated trial step. */ /* The arrays D, G, HD and HS will be used for working space. */ /* CRVMIN will be set to the least curvature of H along the conjugate */ /* directions that occur, except that it is set to zero if STEP goes */ /* all the way to the trust region boundary. */ /* The calculation of STEP begins with the truncated conjugate gradient */ /* method. If the boundary of the trust region is reached, then further */ /* changes to STEP may be made, each one being in the 2D space spanned */ /* by the current STEP and the corresponding gradient of Q. Thus STEP */ /* should provide a substantial reduction to Q within the trust region. */ /* Initialization, which includes setting HD to H times XOPT. */ /* Parameter adjustments */ xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xopt; --gq; --hq; --pq; --step; --d__; --g; --hd; --hs; if (lb && ub) { nlopt_opt opt; double *slb, *sub, *xtol, minf, crv; nlopt_result ret; quad_model_data qmd; qmd.npt = *npt; qmd.xpt = &xpt[1 + 1 * xpt_dim1]; qmd.pq = &pq[1]; qmd.hq = &hq[1]; qmd.gq = &gq[1]; qmd.xopt = &xopt[1]; qmd.hd = &hd[1]; qmd.iter = 0; slb = &g[1]; sub = &hs[1]; xtol = &d__[1]; for (j = 0; j < *n; ++j) { slb[j] = -(sub[j] = *delta); if (slb[j] < lb[j] - xbase[j] - xopt[j+1]) slb[j] = lb[j] - xbase[j] - xopt[j+1]; if (sub[j] > ub[j] - xbase[j] - xopt[j+1]) sub[j] = ub[j] - xbase[j] - xopt[j+1]; if (slb[j] > 0) slb[j] = 0; if (sub[j] < 0) sub[j] = 0; xtol[j] = 1e-7 * *delta; /* absolute x tolerance */ } memset(&step[1], 0, sizeof(double) * *n); opt = nlopt_create(NLOPT_LD_MMA, *n); nlopt_set_min_objective(opt, quad_model, &qmd); nlopt_add_inequality_constraint(opt, rho_constraint, delta, 0.0); nlopt_set_lower_bounds(opt, slb); nlopt_set_upper_bounds(opt, sub); nlopt_set_xtol_abs(opt, xtol); nlopt_set_maxeval(opt, 1000); ret = nlopt_optimize(opt, &step[1], &minf); nlopt_destroy(opt); if (rho_constraint(*n, &step[1], 0, delta) > -1e-6*(*delta)*(*delta)) crv = 0; else { for (j = 1; j <= *n; ++j) d__[j] = step[j] - xopt[j]; quad_model(*n, &d__[1], &g[1], &qmd); crv = gg = 0; for (j = 1; j <= *n; ++j) { crv += step[j] * (g[j] - gq[j]); gg += step[j] * step[j]; } if (gg <= 1e-16 * crv) crv = 1e16; else crv = crv / gg; } *crvmin = crv; return ret; } /* Function Body */ half = .5; zero = 0.; twopi = atan(1.) * 8.; delsq = *delta * *delta; iterc = 0; itermax = *n; itersw = itermax; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L10: */ d__[i__] = xopt[i__]; } goto L170; /* Prepare for the first line search. */ L20: qred = zero; dd = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { step[i__] = zero; hs[i__] = zero; g[i__] = gq[i__] + hd[i__]; d__[i__] = -g[i__]; /* L30: */ /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; } *crvmin = zero; if (dd == zero) { goto L160; } ds = zero; ss = zero; gg = dd; ggbeg = gg; /* Calculate the step to the trust region boundary and the product HD. */ L40: ++iterc; temp = delsq - ss; bstep = temp / (ds + sqrt(ds * ds + dd * temp)); goto L170; L50: dhd = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L60: */ dhd += d__[j] * hd[j]; } /* Update CRVMIN and set the step-length ALPHA. */ alpha = bstep; if (dhd > zero) { temp = dhd / dd; if (iterc == 1) { *crvmin = temp; } *crvmin = MIN2(*crvmin,temp); /* Computing MIN */ d__1 = alpha, d__2 = gg / dhd; alpha = MIN2(d__1,d__2); } qadd = alpha * (gg - half * alpha * dhd); qred += qadd; /* Update STEP and HS. */ ggsav = gg; gg = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { step[i__] += alpha * d__[i__]; hs[i__] += alpha * hd[i__]; /* L70: */ /* Computing 2nd power */ d__1 = g[i__] + hs[i__]; gg += d__1 * d__1; } /* Begin another conjugate direction iteration if required. */ if (alpha < bstep) { if (qadd <= qred * .01) { goto L160; } if (gg <= ggbeg * 1e-4) { goto L160; } if (iterc == itermax) { goto L160; } temp = gg / ggsav; dd = zero; ds = zero; ss = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = temp * d__[i__] - g[i__] - hs[i__]; /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; ds += d__[i__] * step[i__]; /* L80: */ /* Computing 2nd power */ d__1 = step[i__]; ss += d__1 * d__1; } if (ds <= zero) { goto L160; } if (ss < delsq) { goto L40; } } *crvmin = zero; itersw = iterc; /* Test whether an alternative iteration is required. */ L90: if (gg <= ggbeg * 1e-4) { goto L160; } sg = zero; shs = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sg += step[i__] * g[i__]; /* L100: */ shs += step[i__] * hs[i__]; } sgk = sg + shs; angtest = sgk / sqrt(gg * delsq); if (angtest <= -.99) { goto L160; } /* Begin the alternative iteration by calculating D and HD and some */ /* scalar products. */ ++iterc; temp = sqrt(delsq * gg - sgk * sgk); tempa = delsq / temp; tempb = sgk / temp; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L110: */ d__[i__] = tempa * (g[i__] + hs[i__]) - tempb * step[i__]; } goto L170; L120: dg = zero; dhd = zero; dhs = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dg += d__[i__] * g[i__]; dhd += hd[i__] * d__[i__]; /* L130: */ dhs += hd[i__] * step[i__]; } /* Seek the value of the angle that minimizes Q. */ cf = half * (shs - dhd); qbeg = sg + cf; qsav = qbeg; qmin = qbeg; isave = 0; iu = 49; temp = twopi / (double) (iu + 1); i__1 = iu; for (i__ = 1; i__ <= i__1; ++i__) { angle = (double) i__ * temp; cth = cos(angle); sth = sin(angle); qnew = (sg + cf * cth) * cth + (dg + dhs * cth) * sth; if (qnew < qmin) { qmin = qnew; isave = i__; tempa = qsav; } else if (i__ == isave + 1) { tempb = qnew; } /* L140: */ qsav = qnew; } if ((double) isave == zero) { tempa = qnew; } if (isave == iu) { tempb = qbeg; } angle = zero; if (tempa != tempb) { tempa -= qmin; tempb -= qmin; angle = half * (tempa - tempb) / (tempa + tempb); } angle = temp * ((double) isave + angle); /* Calculate the new STEP and HS. Then test for convergence. */ cth = cos(angle); sth = sin(angle); reduc = qbeg - (sg + cf * cth) * cth - (dg + dhs * cth) * sth; gg = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { step[i__] = cth * step[i__] + sth * d__[i__]; hs[i__] = cth * hs[i__] + sth * hd[i__]; /* L150: */ /* Computing 2nd power */ d__1 = g[i__] + hs[i__]; gg += d__1 * d__1; } qred += reduc; ratio = reduc / qred; if (iterc < itermax && ratio > .01) { goto L90; } L160: return NLOPT_SUCCESS; /* The following instructions act as a subroutine for setting the vector */ /* HD to the vector D multiplied by the second derivative matrix of Q. */ /* They are called from three different places, which are distinguished */ /* by the value of ITERC. */ L170: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L180: */ hd[i__] = zero; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { temp = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L190: */ temp += xpt[k + j * xpt_dim1] * d__[j]; } temp *= pq[k]; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L200: */ hd[i__] += temp * xpt[k + i__ * xpt_dim1]; } } ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; if (i__ < j) { hd[j] += hq[ih] * d__[i__]; } /* L210: */ hd[i__] += hq[ih] * d__[j]; } } if (iterc == 0) { goto L20; } if (iterc <= itersw) { goto L50; } goto L120; } /* trsapp_ */ /*************************************************************************/ /* bigden.f */ static nlopt_result bigden_(int *n, int *npt, double *xopt, double *xpt, double *bmat, double *zmat, int *idz, int *ndim, int *kopt, int *knew, double *d__, double *w, double *vlag, double *beta, double *s, double *wvec, double *prod, const double *xbase, const double *lb, const double *ub) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, wvec_dim1, wvec_offset, prod_dim1, prod_offset, i__1, i__2; double d__1; /* Local variables */ int i__, j, k; double dd; int jc; double ds; int ip, iu, nw; double ss, den[9], one, par[9], tau, sum, two, diff, half, temp; int ksav; double step; int nptm; double zero, alpha, angle, denex[9]; int iterc; double tempa, tempb, tempc; int isave; double ssden, dtest, quart, xoptd, twopi, xopts, denold, denmax, densav, dstemp, sumold, sstemp, xoptsq; /* N is the number of variables. */ /* NPT is the number of interpolation equations. */ /* XOPT is the best interpolation point so far. */ /* XPT contains the coordinates of the current interpolation points. */ /* BMAT provides the last N columns of H. */ /* ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H. */ /* NDIM is the first dimension of BMAT and has the value NPT+N. */ /* KOPT is the index of the optimal interpolation point. */ /* KNEW is the index of the interpolation point that is going to be moved. */ /* D will be set to the step from XOPT to the new point, and on entry it */ /* should be the D that was calculated by the last call of BIGLAG. The */ /* length of the initial D provides a trust region bound on the final D. */ /* W will be set to Wcheck for the final choice of D. */ /* VLAG will be set to Theta*Wcheck+e_b for the final choice of D. */ /* BETA will be set to the value that will occur in the updating formula */ /* when the KNEW-th interpolation point is moved to its new position. */ /* S, WVEC, PROD and the private arrays DEN, DENEX and PAR will be used */ /* for working space. */ /* D is calculated in a way that should provide a denominator with a large */ /* modulus in the updating formula when the KNEW-th interpolation point is */ /* shifted to the new position XOPT+D. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xopt; prod_dim1 = *ndim; prod_offset = 1 + prod_dim1; prod -= prod_offset; wvec_dim1 = *ndim; wvec_offset = 1 + wvec_dim1; wvec -= wvec_offset; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --d__; --w; --vlag; --s; /* Function Body */ half = .5; one = 1.; quart = .25; two = 2.; zero = 0.; twopi = atan(one) * 8.; nptm = *npt - *n - 1; /* Store the first NPT elements of the KNEW-th column of H in W(N+1) */ /* to W(N+NPT). */ i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L10: */ w[*n + k] = zero; } i__1 = nptm; for (j = 1; j <= i__1; ++j) { temp = zmat[*knew + j * zmat_dim1]; if (j < *idz) { temp = -temp; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L20: */ w[*n + k] += temp * zmat[k + j * zmat_dim1]; } } alpha = w[*n + *knew]; /* The initial search direction D is taken from the last call of BIGLAG, */ /* and the initial S is set below, usually to the direction from X_OPT */ /* to X_KNEW, but a different direction to an interpolation point may */ /* be chosen, in order to prevent S from being nearly parallel to D. */ dd = zero; ds = zero; ss = zero; xoptsq = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; s[i__] = xpt[*knew + i__ * xpt_dim1] - xopt[i__]; ds += d__[i__] * s[i__]; /* Computing 2nd power */ d__1 = s[i__]; ss += d__1 * d__1; /* L30: */ /* Computing 2nd power */ d__1 = xopt[i__]; xoptsq += d__1 * d__1; } if (ds * ds > dd * .99 * ss) { ksav = *knew; dtest = ds * ds / ss; i__2 = *npt; for (k = 1; k <= i__2; ++k) { if (k != *kopt) { dstemp = zero; sstemp = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { diff = xpt[k + i__ * xpt_dim1] - xopt[i__]; dstemp += d__[i__] * diff; /* L40: */ sstemp += diff * diff; } if (sstemp == 0) return NLOPT_ROUNDOFF_LIMITED; if (dstemp * dstemp / sstemp < dtest) { ksav = k; dtest = dstemp * dstemp / sstemp; ds = dstemp; ss = sstemp; } } /* L50: */ } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L60: */ s[i__] = xpt[ksav + i__ * xpt_dim1] - xopt[i__]; } } ssden = dd * ss - ds * ds; iterc = 0; densav = zero; /* Begin the iteration by overwriting S with a vector that has the */ /* required length and direction. */ L70: ++iterc; if (ssden < 0) return NLOPT_ROUNDOFF_LIMITED; temp = one / sqrt(ssden); xoptd = zero; xopts = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { s[i__] = temp * (dd * s[i__] - ds * d__[i__]); xoptd += xopt[i__] * d__[i__]; /* L80: */ if (nlopt_isinf(s[i__])) return NLOPT_ROUNDOFF_LIMITED; xopts += xopt[i__] * s[i__]; } /* Set the coefficients of the first two terms of BETA. */ tempa = half * xoptd * xoptd; tempb = half * xopts * xopts; den[0] = dd * (xoptsq + half * dd) + tempa + tempb; den[1] = two * xoptd * dd; den[2] = two * xopts * dd; den[3] = tempa - tempb; den[4] = xoptd * xopts; for (i__ = 6; i__ <= 9; ++i__) { /* L90: */ den[i__ - 1] = zero; } /* Put the coefficients of Wcheck in WVEC. */ i__2 = *npt; for (k = 1; k <= i__2; ++k) { tempa = zero; tempb = zero; tempc = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { tempa += xpt[k + i__ * xpt_dim1] * d__[i__]; tempb += xpt[k + i__ * xpt_dim1] * s[i__]; /* L100: */ tempc += xpt[k + i__ * xpt_dim1] * xopt[i__]; } wvec[k + wvec_dim1] = quart * (tempa * tempa + tempb * tempb); wvec[k + (wvec_dim1 << 1)] = tempa * tempc; wvec[k + wvec_dim1 * 3] = tempb * tempc; wvec[k + (wvec_dim1 << 2)] = quart * (tempa * tempa - tempb * tempb); /* L110: */ wvec[k + wvec_dim1 * 5] = half * tempa * tempb; } i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { ip = i__ + *npt; wvec[ip + wvec_dim1] = zero; wvec[ip + (wvec_dim1 << 1)] = d__[i__]; wvec[ip + wvec_dim1 * 3] = s[i__]; wvec[ip + (wvec_dim1 << 2)] = zero; /* L120: */ wvec[ip + wvec_dim1 * 5] = zero; } /* Put the coefficents of THETA*Wcheck in PROD. */ for (jc = 1; jc <= 5; ++jc) { nw = *npt; if (jc == 2 || jc == 3) { nw = *ndim; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L130: */ prod[k + jc * prod_dim1] = zero; } i__2 = nptm; for (j = 1; j <= i__2; ++j) { sum = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L140: */ sum += zmat[k + j * zmat_dim1] * wvec[k + jc * wvec_dim1]; } if (j < *idz) { sum = -sum; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L150: */ prod[k + jc * prod_dim1] += sum * zmat[k + j * zmat_dim1]; } } if (nw == *ndim) { i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L160: */ sum += bmat[k + j * bmat_dim1] * wvec[*npt + j + jc * wvec_dim1]; } /* L170: */ prod[k + jc * prod_dim1] += sum; } } i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; i__2 = nw; for (i__ = 1; i__ <= i__2; ++i__) { /* L180: */ sum += bmat[i__ + j * bmat_dim1] * wvec[i__ + jc * wvec_dim1]; } /* L190: */ prod[*npt + j + jc * prod_dim1] = sum; } } /* Include in DEN the part of BETA that depends on THETA. */ i__1 = *ndim; for (k = 1; k <= i__1; ++k) { sum = zero; for (i__ = 1; i__ <= 5; ++i__) { par[i__ - 1] = half * prod[k + i__ * prod_dim1] * wvec[k + i__ * wvec_dim1]; /* L200: */ sum += par[i__ - 1]; } den[0] = den[0] - par[0] - sum; tempa = prod[k + prod_dim1] * wvec[k + (wvec_dim1 << 1)] + prod[k + ( prod_dim1 << 1)] * wvec[k + wvec_dim1]; tempb = prod[k + (prod_dim1 << 1)] * wvec[k + (wvec_dim1 << 2)] + prod[k + (prod_dim1 << 2)] * wvec[k + (wvec_dim1 << 1)]; tempc = prod[k + prod_dim1 * 3] * wvec[k + wvec_dim1 * 5] + prod[k + prod_dim1 * 5] * wvec[k + wvec_dim1 * 3]; den[1] = den[1] - tempa - half * (tempb + tempc); den[5] -= half * (tempb - tempc); tempa = prod[k + prod_dim1] * wvec[k + wvec_dim1 * 3] + prod[k + prod_dim1 * 3] * wvec[k + wvec_dim1]; tempb = prod[k + (prod_dim1 << 1)] * wvec[k + wvec_dim1 * 5] + prod[k + prod_dim1 * 5] * wvec[k + (wvec_dim1 << 1)]; tempc = prod[k + prod_dim1 * 3] * wvec[k + (wvec_dim1 << 2)] + prod[k + (prod_dim1 << 2)] * wvec[k + wvec_dim1 * 3]; den[2] = den[2] - tempa - half * (tempb - tempc); den[6] -= half * (tempb + tempc); tempa = prod[k + prod_dim1] * wvec[k + (wvec_dim1 << 2)] + prod[k + ( prod_dim1 << 2)] * wvec[k + wvec_dim1]; den[3] = den[3] - tempa - par[1] + par[2]; tempa = prod[k + prod_dim1] * wvec[k + wvec_dim1 * 5] + prod[k + prod_dim1 * 5] * wvec[k + wvec_dim1]; tempb = prod[k + (prod_dim1 << 1)] * wvec[k + wvec_dim1 * 3] + prod[k + prod_dim1 * 3] * wvec[k + (wvec_dim1 << 1)]; den[4] = den[4] - tempa - half * tempb; den[7] = den[7] - par[3] + par[4]; tempa = prod[k + (prod_dim1 << 2)] * wvec[k + wvec_dim1 * 5] + prod[k + prod_dim1 * 5] * wvec[k + (wvec_dim1 << 2)]; /* L210: */ den[8] -= half * tempa; } /* Extend DEN so that it holds all the coefficients of DENOM. */ sum = zero; for (i__ = 1; i__ <= 5; ++i__) { /* Computing 2nd power */ d__1 = prod[*knew + i__ * prod_dim1]; par[i__ - 1] = half * (d__1 * d__1); /* L220: */ sum += par[i__ - 1]; } denex[0] = alpha * den[0] + par[0] + sum; tempa = two * prod[*knew + prod_dim1] * prod[*knew + (prod_dim1 << 1)]; tempb = prod[*knew + (prod_dim1 << 1)] * prod[*knew + (prod_dim1 << 2)]; tempc = prod[*knew + prod_dim1 * 3] * prod[*knew + prod_dim1 * 5]; denex[1] = alpha * den[1] + tempa + tempb + tempc; denex[5] = alpha * den[5] + tempb - tempc; tempa = two * prod[*knew + prod_dim1] * prod[*knew + prod_dim1 * 3]; tempb = prod[*knew + (prod_dim1 << 1)] * prod[*knew + prod_dim1 * 5]; tempc = prod[*knew + prod_dim1 * 3] * prod[*knew + (prod_dim1 << 2)]; denex[2] = alpha * den[2] + tempa + tempb - tempc; denex[6] = alpha * den[6] + tempb + tempc; tempa = two * prod[*knew + prod_dim1] * prod[*knew + (prod_dim1 << 2)]; denex[3] = alpha * den[3] + tempa + par[1] - par[2]; tempa = two * prod[*knew + prod_dim1] * prod[*knew + prod_dim1 * 5]; denex[4] = alpha * den[4] + tempa + prod[*knew + (prod_dim1 << 1)] * prod[ *knew + prod_dim1 * 3]; denex[7] = alpha * den[7] + par[3] - par[4]; denex[8] = alpha * den[8] + prod[*knew + (prod_dim1 << 2)] * prod[*knew + prod_dim1 * 5]; /* Seek the value of the angle that maximizes the modulus of DENOM. */ sum = denex[0] + denex[1] + denex[3] + denex[5] + denex[7]; denold = sum; denmax = sum; isave = 0; iu = 49; temp = twopi / (double) (iu + 1); par[0] = one; i__1 = iu; for (i__ = 1; i__ <= i__1; ++i__) { angle = (double) i__ * temp; par[1] = cos(angle); par[2] = sin(angle); for (j = 4; j <= 8; j += 2) { par[j - 1] = par[1] * par[j - 3] - par[2] * par[j - 2]; /* L230: */ par[j] = par[1] * par[j - 2] + par[2] * par[j - 3]; } sumold = sum; sum = zero; for (j = 1; j <= 9; ++j) { /* L240: */ sum += denex[j - 1] * par[j - 1]; } if (fabs(sum) > fabs(denmax)) { denmax = sum; isave = i__; tempa = sumold; } else if (i__ == isave + 1) { tempb = sum; } /* L250: */ } if (isave == 0) { tempa = sum; } if (isave == iu) { tempb = denold; } step = zero; if (tempa != tempb) { tempa -= denmax; tempb -= denmax; step = half * (tempa - tempb) / (tempa + tempb); } angle = temp * ((double) isave + step); /* Calculate the new parameters of the denominator, the new VLAG vector */ /* and the new D. Then test for convergence. */ par[1] = cos(angle); par[2] = sin(angle); for (j = 4; j <= 8; j += 2) { par[j - 1] = par[1] * par[j - 3] - par[2] * par[j - 2]; /* L260: */ par[j] = par[1] * par[j - 2] + par[2] * par[j - 3]; } *beta = zero; denmax = zero; for (j = 1; j <= 9; ++j) { *beta += den[j - 1] * par[j - 1]; /* L270: */ denmax += denex[j - 1] * par[j - 1]; } i__1 = *ndim; for (k = 1; k <= i__1; ++k) { vlag[k] = zero; for (j = 1; j <= 5; ++j) { /* L280: */ vlag[k] += prod[k + j * prod_dim1] * par[j - 1]; } } tau = vlag[*knew]; dd = zero; tempa = zero; tempb = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = par[1] * d__[i__] + par[2] * s[i__]; w[i__] = xopt[i__] + d__[i__]; /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; tempa += d__[i__] * w[i__]; /* L290: */ tempb += w[i__] * w[i__]; } if (iterc >= *n) { goto L340; } if (iterc > 1) { densav = MAX2(densav,denold); } if (fabs(denmax) <= fabs(densav) * 1.1) { goto L340; } densav = denmax; /* Set S to half the gradient of the denominator with respect to D. */ /* Then branch for the next iteration. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = tempa * xopt[i__] + tempb * d__[i__] - vlag[*npt + i__]; /* L300: */ s[i__] = tau * bmat[*knew + i__ * bmat_dim1] + alpha * temp; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L310: */ sum += xpt[k + j * xpt_dim1] * w[j]; } if (nlopt_isinf(tau * w[*n + k]) || nlopt_isinf(alpha * vlag[k])) return NLOPT_ROUNDOFF_LIMITED; temp = (tau * w[*n + k] - alpha * vlag[k]) * sum; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L320: */ s[i__] += temp * xpt[k + i__ * xpt_dim1]; } } ss = zero; ds = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing 2nd power */ d__1 = s[i__]; ss += d__1 * d__1; /* L330: */ ds += d__[i__] * s[i__]; } ssden = dd * ss - ds * ds; if (ssden >= dd * 1e-8 * ss) { goto L70; } /* Set the vector W before the RETURN from the subroutine. */ L340: /* SGJ, 2008: crude hack: truncate d to [lb,ub] bounds if given */ if (lb && ub) { for (k = 1; k <= *n; ++k) { if (d__[k] > ub[k-1] - xbase[k-1] - xopt[k]) d__[k] = ub[k-1] - xbase[k-1] - xopt[k]; else if (d__[k] < lb[k-1] - xbase[k-1] - xopt[k]) d__[k] = lb[k-1] - xbase[k-1] - xopt[k]; } } i__2 = *ndim; for (k = 1; k <= i__2; ++k) { w[k] = zero; for (j = 1; j <= 5; ++j) { /* L350: */ w[k] += wvec[k + j * wvec_dim1] * par[j - 1]; } } vlag[*kopt] += one; return NLOPT_SUCCESS; } /* bigden_ */ /*************************************************************************/ /* biglag.f */ typedef struct { int npt, ndim, iter; double *hcol, *xpt, *bmat, *xopt; int flipsign; } lag_data; /* the Lagrange function, whose absolute value biglag maximizes */ static double lag(unsigned n, const double *dx, double *grad, void *data) { lag_data *d = (lag_data *) data; int i, npt = d->npt, ndim = d->ndim; unsigned j; const double *hcol = d->hcol, *xpt = d->xpt, *bmat = d->bmat, *xopt = d->xopt; double val = 0; for (j = 0; j < n; ++j) { val += bmat[j * ndim] * (xopt[j] + dx[j]); if (grad) grad[j] = bmat[j * ndim]; } for (i = 0; i < npt; ++i) { double dot = 0; for (j = 0; j < n; ++j) dot += xpt[i + j * npt] * (xopt[j] + dx[j]); val += 0.5 * hcol[i] * (dot * dot); dot *= hcol[i]; if (grad) for (j = 0; j < n; ++j) grad[j] += dot * xpt[i + j * npt]; } if (d->flipsign) { val = -val; if (grad) for (j = 0; j < n; ++j) grad[j] = -grad[j]; } d->iter++; return val; } static nlopt_result biglag_(int *n, int *npt, double *xopt, double *xpt, double *bmat, double *zmat, int *idz, int *ndim, int *knew, double *delta, double *d__, double *alpha, double *hcol, double *gc, double *gd, double *s, double *w, const double *xbase, const double *lb, const double *ub) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2; double d__1; /* Local variables */ int i__, j, k; double dd, gg; int iu; double sp, ss, cf1, cf2, cf3, cf4, cf5, dhd, cth, one, tau, sth, sum, half, temp, step; int nptm; double zero, angle, scale, denom; int iterc, isave; /* Note: tempa is initialized below, initialization here is only used to avoid 'maybe-uninitialized' warning */ double delsq, tempa = 0.0, tempb = 0.0, twopi, taubeg, tauold, taumax; /* N is the number of variables. */ /* NPT is the number of interpolation equations. */ /* XOPT is the best interpolation point so far. */ /* XPT contains the coordinates of the current interpolation points. */ /* BMAT provides the last N columns of H. */ /* ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H. */ /* NDIM is the first dimension of BMAT and has the value NPT+N. */ /* KNEW is the index of the interpolation point that is going to be moved. */ /* DELTA is the current trust region bound. */ /* D will be set to the step from XOPT to the new point. */ /* ALPHA will be set to the KNEW-th diagonal element of the H matrix. */ /* HCOL, GC, GD, S and W will be used for working space. */ /* The step D is calculated in a way that attempts to maximize the modulus */ /* of LFUNC(XOPT+D), subject to the bound ||D|| .LE. DELTA, where LFUNC is */ /* the KNEW-th Lagrange function. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --xopt; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --d__; --hcol; --gc; --gd; --s; --w; /* Function Body */ half = .5; one = 1.; zero = 0.; twopi = atan(one) * 8.; delsq = *delta * *delta; nptm = *npt - *n - 1; /* Set the first NPT components of HCOL to the leading elements of the */ /* KNEW-th column of H. */ iterc = 0; i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L10: */ hcol[k] = zero; } i__1 = nptm; for (j = 1; j <= i__1; ++j) { temp = zmat[*knew + j * zmat_dim1]; if (j < *idz) { temp = -temp; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L20: */ hcol[k] += temp * zmat[k + j * zmat_dim1]; if (nlopt_isinf(hcol[k])) return NLOPT_ROUNDOFF_LIMITED; } } *alpha = hcol[*knew]; /* Set the unscaled initial direction D. Form the gradient of LFUNC at */ /* XOPT, and multiply D by the second derivative matrix of LFUNC. */ dd = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { d__[i__] = xpt[*knew + i__ * xpt_dim1] - xopt[i__]; gc[i__] = bmat[*knew + i__ * bmat_dim1]; gd[i__] = zero; /* L30: */ /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { temp = zero; sum = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { temp += xpt[k + j * xpt_dim1] * xopt[j]; /* L40: */ sum += xpt[k + j * xpt_dim1] * d__[j]; } temp = hcol[k] * temp; sum = hcol[k] * sum; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { gc[i__] += temp * xpt[k + i__ * xpt_dim1]; /* L50: */ gd[i__] += sum * xpt[k + i__ * xpt_dim1]; } } /* Scale D and GD, with a sign change if required. Set S to another */ /* vector in the initial two dimensional subspace. */ gg = zero; sp = zero; dhd = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing 2nd power */ d__1 = gc[i__]; gg += d__1 * d__1; sp += d__[i__] * gc[i__]; /* L60: */ dhd += d__[i__] * gd[i__]; } scale = *delta / sqrt(dd); if (sp * dhd < zero) { scale = -scale; } temp = zero; if (sp * sp > dd * .99 * gg) { temp = one; } tau = scale * (fabs(sp) + half * scale * fabs(dhd)); if (gg * delsq < tau * .01 * tau) { temp = one; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = scale * d__[i__]; gd[i__] = scale * gd[i__]; /* L70: */ s[i__] = gc[i__] + temp * gd[i__]; } if (lb && ub) { double minf, *dlb, *dub, *xtol; nlopt_opt opt; nlopt_result ret; lag_data ld; ld.npt = *npt; ld.ndim = *ndim; ld.iter = 0; ld.hcol = &hcol[1]; ld.xpt = &xpt[1 + 1 * xpt_dim1]; ld.bmat = &bmat[*knew + 1 * bmat_dim1]; ld.xopt = &xopt[1]; ld.flipsign = 0; dlb = &gc[1]; dub = &gd[1]; xtol = &s[1]; /* make sure rounding errors don't push initial |d| > delta */ for (j = 1; j <= *n; ++j) d__[j] *= 0.99999; for (j = 0; j < *n; ++j) { dlb[j] = -(dub[j] = *delta); if (dlb[j] < lb[j] - xbase[j] - xopt[j+1]) dlb[j] = lb[j] - xbase[j] - xopt[j+1]; if (dub[j] > ub[j] - xbase[j] - xopt[j+1]) dub[j] = ub[j] - xbase[j] - xopt[j+1]; if (dlb[j] > 0) dlb[j] = 0; if (dub[j] < 0) dub[j] = 0; if (d__[j+1] < dlb[j]) d__[j+1] = dlb[j]; else if (d__[j+1] > dub[j]) d__[j+1] = dub[j]; xtol[j] = 1e-5 * *delta; } ld.flipsign = lag(*n, &d__[1], 0, &ld) > 0; /* maximize if > 0 */ opt = nlopt_create(NLOPT_LD_MMA, *n); nlopt_set_min_objective(opt, lag, &ld); nlopt_add_inequality_constraint(opt, rho_constraint, delta, 0.0); nlopt_set_lower_bounds(opt, dlb); nlopt_set_upper_bounds(opt, dub); nlopt_set_xtol_abs(opt, xtol); nlopt_set_maxeval(opt, 1000); ret = nlopt_optimize(opt, &d__[1], &minf); nlopt_destroy(opt); return ret; } /* Begin the iteration by overwriting S with a vector that has the */ /* required length and direction, except that termination occurs if */ /* the given D and S are nearly parallel. */ L80: ++iterc; dd = zero; sp = zero; ss = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing 2nd power */ d__1 = d__[i__]; dd += d__1 * d__1; sp += d__[i__] * s[i__]; /* L90: */ /* Computing 2nd power */ d__1 = s[i__]; ss += d__1 * d__1; } temp = dd * ss - sp * sp; if (temp <= dd * 1e-8 * ss) { goto L160; } denom = sqrt(temp); i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { s[i__] = (dd * s[i__] - sp * d__[i__]) / denom; /* L100: */ w[i__] = zero; } /* Calculate the coefficients of the objective function on the circle, */ /* beginning with the multiplication of S by the second derivative matrix. */ i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L110: */ sum += xpt[k + j * xpt_dim1] * s[j]; } sum = hcol[k] * sum; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L120: */ w[i__] += sum * xpt[k + i__ * xpt_dim1]; } } cf1 = zero; cf2 = zero; cf3 = zero; cf4 = zero; cf5 = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { cf1 += s[i__] * w[i__]; cf2 += d__[i__] * gc[i__]; cf3 += s[i__] * gc[i__]; cf4 += d__[i__] * gd[i__]; /* L130: */ cf5 += s[i__] * gd[i__]; } cf1 = half * cf1; cf4 = half * cf4 - cf1; /* Seek the value of the angle that maximizes the modulus of TAU. */ taubeg = cf1 + cf2 + cf4; taumax = taubeg; tauold = taubeg; isave = 0; iu = 49; temp = twopi / (double) (iu + 1); i__2 = iu; for (i__ = 1; i__ <= i__2; ++i__) { angle = (double) i__ * temp; cth = cos(angle); sth = sin(angle); tau = cf1 + (cf2 + cf4 * cth) * cth + (cf3 + cf5 * cth) * sth; if (fabs(tau) > fabs(taumax)) { taumax = tau; isave = i__; tempa = tauold; } else if (i__ == isave + 1) { tempb = tau; } /* L140: */ tauold = tau; } if (isave == 0) { tempa = tau; } if (isave == iu) { tempb = taubeg; } step = zero; if (tempa != tempb) { tempa -= taumax; tempb -= taumax; step = half * (tempa - tempb) / (tempa + tempb); } angle = temp * ((double) isave + step); /* Calculate the new D and GD. Then test for convergence. */ cth = cos(angle); sth = sin(angle); tau = cf1 + (cf2 + cf4 * cth) * cth + (cf3 + cf5 * cth) * sth; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { d__[i__] = cth * d__[i__] + sth * s[i__]; gd[i__] = cth * gd[i__] + sth * w[i__]; /* L150: */ s[i__] = gc[i__] + gd[i__]; } if (fabs(tau) <= fabs(taubeg) * 1.1) { goto L160; } if (iterc < *n) { goto L80; } L160: return NLOPT_SUCCESS; } /* biglag_ */ /*************************************************************************/ /* update.f */ static void update_(int *n, int *npt, double *bmat, double *zmat, int *idz, int *ndim, double *vlag, double *beta, int *knew, double *w) { /* System generated locals */ int bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2; double d__1, d__2; /* Local variables */ int i__, j, ja, jb, jl, jp; double one, tau, temp; int nptm; double zero; int iflag; double scala, scalb_, alpha, denom, tempa, tempb = 0.0, tausq; /* The arrays BMAT and ZMAT with IDZ are updated, in order to shift the */ /* interpolation point that has index KNEW. On entry, VLAG contains the */ /* components of the vector Theta*Wcheck+e_b of the updating formula */ /* (6.11), and BETA holds the value of the parameter that has this name. */ /* The vector W is used for working space. */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --vlag; --w; /* Function Body */ one = 1.; zero = 0.; nptm = *npt - *n - 1; /* Apply the rotations that put zeros in the KNEW-th row of ZMAT. */ jl = 1; i__1 = nptm; for (j = 2; j <= i__1; ++j) { if (j == *idz) { jl = *idz; } else if (zmat[*knew + j * zmat_dim1] != zero) { /* Computing 2nd power */ d__1 = zmat[*knew + jl * zmat_dim1]; /* Computing 2nd power */ d__2 = zmat[*knew + j * zmat_dim1]; temp = sqrt(d__1 * d__1 + d__2 * d__2); tempa = zmat[*knew + jl * zmat_dim1] / temp; tempb = zmat[*knew + j * zmat_dim1] / temp; i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { temp = tempa * zmat[i__ + jl * zmat_dim1] + tempb * zmat[i__ + j * zmat_dim1]; zmat[i__ + j * zmat_dim1] = tempa * zmat[i__ + j * zmat_dim1] - tempb * zmat[i__ + jl * zmat_dim1]; /* L10: */ zmat[i__ + jl * zmat_dim1] = temp; } zmat[*knew + j * zmat_dim1] = zero; } /* L20: */ } /* Put the first NPT components of the KNEW-th column of HLAG into W, */ /* and calculate the parameters of the updating formula. */ tempa = zmat[*knew + zmat_dim1]; if (*idz >= 2) { tempa = -tempa; } if (jl > 1) { tempb = zmat[*knew + jl * zmat_dim1]; } i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { w[i__] = tempa * zmat[i__ + zmat_dim1]; if (jl > 1) { w[i__] += tempb * zmat[i__ + jl * zmat_dim1]; } /* L30: */ } alpha = w[*knew]; tau = vlag[*knew]; tausq = tau * tau; denom = alpha * *beta + tausq; vlag[*knew] -= one; /* Complete the updating of ZMAT when there is only one nonzero element */ /* in the KNEW-th row of the new matrix ZMAT, but, if IFLAG is set to one, */ /* then the first column of ZMAT will be exchanged with another one later. */ iflag = 0; if (jl == 1) { temp = sqrt((fabs(denom))); tempb = tempa / temp; tempa = tau / temp; i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { /* L40: */ zmat[i__ + zmat_dim1] = tempa * zmat[i__ + zmat_dim1] - tempb * vlag[i__]; } if (*idz == 1 && temp < zero) { *idz = 2; } if (*idz >= 2 && temp >= zero) { iflag = 1; } } else { /* Complete the updating of ZMAT in the alternative case. */ ja = 1; if (*beta >= zero) { ja = jl; } jb = jl + 1 - ja; temp = zmat[*knew + jb * zmat_dim1] / denom; tempa = temp * *beta; tempb = temp * tau; temp = zmat[*knew + ja * zmat_dim1]; scala = one / sqrt(fabs(*beta) * temp * temp + tausq); scalb_ = scala * sqrt((fabs(denom))); i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { zmat[i__ + ja * zmat_dim1] = scala * (tau * zmat[i__ + ja * zmat_dim1] - temp * vlag[i__]); /* L50: */ zmat[i__ + jb * zmat_dim1] = scalb_ * (zmat[i__ + jb * zmat_dim1] - tempa * w[i__] - tempb * vlag[i__]); } if (denom <= zero) { if (*beta < zero) { ++(*idz); } if (*beta >= zero) { iflag = 1; } } } /* IDZ is reduced in the following case, and usually the first column */ /* of ZMAT is exchanged with a later one. */ if (iflag == 1) { --(*idz); i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { temp = zmat[i__ + zmat_dim1]; zmat[i__ + zmat_dim1] = zmat[i__ + *idz * zmat_dim1]; /* L60: */ zmat[i__ + *idz * zmat_dim1] = temp; } } /* Finally, update the matrix BMAT. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { jp = *npt + j; w[jp] = bmat[*knew + j * bmat_dim1]; tempa = (alpha * vlag[jp] - tau * w[jp]) / denom; tempb = (-(*beta) * w[jp] - tau * vlag[jp]) / denom; i__2 = jp; for (i__ = 1; i__ <= i__2; ++i__) { bmat[i__ + j * bmat_dim1] = bmat[i__ + j * bmat_dim1] + tempa * vlag[i__] + tempb * w[i__]; if (i__ > *npt) { bmat[jp + (i__ - *npt) * bmat_dim1] = bmat[i__ + j * bmat_dim1]; } /* L70: */ } } return; } /* update_ */ /*************************************************************************/ /* newuob.f */ static nlopt_result newuob_(int *n, int *npt, double *x, double *rhobeg, const double *lb, const double *ub, nlopt_stopping *stop, double *minf, newuoa_func calfun, void *calfun_data, double *xbase, double *xopt, double *xnew, double *xpt, double *fval, double *gq, double *hq, double *pq, double *bmat, double *zmat, int *ndim, double *d__, double *vlag, double *w) { /* System generated locals */ int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2, i__3; double d__1, d__2, d__3; /* Local variables */ double f = 0.0; int i__, j, k, ih, nf, nh, ip, jp; double dx; int np, nfm; double one; int idz; double dsq, rho = 0.0; int ipt = 0, jpt = 0; double sum, fbeg = 0.0, diff, half, beta; int nfmm; double gisq; int knew; double temp, suma, sumb, fopt = HUGE_VAL, bsum, gqsq; int kopt, nptm; double zero, xipt = 0.0, xjpt = 0.0, sumz, diffa = 0.0, diffb = 0.0, diffc = 0.0, hdiag, alpha = 0.0, delta, recip, reciq, fsave; int ksave, nfsav = 0, itemp; double dnorm = 0.0, ratio = 0.0, dstep, tenth, vquad; int ktemp; double tempq; int itest = 0; double rhosq; double detrat, crvmin = 0.0; double distsq; double xoptsq = 0.0; double rhoend; nlopt_result rc = NLOPT_SUCCESS, rc2; /* SGJ, 2008: compute rhoend from NLopt stop info */ rhoend = stop->xtol_rel * (*rhobeg); for (j = 0; j < *n; ++j) if (rhoend < stop->xtol_abs[j]) rhoend = stop->xtol_abs[j]; /* The arguments N, NPT, X, RHOBEG, RHOEND, IPRINT and MAXFUN are identical */ /* to the corresponding arguments in SUBROUTINE NEWUOA. */ /* XBASE will hold a shift of origin that should reduce the contributions */ /* from rounding errors to values of the model and Lagrange functions. */ /* XOPT will be set to the displacement from XBASE of the vector of */ /* variables that provides the least calculated F so far. */ /* XNEW will be set to the displacement from XBASE of the vector of */ /* variables for the current calculation of F. */ /* XPT will contain the interpolation point coordinates relative to XBASE. */ /* FVAL will hold the values of F at the interpolation points. */ /* GQ will hold the gradient of the quadratic model at XBASE. */ /* HQ will hold the explicit second derivatives of the quadratic model. */ /* PQ will contain the parameters of the implicit second derivatives of */ /* the quadratic model. */ /* BMAT will hold the last N columns of H. */ /* ZMAT will hold the factorization of the leading NPT by NPT submatrix of */ /* H, this factorization being ZMAT times Diag(DZ) times ZMAT^T, where */ /* the elements of DZ are plus or minus one, as specified by IDZ. */ /* NDIM is the first dimension of BMAT and has the value NPT+N. */ /* D is reserved for trial steps from XOPT. */ /* VLAG will contain the values of the Lagrange functions at a new point X. */ /* They are part of a product that requires VLAG to be of length NDIM. */ /* The array W will be used for working space. Its length must be at least */ /* 10*NDIM = 10*(NPT+N). */ /* Set some constants. */ /* Parameter adjustments */ zmat_dim1 = *npt; zmat_offset = 1 + zmat_dim1; zmat -= zmat_offset; xpt_dim1 = *npt; xpt_offset = 1 + xpt_dim1; xpt -= xpt_offset; --x; --xbase; --xopt; --xnew; --fval; --gq; --hq; --pq; bmat_dim1 = *ndim; bmat_offset = 1 + bmat_dim1; bmat -= bmat_offset; --d__; --vlag; --w; /* Function Body */ half = .5; one = 1.; tenth = .1; zero = 0.; np = *n + 1; nh = *n * np / 2; nptm = *npt - np; /* Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { xbase[j] = x[j]; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L10: */ xpt[k + j * xpt_dim1] = zero; } i__2 = *ndim; for (i__ = 1; i__ <= i__2; ++i__) { /* L20: */ bmat[i__ + j * bmat_dim1] = zero; } } i__2 = nh; for (ih = 1; ih <= i__2; ++ih) { /* L30: */ hq[ih] = zero; } i__2 = *npt; for (k = 1; k <= i__2; ++k) { pq[k] = zero; i__1 = nptm; for (j = 1; j <= i__1; ++j) { /* L40: */ zmat[k + j * zmat_dim1] = zero; } } /* Begin the initialization procedure. NF becomes one more than the number */ /* of function values so far. The coordinates of the displacement of the */ /* next initial interpolation point from XBASE are set in XPT(NF,.). */ rhosq = *rhobeg * *rhobeg; recip = one / rhosq; reciq = sqrt(half) / rhosq; nf = 0; L50: nfm = nf; nfmm = nf - *n; ++nf; if (nfm <= *n << 1) { if (nfm >= 1 && nfm <= *n) { xpt[nf + nfm * xpt_dim1] = *rhobeg; } else if (nfm > *n) { xpt[nf + nfmm * xpt_dim1] = -(*rhobeg); } } else { itemp = (nfmm - 1) / *n; jpt = nfm - itemp * *n - *n; ipt = jpt + itemp; if (ipt > *n) { itemp = jpt; jpt = ipt - *n; ipt = itemp; } xipt = *rhobeg; if (fval[ipt + np] < fval[ipt + 1]) { xipt = -xipt; } xjpt = *rhobeg; if (fval[jpt + np] < fval[jpt + 1]) { xjpt = -xjpt; } xpt[nf + ipt * xpt_dim1] = xipt; xpt[nf + jpt * xpt_dim1] = xjpt; } /* Calculate the next value of F, label 70 being reached immediately */ /* after this calculation. The least function value so far and its index */ /* are required. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L60: */ x[j] = xpt[nf + j * xpt_dim1] + xbase[j]; } if (lb && ub) { /* SGJ, 2008: make sure we are within bounds */ for (j = 1; j <= i__1; ++j) { if (x[j] < lb[j-1]) x[j] = lb[j-1]; else if (x[j] > ub[j-1]) x[j] = ub[j-1]; } } goto L310; L70: fval[nf] = f; if (nf == 1) { fbeg = f; fopt = f; kopt = 1; } else if (f < fopt) { fopt = f; kopt = nf; } /* Set the nonzero initial elements of BMAT and the quadratic model in */ /* the cases when NF is at most 2*N+1. */ if (nfm <= *n << 1) { if (nfm >= 1 && nfm <= *n) { gq[nfm] = (f - fbeg) / *rhobeg; if (*npt < nf + *n) { bmat[nfm * bmat_dim1 + 1] = -one / *rhobeg; bmat[nf + nfm * bmat_dim1] = one / *rhobeg; bmat[*npt + nfm + nfm * bmat_dim1] = -half * rhosq; } } else if (nfm > *n) { bmat[nf - *n + nfmm * bmat_dim1] = half / *rhobeg; bmat[nf + nfmm * bmat_dim1] = -half / *rhobeg; zmat[nfmm * zmat_dim1 + 1] = -reciq - reciq; zmat[nf - *n + nfmm * zmat_dim1] = reciq; zmat[nf + nfmm * zmat_dim1] = reciq; ih = nfmm * (nfmm + 1) / 2; temp = (fbeg - f) / *rhobeg; hq[ih] = (gq[nfmm] - temp) / *rhobeg; gq[nfmm] = half * (gq[nfmm] + temp); } /* Set the off-diagonal second derivatives of the Lagrange functions and */ /* the initial quadratic model. */ } else { ih = ipt * (ipt - 1) / 2 + jpt; if (xipt < zero) { ipt += *n; } if (xjpt < zero) { jpt += *n; } zmat[nfmm * zmat_dim1 + 1] = recip; zmat[nf + nfmm * zmat_dim1] = recip; zmat[ipt + 1 + nfmm * zmat_dim1] = -recip; zmat[jpt + 1 + nfmm * zmat_dim1] = -recip; hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / (xipt * xjpt); } if (nf < *npt) { goto L50; } /* Begin the iterative procedure, because the initial model is complete. */ rho = *rhobeg; delta = rho; idz = 1; diffa = zero; diffb = zero; itest = 0; xoptsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xopt[i__] = xpt[kopt + i__ * xpt_dim1]; /* L80: */ /* Computing 2nd power */ d__1 = xopt[i__]; xoptsq += d__1 * d__1; } L90: nfsav = nf; /* Generate the next trust region step and test its length. Set KNEW */ /* to -1 if the purpose of the next F will be to improve the model. */ L100: knew = 0; rc2 = trsapp_(n, npt, &xopt[1], &xpt[xpt_offset], &gq[1], &hq[1], &pq[1], & delta, &d__[1], &w[1], &w[np], &w[np + *n], &w[np + (*n << 1)], & crvmin, &xbase[1], lb, ub); if (rc2 < 0) { rc = rc2; goto L530; } dsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L110: */ /* Computing 2nd power */ d__1 = d__[i__]; dsq += d__1 * d__1; } /* Computing MIN */ d__1 = delta, d__2 = sqrt(dsq); dnorm = MIN2(d__1,d__2); if (dnorm < half * rho) { knew = -1; delta = tenth * delta; ratio = -1.; if (delta <= rho * 1.5) { delta = rho; } if (nf <= nfsav + 2) { goto L460; } temp = crvmin * .125 * rho * rho; /* Computing MAX */ d__1 = MAX2(diffa,diffb); if (temp <= MAX2(d__1,diffc)) { goto L460; } goto L490; } /* Shift XBASE if XOPT may be too far from XBASE. First make the changes */ /* to BMAT that do not depend on ZMAT. */ L120: if (dsq <= xoptsq * .001) { tempq = xoptsq * .25; i__1 = *npt; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L130: */ sum += xpt[k + i__ * xpt_dim1] * xopt[i__]; } temp = pq[k] * sum; sum -= half * xoptsq; w[*npt + k] = sum; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { gq[i__] += temp * xpt[k + i__ * xpt_dim1]; xpt[k + i__ * xpt_dim1] -= half * xopt[i__]; vlag[i__] = bmat[k + i__ * bmat_dim1]; w[i__] = sum * xpt[k + i__ * xpt_dim1] + tempq * xopt[i__]; ip = *npt + i__; i__3 = i__; for (j = 1; j <= i__3; ++j) { /* L140: */ bmat[ip + j * bmat_dim1] = bmat[ip + j * bmat_dim1] + vlag[i__] * w[j] + w[i__] * vlag[j]; } } } /* Then the revisions of BMAT that depend on ZMAT are calculated. */ i__3 = nptm; for (k = 1; k <= i__3; ++k) { sumz = zero; i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { sumz += zmat[i__ + k * zmat_dim1]; /* L150: */ w[i__] = w[*npt + i__] * zmat[i__ + k * zmat_dim1]; } i__2 = *n; for (j = 1; j <= i__2; ++j) { sum = tempq * sumz * xopt[j]; i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { /* L160: */ sum += w[i__] * xpt[i__ + j * xpt_dim1]; } vlag[j] = sum; if (k < idz) { sum = -sum; } i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { /* L170: */ bmat[i__ + j * bmat_dim1] += sum * zmat[i__ + k * zmat_dim1]; } } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { ip = i__ + *npt; temp = vlag[i__]; if (k < idz) { temp = -temp; } i__2 = i__; for (j = 1; j <= i__2; ++j) { /* L180: */ bmat[ip + j * bmat_dim1] += temp * vlag[j]; } } } /* The following instructions complete the shift of XBASE, including */ /* the changes to the parameters of the quadratic model. */ ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { w[j] = zero; i__1 = *npt; for (k = 1; k <= i__1; ++k) { w[j] += pq[k] * xpt[k + j * xpt_dim1]; /* L190: */ xpt[k + j * xpt_dim1] -= half * xopt[j]; } i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; if (i__ < j) { gq[j] += hq[ih] * xopt[i__]; } gq[i__] += hq[ih] * xopt[j]; hq[ih] = hq[ih] + w[i__] * xopt[j] + xopt[i__] * w[j]; /* L200: */ bmat[*npt + i__ + j * bmat_dim1] = bmat[*npt + j + i__ * bmat_dim1]; } } i__1 = *n; for (j = 1; j <= i__1; ++j) { xbase[j] += xopt[j]; /* L210: */ xopt[j] = zero; } xoptsq = zero; } /* Pick the model step if KNEW is positive. A different choice of D */ /* may be made later, if the choice of D by BIGLAG causes substantial */ /* cancellation in DENOM. */ if (knew > 0) { rc2 = biglag_(n, npt, &xopt[1], &xpt[xpt_offset], &bmat[bmat_offset], &zmat[ zmat_offset], &idz, ndim, &knew, &dstep, &d__[1], &alpha, & vlag[1], &vlag[*npt + 1], &w[1], &w[np], &w[np + *n], &xbase[1], lb, ub); if (rc2 < 0) { rc = rc2; goto L530; } } /* Calculate VLAG and BETA for the current choice of D. The first NPT */ /* components of W_check will be held in W. */ i__1 = *npt; for (k = 1; k <= i__1; ++k) { suma = zero; sumb = zero; sum = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { suma += xpt[k + j * xpt_dim1] * d__[j]; sumb += xpt[k + j * xpt_dim1] * xopt[j]; /* L220: */ sum += bmat[k + j * bmat_dim1] * d__[j]; } w[k] = suma * (half * suma + sumb); /* L230: */ vlag[k] = sum; } beta = zero; i__1 = nptm; for (k = 1; k <= i__1; ++k) { sum = zero; i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { /* L240: */ sum += zmat[i__ + k * zmat_dim1] * w[i__]; } if (k < idz) { beta += sum * sum; sum = -sum; } else { beta -= sum * sum; } i__2 = *npt; for (i__ = 1; i__ <= i__2; ++i__) { /* L250: */ vlag[i__] += sum * zmat[i__ + k * zmat_dim1]; } } bsum = zero; dx = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { sum = zero; i__1 = *npt; for (i__ = 1; i__ <= i__1; ++i__) { /* L260: */ sum += w[i__] * bmat[i__ + j * bmat_dim1]; } bsum += sum * d__[j]; jp = *npt + j; i__1 = *n; for (k = 1; k <= i__1; ++k) { /* L270: */ sum += bmat[jp + k * bmat_dim1] * d__[k]; } vlag[jp] = sum; bsum += sum * d__[j]; /* L280: */ dx += d__[j] * xopt[j]; } beta = dx * dx + dsq * (xoptsq + dx + dx + half * dsq) + beta - bsum; vlag[kopt] += one; /* If KNEW is positive and if the cancellation in DENOM is unacceptable, */ /* then BIGDEN calculates an alternative model step, XNEW being used for */ /* working space. */ if (knew > 0) { /* Computing 2nd power */ d__1 = vlag[knew]; if (d__1 == 0) { rc = NLOPT_ROUNDOFF_LIMITED; goto L530; } temp = one + alpha * beta / (d__1 * d__1); if (fabs(temp) <= .8) { rc2 = bigden_(n, npt, &xopt[1], &xpt[xpt_offset], &bmat[bmat_offset], & zmat[zmat_offset], &idz, ndim, &kopt, &knew, &d__[1], &w[ 1], &vlag[1], &beta, &xnew[1], &w[*ndim + 1], &w[*ndim * 6 + 1], &xbase[1], lb, ub); if (rc2 < 0) { rc = rc2; goto L530; } } } /* Calculate the next value of the objective function. */ L290: i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { xnew[i__] = xopt[i__] + d__[i__]; /* L300: */ x[i__] = xbase[i__] + xnew[i__]; } if (lb && ub) { /* SGJ, 2008: make sure we are within bounds, since roundoff errors can push us slightly outside */ for (j = 1; j <= i__1; ++j) { if (x[j] < lb[j-1]) x[j] = lb[j-1]; else if (x[j] > ub[j-1]) x[j] = ub[j-1]; } } ++nf; L310: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; else if (*(stop->nevals_p) > 0) { if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; } if (rc != NLOPT_SUCCESS) goto L530; ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); if (f < stop->minf_max) { rc = NLOPT_MINF_MAX_REACHED; goto L530; } if (nf <= *npt) { goto L70; } if (knew == -1) { goto L530; } /* Use the quadratic model to predict the change in F due to the step D, */ /* and set DIFF to the error of this prediction. */ vquad = zero; ih = 0; i__2 = *n; for (j = 1; j <= i__2; ++j) { vquad += d__[j] * gq[j]; i__1 = j; for (i__ = 1; i__ <= i__1; ++i__) { ++ih; temp = d__[i__] * xnew[j] + d__[j] * xopt[i__]; if (i__ == j) { temp = half * temp; } /* L340: */ vquad += temp * hq[ih]; } } i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L350: */ vquad += pq[k] * w[k]; } diff = f - fopt - vquad; diffc = diffb; diffb = diffa; diffa = fabs(diff); if (dnorm > rho) { nfsav = nf; } /* Update FOPT and XOPT if the new F is the least value of the objective */ /* function so far. The branch when KNEW is positive occurs if D is not */ /* a trust region step. */ fsave = fopt; if (f < fopt) { fopt = f; xoptsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xopt[i__] = xnew[i__]; /* L360: */ /* Computing 2nd power */ d__1 = xopt[i__]; xoptsq += d__1 * d__1; } if (nlopt_stop_ftol(stop, fopt, fsave)) { rc = NLOPT_FTOL_REACHED; goto L530; } } ksave = knew; if (knew > 0) { goto L410; } /* Pick the next value of DELTA after a trust region step. */ if (vquad >= zero) { goto L530; } ratio = (f - fsave) / vquad; if (ratio <= tenth) { delta = half * dnorm; } else if (ratio <= .7) { /* Computing MAX */ d__1 = half * delta; delta = MAX2(d__1,dnorm); } else { /* Computing MAX */ d__1 = half * delta, d__2 = dnorm + dnorm; delta = MAX2(d__1,d__2); } if (delta <= rho * 1.5) { delta = rho; } /* Set KNEW to the index of the next interpolation point to be deleted. */ /* Computing MAX */ d__2 = tenth * delta; /* Computing 2nd power */ d__1 = MAX2(d__2,rho); rhosq = d__1 * d__1; ktemp = 0; detrat = zero; if (f >= fsave) { ktemp = kopt; detrat = one; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { hdiag = zero; i__2 = nptm; for (j = 1; j <= i__2; ++j) { temp = one; if (j < idz) { temp = -one; } /* L380: */ /* Computing 2nd power */ d__1 = zmat[k + j * zmat_dim1]; hdiag += temp * (d__1 * d__1); } /* Computing 2nd power */ d__2 = vlag[k]; temp = (d__1 = beta * hdiag + d__2 * d__2, fabs(d__1)); distsq = zero; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L390: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1] - xopt[j]; distsq += d__1 * d__1; } if (distsq > rhosq) { /* Computing 3rd power */ d__1 = distsq / rhosq; temp *= d__1 * (d__1 * d__1); } if (temp > detrat && k != ktemp) { detrat = temp; knew = k; } /* L400: */ } if (knew == 0) { goto L460; } /* Update BMAT, ZMAT and IDZ, so that the KNEW-th interpolation point */ /* can be moved. Begin the updating of the quadratic model, starting */ /* with the explicit second derivative term. */ L410: update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], &idz, ndim, &vlag[ 1], &beta, &knew, &w[1]); fval[knew] = f; ih = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = pq[knew] * xpt[knew + i__ * xpt_dim1]; i__2 = i__; for (j = 1; j <= i__2; ++j) { ++ih; /* L420: */ hq[ih] += temp * xpt[knew + j * xpt_dim1]; } } pq[knew] = zero; /* Update the other second derivative parameters, and then the gradient */ /* vector of the model. Also include the new interpolation point. */ i__2 = nptm; for (j = 1; j <= i__2; ++j) { temp = diff * zmat[knew + j * zmat_dim1]; if (j < idz) { temp = -temp; } i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L440: */ pq[k] += temp * zmat[k + j * zmat_dim1]; } } gqsq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { gq[i__] += diff * bmat[knew + i__ * bmat_dim1]; /* Computing 2nd power */ d__1 = gq[i__]; gqsq += d__1 * d__1; /* L450: */ xpt[knew + i__ * xpt_dim1] = xnew[i__]; } /* If a trust region step makes a small change to the objective function, */ /* then calculate the gradient of the least Frobenius norm interpolant at */ /* XBASE, and store it in W, using VLAG for a vector of right hand sides. */ if (ksave == 0 && delta == rho) { if (fabs(ratio) > .01) { itest = 0; } else { i__1 = *npt; for (k = 1; k <= i__1; ++k) { /* L700: */ vlag[k] = fval[k] - fval[kopt]; } gisq = zero; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { sum = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L710: */ sum += bmat[k + i__ * bmat_dim1] * vlag[k]; } gisq += sum * sum; /* L720: */ w[i__] = sum; } /* Test whether to replace the new quadratic model by the least Frobenius */ /* norm interpolant, making the replacement if the test is satisfied. */ ++itest; if (gqsq < gisq * 100.) { itest = 0; } if (itest >= 3) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L730: */ gq[i__] = w[i__]; } i__1 = nh; for (ih = 1; ih <= i__1; ++ih) { /* L740: */ hq[ih] = zero; } i__1 = nptm; for (j = 1; j <= i__1; ++j) { w[j] = zero; i__2 = *npt; for (k = 1; k <= i__2; ++k) { /* L750: */ w[j] += vlag[k] * zmat[k + j * zmat_dim1]; } /* L760: */ if (j < idz) { w[j] = -w[j]; } } i__1 = *npt; for (k = 1; k <= i__1; ++k) { pq[k] = zero; i__2 = nptm; for (j = 1; j <= i__2; ++j) { /* L770: */ pq[k] += zmat[k + j * zmat_dim1] * w[j]; } } itest = 0; } } } if (f < fsave) { kopt = knew; } /* If a trust region step has provided a sufficient decrease in F, then */ /* branch for another trust region calculation. The case KSAVE>0 occurs */ /* when the new function value was calculated by a model step. */ if (f <= fsave + tenth * vquad) { goto L100; } if (ksave > 0) { goto L100; } /* Alternatively, find out if the interpolation points are close enough */ /* to the best point so far. */ knew = 0; L460: distsq = delta * 4. * delta; i__2 = *npt; for (k = 1; k <= i__2; ++k) { sum = zero; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L470: */ /* Computing 2nd power */ d__1 = xpt[k + j * xpt_dim1] - xopt[j]; sum += d__1 * d__1; } if (sum > distsq) { knew = k; distsq = sum; } /* L480: */ } /* If KNEW is positive, then set DSTEP, and branch back for the next */ /* iteration, which will generate a "model step". */ if (knew > 0) { /* Computing MAX */ /* Computing MIN */ d__2 = tenth * sqrt(distsq), d__3 = half * delta; d__1 = MIN2(d__2,d__3); dstep = MAX2(d__1,rho); dsq = dstep * dstep; goto L120; } if (ratio > zero) { goto L100; } if (MAX2(delta,dnorm) > rho) { goto L100; } /* The calculations with the current value of RHO are complete. Pick the */ /* next values of RHO and DELTA. */ L490: if (rho > rhoend) { delta = half * rho; ratio = rho / rhoend; if (ratio <= 16.) { rho = rhoend; } else if (ratio <= 250.) { rho = sqrt(ratio) * rhoend; } else { rho = tenth * rho; } delta = MAX2(delta,rho); goto L90; } /* Return from the calculation, after another Newton-Raphson step, if */ /* it is too short to have been tried before. */ if (knew == -1) { goto L290; } rc = NLOPT_XTOL_REACHED; L530: if (fopt <= f) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L540: */ x[i__] = xbase[i__] + xopt[i__]; } f = fopt; } *minf = f; return rc; } /* newuob_ */ /*************************************************************************/ /* newuoa.f */ nlopt_result newuoa(int n, int npt, double *x, const double *lb, const double *ub, double rhobeg, nlopt_stopping *stop, double *minf, newuoa_func calfun, void *calfun_data) { /* Local variables */ int id, np, iw, igq, ihq, ixb, ifv, ipq, ivl, ixn, ixo, ixp, ndim, nptm, ibmat, izmat; nlopt_result ret; double *w; /* This subroutine seeks the least value of a function of many variables, */ /* by a trust region method that forms quadratic models by interpolation. */ /* There can be some freedom in the interpolation conditions, which is */ /* taken up by minimizing the Frobenius norm of the change to the second */ /* derivative of the quadratic model, beginning with a zero matrix. The */ /* arguments of the subroutine are as follows. */ /* N must be set to the number of variables and must be at least two. */ /* NPT is the number of interpolation conditions. Its value must be in the */ /* interval [N+2,(N+1)(N+2)/2]. */ /* Initial values of the variables must be set in X(1),X(2),...,X(N). They */ /* will be changed to the values that give the least calculated F. */ /* RHOBEG and RHOEND must be set to the initial and final values of a trust */ /* region radius, so both must be positive with RHOEND<=RHOBEG. Typically */ /* RHOBEG should be about one tenth of the greatest expected change to a */ /* variable, and RHOEND should indicate the accuracy that is required in */ /* the final values of the variables. */ /* The value of IPRINT should be set to 0, 1, 2 or 3, which controls the */ /* amount of printing. Specifically, there is no output if IPRINT=0 and */ /* there is output only at the return if IPRINT=1. Otherwise, each new */ /* value of RHO is printed, with the best vector of variables so far and */ /* the corresponding value of the objective function. Further, each new */ /* value of F with its variables are output if IPRINT=3. */ /* MAXFUN must be set to an upper bound on the number of calls of CALFUN. */ /* The array W will be used for working space. Its length must be at least */ /* (NPT+13)*(NPT+N)+3*N*(N+3)/2. */ /* SUBROUTINE CALFUN (N,X,F) must be provided by the user. It must set F to */ /* the value of the objective function for the variables X(1),X(2),...,X(N). */ /* Partition the working space array, so that different parts of it can be */ /* treated separately by the subroutine that performs the main calculation. */ /* Parameter adjustments */ --x; /* Function Body */ np = n + 1; nptm = npt - np; if (n < 2) { nlopt_stop_msg(stop, "dimension %d must be >= 2", n); return NLOPT_INVALID_ARGS; } if (npt < n + 2 || npt > (n + 2) * np / 2) { nlopt_stop_msg(stop, "invalid # of interpolation conditions %d", npt); return NLOPT_INVALID_ARGS; } ndim = npt + n; ixb = 1; ixo = ixb + n; ixn = ixo + n; ixp = ixn + n; ifv = ixp + n * npt; igq = ifv + npt; ihq = igq + n; ipq = ihq + n * np / 2; ibmat = ipq + npt; izmat = ibmat + ndim * n; id = izmat + npt * nptm; ivl = id + n; iw = ivl + ndim; w = (double *) malloc(sizeof(double) * ((npt+13)*(npt+n) + 3*(n*(n+3))/2)); if (!w) return NLOPT_OUT_OF_MEMORY; --w; /* The above settings provide a partition of W for subroutine NEWUOB. */ /* The partition requires the first NPT*(NPT+N)+5*N*(N+3)/2 elements of */ /* W plus the space that is needed by the last array of NEWUOB. */ ret = newuob_(&n, &npt, &x[1], &rhobeg, lb, ub, stop, minf, calfun, calfun_data, &w[ixb], &w[ixo], &w[ixn], &w[ixp], &w[ifv], &w[igq], &w[ihq], &w[ipq], &w[ibmat], &w[izmat], &ndim, &w[id], &w[ivl], &w[iw]); ++w; free(w); return ret; } /* newuoa_ */ /*************************************************************************/ /*************************************************************************/ nlopt-2.6.1/src/algs/newuoa/newuoa.h000066400000000000000000000005711345435414600173520ustar00rootroot00000000000000#ifndef NEWUOA_H #define NEWUOA_H 1 #include "nlopt-util.h" #include "nlopt.h" typedef double (*newuoa_func)(int n, const double *x, void *func_data); extern nlopt_result newuoa(int n, int npt, double *x, const double *lb, const double *ub, double rhobeg, nlopt_stopping *stop, double *minf, newuoa_func calfun, void *calfun_data); #endif /* NEWUOA_H */ nlopt-2.6.1/src/algs/praxis/000077500000000000000000000000001345435414600157105ustar00rootroot00000000000000nlopt-2.6.1/src/algs/praxis/README000066400000000000000000000011671345435414600165750ustar00rootroot00000000000000praxis gradient-free local optimization via the "principal-axis method", downloaded from Netlib: http://netlib.org/opt/praxis The original Fortran code was written by Richard Brent and made available by the Stanford Linear Accelerator Center, dated 3/1/73. Since this code contains no copyright statements and is dated prior to 1977, under US copyright law it is in the public domain (not copyrighted). Converted to C via f2c and cleaned up by Steven G. Johnson (stevenj@alum.mit.edu). C version is licensed under the MIT license (which is in the same spirit as public domain, but disclaims warranty and is clearer legally). nlopt-2.6.1/src/algs/praxis/praxis.c000066400000000000000000000763151345435414600173760ustar00rootroot00000000000000/* See README */ #include #include #include #include "nlopt-util.h" #include "praxis.h" /* Common Block Declarations */ struct global_s { double fx, ldt, dmin__; int nf, nl; }; struct q_s { double *v; /* size n x n */ double *q0, *q1, *t_flin; /* size n */ double qa, qb, qc, qd0, qd1, qf1; double fbest, *xbest; /* size n */ nlopt_stopping *stop; }; /* Table of constant values */ static int pow_ii(int x, int n) /* compute x^n, n >= 0 */ { int p = 1; while (n > 0) { if (n & 1) { n--; p *= x; } else { n >>= 1; x *= x; } } return p; } static void minfit_(int m, int n, double machep, double *tol, double *ab, double *q, double *ework); static nlopt_result min_(int n, int j, int nits, double *d2, double *x1, double *f1, int fk, praxis_func f, void *f_data, double *x, double *t_old, double machep, double *h__, struct global_s *global_1, struct q_s *q_1); static double flin_(int n, int j, double *l, praxis_func f, void *f_data, double *x, int *nf, struct q_s *q_1, nlopt_result *ret); static void sort_(int m, int n, double *d__, double *v); static void quad_(int n, praxis_func f, void *f_data, double *x, double *t_old, double machep, double *h__, struct global_s *global_1, struct q_s *q_1); nlopt_result praxis_(double t0, double machep, double h0, int n, double *x, praxis_func f, void *f_data, nlopt_stopping *stop, double *minf) { /* System generated locals */ int i__1, i__2, i__3; nlopt_result ret = NLOPT_SUCCESS; double d__1; /* Global */ struct global_s global_1; struct q_s q_1; /* Local variables */ double *d__, *y, *z__, *e_minfit, *prev_xbest; /* size n */ double prev_fbest; double h__; int i__, j, k; double s, t_old, f1; int k2; double m2, m4, t2_old, df, dn; int kl, ii; double sf; int kt; double sl; int im1, km1; double dni, lds; int ktm; double scbd; int illc; int klmk; double ldfac, large, small, value; double vlarge; double vsmall; double *work; /* LAST MODIFIED 3/1/73 */ /* Modified August 2007 by S. G. Johnson: after conversion to C via f2c and some manual cleanup, eliminating write statements, I additionally: - modified the routine to use NLopt stop criteria - allocate arrays dynamically to allow n > 20 - return the NLopt return code, where the min. function value is now given by the parameter minf */ /* PRAXIS RETURNS THE MINIMUM OF THE FUNCTION F(N,X) OF N VARIABLES */ /* USING THE PRINCIPAL AXIS METHOD. THE GRADIENT OF THE FUNCTION IS */ /* NOT REQUIRED. */ /* FOR A DESCRIPTION OF THE ALGORITHM, SEE CHAPTER SEVEN OF */ /* "ALGORITHMS FOR FINDING ZEROS AND EXTREMA OF FUNCTIONS WITHOUT */ /* CALCULATING DERIVATIVES" BY RICHARD P BRENT. */ /* THE PARAMETERS ARE: */ /* T0 IS A TOLERANCE. PRAXIS ATTEMPTS TO RETURN PRAXIS=F(X) */ /* SUCH THAT IF X0 IS THE TRUE LOCAL MINIMUM NEAR X, THEN */ /* NORM(X-X0) < T0 + SQUAREROOT(MACHEP)*NORM(X). */ /* MACHEP IS THE MACHINE PRECISION, THE SMALLEST NUMBER SUCH THAT */ /* 1 + MACHEP > 1. MACHEP SHOULD BE 16.**-13 (ABOUT */ /* 2.22D-16) FOR REAL*8 ARITHMETIC ON THE IBM 360. */ /* H0 IS THE MAXIMUM STEP SIZE. H0 SHOULD BE SET TO ABOUT THE */ /* MAXIMUM DISTANCE FROM THE INITIAL GUESS TO THE MINIMUM. */ /* (IF H0 IS SET TOO LARGE OR TOO SMALL, THE INITIAL RATE OF */ /* CONVERGENCE MAY BE SLOW.) */ /* N (AT LEAST TWO) IS THE NUMBER OF VARIABLES UPON WHICH */ /* THE FUNCTION DEPENDS. */ /* X IS AN ARRAY CONTAINING ON ENTRY A GUESS OF THE POINT OF */ /* MINIMUM, ON RETURN THE ESTIMATED POINT OF MINIMUM. */ /* F(N,X) IS THE FUNCTION TO BE MINIMIZED. F SHOULD BE A REAL*8 */ /* FUNCTION DECLARED EXTERNAL IN THE CALLING PROGRAM. */ /* THE APPROXIMATING QUADRATIC FORM IS */ /* Q(X') = F(N,X) + (1/2) * (X'-X)-TRANSPOSE * A * (X'-X) */ /* WHERE X IS THE BEST ESTIMATE OF THE MINIMUM AND A IS */ /* INVERSE(V-TRANSPOSE) * D * INVERSE(V) */ /* (V(*,*) IS THE MATRIX OF SEARCH DIRECTIONS; D(*) IS THE ARRAY */ /* OF SECOND DIFFERENCES). IF F HAS CONTINUOUS SECOND DERIVATIVES */ /* NEAR X0, A WILL TEND TO THE HESSIAN OF F AT X0 AS X APPROACHES X0. */ /* IT IS ASSUMED THAT ON FLOATING-POINT UNDERFLOW THE RESULT IS SET */ /* TO ZERO. */ /* THE USER SHOULD OBSERVE THE COMMENT ON HEURISTIC NUMBERS AFTER */ /* THE INITIALIZATION OF MACHINE DEPENDENT NUMBERS. */ /* .....IF N>20 OR IF N<20 AND YOU NEED MORE SPACE, CHANGE '20' TO THE */ /* LARGEST VALUE OF N IN THE NEXT CARD, IN THE CARD 'IDIM=20', AND */ /* IN THE DIMENSION STATEMENTS IN SUBROUTINES MINFIT,MIN,FLIN,QUAD. */ /* ...changed by S. G. Johnson, 2007, to use malloc */ /* .....INITIALIZATION..... */ /* MACHINE DEPENDENT NUMBERS: */ /* Parameter adjustments */ --x; /* Function Body */ small = machep * machep; vsmall = small * small; large = 1. / small; vlarge = 1. / vsmall; m2 = sqrt(machep); m4 = sqrt(m2); /* new: dynamic allocation of temporary arrays */ work = (double *) malloc(sizeof(double) * (n*n + n*9)); if (!work) return NLOPT_OUT_OF_MEMORY; q_1.v = work; q_1.q0 = q_1.v + n*n; q_1.q1 = q_1.q0 + n; q_1.t_flin = q_1.q1 + n; q_1.xbest = q_1.t_flin + n; d__ = q_1.xbest + n; y = d__ + n; z__ = y + n; e_minfit = y + n; prev_xbest = e_minfit + n; /* HEURISTIC NUMBERS: */ /* IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF */ /* POSSIBLE), THEN SET SCBD=10. OTHERWISE SET SCBD=1. */ /* IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED, SET ILLC=TRUE. */ /* OTHERWISE SET ILLC=FALSE. */ /* KTM IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT BEFORE THE */ /* ALGORITHM TERMINATES. KTM=4 IS VERY CAUTIOUS; USUALLY KTM=1 */ /* IS SATISFACTORY. */ scbd = 1.; illc = 0 /* false */; ktm = 1; ldfac = .01; if (illc) { ldfac = .1; } kt = 0; global_1.nl = 0; global_1.nf = 1; prev_fbest = q_1.fbest = global_1.fx = f(n, &x[1], f_data); memcpy(q_1.xbest, &x[1], n*sizeof(double)); memcpy(prev_xbest, &x[1], n*sizeof(double)); ++ *(stop->nevals_p); q_1.stop = stop; q_1.qf1 = global_1.fx; if (t0 > 0) t_old = small + t0; else { t_old = 0; for (i__ = 0; i__ < n; ++i__) if (stop->xtol_abs[i__] > t_old) t_old = stop->xtol_abs[i__]; t_old += small; } t2_old = t_old; global_1.dmin__ = small; h__ = h0; if (h__ < t_old * 100) { h__ = t_old * 100; } global_1.ldt = h__; /* .....THE FIRST SET OF SEARCH DIRECTIONS V IS THE IDENTITY MATRIX..... */ i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = n; for (j = 1; j <= i__2; ++j) { /* L10: */ q_1.v[i__ + j * n - (n+1)] = 0.; } /* L20: */ q_1.v[i__ + i__ * n - (n+1)] = 1.; } d__[0] = 0.; q_1.qd0 = 0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { q_1.q0[i__ - 1] = x[i__]; /* L30: */ q_1.q1[i__ - 1] = x[i__]; } /* .....THE MAIN LOOP STARTS HERE..... */ L40: sf = d__[0]; d__[0] = 0.; s = 0.; /* .....MINIMIZE ALONG THE FIRST DIRECTION V(*,1). */ /* FX MUST BE PASSED TO MIN BY VALUE. */ value = global_1.fx; ret = min_(n, 1, 2, d__, &s, &value, 0, f,f_data, &x[1], &t_old, machep, &h__, &global_1, &q_1); if (ret != NLOPT_SUCCESS) goto done; if (s > 0.) { goto L50; } i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { /* L45: */ q_1.v[i__ - 1] = -q_1.v[i__ - 1]; } L50: if (sf > d__[0] * .9 && sf * .9 < d__[0]) { goto L70; } i__1 = n; for (i__ = 2; i__ <= i__1; ++i__) { /* L60: */ d__[i__ - 1] = 0.; } /* .....THE INNER LOOP STARTS HERE..... */ L70: i__1 = n; for (k = 2; k <= i__1; ++k) { i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* L75: */ y[i__ - 1] = x[i__]; } sf = global_1.fx; if (kt > 0) { illc = 1 /* true */; } L80: kl = k; df = 0.; /* .....A RANDOM STEP FOLLOWS (TO AVOID RESOLUTION VALLEYS). */ /* PRAXIS ASSUMES THAT RANDOM RETURNS A RANDOM NUMBER UNIFORMLY */ /* DISTRIBUTED IN (0,1). */ if (! illc) { goto L95; } i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { s = (global_1.ldt * .1 + t2_old * pow_ii(10, kt)) * nlopt_urand(-.5,.5); /* was: (random_(n) - .5); */ z__[i__ - 1] = s; i__3 = n; for (j = 1; j <= i__3; ++j) { /* L85: */ x[j] += s * q_1.v[j + i__ * n - (n+1)]; } /* L90: */ } global_1.fx = (*f)(n, &x[1], f_data); ++global_1.nf; /* .....MINIMIZE ALONG THE "NON-CONJUGATE" DIRECTIONS V(*,K),...,V(*,N) */ L95: i__2 = n; for (k2 = k; k2 <= i__2; ++k2) { sl = global_1.fx; s = 0.; value = global_1.fx; ret = min_(n, k2, 2, &d__[k2 - 1], &s, &value, 0, f,f_data, & x[1], &t_old, machep, &h__, &global_1, &q_1); if (ret != NLOPT_SUCCESS) goto done; if (illc) { goto L97; } s = sl - global_1.fx; goto L99; L97: /* Computing 2nd power */ d__1 = s + z__[k2 - 1]; s = d__[k2 - 1] * (d__1 * d__1); L99: if (df > s) { goto L105; } df = s; kl = k2; L105: ; } if (illc || df >= (d__1 = machep * 100 * global_1.fx, fabs(d__1))) { goto L110; } /* .....IF THERE WAS NOT MUCH IMPROVEMENT ON THE FIRST TRY, SET */ /* ILLC=TRUE AND START THE INNER LOOP AGAIN..... */ illc = 1 /* true */; goto L80; L110: /* .....MINIMIZE ALONG THE "CONJUGATE" DIRECTIONS V(*,1),...,V(*,K-1) */ km1 = k - 1; i__2 = km1; for (k2 = 1; k2 <= i__2; ++k2) { s = 0.; value = global_1.fx; ret = min_(n, k2, 2, &d__[k2 - 1], &s, &value, 0, f,f_data, & x[1], &t_old, machep, &h__, &global_1, &q_1); if (ret != NLOPT_SUCCESS) goto done; /* L120: */ } f1 = global_1.fx; global_1.fx = sf; lds = 0.; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { sl = x[i__]; x[i__] = y[i__ - 1]; sl -= y[i__ - 1]; y[i__ - 1] = sl; /* L130: */ lds += sl * sl; } lds = sqrt(lds); if (lds <= small) { goto L160; } /* .....DISCARD DIRECTION V(*,KL). */ /* IF NO RANDOM STEP WAS TAKEN, V(*,KL) IS THE "NON-CONJUGATE" */ /* DIRECTION ALONG WHICH THE GREATEST IMPROVEMENT WAS MADE..... */ klmk = kl - k; if (klmk < 1) { goto L141; } i__2 = klmk; for (ii = 1; ii <= i__2; ++ii) { i__ = kl - ii; i__3 = n; for (j = 1; j <= i__3; ++j) { /* L135: */ q_1.v[j + (i__ + 1) * n - (n+1)] = q_1.v[j + i__ * n - (n+1)]; } /* L140: */ d__[i__] = d__[i__ - 1]; } L141: d__[k - 1] = 0.; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* L145: */ q_1.v[i__ + k * n - (n+1)] = y[i__ - 1] / lds; } /* .....MINIMIZE ALONG THE NEW "CONJUGATE" DIRECTION V(*,K), WHICH IS */ /* THE NORMALIZED VECTOR: (NEW X) - (0LD X)..... */ value = f1; ret = min_(n, k, 4, &d__[k - 1], &lds, &value, 1, f,f_data, &x[1], &t_old, machep, &h__, &global_1, &q_1); if (ret != NLOPT_SUCCESS) goto done; if (lds > 0.) { goto L160; } lds = -lds; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* L150: */ q_1.v[i__ + k * n - (n+1)] = -q_1.v[i__ + k * n - (n+1)]; } L160: global_1.ldt = ldfac * global_1.ldt; if (global_1.ldt < lds) { global_1.ldt = lds; } t2_old = 0.; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* L165: */ /* Computing 2nd power */ d__1 = x[i__]; t2_old += d__1 * d__1; } t2_old = m2 * sqrt(t2_old) + t_old; /* .....SEE WHETHER THE LENGTH OF THE STEP TAKEN SINCE STARTING THE */ /* INNER LOOP EXCEEDS HALF THE TOLERANCE..... */ if (global_1.ldt > t2_old * .5f && !nlopt_stop_f(stop, q_1.fbest, prev_fbest) && !nlopt_stop_x(stop, q_1.xbest, prev_xbest)) { kt = -1; } ++kt; if (kt > ktm) { if (nlopt_stop_f(stop, q_1.fbest, prev_fbest)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, q_1.xbest, prev_xbest)) ret = NLOPT_XTOL_REACHED; goto done; } prev_fbest = q_1.fbest; memcpy(prev_xbest, q_1.xbest, n * sizeof(double)); /* L170: */ } /* .....THE INNER LOOP ENDS HERE. */ /* TRY QUADRATIC EXTRAPOLATION IN CASE WE ARE IN A CURVED VALLEY. */ /* L171: */ quad_(n, f,f_data, &x[1], &t_old, machep, &h__, &global_1, &q_1); dn = 0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__ - 1] = 1. / sqrt(d__[i__ - 1]); if (dn < d__[i__ - 1]) { dn = d__[i__ - 1]; } /* L175: */ } i__1 = n; for (j = 1; j <= i__1; ++j) { s = d__[j - 1] / dn; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { /* L180: */ q_1.v[i__ + j * n - (n+1)] = s * q_1.v[i__ + j * n - (n+1)]; } } /* .....SCALE THE AXES TO TRY TO REDUCE THE CONDITION NUMBER..... */ if (scbd <= 1.) { goto L200; } s = vlarge; i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { sl = 0.; i__1 = n; for (j = 1; j <= i__1; ++j) { /* L182: */ sl += q_1.v[i__ + j * n - (n+1)] * q_1.v[i__ + j * n - (n+1)]; } z__[i__ - 1] = sqrt(sl); if (z__[i__ - 1] < m4) { z__[i__ - 1] = m4; } if (s > z__[i__ - 1]) { s = z__[i__ - 1]; } /* L185: */ } i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { sl = s / z__[i__ - 1]; z__[i__ - 1] = 1. / sl; if (z__[i__ - 1] <= scbd) { goto L189; } sl = 1. / scbd; z__[i__ - 1] = scbd; L189: i__1 = n; for (j = 1; j <= i__1; ++j) { /* L190: */ q_1.v[i__ + j * n - (n+1)] = sl * q_1.v[i__ + j * n - (n+1)]; } /* L195: */ } /* .....CALCULATE A NEW SET OF ORTHOGONAL DIRECTIONS BEFORE REPEATING */ /* THE MAIN LOOP. */ /* FIRST TRANSPOSE V FOR MINFIT: */ L200: i__2 = n; for (i__ = 2; i__ <= i__2; ++i__) { im1 = i__ - 1; i__1 = im1; for (j = 1; j <= i__1; ++j) { s = q_1.v[i__ + j * n - (n+1)]; q_1.v[i__ + j * n - (n+1)] = q_1.v[j + i__ * n - (n+1)]; /* L210: */ q_1.v[j + i__ * n - (n+1)] = s; } /* L220: */ } /* .....CALL MINFIT TO FIND THE SINGULAR VALUE DECOMPOSITION OF V. */ /* THIS GIVES THE PRINCIPAL VALUES AND PRINCIPAL DIRECTIONS OF THE */ /* APPROXIMATING QUADRATIC FORM WITHOUT SQUARING THE CONDITION */ /* NUMBER..... */ minfit_(n, n, machep, &vsmall, q_1.v, d__, e_minfit); /* .....UNSCALE THE AXES..... */ if (scbd <= 1.) { goto L250; } i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { s = z__[i__ - 1]; i__1 = n; for (j = 1; j <= i__1; ++j) { /* L225: */ q_1.v[i__ + j * n - (n+1)] = s * q_1.v[i__ + j * n - (n+1)]; } /* L230: */ } i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { s = 0.; i__1 = n; for (j = 1; j <= i__1; ++j) { /* L235: */ /* Computing 2nd power */ d__1 = q_1.v[j + i__ * n - (n+1)]; s += d__1 * d__1; } s = sqrt(s); d__[i__ - 1] = s * d__[i__ - 1]; s = 1 / s; i__1 = n; for (j = 1; j <= i__1; ++j) { /* L240: */ q_1.v[j + i__ * n - (n+1)] = s * q_1.v[j + i__ * n - (n+1)]; } /* L245: */ } L250: i__2 = n; for (i__ = 1; i__ <= i__2; ++i__) { dni = dn * d__[i__ - 1]; if (dni > large) { goto L265; } if (dni < small) { goto L260; } d__[i__ - 1] = 1 / (dni * dni); goto L270; L260: d__[i__ - 1] = vlarge; goto L270; L265: d__[i__ - 1] = vsmall; L270: ; } /* .....SORT THE EIGENVALUES AND EIGENVECTORS..... */ sort_(n, n, d__, q_1.v); global_1.dmin__ = d__[n - 1]; if (global_1.dmin__ < small) { global_1.dmin__ = small; } illc = 0 /* false */; if (m2 * d__[0] > global_1.dmin__) { illc = 1 /* true */; } /* .....THE MAIN LOOP ENDS HERE..... */ goto L40; /* .....RETURN..... */ done: if (ret != NLOPT_OUT_OF_MEMORY) { *minf = q_1.fbest; memcpy(&x[1], q_1.xbest, n * sizeof(double)); } free(work); return ret; } /* praxis_ */ static void minfit_(int m, int n, double machep, double *tol, double *ab, double *q, double *ework) { /* System generated locals */ int ab_dim1, ab_offset, i__1, i__2, i__3; double d__1, d__2; /* Local variables */ double *e; /* size n */ double c__, f = 0.0, g, h__; int i__, j, k, l; double s, x, y, z__; int l2, ii, kk, kt, ll2, lp1; double eps, temp; e = ework; /* ...AN IMPROVED VERSION OF MINFIT (SEE GOLUB AND REINSCH, 1969) */ /* RESTRICTED TO M=N,P=0. */ /* THE SINGULAR VALUES OF THE ARRAY AB ARE RETURNED IN Q AND AB IS */ /* OVERWRITTEN WITH THE ORTHOGONAL MATRIX V SUCH THAT U.DIAG(Q) = AB.V, */ /* WHERE U IS ANOTHER ORTHOGONAL MATRIX. */ /* ...HOUSEHOLDER'S REDUCTION TO BIDIAGONAL FORM... */ /* Parameter adjustments */ --q; ab_dim1 = m; ab_offset = 1 + ab_dim1; ab -= ab_offset; /* Function Body */ if (n == 1) { goto L200; } eps = machep; g = 0.; x = 0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { e[i__ - 1] = g; s = 0.; l = i__ + 1; i__2 = n; for (j = i__; j <= i__2; ++j) { /* L1: */ /* Computing 2nd power */ d__1 = ab[j + i__ * ab_dim1]; s += d__1 * d__1; } g = 0.; if (s < *tol) { goto L4; } f = ab[i__ + i__ * ab_dim1]; g = sqrt(s); if (f >= 0.) { g = -g; } h__ = f * g - s; ab[i__ + i__ * ab_dim1] = f - g; if (l > n) { goto L4; } i__2 = n; for (j = l; j <= i__2; ++j) { f = 0.; i__3 = n; for (k = i__; k <= i__3; ++k) { /* L2: */ f += ab[k + i__ * ab_dim1] * ab[k + j * ab_dim1]; } f /= h__; i__3 = n; for (k = i__; k <= i__3; ++k) { /* L3: */ ab[k + j * ab_dim1] += f * ab[k + i__ * ab_dim1]; } } L4: q[i__] = g; s = 0.; if (i__ == n) { goto L6; } i__3 = n; for (j = l; j <= i__3; ++j) { /* L5: */ s += ab[i__ + j * ab_dim1] * ab[i__ + j * ab_dim1]; } L6: g = 0.; if (s < *tol) { goto L10; } if (i__ == n) { goto L16; } f = ab[i__ + (i__ + 1) * ab_dim1]; L16: g = sqrt(s); if (f >= 0.) { g = -g; } h__ = f * g - s; if (i__ == n) { goto L10; } ab[i__ + (i__ + 1) * ab_dim1] = f - g; i__3 = n; for (j = l; j <= i__3; ++j) { /* L7: */ e[j - 1] = ab[i__ + j * ab_dim1] / h__; } i__3 = n; for (j = l; j <= i__3; ++j) { s = 0.; i__2 = n; for (k = l; k <= i__2; ++k) { /* L8: */ s += ab[j + k * ab_dim1] * ab[i__ + k * ab_dim1]; } i__2 = n; for (k = l; k <= i__2; ++k) { /* L9: */ ab[j + k * ab_dim1] += s * e[k - 1]; } } L10: y = (d__1 = q[i__], fabs(d__1)) + (d__2 = e[i__ - 1], fabs(d__2)); /* L11: */ if (y > x) { x = y; } } /* ...ACCUMULATION OF RIGHT-HAND TRANSFORMATIONS... */ ab[n + n * ab_dim1] = 1.; g = e[n - 1]; l = n; i__1 = n; for (ii = 2; ii <= i__1; ++ii) { i__ = n - ii + 1; if (g == 0.) { goto L23; } h__ = ab[i__ + (i__ + 1) * ab_dim1] * g; i__2 = n; for (j = l; j <= i__2; ++j) { /* L20: */ ab[j + i__ * ab_dim1] = ab[i__ + j * ab_dim1] / h__; } i__2 = n; for (j = l; j <= i__2; ++j) { s = 0.; i__3 = n; for (k = l; k <= i__3; ++k) { /* L21: */ s += ab[i__ + k * ab_dim1] * ab[k + j * ab_dim1]; } i__3 = n; for (k = l; k <= i__3; ++k) { /* L22: */ ab[k + j * ab_dim1] += s * ab[k + i__ * ab_dim1]; } } L23: i__3 = n; for (j = l; j <= i__3; ++j) { ab[i__ + j * ab_dim1] = 0.; /* L24: */ ab[j + i__ * ab_dim1] = 0.; } ab[i__ + i__ * ab_dim1] = 1.; g = e[i__ - 1]; /* L25: */ l = i__; } /* ...DIAGONALIZATION OF THE BIDIAGONAL FORM... */ /* L100: */ eps *= x; i__1 = n; for (kk = 1; kk <= i__1; ++kk) { k = n - kk + 1; kt = 0; L101: ++kt; if (kt <= 30) { goto L102; } e[k - 1] = 0.; /* fprintf(stderr, "QR failed\n"); */ L102: i__3 = k; for (ll2 = 1; ll2 <= i__3; ++ll2) { l2 = k - ll2 + 1; l = l2; if ((d__1 = e[l - 1], fabs(d__1)) <= eps) { goto L120; } if (l == 1) { goto L103; } if ((d__1 = q[l - 1], fabs(d__1)) <= eps) { goto L110; } L103: ; } /* ...CANCELLATION OF E(L) IF L>1... */ L110: c__ = 0.; s = 1.; i__3 = k; for (i__ = l; i__ <= i__3; ++i__) { f = s * e[i__ - 1]; e[i__ - 1] = c__ * e[i__ - 1]; if (fabs(f) <= eps) { goto L120; } g = q[i__]; /* ...Q(I) = H = DSQRT(G*G + F*F)... */ if (fabs(f) < fabs(g)) { goto L113; } if (f != 0.) { goto L112; } else { goto L111; } L111: h__ = 0.; goto L114; L112: /* Computing 2nd power */ d__1 = g / f; h__ = fabs(f) * sqrt(d__1 * d__1 + 1); goto L114; L113: /* Computing 2nd power */ d__1 = f / g; h__ = fabs(g) * sqrt(d__1 * d__1 + 1); L114: q[i__] = h__; if (h__ != 0.) { goto L115; } g = 1.; h__ = 1.; L115: c__ = g / h__; /* L116: */ s = -f / h__; } /* ...TEST FOR CONVERGENCE... */ L120: z__ = q[k]; if (l == k) { goto L140; } /* ...SHIFT FROM BOTTOM 2*2 MINOR... */ x = q[l]; y = q[k - 1]; g = e[k - 2]; h__ = e[k - 1]; f = ((y - z__) * (y + z__) + (g - h__) * (g + h__)) / (h__ * 2 * y); g = sqrt(f * f + 1.); temp = f - g; if (f >= 0.) { temp = f + g; } f = ((x - z__) * (x + z__) + h__ * (y / temp - h__)) / x; /* ...NEXT QR TRANSFORMATION... */ c__ = 1.; s = 1.; lp1 = l + 1; if (lp1 > k) { goto L133; } i__3 = k; for (i__ = lp1; i__ <= i__3; ++i__) { g = e[i__ - 1]; y = q[i__]; h__ = s * g; g *= c__; if (fabs(f) < fabs(h__)) { goto L123; } if (f != 0.) { goto L122; } else { goto L121; } L121: z__ = 0.; goto L124; L122: /* Computing 2nd power */ d__1 = h__ / f; z__ = fabs(f) * sqrt(d__1 * d__1 + 1); goto L124; L123: /* Computing 2nd power */ d__1 = f / h__; z__ = fabs(h__) * sqrt(d__1 * d__1 + 1); L124: e[i__ - 2] = z__; if (z__ != 0.) { goto L125; } f = 1.; z__ = 1.; L125: c__ = f / z__; s = h__ / z__; f = x * c__ + g * s; g = -x * s + g * c__; h__ = y * s; y *= c__; i__2 = n; for (j = 1; j <= i__2; ++j) { x = ab[j + (i__ - 1) * ab_dim1]; z__ = ab[j + i__ * ab_dim1]; ab[j + (i__ - 1) * ab_dim1] = x * c__ + z__ * s; /* L126: */ ab[j + i__ * ab_dim1] = -x * s + z__ * c__; } if (fabs(f) < fabs(h__)) { goto L129; } if (f != 0.) { goto L128; } else { goto L127; } L127: z__ = 0.; goto L130; L128: /* Computing 2nd power */ d__1 = h__ / f; z__ = fabs(f) * sqrt(d__1 * d__1 + 1); goto L130; L129: /* Computing 2nd power */ d__1 = f / h__; z__ = fabs(h__) * sqrt(d__1 * d__1 + 1); L130: q[i__ - 1] = z__; if (z__ != 0.) { goto L131; } f = 1.; z__ = 1.; L131: c__ = f / z__; s = h__ / z__; f = c__ * g + s * y; /* L132: */ x = -s * g + c__ * y; } L133: e[l - 1] = 0.; e[k - 1] = f; q[k] = x; goto L101; /* ...CONVERGENCE: Q(K) IS MADE NON-NEGATIVE... */ L140: if (z__ >= 0.) { goto L150; } q[k] = -z__; i__3 = n; for (j = 1; j <= i__3; ++j) { /* L141: */ ab[j + k * ab_dim1] = -ab[j + k * ab_dim1]; } L150: ; } return; L200: q[1] = ab[ab_dim1 + 1]; ab[ab_dim1 + 1] = 1.; } /* minfit_ */ static nlopt_result min_(int n, int j, int nits, double * d2, double *x1, double *f1, int fk, praxis_func f, void *f_data, double * x, double *t_old, double machep, double *h__, struct global_s *global_1, struct q_s *q_1) { /* System generated locals */ int i__1; double d__1, d__2; /* Local variables */ int i__, k; double s, d1, f0, f2, m2, m4, t2, x2, fm; int dz; double xm, sf1, sx1; double temp, small; nlopt_result ret = NLOPT_SUCCESS; /* ...THE SUBROUTINE MIN MINIMIZES F FROM X IN THE DIRECTION V(*,J) UNLESS */ /* J IS LESS THAN 1, WHEN A QUADRATIC SEARCH IS MADE IN THE PLANE */ /* DEFINED BY Q0,Q1,X. */ /* D2 IS EITHER ZERO OR AN APPROXIMATION TO HALF F". */ /* ON ENTRY, X1 IS AN ESTIMATE OF THE DISTANCE FROM X TO THE MINIMUM */ /* ALONG V(*,J) (OR, IF J=0, A CURVE). ON RETURN, X1 IS THE DISTANCE */ /* FOUND. */ /* IF FK=.TRUE., THEN F1 IS FLIN(X1). OTHERWISE X1 AND F1 ARE IGNORED */ /* ON ENTRY UNLESS FINAL FX IS GREATER THAN F1. */ /* NITS CONTROLS THE NUMBER OF TIMES AN ATTEMPT WILL BE MADE TO HALVE */ /* THE INTERVAL. */ /* Parameter adjustments */ --x; /* Function Body */ /* Computing 2nd power */ d__1 = machep; small = d__1 * d__1; m2 = sqrt(machep); m4 = sqrt(m2); sf1 = *f1; sx1 = *x1; k = 0; xm = 0.; fm = global_1->fx; f0 = global_1->fx; dz = *d2 < machep; /* ...FIND THE STEP SIZE... */ s = 0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { /* L1: */ /* Computing 2nd power */ d__1 = x[i__]; s += d__1 * d__1; } s = sqrt(s); temp = *d2; if (dz) { temp = global_1->dmin__; } t2 = m4 * sqrt(fabs(global_1->fx) / temp + s * global_1->ldt) + m2 * global_1->ldt; s = m4 * s + *t_old; if (dz && t2 > s) { t2 = s; } t2 = t2 > small ? t2 : small; /* Computing MIN */ d__1 = t2, d__2 = *h__ * .01; t2 = d__1 < d__2 ? d__1 : d__2; if (! (fk) || *f1 > fm) { goto L2; } xm = *x1; fm = *f1; L2: if (fk && fabs(*x1) >= t2) { goto L3; } temp = 1.; if (*x1 < 0.) { temp = -1.; } *x1 = temp * t2; *f1 = flin_(n, j, x1, f,f_data, &x[1], &global_1->nf, q_1, &ret); if (ret != NLOPT_SUCCESS) return ret; L3: if (*f1 > fm) { goto L4; } xm = *x1; fm = *f1; L4: if (! dz) { goto L6; } /* ...EVALUATE FLIN AT ANOTHER POINT AND ESTIMATE THE SECOND DERIVATIVE... */ x2 = -(*x1); if (f0 >= *f1) { x2 = *x1 * 2.; } f2 = flin_(n, j, &x2, f,f_data, &x[1], &global_1->nf, q_1, &ret); if (ret != NLOPT_SUCCESS) return ret; if (f2 > fm) { goto L5; } xm = x2; fm = f2; L5: *d2 = (x2 * (*f1 - f0) - *x1 * (f2 - f0)) / (*x1 * x2 * (*x1 - x2)); /* ...ESTIMATE THE FIRST DERIVATIVE AT 0... */ L6: d1 = (*f1 - f0) / *x1 - *x1 * *d2; dz = 1 /* true */; /* ...PREDICT THE MINIMUM... */ if (*d2 > small) { goto L7; } x2 = *h__; if (d1 >= 0.) { x2 = -x2; } goto L8; L7: x2 = d1 * -.5 / *d2; L8: if (fabs(x2) <= *h__) { goto L11; } if (x2 <= 0.) { goto L9; } else { goto L10; } L9: x2 = -(*h__); goto L11; L10: x2 = *h__; /* ...EVALUATE F AT THE PREDICTED MINIMUM... */ L11: f2 = flin_(n, j, &x2, f,f_data, &x[1], &global_1->nf, q_1, &ret); if (ret != NLOPT_SUCCESS) return ret; if (k >= nits || f2 <= f0) { goto L12; } /* ...NO SUCCESS, SO TRY AGAIN... */ ++k; if (f0 < *f1 && *x1 * x2 > 0.) { goto L4; } x2 *= .5; goto L11; /* ...INCREMENT THE ONE-DIMENSIONAL SEARCH COUNTER... */ L12: ++global_1->nl; if (f2 <= fm) { goto L13; } x2 = xm; goto L14; L13: fm = f2; /* ...GET A NEW ESTIMATE OF THE SECOND DERIVATIVE... */ L14: if ((d__1 = x2 * (x2 - *x1), fabs(d__1)) <= small) { goto L15; } *d2 = (x2 * (*f1 - f0) - *x1 * (fm - f0)) / (*x1 * x2 * (*x1 - x2)); goto L16; L15: if (k > 0) { *d2 = 0.; } L16: if (*d2 <= small) { *d2 = small; } *x1 = x2; global_1->fx = fm; if (sf1 >= global_1->fx) { goto L17; } global_1->fx = sf1; *x1 = sx1; /* ...UPDATE X FOR LINEAR BUT NOT PARABOLIC SEARCH... */ L17: if (j == 0) { return NLOPT_SUCCESS; } i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { /* L18: */ x[i__] += *x1 * q_1->v[i__ + j * n - (n+1)]; } return NLOPT_SUCCESS; } /* min_ */ static double flin_(int n, int j, double *l, praxis_func f, void *f_data, double *x, int *nf, struct q_s *q_1, nlopt_result *ret) { /* System generated locals */ int i__1; double ret_val; /* Local variables */ nlopt_stopping *stop = q_1->stop; int i__; double *t; /* size n */ t = q_1->t_flin; /* ...FLIN IS THE FUNCTION OF ONE REAL VARIABLE L THAT IS MINIMIZED */ /* BY THE SUBROUTINE MIN... */ /* Parameter adjustments */ --x; /* Function Body */ if (j == 0) { goto L2; } /* ...THE SEARCH IS LINEAR... */ i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { /* L1: */ t[i__ - 1] = x[i__] + *l * q_1->v[i__ + j * n - (n+1)]; } goto L4; /* ...THE SEARCH IS ALONG A PARABOLIC SPACE CURVE... */ L2: q_1->qa = *l * (*l - q_1->qd1) / (q_1->qd0 * (q_1->qd0 + q_1->qd1)); q_1->qb = (*l + q_1->qd0) * (q_1->qd1 - *l) / (q_1->qd0 * q_1->qd1); q_1->qc = *l * (*l + q_1->qd0) / (q_1->qd1 * (q_1->qd0 + q_1->qd1)); i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { /* L3: */ t[i__ - 1] = q_1->qa * q_1->q0[i__ - 1] + q_1->qb * x[i__] + q_1->qc * q_1->q1[i__ - 1]; } /* ...THE FUNCTION EVALUATION COUNTER NF IS INCREMENTED... */ L4: ++(*nf); ret_val = f(n, t, f_data); ++ *(stop->nevals_p); if (ret_val < q_1->fbest) { q_1->fbest = ret_val; memcpy(q_1->xbest, t, n * sizeof(double)); } if (nlopt_stop_forced(stop)) *ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) *ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) *ret = NLOPT_MAXTIME_REACHED; else if (ret_val <= stop->minf_max) *ret = NLOPT_MINF_MAX_REACHED; return ret_val; } /* flin_ */ static void sort_(int m, int n, double *d__, double *v) { /* System generated locals */ int v_dim1, v_offset, i__1, i__2; /* Local variables */ int i__, j, k; double s; int ip1, nm1; /* ...SORTS THE ELEMENTS OF D(N) INTO DESCENDING ORDER AND MOVES THE */ /* CORRESPONDING COLUMNS OF V(N,N). */ /* M IS THE ROW DIMENSION OF V AS DECLARED IN THE CALLING PROGRAM. */ /* Parameter adjustments */ v_dim1 = m; v_offset = 1 + v_dim1; v -= v_offset; --d__; /* Function Body */ if (n == 1) { return; } nm1 = n - 1; i__1 = nm1; for (i__ = 1; i__ <= i__1; ++i__) { k = i__; s = d__[i__]; ip1 = i__ + 1; i__2 = n; for (j = ip1; j <= i__2; ++j) { if (d__[j] <= s) { goto L1; } k = j; s = d__[j]; L1: ; } if (k <= i__) { goto L3; } d__[k] = d__[i__]; d__[i__] = s; i__2 = n; for (j = 1; j <= i__2; ++j) { s = v[j + i__ * v_dim1]; v[j + i__ * v_dim1] = v[j + k * v_dim1]; /* L2: */ v[j + k * v_dim1] = s; } L3: ; } } /* sort_ */ static void quad_(int n, praxis_func f, void *f_data, double *x, double *t_old, double machep, double *h__, struct global_s *global_1, struct q_s *q_1) { /* System generated locals */ int i__1; double d__1; /* Local variables */ int i__; double l, s; double value; /* ...QUAD LOOKS FOR THE MINIMUM OF F ALONG A CURVE DEFINED BY Q0,Q1,X... */ /* Parameter adjustments */ --x; /* Function Body */ s = global_1->fx; global_1->fx = q_1->qf1; q_1->qf1 = s; q_1->qd1 = 0.; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { s = x[i__]; l = q_1->q1[i__ - 1]; x[i__] = l; q_1->q1[i__ - 1] = s; /* L1: */ /* Computing 2nd power */ d__1 = s - l; q_1->qd1 += d__1 * d__1; } q_1->qd1 = sqrt(q_1->qd1); l = q_1->qd1; s = 0.; if (q_1->qd0 <= 0. || q_1->qd1 <= 0. || global_1->nl < n * 3 * n) { goto L2; } value = q_1->qf1; min_(n, 0, 2, &s, &l, &value, 1, f,f_data, &x[1], t_old, machep, h__, global_1, q_1); q_1->qa = l * (l - q_1->qd1) / (q_1->qd0 * (q_1->qd0 + q_1->qd1)); q_1->qb = (l + q_1->qd0) * (q_1->qd1 - l) / (q_1->qd0 * q_1->qd1); q_1->qc = l * (l + q_1->qd0) / (q_1->qd1 * (q_1->qd0 + q_1->qd1)); goto L3; L2: global_1->fx = q_1->qf1; q_1->qa = 0.; q_1->qb = q_1->qa; q_1->qc = 1.; L3: q_1->qd0 = q_1->qd1; i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { s = q_1->q0[i__ - 1]; q_1->q0[i__ - 1] = x[i__]; /* L4: */ x[i__] = q_1->qa * s + q_1->qb * x[i__] + q_1->qc * q_1->q1[i__ - 1]; } } /* quad_ */ nlopt-2.6.1/src/algs/praxis/praxis.h000066400000000000000000000007041345435414600173700ustar00rootroot00000000000000#ifndef PRAXIS_H #define PRAXIS_H #include "nlopt-util.h" #include "nlopt.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef double (*praxis_func)(int n, const double *x, void *f_data); nlopt_result praxis_(double t0, double machep, double h0, int n, double *x, praxis_func f, void *f_data, nlopt_stopping *stop, double *minf); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* PRAXIS_H */ nlopt-2.6.1/src/algs/slsqp/000077500000000000000000000000001345435414600155445ustar00rootroot00000000000000nlopt-2.6.1/src/algs/slsqp/COPYRIGHT000066400000000000000000000046771345435414600170550ustar00rootroot00000000000000Copyright (c) 1988 Dieter Kraft Copyright (c) 1994 Association for Computing Machinery Copyright (c) 2001, 2002 Enthought, Inc. All rights reserved. Copyright (c) 2003-2009 SciPy Developers. All rights reserved. Copyright (c) 2010 Massachusetts Institute of Technology All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b. 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. c. Neither the name of the Enthought nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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. C http://permalink.gmane.org/gmane.comp.python.scientific.devel/6725 C ------ C From: Deborah Cotton C Date: Fri, 14 Sep 2007 12:35:55 -0500 C Subject: RE: Algorithm License requested C To: Alan Isaac C C Prof. Issac, C C In that case, then because the author consents to [the ACM] releasing C the code currently archived at http://www.netlib.org/toms/733 under the C BSD license, the ACM hereby releases this code under the BSD license. C C Regards, C C Deborah Cotton, Copyright & Permissions C ACM Publications C 2 Penn Plaza, Suite 701** C New York, NY 10121-0701 C permissions@acm.org C 212.869.7440 ext. 652 C Fax. 212.869.0481 C ------ nlopt-2.6.1/src/algs/slsqp/README000066400000000000000000000051461345435414600164320ustar00rootroot00000000000000This code implements a sequential quadratic programming (SQP) algorithm for nonlinearly constrained gradient-based optimization, and was originally written by Dieter Kraft and described in: Dieter Kraft, "A software package for sequential quadratic programming", Technical Report DFVLR-FB 88-28, Institut für Dynamik der Flugsysteme, Oberpfaffenhofen, July 1988. Dieter Kraft, "Algorithm 733: TOMP–Fortran modules for optimal control calculations," ACM Transactions on Mathematical Software, vol. 20, no. 3, pp. 262-281 (1994). (I believe that SLSQP stands for something like Sequential Least-Squares Quadratic Programming, because the problem is treated as a sequence of constrained least-squared problems, but such a least-squares problem is equivalent to a QP.) The actual Fortran file was obtained from the SciPy project, who are responsible for obtaining permission to distribute it under a free-software (3-clause BSD) license (see the permission email from ACM at the top of slsqp.c, and also projects.scipy.org/scipy/ticket/1056). The code was modified for inclusion in NLopt by S. G. Johnson in 2010, with the following changes. The code was converted to C and manually cleaned up. It was modified to be re-entrant, preserving the reverse-communication interface but explicitly saving the state in a data structure. The reverse-communication interface was wrapped with an NLopt-style inteface, with NLopt stopping conditions. The inexact line search was modified to evaluate the functions including gradients for the first step, since this removes the need to evaluate the function+gradient a second time for the same point in the common case when the inexact line search concludes after a single step, since NLopt's interface combines the function and gradient computations. Since roundoff errors sometimes pushed SLSQP's parameters slightly outside the bound constraints (not allowed by NLopt), we added checks to force the parameters within the bounds. Fixed a bug in LSEI (use of uninitialized variables) for the case where the number of equality constraints equals the dimension of the problem. The LSQ subroutine was modified to handle infinite lower/upper bounds (in which case those constraints are omitted). The exact line-search option is currently disabled; if we want to re-enable this (although exact line-search is usually overkill in these kinds of algorithms), we plan to do so using a recursive call to NLopt. (This will allow a user-specified line-search algorithm to be used, and will allow the gradient to be exploited in the exact line search, in contrast to the routine provided with SLSQP.)nlopt-2.6.1/src/algs/slsqp/slsqp.c000066400000000000000000002373711345435414600170670ustar00rootroot00000000000000/* SLSQP: Sequentional Least Squares Programming (aka sequential quadratic programming SQP) method for nonlinearly constrained nonlinear optimization, by Dieter Kraft (1991). Fortran released under a free (BSD) license by ACM to the SciPy project and used there. C translation via f2c + hand-cleanup and incorporation into NLopt by S. G. Johnson (2009). */ /* Table of constant values */ #include #include #include #include "slsqp.h" /* ALGORITHM 733, COLLECTED ALGORITHMS FROM ACM. */ /* TRANSACTIONS ON MATHEMATICAL SOFTWARE, */ /* VOL. 20, NO. 3, SEPTEMBER, 1994, PP. 262-281. */ /* http://doi.acm.org/10.1145/192115.192124 */ /* http://permalink.gmane.org/gmane.comp.python.scientific.devel/6725 */ /* ------ */ /* From: Deborah Cotton */ /* Date: Fri, 14 Sep 2007 12:35:55 -0500 */ /* Subject: RE: Algorithm License requested */ /* To: Alan Isaac */ /* Prof. Issac, */ /* In that case, then because the author consents to [the ACM] releasing */ /* the code currently archived at http://www.netlib.org/toms/733 under the */ /* BSD license, the ACM hereby releases this code under the BSD license. */ /* Regards, */ /* Deborah Cotton, Copyright & Permissions */ /* ACM Publications */ /* 2 Penn Plaza, Suite 701** */ /* New York, NY 10121-0701 */ /* permissions@acm.org */ /* 212.869.7440 ext. 652 */ /* Fax. 212.869.0481 */ /* ------ */ /********************************* BLAS1 routines *************************/ /* COPIES A VECTOR, X, TO A VECTOR, Y, with the given increments */ static void dcopy___(int *n_, const double *dx, int incx, double *dy, int incy) { int i, n = *n_; if (n <= 0) return; if (incx == 1 && incy == 1) memcpy(dy, dx, sizeof(double) * ((unsigned) n)); else if (incx == 0 && incy == 1) { double x = dx[0]; for (i = 0; i < n; ++i) dy[i] = x; } else { for (i = 0; i < n; ++i) dy[i*incy] = dx[i*incx]; } } /* dcopy___ */ /* CONSTANT TIMES A VECTOR PLUS A VECTOR. */ static void daxpy_sl__(int *n_, const double *da_, const double *dx, int incx, double *dy, int incy) { int n = *n_, i; double da = *da_; if (n <= 0 || da == 0) return; for (i = 0; i < n; ++i) dy[i*incy] += da * dx[i*incx]; } /* dot product dx dot dy. */ static double ddot_sl__(int *n_, double *dx, int incx, double *dy, int incy) { int n = *n_, i; long double sum = 0; if (n <= 0) return 0; for (i = 0; i < n; ++i) sum += dx[i*incx] * dy[i*incy]; return (double) sum; } /* compute the L2 norm of array DX of length N, stride INCX */ static double dnrm2___(int *n_, double *dx, int incx) { int i, n = *n_; double xmax = 0, scale; long double sum = 0; for (i = 0; i < n; ++i) { double xabs = fabs(dx[incx*i]); if (xmax < xabs) xmax = xabs; } if (xmax == 0) return 0; scale = 1.0 / xmax; for (i = 0; i < n; ++i) { double xs = scale * dx[incx*i]; sum += xs * xs; } return xmax * sqrt((double) sum); } /* apply Givens rotation */ static void dsrot_(int n, double *dx, int incx, double *dy, int incy, double *c__, double *s_) { int i; double c = *c__, s = *s_; for (i = 0; i < n; ++i) { double x = dx[incx*i], y = dy[incy*i]; dx[incx*i] = c * x + s * y; dy[incy*i] = c * y - s * x; } } /* construct Givens rotation */ static void dsrotg_(double *da, double *db, double *c, double *s) { double absa, absb, roe, scale; absa = fabs(*da); absb = fabs(*db); if (absa > absb) { roe = *da; scale = absa; } else { roe = *db; scale = absb; } if (scale != 0) { double r, iscale = 1 / scale; double tmpa = (*da) * iscale, tmpb = (*db) * iscale; r = (roe < 0 ? -scale : scale) * sqrt((tmpa * tmpa) + (tmpb * tmpb)); *c = *da / r; *s = *db / r; *da = r; if (*c != 0 && fabs(*c) <= *s) *db = 1 / *c; else *db = *s; } else { *c = 1; *s = *da = *db = 0; } } /* scales vector X(n) by constant da */ static void dscal_sl__(int *n_, const double *da, double *dx, int incx) { int i, n = *n_; double alpha = *da; for (i = 0; i < n; ++i) dx[i*incx] *= alpha; } /**************************************************************************/ static const int c__0 = 0; static const int c__1 = 1; static const int c__2 = 2; #define MIN2(a,b) ((a) <= (b) ? (a) : (b)) #define MAX2(a,b) ((a) >= (b) ? (a) : (b)) static void h12_(const int *mode, int *lpivot, int *l1, int *m, double *u, const int *iue, double *up, double *c__, const int *ice, const int *icv, const int *ncv) { /* Initialized data */ const double one = 1.; /* System generated locals */ int u_dim1, u_offset, i__1, i__2; double d__1; /* Local variables */ double b; int i__, j, i2, i3, i4; double cl, sm; int incr; double clinv; /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12 */ /* TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974 */ /* CONSTRUCTION AND/OR APPLICATION OF A SINGLE */ /* HOUSEHOLDER TRANSFORMATION Q = I + U*(U**T)/B */ /* MODE = 1 OR 2 TO SELECT ALGORITHM H1 OR H2 . */ /* LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. */ /* L1,M IF L1 <= M THE TRANSFORMATION WILL BE CONSTRUCTED TO */ /* ZERO ELEMENTS INDEXED FROM L1 THROUGH M. */ /* IF L1 > M THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION. */ /* U(),IUE,UP */ /* ON ENTRY TO H1 U() STORES THE PIVOT VECTOR. */ /* IUE IS THE STORAGE INCREMENT BETWEEN ELEMENTS. */ /* ON EXIT FROM H1 U() AND UP STORE QUANTITIES DEFINING */ /* THE VECTOR U OF THE HOUSEHOLDER TRANSFORMATION. */ /* ON ENTRY TO H2 U() AND UP */ /* SHOULD STORE QUANTITIES PREVIOUSLY COMPUTED BY H1. */ /* THESE WILL NOT BE MODIFIED BY H2. */ /* C() ON ENTRY TO H1 OR H2 C() STORES A MATRIX WHICH WILL BE */ /* REGARDED AS A SET OF VECTORS TO WHICH THE HOUSEHOLDER */ /* TRANSFORMATION IS TO BE APPLIED. */ /* ON EXIT C() STORES THE SET OF TRANSFORMED VECTORS. */ /* ICE STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C(). */ /* ICV STORAGE INCREMENT BETWEEN VECTORS IN C(). */ /* NCV NUMBER OF VECTORS IN C() TO BE TRANSFORMED. */ /* IF NCV <= 0 NO OPERATIONS WILL BE DONE ON C(). */ /* Parameter adjustments */ u_dim1 = *iue; u_offset = 1 + u_dim1; u -= u_offset; --c__; /* Function Body */ if (0 >= *lpivot || *lpivot >= *l1 || *l1 > *m) { goto L80; } cl = (d__1 = u[*lpivot * u_dim1 + 1], fabs(d__1)); if (*mode == 2) { goto L30; } /* ****** CONSTRUCT THE TRANSFORMATION ****** */ i__1 = *m; for (j = *l1; j <= i__1; ++j) { sm = (d__1 = u[j * u_dim1 + 1], fabs(d__1)); /* L10: */ cl = MAX2(sm,cl); } if (cl <= 0.0) { goto L80; } clinv = one / cl; /* Computing 2nd power */ d__1 = u[*lpivot * u_dim1 + 1] * clinv; sm = d__1 * d__1; i__1 = *m; for (j = *l1; j <= i__1; ++j) { /* L20: */ /* Computing 2nd power */ d__1 = u[j * u_dim1 + 1] * clinv; sm += d__1 * d__1; } cl *= sqrt(sm); if (u[*lpivot * u_dim1 + 1] > 0.0) { cl = -cl; } *up = u[*lpivot * u_dim1 + 1] - cl; u[*lpivot * u_dim1 + 1] = cl; goto L40; /* ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C ****** */ L30: if (cl <= 0.0) { goto L80; } L40: if (*ncv <= 0) { goto L80; } b = *up * u[*lpivot * u_dim1 + 1]; if (b >= 0.0) { goto L80; } b = one / b; i2 = 1 - *icv + *ice * (*lpivot - 1); incr = *ice * (*l1 - *lpivot); i__1 = *ncv; for (j = 1; j <= i__1; ++j) { i2 += *icv; i3 = i2 + incr; i4 = i3; sm = c__[i2] * *up; i__2 = *m; for (i__ = *l1; i__ <= i__2; ++i__) { sm += c__[i3] * u[i__ * u_dim1 + 1]; /* L50: */ i3 += *ice; } if (sm == 0.0) { goto L70; } sm *= b; c__[i2] += sm * *up; i__2 = *m; for (i__ = *l1; i__ <= i__2; ++i__) { c__[i4] += sm * u[i__ * u_dim1 + 1]; /* L60: */ i4 += *ice; } L70: ; } L80: return; } /* h12_ */ static void nnls_(double *a, int *mda, int *m, int * n, double *b, double *x, double *rnorm, double *w, double *z__, int *indx, int *mode) { /* Initialized data */ const double one = 1.; const double factor = .01; /* System generated locals */ int a_dim1, a_offset, i__1, i__2; double d__1; /* Local variables */ double c__; int i__, j, k, l; double s, t; int ii, jj, ip, iz, jz; double up; int iz1, iz2, npp1, iter; double wmax, alpha, asave; int itmax, izmax = 0, nsetp; double unorm; /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY: */ /* 'SOLVING LEAST SQUARES PROBLEMS'. PRENTICE-HALL.1974 */ /* ********** NONNEGATIVE LEAST SQUARES ********** */ /* GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN */ /* N-VECTOR, X, WHICH SOLVES THE LEAST SQUARES PROBLEM */ /* A*X = B SUBJECT TO X >= 0 */ /* A(),MDA,M,N */ /* MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE ARRAY,A(). */ /* ON ENTRY A() CONTAINS THE M BY N MATRIX,A. */ /* ON EXIT A() CONTAINS THE PRODUCT Q*A, */ /* WHERE Q IS AN M BY M ORTHOGONAL MATRIX GENERATED */ /* IMPLICITLY BY THIS SUBROUTINE. */ /* EITHER M>=N OR M iz2 || nsetp >= *m) { goto L280; } i__1 = iz2; for (iz = iz1; iz <= i__1; ++iz) { j = indx[iz]; /* L120: */ i__2 = *m - nsetp; w[j] = ddot_sl__(&i__2, &a[npp1 + j * a_dim1], 1, &b[npp1], 1) ; } /* STEP THREE (TEST DUAL VARIABLES) */ L130: wmax = 0.0; i__2 = iz2; for (iz = iz1; iz <= i__2; ++iz) { j = indx[iz]; if (w[j] <= wmax) { goto L140; } wmax = w[j]; izmax = iz; L140: ; } /* .....EXIT LOOP A */ if (wmax <= 0.0) { goto L280; } iz = izmax; j = indx[iz]; /* STEP FOUR (TEST INDX J FOR LINEAR DEPENDENCY) */ asave = a[npp1 + j * a_dim1]; i__2 = npp1 + 1; h12_(&c__1, &npp1, &i__2, m, &a[j * a_dim1 + 1], &c__1, &up, &z__[1], & c__1, &c__1, &c__0); unorm = dnrm2___(&nsetp, &a[j * a_dim1 + 1], 1); t = factor * (d__1 = a[npp1 + j * a_dim1], fabs(d__1)); d__1 = unorm + t; if (d__1 - unorm <= 0.0) { goto L150; } dcopy___(m, &b[1], 1, &z__[1], 1); i__2 = npp1 + 1; h12_(&c__2, &npp1, &i__2, m, &a[j * a_dim1 + 1], &c__1, &up, &z__[1], & c__1, &c__1, &c__1); if (z__[npp1] / a[npp1 + j * a_dim1] > 0.0) { goto L160; } L150: a[npp1 + j * a_dim1] = asave; w[j] = 0.0; goto L130; /* STEP FIVE (ADD COLUMN) */ L160: dcopy___(m, &z__[1], 1, &b[1], 1); indx[iz] = indx[iz1]; indx[iz1] = j; ++iz1; nsetp = npp1; ++npp1; i__2 = iz2; for (jz = iz1; jz <= i__2; ++jz) { jj = indx[jz]; /* L170: */ h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[jj * a_dim1 + 1], &c__1, mda, &c__1); } k = MIN2(npp1,*mda); w[j] = 0.0; i__2 = *m - nsetp; dcopy___(&i__2, &w[j], 0, &a[k + j * a_dim1], 1); /* STEP SIX (SOLVE LEAST SQUARES SUB-PROBLEM) */ /* .....ENTRY LOOP B */ L180: for (ip = nsetp; ip >= 1; --ip) { if (ip == nsetp) { goto L190; } d__1 = -z__[ip + 1]; daxpy_sl__(&ip, &d__1, &a[jj * a_dim1 + 1], 1, &z__[1], 1); L190: jj = indx[ip]; /* L200: */ z__[ip] /= a[ip + jj * a_dim1]; } ++iter; if (iter <= itmax) { goto L220; } L210: *mode = 3; goto L280; /* STEP SEVEN TO TEN (STEP LENGTH ALGORITHM) */ L220: alpha = one; jj = 0; i__2 = nsetp; for (ip = 1; ip <= i__2; ++ip) { if (z__[ip] > 0.0) { goto L230; } l = indx[ip]; t = -x[l] / (z__[ip] - x[l]); if (alpha < t) { goto L230; } alpha = t; jj = ip; L230: ; } i__2 = nsetp; for (ip = 1; ip <= i__2; ++ip) { l = indx[ip]; /* L240: */ x[l] = (one - alpha) * x[l] + alpha * z__[ip]; } /* .....EXIT LOOP B */ if (jj == 0) { goto L110; } /* STEP ELEVEN (DELETE COLUMN) */ i__ = indx[jj]; L250: x[i__] = 0.0; ++jj; i__2 = nsetp; for (j = jj; j <= i__2; ++j) { ii = indx[j]; indx[j - 1] = ii; dsrotg_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &c__, &s); t = a[j - 1 + ii * a_dim1]; dsrot_(*n, &a[j - 1 + a_dim1], *mda, &a[j + a_dim1], *mda, &c__, &s); a[j - 1 + ii * a_dim1] = t; a[j + ii * a_dim1] = 0.0; /* L260: */ dsrot_(1, &b[j - 1], 1, &b[j], 1, &c__, &s); } npp1 = nsetp; --nsetp; --iz1; indx[iz1] = i__; if (nsetp <= 0) { goto L210; } i__2 = nsetp; for (jj = 1; jj <= i__2; ++jj) { i__ = indx[jj]; if (x[i__] <= 0.0) { goto L250; } /* L270: */ } dcopy___(m, &b[1], 1, &z__[1], 1); goto L180; /* STEP TWELVE (SOLUTION) */ L280: k = MIN2(npp1,*m); i__2 = *m - nsetp; *rnorm = dnrm2___(&i__2, &b[k], 1); if (npp1 > *m) { w[1] = 0.0; dcopy___(n, &w[1], 0, &w[1], 1); } /* END OF SUBROUTINE NNLS */ L290: return; } /* nnls_ */ static void ldp_(double *g, int *mg, int *m, int *n, double *h__, double *x, double *xnorm, double *w, int *indx, int *mode) { /* Initialized data */ const double one = 1.; /* System generated locals */ int g_dim1, g_offset, i__1, i__2; double d__1; /* Local variables */ int i__, j, n1, if__, iw, iy, iz; double fac; double rnorm; int iwdual; /* T */ /* MINIMIZE 1/2 X X SUBJECT TO G * X >= H. */ /* C.L. LAWSON, R.J. HANSON: 'SOLVING LEAST SQUARES PROBLEMS' */ /* PRENTICE HALL, ENGLEWOOD CLIFFS, NEW JERSEY, 1974. */ /* PARAMETER DESCRIPTION: */ /* G(),MG,M,N ON ENTRY G() STORES THE M BY N MATRIX OF */ /* LINEAR INEQUALITY CONSTRAINTS. G() HAS FIRST */ /* DIMENSIONING PARAMETER MG */ /* H() ON ENTRY H() STORES THE M VECTOR H REPRESENTING */ /* THE RIGHT SIDE OF THE INEQUALITY SYSTEM */ /* REMARK: G(),H() WILL NOT BE CHANGED DURING CALCULATIONS BY LDP */ /* X() ON ENTRY X() NEED NOT BE INITIALIZED. */ /* ON EXIT X() STORES THE SOLUTION VECTOR X IF MODE=1. */ /* XNORM ON EXIT XNORM STORES THE EUCLIDIAN NORM OF THE */ /* SOLUTION VECTOR IF COMPUTATION IS SUCCESSFUL */ /* W() W IS A ONE DIMENSIONAL WORKING SPACE, THE LENGTH */ /* OF WHICH SHOULD BE AT LEAST (M+2)*(N+1) + 2*M */ /* ON EXIT W() STORES THE LAGRANGE MULTIPLIERS */ /* ASSOCIATED WITH THE CONSTRAINTS */ /* AT THE SOLUTION OF PROBLEM LDP */ /* INDX() INDX() IS A ONE DIMENSIONAL INT WORKING SPACE */ /* OF LENGTH AT LEAST M */ /* MODE MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */ /* MEANINGS: */ /* MODE=1: SUCCESSFUL COMPUTATION */ /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N.LE.0) */ /* 3: ITERATION COUNT EXCEEDED BY NNLS */ /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */ /* Parameter adjustments */ --indx; --h__; --x; g_dim1 = *mg; g_offset = 1 + g_dim1; g -= g_offset; --w; /* Function Body */ *mode = 2; if (*n <= 0) { goto L50; } /* STATE DUAL PROBLEM */ *mode = 1; x[1] = 0.0; dcopy___(n, &x[1], 0, &x[1], 1); *xnorm = 0.0; if (*m == 0) { goto L50; } iw = 0; i__1 = *m; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { ++iw; /* L10: */ w[iw] = g[j + i__ * g_dim1]; } ++iw; /* L20: */ w[iw] = h__[j]; } if__ = iw + 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { ++iw; /* L30: */ w[iw] = 0.0; } w[iw + 1] = one; n1 = *n + 1; iz = iw + 2; iy = iz + n1; iwdual = iy + *m; /* SOLVE DUAL PROBLEM */ nnls_(&w[1], &n1, &n1, m, &w[if__], &w[iy], &rnorm, &w[iwdual], &w[iz], & indx[1], mode); if (*mode != 1) { goto L50; } *mode = 4; if (rnorm <= 0.0) { goto L50; } /* COMPUTE SOLUTION OF PRIMAL PROBLEM */ fac = one - ddot_sl__(m, &h__[1], 1, &w[iy], 1); d__1 = one + fac; if (d__1 - one <= 0.0) { goto L50; } *mode = 1; fac = one / fac; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* L40: */ x[j] = fac * ddot_sl__(m, &g[j * g_dim1 + 1], 1, &w[iy], 1); } *xnorm = dnrm2___(n, &x[1], 1); /* COMPUTE LAGRANGE MULTIPLIERS FOR PRIMAL PROBLEM */ w[1] = 0.0; dcopy___(m, &w[1], 0, &w[1], 1); daxpy_sl__(m, &fac, &w[iy], 1, &w[1], 1); /* END OF SUBROUTINE LDP */ L50: return; } /* ldp_ */ static void lsi_(double *e, double *f, double *g, double *h__, int *le, int *me, int *lg, int *mg, int *n, double *x, double *xnorm, double *w, int * jw, int *mode) { /* Initialized data */ const double epmach = 2.22e-16; const double one = 1.; /* System generated locals */ int e_dim1, e_offset, g_dim1, g_offset, i__1, i__2, i__3; double d__1; /* Local variables */ int i__, j; double t; /* FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF */ /* INEQUALITY CONSTRAINED LINEAR LEAST SQUARES PROBLEM: */ /* MIN ||E*X-F|| */ /* X */ /* S.T. G*X >= H */ /* THE ALGORITHM IS BASED ON QR DECOMPOSITION AS DESCRIBED IN */ /* CHAPTER 23.5 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS */ /* THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM */ /* ARE NECESSARY */ /* DIM(E) : FORMAL (LE,N), ACTUAL (ME,N) */ /* DIM(F) : FORMAL (LE ), ACTUAL (ME ) */ /* DIM(G) : FORMAL (LG,N), ACTUAL (MG,N) */ /* DIM(H) : FORMAL (LG ), ACTUAL (MG ) */ /* DIM(X) : N */ /* DIM(W) : (N+1)*(MG+2) + 2*MG */ /* DIM(JW): LG */ /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS E, F, G, AND H. */ /* ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE. */ /* X STORES THE SOLUTION VECTOR */ /* XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM */ /* W STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST */ /* MG ELEMENTS */ /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */ /* MODE=1: SUCCESSFUL COMPUTATION */ /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */ /* 3: ITERATION COUNT EXCEEDED BY NNLS */ /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */ /* 5: MATRIX E IS NOT OF FULL RANK */ /* 03.01.1980, DIETER KRAFT: CODED */ /* 20.03.1987, DIETER KRAFT: REVISED TO FORTRAN 77 */ /* Parameter adjustments */ --f; --jw; --h__; --x; g_dim1 = *lg; g_offset = 1 + g_dim1; g -= g_offset; e_dim1 = *le; e_offset = 1 + e_dim1; e -= e_offset; --w; /* Function Body */ /* QR-FACTORS OF E AND APPLICATION TO F */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MIN */ i__2 = i__ + 1; j = MIN2(i__2,*n); i__2 = i__ + 1; i__3 = *n - i__; h12_(&c__1, &i__, &i__2, me, &e[i__ * e_dim1 + 1], &c__1, &t, &e[j * e_dim1 + 1], &c__1, le, &i__3); /* L10: */ i__2 = i__ + 1; h12_(&c__2, &i__, &i__2, me, &e[i__ * e_dim1 + 1], &c__1, &t, &f[1], & c__1, &c__1, &c__1); } /* TRANSFORM G AND H TO GET LEAST DISTANCE PROBLEM */ *mode = 5; i__2 = *mg; for (i__ = 1; i__ <= i__2; ++i__) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if ((d__1 = e[j + j * e_dim1], fabs(d__1)) < epmach) { goto L50; } /* L20: */ i__3 = j - 1; g[i__ + j * g_dim1] = (g[i__ + j * g_dim1] - ddot_sl__(&i__3, &g[ i__ + g_dim1], *lg, &e[j * e_dim1 + 1], 1)) / e[j + j * e_dim1]; } /* L30: */ h__[i__] -= ddot_sl__(n, &g[i__ + g_dim1], *lg, &f[1], 1); } /* SOLVE LEAST DISTANCE PROBLEM */ ldp_(&g[g_offset], lg, mg, n, &h__[1], &x[1], xnorm, &w[1], &jw[1], mode); if (*mode != 1) { goto L50; } /* SOLUTION OF ORIGINAL PROBLEM */ daxpy_sl__(n, &one, &f[1], 1, &x[1], 1); for (i__ = *n; i__ >= 1; --i__) { /* Computing MIN */ i__2 = i__ + 1; j = MIN2(i__2,*n); /* L40: */ i__2 = *n - i__; x[i__] = (x[i__] - ddot_sl__(&i__2, &e[i__ + j * e_dim1], *le, &x[j], 1)) / e[i__ + i__ * e_dim1]; } /* Computing MIN */ i__2 = *n + 1; j = MIN2(i__2,*me); i__2 = *me - *n; t = dnrm2___(&i__2, &f[j], 1); *xnorm = sqrt(*xnorm * *xnorm + t * t); /* END OF SUBROUTINE LSI */ L50: return; } /* lsi_ */ static void hfti_(double *a, int *mda, int *m, int * n, double *b, int *mdb, const int *nb, double *tau, int *krank, double *rnorm, double *h__, double *g, int * ip) { /* Initialized data */ const double factor = .001; /* System generated locals */ int a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3; double d__1; /* Local variables */ int i__, j, k, l; int jb, kp1; double tmp, hmax; int lmax, ldiag; /* RANK-DEFICIENT LEAST SQUARES ALGORITHM AS DESCRIBED IN: */ /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12 */ /* TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974 */ /* A(*,*),MDA,M,N THE ARRAY A INITIALLY CONTAINS THE M x N MATRIX A */ /* OF THE LEAST SQUARES PROBLEM AX = B. */ /* THE FIRST DIMENSIONING PARAMETER MDA MUST SATISFY */ /* MDA >= M. EITHER M >= N OR M < N IS PERMITTED. */ /* THERE IS NO RESTRICTION ON THE RANK OF A. */ /* THE MATRIX A WILL BE MODIFIED BY THE SUBROUTINE. */ /* B(*,*),MDB,NB IF NB = 0 THE SUBROUTINE WILL MAKE NO REFERENCE */ /* TO THE ARRAY B. IF NB > 0 THE ARRAY B() MUST */ /* INITIALLY CONTAIN THE M x NB MATRIX B OF THE */ /* THE LEAST SQUARES PROBLEM AX = B AND ON RETURN */ /* THE ARRAY B() WILL CONTAIN THE N x NB SOLUTION X. */ /* IF NB>1 THE ARRAY B() MUST BE DOUBLE SUBSCRIPTED */ /* WITH FIRST DIMENSIONING PARAMETER MDB>=MAX(M,N), */ /* IF NB=1 THE ARRAY B() MAY BE EITHER SINGLE OR */ /* DOUBLE SUBSCRIPTED. */ /* TAU ABSOLUTE TOLERANCE PARAMETER FOR PSEUDORANK */ /* DETERMINATION, PROVIDED BY THE USER. */ /* KRANK PSEUDORANK OF A, SET BY THE SUBROUTINE. */ /* RNORM ON EXIT, RNORM(J) WILL CONTAIN THE EUCLIDIAN */ /* NORM OF THE RESIDUAL VECTOR FOR THE PROBLEM */ /* DEFINED BY THE J-TH COLUMN VECTOR OF THE ARRAY B. */ /* H(), G() ARRAYS OF WORKING SPACE OF LENGTH >= N. */ /* IP() INT ARRAY OF WORKING SPACE OF LENGTH >= N */ /* RECORDING PERMUTATION INDICES OF COLUMN VECTORS */ /* Parameter adjustments */ --ip; --g; --h__; a_dim1 = *mda; a_offset = 1 + a_dim1; a -= a_offset; --rnorm; b_dim1 = *mdb; b_offset = 1 + b_dim1; b -= b_offset; /* Function Body */ k = 0; ldiag = MIN2(*m,*n); if (ldiag <= 0) { goto L270; } /* COMPUTE LMAX */ i__1 = ldiag; for (j = 1; j <= i__1; ++j) { if (j == 1) { goto L20; } lmax = j; i__2 = *n; for (l = j; l <= i__2; ++l) { /* Computing 2nd power */ d__1 = a[j - 1 + l * a_dim1]; h__[l] -= d__1 * d__1; /* L10: */ if (h__[l] > h__[lmax]) { lmax = l; } } d__1 = hmax + factor * h__[lmax]; if (d__1 - hmax > 0.0) { goto L50; } L20: lmax = j; i__2 = *n; for (l = j; l <= i__2; ++l) { h__[l] = 0.0; i__3 = *m; for (i__ = j; i__ <= i__3; ++i__) { /* L30: */ /* Computing 2nd power */ d__1 = a[i__ + l * a_dim1]; h__[l] += d__1 * d__1; } /* L40: */ if (h__[l] > h__[lmax]) { lmax = l; } } hmax = h__[lmax]; /* COLUMN INTERCHANGES IF NEEDED */ L50: ip[j] = lmax; if (ip[j] == j) { goto L70; } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { tmp = a[i__ + j * a_dim1]; a[i__ + j * a_dim1] = a[i__ + lmax * a_dim1]; /* L60: */ a[i__ + lmax * a_dim1] = tmp; } h__[lmax] = h__[j]; /* J-TH TRANSFORMATION AND APPLICATION TO A AND B */ L70: /* Computing MIN */ i__2 = j + 1; i__ = MIN2(i__2,*n); i__2 = j + 1; i__3 = *n - j; h12_(&c__1, &j, &i__2, m, &a[j * a_dim1 + 1], &c__1, &h__[j], &a[i__ * a_dim1 + 1], &c__1, mda, &i__3); /* L80: */ i__2 = j + 1; h12_(&c__2, &j, &i__2, m, &a[j * a_dim1 + 1], &c__1, &h__[j], &b[ b_offset], &c__1, mdb, nb); } /* DETERMINE PSEUDORANK */ i__2 = ldiag; for (j = 1; j <= i__2; ++j) { /* L90: */ if ((d__1 = a[j + j * a_dim1], fabs(d__1)) <= *tau) { goto L100; } } k = ldiag; goto L110; L100: k = j - 1; L110: kp1 = k + 1; /* NORM OF RESIDUALS */ i__2 = *nb; for (jb = 1; jb <= i__2; ++jb) { /* L130: */ i__1 = *m - k; rnorm[jb] = dnrm2___(&i__1, &b[kp1 + jb * b_dim1], 1); } if (k > 0) { goto L160; } i__1 = *nb; for (jb = 1; jb <= i__1; ++jb) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* L150: */ b[i__ + jb * b_dim1] = 0.0; } } goto L270; L160: if (k == *n) { goto L180; } /* HOUSEHOLDER DECOMPOSITION OF FIRST K ROWS */ for (i__ = k; i__ >= 1; --i__) { /* L170: */ i__2 = i__ - 1; h12_(&c__1, &i__, &kp1, n, &a[i__ + a_dim1], mda, &g[i__], &a[ a_offset], mda, &c__1, &i__2); } L180: i__2 = *nb; for (jb = 1; jb <= i__2; ++jb) { /* SOLVE K*K TRIANGULAR SYSTEM */ for (i__ = k; i__ >= 1; --i__) { /* Computing MIN */ i__1 = i__ + 1; j = MIN2(i__1,*n); /* L210: */ i__1 = k - i__; b[i__ + jb * b_dim1] = (b[i__ + jb * b_dim1] - ddot_sl__(&i__1, & a[i__ + j * a_dim1], *mda, &b[j + jb * b_dim1], 1)) / a[i__ + i__ * a_dim1]; } /* COMPLETE SOLUTION VECTOR */ if (k == *n) { goto L240; } i__1 = *n; for (j = kp1; j <= i__1; ++j) { /* L220: */ b[j + jb * b_dim1] = 0.0; } i__1 = k; for (i__ = 1; i__ <= i__1; ++i__) { /* L230: */ h12_(&c__2, &i__, &kp1, n, &a[i__ + a_dim1], mda, &g[i__], &b[jb * b_dim1 + 1], &c__1, mdb, &c__1); } /* REORDER SOLUTION ACCORDING TO PREVIOUS COLUMN INTERCHANGES */ L240: for (j = ldiag; j >= 1; --j) { if (ip[j] == j) { goto L250; } l = ip[j]; tmp = b[l + jb * b_dim1]; b[l + jb * b_dim1] = b[j + jb * b_dim1]; b[j + jb * b_dim1] = tmp; L250: ; } } L270: *krank = k; } /* hfti_ */ static void lsei_(double *c__, double *d__, double *e, double *f, double *g, double *h__, int *lc, int * mc, int *le, int *me, int *lg, int *mg, int *n, double *x, double *xnrm, double *w, int *jw, int * mode) { /* Initialized data */ const double epmach = 2.22e-16; /* System generated locals */ int c_dim1, c_offset, e_dim1, e_offset, g_dim1, g_offset, i__1, i__2, i__3; double d__1; /* Local variables */ int i__, j, k, l; double t; int ie, if__, ig, iw, mc1; int krank; /* FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF */ /* EQUALITY & INEQUALITY CONSTRAINED LEAST SQUARES PROBLEM LSEI : */ /* MIN ||E*X - F|| */ /* X */ /* S.T. C*X = D, */ /* G*X >= H. */ /* USING QR DECOMPOSITION & ORTHOGONAL BASIS OF NULLSPACE OF C */ /* CHAPTER 23.6 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS. */ /* THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM */ /* ARE NECESSARY */ /* DIM(E) : FORMAL (LE,N), ACTUAL (ME,N) */ /* DIM(F) : FORMAL (LE ), ACTUAL (ME ) */ /* DIM(C) : FORMAL (LC,N), ACTUAL (MC,N) */ /* DIM(D) : FORMAL (LC ), ACTUAL (MC ) */ /* DIM(G) : FORMAL (LG,N), ACTUAL (MG,N) */ /* DIM(H) : FORMAL (LG ), ACTUAL (MG ) */ /* DIM(X) : FORMAL (N ), ACTUAL (N ) */ /* DIM(W) : 2*MC+ME+(ME+MG)*(N-MC) for LSEI */ /* +(N-MC+1)*(MG+2)+2*MG for LSI */ /* DIM(JW): MAX(MG,L) */ /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS C, D, E, F, G, AND H. */ /* ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE. */ /* X STORES THE SOLUTION VECTOR */ /* XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM */ /* W STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST */ /* MC+MG ELEMENTS */ /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */ /* MODE=1: SUCCESSFUL COMPUTATION */ /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */ /* 3: ITERATION COUNT EXCEEDED BY NNLS */ /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */ /* 5: MATRIX E IS NOT OF FULL RANK */ /* 6: MATRIX C IS NOT OF FULL RANK */ /* 7: RANK DEFECT IN HFTI */ /* 18.5.1981, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN */ /* 20.3.1987, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN */ /* Parameter adjustments */ --d__; --f; --h__; --x; g_dim1 = *lg; g_offset = 1 + g_dim1; g -= g_offset; e_dim1 = *le; e_offset = 1 + e_dim1; e -= e_offset; c_dim1 = *lc; c_offset = 1 + c_dim1; c__ -= c_offset; --w; --jw; /* Function Body */ *mode = 2; if (*mc > *n) { goto L75; } l = *n - *mc; mc1 = *mc + 1; iw = (l + 1) * (*mg + 2) + (*mg << 1) + *mc; ie = iw + *mc + 1; if__ = ie + *me * l; ig = if__ + *me; /* TRIANGULARIZE C AND APPLY FACTORS TO E AND G */ i__1 = *mc; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MIN */ i__2 = i__ + 1; j = MIN2(i__2,*lc); i__2 = i__ + 1; i__3 = *mc - i__; h12_(&c__1, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], & c__[j + c_dim1], lc, &c__1, &i__3); i__2 = i__ + 1; h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &e[ e_offset], le, &c__1, me); /* L10: */ i__2 = i__ + 1; h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &g[ g_offset], lg, &c__1, mg); } /* SOLVE C*X=D AND MODIFY F */ *mode = 6; i__2 = *mc; for (i__ = 1; i__ <= i__2; ++i__) { if ((d__1 = c__[i__ + i__ * c_dim1], fabs(d__1)) < epmach) { goto L75; } i__1 = i__ - 1; x[i__] = (d__[i__] - ddot_sl__(&i__1, &c__[i__ + c_dim1], *lc, &x[1], 1)) / c__[i__ + i__ * c_dim1]; /* L15: */ } *mode = 1; w[mc1] = 0.0; i__2 = *mg; /* BUGFIX for *mc == *n: changed from *mg - *mc, SGJ 2010 */ dcopy___(&i__2, &w[mc1], 0, &w[mc1], 1); if (*mc == *n) { goto L50; } i__2 = *me; for (i__ = 1; i__ <= i__2; ++i__) { /* L20: */ w[if__ - 1 + i__] = f[i__] - ddot_sl__(mc, &e[i__ + e_dim1], *le, &x[1], 1); } /* STORE TRANSFORMED E & G */ i__2 = *me; for (i__ = 1; i__ <= i__2; ++i__) { /* L25: */ dcopy___(&l, &e[i__ + mc1 * e_dim1], *le, &w[ie - 1 + i__], *me); } i__2 = *mg; for (i__ = 1; i__ <= i__2; ++i__) { /* L30: */ dcopy___(&l, &g[i__ + mc1 * g_dim1], *lg, &w[ig - 1 + i__], *mg); } if (*mg > 0) { goto L40; } /* SOLVE LS WITHOUT INEQUALITY CONSTRAINTS */ *mode = 7; k = MAX2(*le,*n); t = sqrt(epmach); hfti_(&w[ie], me, me, &l, &w[if__], &k, &c__1, &t, &krank, xnrm, &w[1], & w[l + 1], &jw[1]); dcopy___(&l, &w[if__], 1, &x[mc1], 1); if (krank != l) { goto L75; } *mode = 1; goto L50; /* MODIFY H AND SOLVE INEQUALITY CONSTRAINED LS PROBLEM */ L40: i__2 = *mg; for (i__ = 1; i__ <= i__2; ++i__) { /* L45: */ h__[i__] -= ddot_sl__(mc, &g[i__ + g_dim1], *lg, &x[1], 1); } lsi_(&w[ie], &w[if__], &w[ig], &h__[1], me, me, mg, mg, &l, &x[mc1], xnrm, &w[mc1], &jw[1], mode); if (*mc == 0) { goto L75; } t = dnrm2___(mc, &x[1], 1); *xnrm = sqrt(*xnrm * *xnrm + t * t); if (*mode != 1) { goto L75; } /* SOLUTION OF ORIGINAL PROBLEM AND LAGRANGE MULTIPLIERS */ L50: i__2 = *me; for (i__ = 1; i__ <= i__2; ++i__) { /* L55: */ f[i__] = ddot_sl__(n, &e[i__ + e_dim1], *le, &x[1], 1) - f[i__]; } i__2 = *mc; for (i__ = 1; i__ <= i__2; ++i__) { /* L60: */ d__[i__] = ddot_sl__(me, &e[i__ * e_dim1 + 1], 1, &f[1], 1) - ddot_sl__(mg, &g[i__ * g_dim1 + 1], 1, &w[mc1], 1); } for (i__ = *mc; i__ >= 1; --i__) { /* L65: */ i__2 = i__ + 1; h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &x[ 1], &c__1, &c__1, &c__1); } for (i__ = *mc; i__ >= 1; --i__) { /* Computing MIN */ i__2 = i__ + 1; j = MIN2(i__2,*lc); i__2 = *mc - i__; w[i__] = (d__[i__] - ddot_sl__(&i__2, &c__[j + i__ * c_dim1], 1, & w[j], 1)) / c__[i__ + i__ * c_dim1]; /* L70: */ } /* END OF SUBROUTINE LSEI */ L75: return; } /* lsei_ */ static void lsq_(int *m, int *meq, int *n, int *nl, int *la, double *l, double *g, double *a, double * b, const double *xl, const double *xu, double *x, double *y, double *w, int *jw, int *mode) { /* Initialized data */ const double one = 1.; /* System generated locals */ int a_dim1, a_offset, i__1, i__2; double d__1; /* Local variables */ int i__, i1, i2, i3, i4, m1, n1, n2, n3, ic, id, ie, if__, ig, ih, il, im, ip, iu, iw; double diag; int mineq; double xnorm; /* MINIMIZE with respect to X */ /* ||E*X - F|| */ /* 1/2 T */ /* WITH UPPER TRIANGULAR MATRIX E = +D *L , */ /* -1/2 -1 */ /* AND VECTOR F = -D *L *G, */ /* WHERE THE UNIT LOWER TRIDIANGULAR MATRIX L IS STORED COLUMNWISE */ /* DENSE IN THE N*(N+1)/2 ARRAY L WITH VECTOR D STORED IN ITS */ /* 'DIAGONAL' THUS SUBSTITUTING THE ONE-ELEMENTS OF L */ /* SUBJECT TO */ /* A(J)*X - B(J) = 0 , J=1,...,MEQ, */ /* A(J)*X - B(J) >=0, J=MEQ+1,...,M, */ /* XL(I) <= X(I) <= XU(I), I=1,...,N, */ /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS L, G, A, B, XL, XU. */ /* WITH DIMENSIONS: L(N*(N+1)/2), G(N), A(LA,N), B(M), XL(N), XU(N) */ /* THE WORKING ARRAY W MUST HAVE AT LEAST THE FOLLOWING DIMENSION: */ /* DIM(W) = (3*N+M)*(N+1) for LSQ */ /* +(N-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI */ /* +(N+MINEQ)*(N-MEQ) + 2*MEQ + N for LSEI */ /* with MINEQ = M - MEQ + 2*N */ /* ON RETURN, NO ARRAY WILL BE CHANGED BY THE SUBROUTINE. */ /* X STORES THE N-DIMENSIONAL SOLUTION VECTOR */ /* Y STORES THE VECTOR OF LAGRANGE MULTIPLIERS OF DIMENSION */ /* M+N+N (CONSTRAINTS+LOWER+UPPER BOUNDS) */ /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */ /* MODE=1: SUCCESSFUL COMPUTATION */ /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */ /* 3: ITERATION COUNT EXCEEDED BY NNLS */ /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */ /* 5: MATRIX E IS NOT OF FULL RANK */ /* 6: MATRIX C IS NOT OF FULL RANK */ /* 7: RANK DEFECT IN HFTI */ /* coded Dieter Kraft, april 1987 */ /* revised march 1989 */ /* Parameter adjustments */ --y; --x; --xu; --xl; --g; --l; --b; a_dim1 = *la; a_offset = 1 + a_dim1; a -= a_offset; --w; --jw; /* Function Body */ n1 = *n + 1; mineq = *m - *meq; m1 = mineq + *n + *n; /* determine whether to solve problem */ /* with inconsistent linerarization (n2=1) */ /* or not (n2=0) */ n2 = n1 * *n / 2 + 1; if (n2 == *nl) { n2 = 0; } else { n2 = 1; } n3 = *n - n2; /* RECOVER MATRIX E AND VECTOR F FROM L AND G */ i2 = 1; i3 = 1; i4 = 1; ie = 1; if__ = *n * *n + 1; i__1 = n3; for (i__ = 1; i__ <= i__1; ++i__) { i1 = n1 - i__; diag = sqrt(l[i2]); w[i3] = 0.0; dcopy___(&i1, &w[i3], 0, &w[i3], 1); i__2 = i1 - n2; dcopy___(&i__2, &l[i2], 1, &w[i3], *n); i__2 = i1 - n2; dscal_sl__(&i__2, &diag, &w[i3], *n); w[i3] = diag; i__2 = i__ - 1; w[if__ - 1 + i__] = (g[i__] - ddot_sl__(&i__2, &w[i4], 1, &w[if__] , 1)) / diag; i2 = i2 + i1 - n2; i3 += n1; i4 += *n; /* L10: */ } if (n2 == 1) { w[i3] = l[*nl]; w[i4] = 0.0; dcopy___(&n3, &w[i4], 0, &w[i4], 1); w[if__ - 1 + *n] = 0.0; } d__1 = -one; dscal_sl__(n, &d__1, &w[if__], 1); ic = if__ + *n; id = ic + *meq * *n; if (*meq > 0) { /* RECOVER MATRIX C FROM UPPER PART OF A */ i__1 = *meq; for (i__ = 1; i__ <= i__1; ++i__) { dcopy___(n, &a[i__ + a_dim1], *la, &w[ic - 1 + i__], *meq); /* L20: */ } /* RECOVER VECTOR D FROM UPPER PART OF B */ dcopy___(meq, &b[1], 1, &w[id], 1); d__1 = -one; dscal_sl__(meq, &d__1, &w[id], 1); } ig = id + *meq; if (mineq > 0) { /* RECOVER MATRIX G FROM LOWER PART OF A */ i__1 = mineq; for (i__ = 1; i__ <= i__1; ++i__) { dcopy___(n, &a[*meq + i__ + a_dim1], *la, &w[ig - 1 + i__], m1); /* L30: */ } } /* AUGMENT MATRIX G BY +I AND -I */ ip = ig + mineq; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { w[ip - 1 + i__] = 0.0; dcopy___(n, &w[ip - 1 + i__], 0, &w[ip - 1 + i__], m1); /* L40: */ } i__1 = m1 + 1; /* SGJ, 2010: skip constraints for infinite bounds */ for (i__ = 1; i__ <= *n; ++i__) if (!nlopt_isinf(xl[i__])) w[(ip - i__1) + i__ * i__1] = +1.0; /* Old code: w[ip] = one; dcopy___(n, &w[ip], 0, &w[ip], i__1); */ im = ip + *n; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { w[im - 1 + i__] = 0.0; dcopy___(n, &w[im - 1 + i__], 0, &w[im - 1 + i__], m1); /* L50: */ } i__1 = m1 + 1; /* SGJ, 2010: skip constraints for infinite bounds */ for (i__ = 1; i__ <= *n; ++i__) if (!nlopt_isinf(xu[i__])) w[(im - i__1) + i__ * i__1] = -1.0; /* Old code: w[im] = -one; dcopy___(n, &w[im], 0, &w[im], i__1); */ ih = ig + m1 * *n; if (mineq > 0) { /* RECOVER H FROM LOWER PART OF B */ dcopy___(&mineq, &b[*meq + 1], 1, &w[ih], 1); d__1 = -one; dscal_sl__(&mineq, &d__1, &w[ih], 1); } /* AUGMENT VECTOR H BY XL AND XU */ il = ih + mineq; iu = il + *n; /* SGJ, 2010: skip constraints for infinite bounds */ for (i__ = 1; i__ <= *n; ++i__) { w[(il-1) + i__] = nlopt_isinf(xl[i__]) ? 0 : xl[i__]; w[(iu-1) + i__] = nlopt_isinf(xu[i__]) ? 0 : -xu[i__]; } /* Old code: dcopy___(n, &xl[1], 1, &w[il], 1); dcopy___(n, &xu[1], 1, &w[iu], 1); d__1 = -one; dscal_sl__(n, &d__1, &w[iu], 1); */ iw = iu + *n; i__1 = MAX2(1,*meq); lsei_(&w[ic], &w[id], &w[ie], &w[if__], &w[ig], &w[ih], &i__1, meq, n, n, &m1, &m1, n, &x[1], &xnorm, &w[iw], &jw[1], mode); if (*mode == 1) { /* restore Lagrange multipliers */ dcopy___(m, &w[iw], 1, &y[1], 1); dcopy___(&n3, &w[iw + *m], 1, &y[*m + 1], 1); dcopy___(&n3, &w[iw + *m + *n], 1, &y[*m + n3 + 1], 1); /* SGJ, 2010: make sure bound constraints are satisfied, since roundoff error sometimes causes slight violations and NLopt guarantees that bounds are strictly obeyed */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (x[i__] < xl[i__]) x[i__] = xl[i__]; else if (x[i__] > xu[i__]) x[i__] = xu[i__]; } } /* END OF SUBROUTINE LSQ */ } /* lsq_ */ static void ldl_(int *n, double *a, double *z__, double *sigma, double *w) { /* Initialized data */ const double one = 1.; const double four = 4.; const double epmach = 2.22e-16; /* System generated locals */ int i__1, i__2; /* Local variables */ int i__, j; double t, u, v; int ij; double tp, beta, gamma_, alpha, delta; /* LDL LDL' - RANK-ONE - UPDATE */ /* PURPOSE: */ /* UPDATES THE LDL' FACTORS OF MATRIX A BY RANK-ONE MATRIX */ /* SIGMA*Z*Z' */ /* INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION) */ /* N : ORDER OF THE COEFFICIENT MATRIX A */ /* * A : POSITIVE DEFINITE MATRIX OF DIMENSION N; */ /* ONLY THE LOWER TRIANGLE IS USED AND IS STORED COLUMN BY */ /* COLUMN AS ONE DIMENSIONAL ARRAY OF DIMENSION N*(N+1)/2. */ /* * Z : VECTOR OF DIMENSION N OF UPDATING ELEMENTS */ /* SIGMA : SCALAR FACTOR BY WHICH THE MODIFYING DYADE Z*Z' IS */ /* MULTIPLIED */ /* OUTPUT ARGUMENTS: */ /* A : UPDATED LDL' FACTORS */ /* WORKING ARRAY: */ /* W : VECTOR OP DIMENSION N (USED ONLY IF SIGMA .LT. ZERO) */ /* METHOD: */ /* THAT OF FLETCHER AND POWELL AS DESCRIBED IN : */ /* FLETCHER,R.,(1974) ON THE MODIFICATION OF LDL' FACTORIZATION. */ /* POWELL,M.J.D. MATH.COMPUTATION 28, 1067-1078. */ /* IMPLEMENTED BY: */ /* KRAFT,D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME */ /* D-8031 OBERPFAFFENHOFEN */ /* STATUS: 15. JANUARY 1980 */ /* SUBROUTINES REQUIRED: NONE */ /* Parameter adjustments */ --w; --z__; --a; /* Function Body */ if (*sigma == 0.0) { goto L280; } ij = 1; t = one / *sigma; if (*sigma > 0.0) { goto L220; } /* PREPARE NEGATIVE UPDATE */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* L150: */ w[i__] = z__[i__]; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { v = w[i__]; t += v * v / a[ij]; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { ++ij; /* L160: */ w[j] -= v * a[ij]; } /* L170: */ ++ij; } if (t >= 0.0) { t = epmach / *sigma; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { j = *n + 1 - i__; ij -= i__; u = w[j]; w[j] = t; /* L210: */ t -= u * u / a[ij]; } L220: /* HERE UPDATING BEGINS */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { v = z__[i__]; delta = v / a[ij]; if (*sigma < 0.0) { tp = w[i__]; } else /* if (*sigma > 0.0), since *sigma != 0 from above */ { tp = t + delta * v; } alpha = tp / t; a[ij] = alpha * a[ij]; if (i__ == *n) { goto L280; } beta = delta / tp; if (alpha > four) { goto L240; } i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { ++ij; z__[j] -= v * a[ij]; /* L230: */ a[ij] += beta * z__[j]; } goto L260; L240: gamma_ = t / tp; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { ++ij; u = a[ij]; a[ij] = gamma_ * u + beta * z__[j]; /* L250: */ z__[j] -= v * u; } L260: ++ij; /* L270: */ t = tp; } L280: return; /* END OF LDL */ } /* ldl_ */ #if 0 /* we don't want to use this linmin function, for two reasons: 1) it was apparently written assuming an old version of Fortran where all variables are saved by default, hence it was missing a "save" statement ... I would need to go through and figure out which variables need to be declared "static" (or, better yet, save them like I did in slsqp to make it re-entrant) 2) it doesn't exploit gradient information, which is stupid since we have this info 3) in the context of NLopt, it makes much more sence to use the local_opt algorithm to do the line minimization recursively by whatever algorithm the user wants (defaulting to a gradient-based method like LBFGS) */ static double d_sign(double a, double s) { return s < 0 ? -a : a; } static double linmin_(int *mode, const double *ax, const double *bx, double * f, double *tol) { /* Initialized data */ const double c__ = .381966011; const double eps = 1.5e-8; /* System generated locals */ double ret_val, d__1; /* Local variables */ double a, b, d__, e, m, p, q, r__, u, v, w, x, fu, fv, fw, fx, tol1, tol2; /* LINMIN LINESEARCH WITHOUT DERIVATIVES */ /* PURPOSE: */ /* TO FIND THE ARGUMENT LINMIN WHERE THE FUNCTION F TAKES ITS MINIMUM */ /* ON THE INTERVAL AX, BX. */ /* COMBINATION OF GOLDEN SECTION AND SUCCESSIVE QUADRATIC INTERPOLATION. */ /* INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION) */ /* *MODE SEE OUTPUT ARGUMENTS */ /* AX LEFT ENDPOINT OF INITIAL INTERVAL */ /* BX RIGHT ENDPOINT OF INITIAL INTERVAL */ /* F FUNCTION VALUE AT LINMIN WHICH IS TO BE BROUGHT IN BY */ /* REVERSE COMMUNICATION CONTROLLED BY MODE */ /* TOL DESIRED LENGTH OF INTERVAL OF UNCERTAINTY OF FINAL RESULT */ /* OUTPUT ARGUMENTS: */ /* LINMIN ABSCISSA APPROXIMATING THE POINT WHERE F ATTAINS A MINIMUM */ /* MODE CONTROLS REVERSE COMMUNICATION */ /* MUST BE SET TO 0 INITIALLY, RETURNS WITH INTERMEDIATE */ /* VALUES 1 AND 2 WHICH MUST NOT BE CHANGED BY THE USER, */ /* ENDS WITH CONVERGENCE WITH VALUE 3. */ /* WORKING ARRAY: */ /* NONE */ /* METHOD: */ /* THIS FUNCTION SUBPROGRAM IS A SLIGHTLY MODIFIED VERSION OF THE */ /* ALGOL 60 PROCEDURE LOCALMIN GIVEN IN */ /* R.P. BRENT: ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES, */ /* PRENTICE-HALL (1973). */ /* IMPLEMENTED BY: */ /* KRAFT, D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME */ /* D-8031 OBERPFAFFENHOFEN */ /* STATUS: 31. AUGUST 1984 */ /* SUBROUTINES REQUIRED: NONE */ /* EPS = SQUARE - ROOT OF MACHINE PRECISION */ /* C = GOLDEN SECTION RATIO = (3-SQRT(5))/2 */ switch (*mode) { case 1: goto L10; case 2: goto L55; } /* INITIALIZATION */ a = *ax; b = *bx; e = 0.0; v = a + c__ * (b - a); w = v; x = w; ret_val = x; *mode = 1; goto L100; /* MAIN LOOP STARTS HERE */ L10: fx = *f; fv = fx; fw = fv; L20: m = (a + b) * .5; tol1 = eps * fabs(x) + *tol; tol2 = tol1 + tol1; /* TEST CONVERGENCE */ if ((d__1 = x - m, fabs(d__1)) <= tol2 - (b - a) * .5) { goto L90; } r__ = 0.0; q = r__; p = q; if (fabs(e) <= tol1) { goto L30; } /* FIT PARABOLA */ r__ = (x - w) * (fx - fv); q = (x - v) * (fx - fw); p = (x - v) * q - (x - w) * r__; q -= r__; q += q; if (q > 0.0) { p = -p; } if (q < 0.0) { q = -q; } r__ = e; e = d__; /* IS PARABOLA ACCEPTABLE */ L30: if (fabs(p) >= (d__1 = q * r__, fabs(d__1)) * .5 || p <= q * (a - x) || p >= q * (b - x)) { goto L40; } /* PARABOLIC INTERPOLATION STEP */ d__ = p / q; /* F MUST NOT BE EVALUATED TOO CLOSE TO A OR B */ if (u - a < tol2) { d__1 = m - x; d__ = d_sign(tol1, d__1); } if (b - u < tol2) { d__1 = m - x; d__ = d_sign(tol1, d__1); } goto L50; /* GOLDEN SECTION STEP */ L40: if (x >= m) { e = a - x; } if (x < m) { e = b - x; } d__ = c__ * e; /* F MUST NOT BE EVALUATED TOO CLOSE TO X */ L50: if (fabs(d__) < tol1) { d__ = d_sign(tol1, d__); } u = x + d__; ret_val = u; *mode = 2; goto L100; L55: fu = *f; /* UPDATE A, B, V, W, AND X */ if (fu > fx) { goto L60; } if (u >= x) { a = x; } if (u < x) { b = x; } v = w; fv = fw; w = x; fw = fx; x = u; fx = fu; goto L85; L60: if (u < x) { a = u; } if (u >= x) { b = u; } if (fu <= fw || w == x) { goto L70; } if (fu <= fv || v == x || v == w) { goto L80; } goto L85; L70: v = w; fv = fw; w = u; fw = fu; goto L85; L80: v = u; fv = fu; L85: goto L20; /* END OF MAIN LOOP */ L90: ret_val = x; *mode = 3; L100: return ret_val; /* END OF LINMIN */ } /* linmin_ */ #endif typedef struct { double t, f0, h1, h2, h3, h4; int n1, n2, n3; double t0, gs; double tol; int line; double alpha; int iexact; int incons, ireset, itermx; double *x0; } slsqpb_state; #define SS(var) state->var = var #define SAVE_STATE \ SS(t); SS(f0); SS(h1); SS(h2); SS(h3); SS(h4); \ SS(n1); SS(n2); SS(n3); \ SS(t0); SS(gs); \ SS(tol); \ SS(line); \ SS(alpha); \ SS(iexact); \ SS(incons); SS(ireset); SS(itermx) #define RS(var) var = state->var #define RESTORE_STATE \ RS(t); RS(f0); RS(h1); RS(h2); RS(h3); RS(h4); \ RS(n1); RS(n2); RS(n3); \ RS(t0); RS(gs); \ RS(tol); \ RS(line); \ RS(alpha); \ RS(iexact); \ RS(incons); RS(ireset); RS(itermx) static void slsqpb_(int *m, int *meq, int *la, int * n, double *x, const double *xl, const double *xu, double *f, double *c__, double *g, double *a, double *acc, int *iter, int *mode, double *r__, double *l, double *x0, double *mu, double *s, double *u, double *v, double *w, int *iw, slsqpb_state *state) { /* Initialized data */ const double one = 1.; const double alfmin = .1; const double hun = 100.; const double ten = 10.; const double two = 2.; /* System generated locals */ int a_dim1, a_offset, i__1, i__2; double d__1, d__2; /* Local variables */ int i__, j, k; /* saved state from one call to the next; SGJ 2010: save/restore via state parameter, to make re-entrant. */ double t, f0, h1, h2, h3, h4; int n1, n2, n3; double t0, gs; double tol; int line; double alpha; int iexact; int incons, ireset, itermx; RESTORE_STATE; /* NONLINEAR PROGRAMMING BY SOLVING SEQUENTIALLY QUADRATIC PROGRAMS */ /* - L1 - LINE SEARCH, POSITIVE DEFINITE BFGS UPDATE - */ /* BODY SUBROUTINE FOR SLSQP */ /* dim(W) = N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1) for LSQ */ /* +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ */ /* +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI */ /* with MINEQ = M - MEQ + 2*N1 & N1 = N+1 */ /* Parameter adjustments */ --mu; --c__; --v; --u; --s; --x0; --l; --r__; a_dim1 = *la; a_offset = 1 + a_dim1; a -= a_offset; --g; --xu; --xl; --x; --w; --iw; /* Function Body */ if (*mode == -1) { goto L260; } else if (*mode == 0) { goto L100; } else { goto L220; } L100: itermx = *iter; if (*acc >= 0.0) { iexact = 0; } else { iexact = 1; } *acc = fabs(*acc); tol = ten * *acc; *iter = 0; ireset = 0; n1 = *n + 1; n2 = n1 * *n / 2; n3 = n2 + 1; s[1] = 0.0; mu[1] = 0.0; dcopy___(n, &s[1], 0, &s[1], 1); dcopy___(m, &mu[1], 0, &mu[1], 1); /* RESET BFGS MATRIX */ L110: ++ireset; if (ireset > 5) { goto L255; } l[1] = 0.0; dcopy___(&n2, &l[1], 0, &l[1], 1); j = 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { l[j] = one; j = j + n1 - i__; /* L120: */ } /* MAIN ITERATION : SEARCH DIRECTION, STEPLENGTH, LDL'-UPDATE */ L130: ++(*iter); *mode = 9; if (*iter > itermx && itermx > 0) { /* SGJ 2010: ignore if itermx <= 0 */ goto L330; } /* SEARCH DIRECTION AS SOLUTION OF QP - SUBPROBLEM */ dcopy___(n, &xl[1], 1, &u[1], 1); dcopy___(n, &xu[1], 1, &v[1], 1); d__1 = -one; daxpy_sl__(n, &d__1, &x[1], 1, &u[1], 1); d__1 = -one; daxpy_sl__(n, &d__1, &x[1], 1, &v[1], 1); h4 = one; lsq_(m, meq, n, &n3, la, &l[1], &g[1], &a[a_offset], &c__[1], &u[1], &v[1] , &s[1], &r__[1], &w[1], &iw[1], mode); /* AUGMENTED PROBLEM FOR INCONSISTENT LINEARIZATION */ if (*mode == 6) { if (*n == *meq) { *mode = 4; } } if (*mode == 4) { i__1 = *m; for (j = 1; j <= i__1; ++j) { if (j <= *meq) { a[j + n1 * a_dim1] = -c__[j]; } else { /* Computing MAX */ d__1 = -c__[j]; a[j + n1 * a_dim1] = MAX2(d__1,0.0); } /* L140: */ } s[1] = 0.0; dcopy___(n, &s[1], 0, &s[1], 1); h3 = 0.0; g[n1] = 0.0; l[n3] = hun; s[n1] = one; u[n1] = 0.0; v[n1] = one; incons = 0; L150: lsq_(m, meq, &n1, &n3, la, &l[1], &g[1], &a[a_offset], &c__[1], &u[1], &v[1], &s[1], &r__[1], &w[1], &iw[1], mode); h4 = one - s[n1]; if (*mode == 4) { l[n3] = ten * l[n3]; ++incons; if (incons > 5) { goto L330; } goto L150; } else if (*mode != 1) { goto L330; } } else if (*mode != 1) { goto L330; } /* UPDATE MULTIPLIERS FOR L1-TEST */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { v[i__] = g[i__] - ddot_sl__(m, &a[i__ * a_dim1 + 1], 1, &r__[1], 1); /* L160: */ } f0 = *f; dcopy___(n, &x[1], 1, &x0[1], 1); gs = ddot_sl__(n, &g[1], 1, &s[1], 1); h1 = fabs(gs); h2 = 0.0; i__1 = *m; for (j = 1; j <= i__1; ++j) { if (j <= *meq) { h3 = c__[j]; } else { h3 = 0.0; } /* Computing MAX */ d__1 = -c__[j]; h2 += MAX2(d__1,h3); h3 = (d__1 = r__[j], fabs(d__1)); /* Computing MAX */ d__1 = h3, d__2 = (mu[j] + h3) / two; mu[j] = MAX2(d__1,d__2); h1 += h3 * (d__1 = c__[j], fabs(d__1)); /* L170: */ } /* CHECK CONVERGENCE */ *mode = 0; if (h1 < *acc && h2 < *acc) { goto L330; } h1 = 0.0; i__1 = *m; for (j = 1; j <= i__1; ++j) { if (j <= *meq) { h3 = c__[j]; } else { h3 = 0.0; } /* Computing MAX */ d__1 = -c__[j]; h1 += mu[j] * MAX2(d__1,h3); /* L180: */ } t0 = *f + h1; h3 = gs - h1 * h4; *mode = 8; if (h3 >= 0.0) { goto L110; } /* LINE SEARCH WITH AN L1-TESTFUNCTION */ line = 0; alpha = one; if (iexact == 1) { goto L210; } /* INEXACT LINESEARCH */ L190: ++line; h3 = alpha * h3; dscal_sl__(n, &alpha, &s[1], 1); dcopy___(n, &x0[1], 1, &x[1], 1); daxpy_sl__(n, &one, &s[1], 1, &x[1], 1); /* SGJ 2010: ensure roundoff doesn't push us past bound constraints */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (x[i__] < xl[i__]) x[i__] = xl[i__]; else if (x[i__] > xu[i__]) x[i__] = xu[i__]; } /* SGJ 2010: optimizing for the common case where the inexact line search succeeds in one step, use special mode = -2 here to eliminate a a subsequent unnecessary mode = -1 call, at the expense of extra gradient evaluations when more than one inexact line-search step is required */ *mode = line == 1 ? -2 : 1; goto L330; L200: if (nlopt_isfinite(h1)) { if (h1 <= h3 / ten || line > 10) { goto L240; } /* Computing MAX */ d__1 = h3 / (two * (h3 - h1)); alpha = MAX2(d__1,alfmin); } else { alpha = MAX2(alpha*.5,alfmin); } goto L190; /* EXACT LINESEARCH */ L210: #if 0 /* SGJ: see comments by linmin_ above: if we want to do an exact linesearch (which usually we probably don't), we should call NLopt recursively */ if (line != 3) { alpha = linmin_(&line, &alfmin, &one, &t, &tol); dcopy___(n, &x0[1], 1, &x[1], 1); daxpy_sl__(n, &alpha, &s[1], 1, &x[1], 1); *mode = 1; goto L330; } #else *mode = 9 /* will yield nlopt_failure */; return; #endif dscal_sl__(n, &alpha, &s[1], 1); goto L240; /* CALL FUNCTIONS AT CURRENT X */ L220: t = *f; i__1 = *m; for (j = 1; j <= i__1; ++j) { if (j <= *meq) { h1 = c__[j]; } else { h1 = 0.0; } /* Computing MAX */ d__1 = -c__[j]; t += mu[j] * MAX2(d__1,h1); /* L230: */ } h1 = t - t0; switch (iexact + 1) { case 1: goto L200; case 2: goto L210; } /* CHECK CONVERGENCE */ L240: h3 = 0.0; i__1 = *m; for (j = 1; j <= i__1; ++j) { if (j <= *meq) { h1 = c__[j]; } else { h1 = 0.0; } /* Computing MAX */ d__1 = -c__[j]; h3 += MAX2(d__1,h1); /* L250: */ } if (((d__1 = *f - f0, fabs(d__1)) < *acc || dnrm2___(n, &s[1], 1) < * acc) && h3 < *acc) { *mode = 0; } else { *mode = -1; } goto L330; /* CHECK relaxed CONVERGENCE in case of positive directional derivative */ L255: if (((d__1 = *f - f0, fabs(d__1)) < tol || dnrm2___(n, &s[1], 1) < tol) && h3 < tol) { *mode = 0; } else { *mode = 8; } goto L330; /* CALL JACOBIAN AT CURRENT X */ /* UPDATE CHOLESKY-FACTORS OF HESSIAN MATRIX BY MODIFIED BFGS FORMULA */ L260: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { u[i__] = g[i__] - ddot_sl__(m, &a[i__ * a_dim1 + 1], 1, &r__[1], 1) - v[i__]; /* L270: */ } /* L'*S */ k = 0; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { h1 = 0.0; ++k; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { ++k; h1 += l[k] * s[j]; /* L280: */ } v[i__] = s[i__] + h1; /* L290: */ } /* D*L'*S */ k = 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { v[i__] = l[k] * v[i__]; k = k + n1 - i__; /* L300: */ } /* L*D*L'*S */ for (i__ = *n; i__ >= 1; --i__) { h1 = 0.0; k = i__; i__1 = i__ - 1; for (j = 1; j <= i__1; ++j) { h1 += l[k] * v[j]; k = k + *n - j; /* L310: */ } v[i__] += h1; /* L320: */ } h1 = ddot_sl__(n, &s[1], 1, &u[1], 1); h2 = ddot_sl__(n, &s[1], 1, &v[1], 1); h3 = h2 * .2; if (h1 < h3) { h4 = (h2 - h3) / (h2 - h1); h1 = h3; dscal_sl__(n, &h4, &u[1], 1); d__1 = one - h4; daxpy_sl__(n, &d__1, &v[1], 1, &u[1], 1); } d__1 = one / h1; ldl_(n, &l[1], &u[1], &d__1, &v[1]); d__1 = -one / h2; ldl_(n, &l[1], &v[1], &d__1, &u[1]); /* END OF MAIN ITERATION */ goto L130; /* END OF SLSQPB */ L330: SAVE_STATE; } /* slsqpb_ */ /* *********************************************************************** */ /* optimizer * */ /* *********************************************************************** */ static void slsqp(int *m, int *meq, int *la, int *n, double *x, const double *xl, const double *xu, double *f, double *c__, double *g, double *a, double *acc, int *iter, int *mode, double *w, int *l_w__, int * jw, int *l_jw__, slsqpb_state *state) { /* System generated locals */ int a_dim1, a_offset, i__1, i__2; /* Local variables */ int n1, il, im, ir, is, iu, iv, iw, ix, mineq; /* SLSQP S EQUENTIAL L EAST SQ UARES P ROGRAMMING */ /* TO SOLVE GENERAL NONLINEAR OPTIMIZATION PROBLEMS */ /* *********************************************************************** */ /* * * */ /* * * */ /* * A NONLINEAR PROGRAMMING METHOD WITH * */ /* * QUADRATIC PROGRAMMING SUBPROBLEMS * */ /* * * */ /* * * */ /* * THIS SUBROUTINE SOLVES THE GENERAL NONLINEAR PROGRAMMING PROBLEM * */ /* * * */ /* * MINIMIZE F(X) * */ /* * * */ /* * SUBJECT TO C (X) .EQ. 0 , J = 1,...,MEQ * */ /* * J * */ /* * * */ /* * C (X) .GE. 0 , J = MEQ+1,...,M * */ /* * J * */ /* * * */ /* * XL .LE. X .LE. XU , I = 1,...,N. * */ /* * I I I * */ /* * * */ /* * THE ALGORITHM IMPLEMENTS THE METHOD OF HAN AND POWELL * */ /* * WITH BFGS-UPDATE OF THE B-MATRIX AND L1-TEST FUNCTION * */ /* * WITHIN THE STEPLENGTH ALGORITHM. * */ /* * * */ /* * PARAMETER DESCRIPTION: * */ /* * ( * MEANS THIS PARAMETER WILL BE CHANGED DURING CALCULATION ) * */ /* * * */ /* * M IS THE TOTAL NUMBER OF CONSTRAINTS, M .GE. 0 * */ /* * MEQ IS THE NUMBER OF EQUALITY CONSTRAINTS, MEQ .GE. 0 * */ /* * LA SEE A, LA .GE. MAX(M,1) * */ /* * N IS THE NUMBER OF VARIBLES, N .GE. 1 * */ /* * * X() X() STORES THE CURRENT ITERATE OF THE N VECTOR X * */ /* * ON ENTRY X() MUST BE INITIALIZED. ON EXIT X() * */ /* * STORES THE SOLUTION VECTOR X IF MODE = 0. * */ /* * XL() XL() STORES AN N VECTOR OF LOWER BOUNDS XL TO X. * */ /* * XU() XU() STORES AN N VECTOR OF UPPER BOUNDS XU TO X. * */ /* * F IS THE VALUE OF THE OBJECTIVE FUNCTION. * */ /* * C() C() STORES THE M VECTOR C OF CONSTRAINTS, * */ /* * EQUALITY CONSTRAINTS (IF ANY) FIRST. * */ /* * DIMENSION OF C MUST BE GREATER OR EQUAL LA, * */ /* * which must be GREATER OR EQUAL MAX(1,M). * */ /* * G() G() STORES THE N VECTOR G OF PARTIALS OF THE * */ /* * OBJECTIVE FUNCTION; DIMENSION OF G MUST BE * */ /* * GREATER OR EQUAL N+1. * */ /* * A(),LA,M,N THE LA BY N + 1 ARRAY A() STORES * */ /* * THE M BY N MATRIX A OF CONSTRAINT NORMALS. * */ /* * A() HAS FIRST DIMENSIONING PARAMETER LA, * */ /* * WHICH MUST BE GREATER OR EQUAL MAX(1,M). * */ /* * F,C,G,A MUST ALL BE SET BY THE USER BEFORE EACH CALL. * */ /* * * ACC ABS(ACC) CONTROLS THE FINAL ACCURACY. * */ /* * IF ACC .LT. ZERO AN EXACT LINESEARCH IS PERFORMED,* */ /* * OTHERWISE AN ARMIJO-TYPE LINESEARCH IS USED. * */ /* * * ITER PRESCRIBES THE MAXIMUM NUMBER OF ITERATIONS. * */ /* * ON EXIT ITER INDICATES THE NUMBER OF ITERATIONS. * */ /* * * MODE MODE CONTROLS CALCULATION: * */ /* * REVERSE COMMUNICATION IS USED IN THE SENSE THAT * */ /* * THE PROGRAM IS INITIALIZED BY MODE = 0; THEN IT IS* */ /* * TO BE CALLED REPEATEDLY BY THE USER UNTIL A RETURN* */ /* * WITH MODE .NE. IABS(1) TAKES PLACE. * */ /* * IF MODE = -1 GRADIENTS HAVE TO BE CALCULATED, * */ /* * WHILE WITH MODE = 1 FUNCTIONS HAVE TO BE CALCULATED */ /* * MODE MUST NOT BE CHANGED BETWEEN SUBSEQUENT CALLS * */ /* * OF SQP. * */ /* * EVALUATION MODES: * */ /* * MODE = -2,-1: GRADIENT EVALUATION, (G&A) * */ /* * 0: ON ENTRY: INITIALIZATION, (F,G,C&A) * */ /* * ON EXIT : REQUIRED ACCURACY FOR SOLUTION OBTAINED * */ /* * 1: FUNCTION EVALUATION, (F&C) * */ /* * * */ /* * FAILURE MODES: * */ /* * 2: NUMBER OF EQUALITY CONTRAINTS LARGER THAN N * */ /* * 3: MORE THAN 3*N ITERATIONS IN LSQ SUBPROBLEM * */ /* * 4: INEQUALITY CONSTRAINTS INCOMPATIBLE * */ /* * 5: SINGULAR MATRIX E IN LSQ SUBPROBLEM * */ /* * 6: SINGULAR MATRIX C IN LSQ SUBPROBLEM * */ /* * 7: RANK-DEFICIENT EQUALITY CONSTRAINT SUBPROBLEM HFTI* */ /* * 8: POSITIVE DIRECTIONAL DERIVATIVE FOR LINESEARCH * */ /* * 9: MORE THAN ITER ITERATIONS IN SQP * */ /* * >=10: WORKING SPACE W OR JW TOO SMALL, * */ /* * W SHOULD BE ENLARGED TO L_W=MODE/1000 * */ /* * JW SHOULD BE ENLARGED TO L_JW=MODE-1000*L_W * */ /* * * W(), L_W W() IS A ONE DIMENSIONAL WORKING SPACE, * */ /* * THE LENGTH L_W OF WHICH SHOULD BE AT LEAST * */ /* * (3*N1+M)*(N1+1) for LSQ * */ /* * +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI * */ /* * +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI * */ /* * + N1*N/2 + 2*M + 3*N + 3*N1 + 1 for SLSQPB * */ /* * with MINEQ = M - MEQ + 2*N1 & N1 = N+1 * */ /* * NOTICE: FOR PROPER DIMENSIONING OF W IT IS RECOMMENDED TO * */ /* * COPY THE FOLLOWING STATEMENTS INTO THE HEAD OF * */ /* * THE CALLING PROGRAM (AND REMOVE THE COMMENT C) * */ /* ####################################################################### */ /* INT LEN_W, LEN_JW, M, N, N1, MEQ, MINEQ */ /* PARAMETER (M=... , MEQ=... , N=... ) */ /* PARAMETER (N1= N+1, MINEQ= M-MEQ+N1+N1) */ /* PARAMETER (LEN_W= */ /* $ (3*N1+M)*(N1+1) */ /* $ +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ */ /* $ +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 */ /* $ +(N+1)*N/2 + 2*M + 3*N + 3*N1 + 1, */ /* $ LEN_JW=MINEQ) */ /* DOUBLE PRECISION W(LEN_W) */ /* INT JW(LEN_JW) */ /* ####################################################################### */ /* * THE FIRST M+N+N*N1/2 ELEMENTS OF W MUST NOT BE * */ /* * CHANGED BETWEEN SUBSEQUENT CALLS OF SLSQP. * */ /* * ON RETURN W(1) ... W(M) CONTAIN THE MULTIPLIERS * */ /* * ASSOCIATED WITH THE GENERAL CONSTRAINTS, WHILE * */ /* * W(M+1) ... W(M+N(N+1)/2) STORE THE CHOLESKY FACTOR* */ /* * L*D*L(T) OF THE APPROXIMATE HESSIAN OF THE * */ /* * LAGRANGIAN COLUMNWISE DENSE AS LOWER TRIANGULAR * */ /* * UNIT MATRIX L WITH D IN ITS 'DIAGONAL' and * */ /* * W(M+N(N+1)/2+N+2 ... W(M+N(N+1)/2+N+2+M+2N) * */ /* * CONTAIN THE MULTIPLIERS ASSOCIATED WITH ALL * */ /* * ALL CONSTRAINTS OF THE QUADRATIC PROGRAM FINDING * */ /* * THE SEARCH DIRECTION TO THE SOLUTION X* * */ /* * * JW(), L_JW JW() IS A ONE DIMENSIONAL INT WORKING SPACE * */ /* * THE LENGTH L_JW OF WHICH SHOULD BE AT LEAST * */ /* * MINEQ * */ /* * with MINEQ = M - MEQ + 2*N1 & N1 = N+1 * */ /* * * */ /* * THE USER HAS TO PROVIDE THE FOLLOWING SUBROUTINES: * */ /* * LDL(N,A,Z,SIG,W) : UPDATE OF THE LDL'-FACTORIZATION. * */ /* * LINMIN(A,B,F,TOL) : LINESEARCH ALGORITHM IF EXACT = 1 * */ /* * LSQ(M,MEQ,LA,N,NC,C,D,A,B,XL,XU,X,LAMBDA,W,....) : * */ /* * * */ /* * SOLUTION OF THE QUADRATIC PROGRAM * */ /* * QPSOL IS RECOMMENDED: * */ /* * PE GILL, W MURRAY, MA SAUNDERS, MH WRIGHT: * */ /* * USER'S GUIDE FOR SOL/QPSOL: * */ /* * A FORTRAN PACKAGE FOR QUADRATIC PROGRAMMING, * */ /* * TECHNICAL REPORT SOL 83-7, JULY 1983 * */ /* * DEPARTMENT OF OPERATIONS RESEARCH, STANFORD UNIVERSITY * */ /* * STANFORD, CA 94305 * */ /* * QPSOL IS THE MOST ROBUST AND EFFICIENT QP-SOLVER * */ /* * AS IT ALLOWS WARM STARTS WITH PROPER WORKING SETS * */ /* * * */ /* * IF IT IS NOT AVAILABLE USE LSEI, A CONSTRAINT LINEAR LEAST * */ /* * SQUARES SOLVER IMPLEMENTED USING THE SOFTWARE HFTI, LDP, NNLS * */ /* * FROM C.L. LAWSON, R.J.HANSON: SOLVING LEAST SQUARES PROBLEMS, * */ /* * PRENTICE HALL, ENGLEWOOD CLIFFS, 1974. * */ /* * LSEI COMES WITH THIS PACKAGE, together with all necessary SR's. * */ /* * * */ /* * TOGETHER WITH A COUPLE OF SUBROUTINES FROM BLAS LEVEL 1 * */ /* * * */ /* * SQP IS HEAD SUBROUTINE FOR BODY SUBROUTINE SQPBDY * */ /* * IN WHICH THE ALGORITHM HAS BEEN IMPLEMENTED. * */ /* * * */ /* * IMPLEMENTED BY: DIETER KRAFT, DFVLR OBERPFAFFENHOFEN * */ /* * as described in Dieter Kraft: A Software Package for * */ /* * Sequential Quadratic Programming * */ /* * DFVLR-FB 88-28, 1988 * */ /* * which should be referenced if the user publishes results of SLSQP * */ /* * * */ /* * DATE: APRIL - OCTOBER, 1981. * */ /* * STATUS: DECEMBER, 31-ST, 1984. * */ /* * STATUS: MARCH , 21-ST, 1987, REVISED TO FORTAN 77 * */ /* * STATUS: MARCH , 20-th, 1989, REVISED TO MS-FORTRAN * */ /* * STATUS: APRIL , 14-th, 1989, HESSE in-line coded * */ /* * STATUS: FEBRUARY, 28-th, 1991, FORTRAN/2 Version 1.04 * */ /* * accepts Statement Functions * */ /* * STATUS: MARCH , 1-st, 1991, tested with SALFORD * */ /* * FTN77/386 COMPILER VERS 2.40* */ /* * in protected mode * */ /* * * */ /* *********************************************************************** */ /* * * */ /* * Copyright 1991: Dieter Kraft, FHM * */ /* * * */ /* *********************************************************************** */ /* dim(W) = N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1) for LSQ */ /* +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI */ /* +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI */ /* + N1*N/2 + 2*M + 3*N +3*N1 + 1 for SLSQPB */ /* with MINEQ = M - MEQ + 2*N1 & N1 = N+1 */ /* CHECK LENGTH OF WORKING ARRAYS */ /* Parameter adjustments */ --c__; a_dim1 = *la; a_offset = 1 + a_dim1; a -= a_offset; --g; --xu; --xl; --x; --w; --jw; /* Function Body */ n1 = *n + 1; mineq = *m - *meq + n1 + n1; il = (n1 * 3 + *m) * (n1 + 1) + (n1 - *meq + 1) * (mineq + 2) + (mineq << 1) + (n1 + mineq) * (n1 - *meq) + (*meq << 1) + n1 * *n / 2 + (*m << 1) + *n * 3 + (n1 << 2) + 1; /* Computing MAX */ i__1 = mineq, i__2 = n1 - *meq; im = MAX2(i__1,i__2); if (*l_w__ < il || *l_jw__ < im) { *mode = MAX2(10,il) * 1000; *mode += MAX2(10,im); return; } /* PREPARE DATA FOR CALLING SQPBDY - INITIAL ADDRESSES IN W */ im = 1; il = im + MAX2(1,*m); il = im + *la; ix = il + n1 * *n / 2 + 1; ir = ix + *n; is = ir + *n + *n + MAX2(1,*m); is = ir + *n + *n + *la; iu = is + n1; iv = iu + n1; iw = iv + n1; slsqpb_(m, meq, la, n, &x[1], &xl[1], &xu[1], f, &c__[1], &g[1], &a[ a_offset], acc, iter, mode, &w[ir], &w[il], &w[ix], &w[im], &w[is] , &w[iu], &w[iv], &w[iw], &jw[1], state); state->x0 = &w[ix]; return; } /* slsqp_ */ static void length_work(int *LEN_W, int *LEN_JW, int M, int MEQ, int N) { int N1 = N+1, MINEQ = M-MEQ+N1+N1; *LEN_W = (3*N1+M)*(N1+1) +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 +(N+1)*N/2 + 2*M + 3*N + 3*N1 + 1; *LEN_JW = MINEQ; } nlopt_result nlopt_slsqp(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, unsigned p, nlopt_constraint *h, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop) { slsqpb_state state = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL}; unsigned mtot = nlopt_count_constraints(m, fc); unsigned ptot = nlopt_count_constraints(p, h); double *work, *cgrad, *c, *grad, *w, fcur, *xcur, fprev, *xprev, *cgradtmp; int mpi = (int) (mtot + ptot), pi = (int) ptot, ni = (int) n, mpi1 = mpi > 0 ? mpi : 1; int len_w, len_jw, *jw; int mode = 0, prev_mode = 0; double acc = 0; /* we do our own convergence tests below */ int iter = 0; /* tell sqsqp to ignore this check, since we check evaluation counts ourselves */ unsigned i, ii; nlopt_result ret = NLOPT_SUCCESS; int feasible, feasible_cur; double infeasibility = HUGE_VAL, infeasibility_cur = HUGE_VAL; unsigned max_cdim; int want_grad = 1; max_cdim = MAX2(nlopt_max_constraint_dim(m, fc), nlopt_max_constraint_dim(p, h)); length_work(&len_w, &len_jw, mpi, pi, ni); #define U(n) ((unsigned) (n)) work = (double *) malloc(sizeof(double) * (U(mpi1) * (n + 1) + U(mpi) + n+1 + n + n + max_cdim*n + U(len_w)) + sizeof(int) * U(len_jw)); if (!work) return NLOPT_OUT_OF_MEMORY; cgrad = work; c = cgrad + U(mpi1) * (n + 1); grad = c + mpi; xcur = grad + n+1; xprev = xcur + n; cgradtmp = xprev + n; w = cgradtmp + max_cdim*n; jw = (int *) (w + len_w); memcpy(xcur, x, sizeof(double) * n); memcpy(xprev, x, sizeof(double) * n); fprev = fcur = *minf = HUGE_VAL; feasible = feasible_cur = 0; goto eval_f_and_grad; /* eval before calling slsqp the first time */ do { slsqp(&mpi, &pi, &mpi1, &ni, xcur, lb, ub, &fcur, c, grad, cgrad, &acc, &iter, &mode, w, &len_w, jw, &len_jw, &state); switch (mode) { case -1: /* objective & gradient evaluation */ if (prev_mode == -2 && !want_grad) break; /* just evaluated this point */ /* fall through */ case -2: eval_f_and_grad: want_grad = 1; /* fall through */ case 1:{ /* don't need grad unless we don't have it yet */ double *newgrad = 0; double *newcgrad = 0; if (want_grad) { newgrad = grad; newcgrad = cgradtmp; } feasible_cur = 1; infeasibility_cur = 0; fcur = f(n, xcur, newgrad, f_data); ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { fcur = HUGE_VAL; ret = NLOPT_FORCED_STOP; goto done; } if (nlopt_isfinite(fcur)) { want_grad = 0; ii = 0; for (i = 0; i < p; ++i) { unsigned j, k; nlopt_eval_constraint(c+ii, newcgrad, h+i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < h[i].m; ++k, ++ii) { infeasibility_cur = MAX2(infeasibility_cur, fabs(c[ii])); feasible_cur = feasible_cur && fabs(c[ii]) <= h[i].tol[k]; if (newcgrad) { for (j = 0; j < n; ++ j) cgrad[j*U(mpi1) + ii] = cgradtmp[k*n + j]; } } } for (i = 0; i < m; ++i) { unsigned j, k; nlopt_eval_constraint(c+ii, newcgrad, fc+i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < fc[i].m; ++k, ++ii) { infeasibility_cur = MAX2(infeasibility_cur, c[ii]); feasible_cur = feasible_cur && c[ii] <= fc[i].tol[k]; if (newcgrad) { for (j = 0; j < n; ++ j) cgrad[j*U(mpi1) + ii] = -cgradtmp[k*n + j]; } c[ii] = -c[ii]; /* slsqp sign convention */ } } } break;} case 0: /* required accuracy for solution obtained */ goto done; case 8: /* positive directional derivative for linesearch */ /* relaxed convergence check for a feasible_cur point, as in the SLSQP code (except xtol as well as ftol) */ ret = NLOPT_ROUNDOFF_LIMITED; /* usually why deriv>0 */ if (feasible_cur) { double save_ftol_rel = stop->ftol_rel; double save_xtol_rel = stop->xtol_rel; double save_ftol_abs = stop->ftol_abs; stop->ftol_rel *= 10; stop->ftol_abs *= 10; stop->xtol_rel *= 10; if (nlopt_stop_ftol(stop, fcur, state.f0)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xcur, state.x0)) ret = NLOPT_XTOL_REACHED; stop->ftol_rel = save_ftol_rel; stop->ftol_abs = save_ftol_abs; stop->xtol_rel = save_xtol_rel; } goto done; case 5: /* singular matrix E in LSQ subproblem */ case 6: /* singular matrix C in LSQ subproblem */ case 7: /* rank-deficient equality constraint subproblem HFTI */ ret = NLOPT_ROUNDOFF_LIMITED; goto done; case 4: /* inequality constraints incompatible */ case 3: /* more than 3*n iterations in LSQ subproblem */ case 9: /* more than iter iterations in SQP */ nlopt_stop_msg(stop, "bug: more than iter SQP iterations"); ret = NLOPT_FAILURE; goto done; case 2: /* number of equality constraints > n */ default: /* >= 10: working space w or jw too small */ nlopt_stop_msg(stop, "bug: workspace is too small"); ret = NLOPT_INVALID_ARGS; goto done; } prev_mode = mode; /* update best point so far */ if (nlopt_isfinite(fcur) && ((fcur < *minf && (feasible_cur || !feasible)) || (!feasible && infeasibility_cur < infeasibility))) { *minf = fcur; feasible = feasible_cur; infeasibility = infeasibility_cur; memcpy(x, xcur, sizeof(double)*n); } /* note: mode == -1 corresponds to the completion of a line search, and is the only time we should check convergence (as in original slsqp code) */ if (mode == -1) { if (!nlopt_isinf(fprev)) { if (nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; } fprev = fcur; memcpy(xprev, xcur, sizeof(double)*n); } /* do some additional termination tests */ if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; } while (ret == NLOPT_SUCCESS); done: if (nlopt_isinf(*minf)) { /* didn't find any feasible points, just return last point evaluated */ if (nlopt_isinf(fcur)) { /* invalid cur. point, use previous pt. */ *minf = fprev; memcpy(x, xprev, sizeof(double)*n); } else { *minf = fcur; memcpy(x, xcur, sizeof(double)*n); } } free(work); return ret; } nlopt-2.6.1/src/algs/slsqp/slsqp.h000066400000000000000000000006731345435414600170650ustar00rootroot00000000000000#ifndef SLSQP_H #define SLSQP_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ nlopt_result nlopt_slsqp(unsigned n, nlopt_func f, void *f_data, unsigned m, nlopt_constraint *fc, unsigned p, nlopt_constraint *h, const double *lb, const double *ub, double *x, double *minf, nlopt_stopping *stop); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/algs/stogo/000077500000000000000000000000001345435414600155355ustar00rootroot00000000000000nlopt-2.6.1/src/algs/stogo/COPYRIGHT000066400000000000000000000061301345435414600170300ustar00rootroot00000000000000The original StoGO code is: Copyright (c) 1998 by S. Zertchaninov and K. Madsen. 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. ---------------------------------------------------------------------- The StoGO source code on the authors' web site has no copyright or license information, but I (Steven G. Johnson) contacted the author K. Madsen for clarification and he gave me permission to distribute it under the MIT license above. See the correspondence below: ---------------------------------------------------------------------- Date: Fri, 24 Aug 2007 10:46:09 +0200 From: Kaj Madsen To: stevenj@math.mit.edu Subject: RE: open source license for StoGO software? The MIT licence is ok with me, and so is your copyright suggestion. Kaj Madsen. -----Original Message----- From: Steven G. Johnson [mailto:stevenj@fftw.org] Sent: 23. august 2007 22:23 To: Kaj Madsen Subject: RE: open source license for StoGO software? On Thu, 23 Aug 2007, Kaj Madsen wrote: > Many thanks for your mail. You can definitely consider the software as > open source, please use it as you like, however please refer to us if > you publish results based on the software. > > I am now in a heavy administrative position as a Head of Department > (has been since 1998, therefore I never really followed up on this). > The paper was never published, however I am attaching two fdf-files, > one with the paper, one with some descriptions of the code. I hope > this makes sense, otherwise please don't hesitate to contact me again. Thanks so much for your response! To be open source it needs some specific open-source license to specify the permissions in legal terms. The simplest open-source license is probably the MIT license, is this okay? http://opensource.org/licenses/mit-license.php Also, I need to know who the authors are for the copyright statement. Should I list it as: Copyright (c) 1998 by S. Zertchaninov and K. Madsen ? Thanks again! I will definitely cite it if I publish any results based on StoGO! (It's one of the few public global-optimization programs that is able to exploit gradient information.) Regards, Steven G. Johnson nlopt-2.6.1/src/algs/stogo/README000066400000000000000000000016151345435414600164200ustar00rootroot00000000000000This code is modified from the original StoGO Global Optimization library by Madsen et al., downloaded from: http://www2.imm.dtu.dk/~km/GlobOpt/opt.html It was modified to allow C-callable wrappers and some other niceties by Steven G. Johnson (stevenj@alum.mit.edu) in 2007. StoGO uses a gradient-based direct-search branch-and-bound algorithm, described in: S. Gudmundsson, "Parallel Global Optimization," M.Sc. Thesis, IMM, Technical University of Denmark, 1998. K. Madsen, S. Zertchaninov, and A. Zilinskas, "Global Optimization using Branch-and-Bound," Submitted to the Journal of Global Optimization, 1998. [ never published, but preprint is included as paper.pdf ] S. Zertchaninov and K. Madsen, "A C++ Programme for Global Optimization," IMM-REP-1998-04, Department of Mathematical Modelling, Technical University of Denmark, DK-2800 Lyngby, Denmark, 1998. [ included as techreport.pdf ] nlopt-2.6.1/src/algs/stogo/global.cc000066400000000000000000000177631345435414600173220ustar00rootroot00000000000000/* Multi Dimensional Global Search. Author: Steinn Gudmundsson Email: steinng@hotmail.com This program is supplied without any warranty whatsoever. NB The RNGs seed should be initialized using some timer */ #include #include #include #include #include "stogo_config.h" #include "global.h" #include "local.h" #include "nlopt-util.h" // Timer stuff double StartTime; double MacEpsilon ; int FC=0, GC=0 ; int stogo_verbose = 0; /* set to nonzero for verbose output */ Global::Global(RTBox D, Pobj o, Pgrad g, GlobalParams P): Domain(D) { dim=Domain.GetDim(); Objective=o; Gradient=g; // Initialize parameters #ifdef NLOPT_UTIL_H stop = P.stop; #else maxtime=P.maxtime; maxeval = P.maxeval; #endif numeval = 0; eps_cl=P.eps_cl; mu=P.mu; rshift=P.rshift; det_pnts=P.det_pnts; rnd_pnts=P.rnd_pnts; fbound=DBL_MAX; } #if 0 // not necessary; default copy is sufficient Global& Global::operator=(const Global &G) { // Copy the problem info and parameter settings Domain=G.Domain; Objective=G.Objective; Gradient=G.Gradient; #ifdef NLOPT_UTIL_H stop = G.stop; #else maxtime=G.maxtime; maxeval = G.maxeval; #endif numeval = G.numeval; eps_cl=G.eps_cl; mu=G.mu; rshift=G.rshift; det_pnts=G.det_pnts; rnd_pnts=G.rnd_pnts; return *this; } #endif void Global::FillRegular(RTBox SampleBox, RTBox box) { // Generation of regular sampling points double w; int i, flag, dir; Trial tmpTrial(dim); RVector m(dim), x(dim); if (det_pnts>0) { box.Midpoint(m) ; tmpTrial.objval=DBL_MAX ; // Add the rest i=1 ; flag=1 ; dir=0 ; x=m ; while (iminf_max) { done = TRUE; break; } #endif if (!InTime()) { done=TRUE; if (stogo_verbose) cout << "The program has run out of time or function evaluations\n"; break; } } // inner while-loop if (stogo_verbose) cout << endl << "*** Inner loop completed ***" << endl ; // Reduce SolSet if necessary SolSet.erase(remove_if(SolSet.begin(), SolSet.end(), TrialGT(fbound+mu)),SolSet.end()); if (InTime()) { if (stogo_verbose) { cout << "Current set of minimizers (" << SolSet.size() << ")" << endl ; DispMinimizers() ; } while (!Garbage.empty()) { box=Garbage.top() ; Garbage.pop() ; // Split box B1.ClearBox() ; B2.ClearBox() ; box.split(B1,B2) ; // Add boxes to Candidate set CandSet.push(B1) ; CandSet.push(B2) ; } } } // Outer while-loop if (stogo_verbose) { cout << "Number of outer iterations : " << outer_iter << endl; cout << "Number of unexplored boxes : " << CandSet.size() << endl; cout << "Number of boxes in garbage : " << Garbage.size() << endl; cout << "Number of elements in SolSet : " << SolSet.size() << endl; cout << "Number of function evaluations : " << FC << endl; cout << "Number of gradient evaluations : " << GC << endl; } if (axis != -1) { // Return minimizer when doing the AV method tmpTrial=SolSet.back(); x_av(axis)=tmpTrial.xvals(0); } } /************* Various utility functions ****************/ double Global::GetTime() { return nlopt_seconds() - StartTime; } bool Global::InTime() { #ifdef NLOPT_UTIL_H return !nlopt_stop_evalstime(stop); #else return (maxtime <= 0.0 || GetTime()(cout)); } double Global::OneMinimizer(RCRVector x) { if (NoMinimizers()) return 0.0; for (int i=0;i //#include "function.h" #include "tools.h" using namespace std; extern "C" int stogo_verbose; typedef void dom(RTBox) ; typedef dom* Pdom ; typedef double obj(RCRVector) ; typedef obj* Pobj ; typedef void grad(RCRVector,RVector&) ; typedef grad* Pgrad ; typedef enum { OBJECTIVE_ONLY, GRADIENT_ONLY, OBJECTIVE_AND_GRADIENT } whichO; typedef double objgrad(RCRVector,RCRVector,whichO) ; typedef objgrad* Pobjgrad ; class GlobalParams { public: #ifdef NLOPT_UTIL_H nlopt_stopping *stop; #else double maxtime; long int maxeval; #endif double eps_cl, mu, rshift; int det_pnts, rnd_pnts; }; class Global: public GlobalParams { public: // Problem specification int dim ; Pobj Objective ; Pgrad Gradient ; long int numeval; virtual double ObjectiveGradient(RCRVector xy, RVector&grad, whichO which){ ++numeval; switch (which) { case OBJECTIVE_AND_GRADIENT: Gradient(xy, grad); return Objective(xy); case OBJECTIVE_ONLY: return Objective(xy); case GRADIENT_ONLY: Gradient(xy, grad); } return 0.0; } Global(RTBox, Pobj, Pgrad, GlobalParams); virtual ~Global(){}; // Global& operator=(const Global &); void Search(int, RCRVector); void DispMinimizers(); double OneMinimizer(RCRVector); bool NoMinimizers(); void SetDomain(RTBox); void GetDomain(RTBox); double GetMinValue(); void SetMinValue(double); void ClearSolSet(); void AddPoint(RCRVector, double); double GetTime(); bool InTime(); private: list SolSet; list::const_iterator titr; priority_queue CandSet; priority_queue Garbage; double fbound; TBox Domain; void FillRegular(RTBox, RTBox); void FillRandom(RTBox, RTBox); double NewtonTest(RTBox, int, RCRVector, int*); void ReduceOrSubdivide(RTBox, int, RCRVector); }; #endif nlopt-2.6.1/src/algs/stogo/linalg.cc000066400000000000000000000104451345435414600173160ustar00rootroot00000000000000/* Temporary implementation of vector and matrix classes No attempt is made to check if the function arguments are valid */ #include #include // for sqrt() #include "linalg.h" double eps() { /* Returns the machine precision : (min { x >= 0 : 1 + x > 1 }) NB This routine should be replaced by LAPACK_LAMCH */ double Current, Last, OnePlusCurrent ; Current = 1.0 ; do { Last = Current ; Current /= 2.0 ; OnePlusCurrent = 1.0 + Current ; } while (OnePlusCurrent > 1.0) ; return Last ; } RVector::RVector() { // Constructor len=0; elements=0; (*this)=0.; } RVector::RVector(int n) { // Constructor len=n; elements=new double[len]; (*this)=0.; } RVector::RVector(RCRVector vect) { // Constructor + Copy len=vect.len; elements=new double[len]; (*this)=vect; } RCRVector RVector::operator=(RCRVector vect) { // Copy for (int i=0;i0) os << "," ; os << v.elements[i] ; } return os << ']'; } /*************************** Matrix Class ***********************/ RMatrix::RMatrix() { // Constructor Dim=0 ; Vals=0 ; (*this)=0 ; } RMatrix::RMatrix(int dim) { // Constructor Dim=dim; Vals=new double[long(Dim)*long(Dim)]; (*this)=0.; } RMatrix::RMatrix(RCRMatrix matr) { // Constructor + Copy Dim=matr.Dim; Vals=new double[long(Dim)*long(Dim)]; (*this)=matr; } RCRMatrix RMatrix::operator=(RCRMatrix mat) { // Assignment, A=B long int Len=long(Dim)*long(Dim); for (int i=0;i using namespace std; #include // for sqrt() #include typedef const class RVector CRVector; typedef CRVector& RCRVector; typedef const class RMatrix CRMatrix ; typedef CRMatrix& RCRMatrix; double eps() ; #define max(A,B) ((A) > (B) ? (A):(B)) #define min(A,B) ((A) < (B) ? (A):(B)) /********************* Class RVector *********************/ class RVector{ protected: public: int len; // size of array double* elements; // array of values RVector() ; RVector(int); // Constructor RVector(RCRVector); // copy constructor ~RVector() { delete[] elements; elements=0 ; len=0; } RCRVector operator=(double) ; RCRVector operator=(RCRVector); double & operator () (int i) const {return elements[i] ; } double nrm2() ; // Euclidian norm double *raw_data() { return elements; } const double *raw_data_const() const { return elements; } friend ostream & operator << (ostream &, const RVector &); friend double norm2(RCRVector) ; friend double normInf(RCRVector) ; friend double dot(RCRVector, RCRVector) ; friend void scal(double, RCRVector) ; friend void copy(RCRVector, RCRVector) ; friend void axpy(double, RCRVector, RCRVector) ; friend void gemv(char,double, RCRMatrix, RCRVector, double, RCRVector); friend void ger(double alpha, RCRVector, RCRVector, RCRMatrix); int GetLength() const { return len; }; // get vector size }; /******************* Class RMatrix *************************/ class RMatrix { protected: double* Vals; // array of values int Dim; // dimension public: RMatrix() ; RMatrix(int); // dimension ~RMatrix() { delete[] Vals; Vals=0 ; Dim=0; } RMatrix(RCRMatrix); // copy constructor RCRMatrix operator=(double num) ; RCRMatrix operator=(RCRMatrix) ; // (needed for template stuff) double& operator()(int vidx,int hidx) ; friend ostream & operator << (ostream &, const RMatrix &); friend void gemv(char,double, RCRMatrix, RCRVector, double, RCRVector); friend void ger(double alpha,RCRVector,RCRVector,RCRMatrix); int GetDim() { return Dim; }; // get dimension }; #endif nlopt-2.6.1/src/algs/stogo/local.cc000066400000000000000000000231121345435414600171350ustar00rootroot00000000000000 /* Local search - A trust region algorithm with BFGS update. */ #include #include #include "stogo_config.h" #include "global.h" #include "local.h" #include "tools.h" #ifdef NLOPT_UTIL_H # define IF_NLOPT_CHECK_EVALS ++ *(stop->nevals_p); \ if (nlopt_stop_evalstime(stop)) \ return LS_MaxEvalTime #else # define IF_NLOPT_CHECK_EVALS #endif //////////////////////////////////////////////////////////////////////// // SGJ, 2007: allow local to use local optimizers in NLopt, to compare // to the BFGS code below #if 0 #include "nlopt.h" typedef struct { Global *glob; double maxgrad; nlopt_stopping *stop; } f_local_data; static double f_local(int n, const double *x, double *grad, void *data_) { f_local_data *data = (f_local_data *) data_; double f; RVector xv, gv; // hack to avoid pointless copy of x and grad xv.len = gv.len = n; xv.elements = const_cast(x); gv.elements = grad; f=data->glob->ObjectiveGradient(xv, gv, grad?OBJECTIVE_AND_GRADIENT:OBJECTIVE_ONLY); if (grad) data->maxgrad = max(data->maxgrad, normInf(gv)); xv.elements = gv.elements = 0; // prevent deallocation ++ *(data->stop->nevals_p); return f; } #endif //////////////////////////////////////////////////////////////////////// int local(Trial &T, TBox &box, TBox &domain, double eps_cl, double *mgr, Global &glob, int axis, RCRVector x_av #ifdef NLOPT_UTIL_H , nlopt_stopping *stop #endif ) { int n=box.GetDim(); RVector x(n); double tmp, f; x=T.xvals ; #ifdef LS_DEBUG cout << "Local Search, x=" << x << endl; #endif if (box.OutsideBox(x, domain) != 0) { cout << "Starting point is not inside the boundary. Exiting...\n" ; exit(1) ; return LS_Out ; } // Check if we are close to a stationary point located previously if (box.CloseToMin(x, &tmp, eps_cl)) { #ifdef LS_DEBUG cout << "Close to a previously located stationary point, exiting" << endl; #endif T.objval=tmp; return LS_Old ; } #if 0 if (axis != -1) { cout << "NLopt code only works with axis == -1, exiting...\n" ; exit(EXIT_FAILURE); } f_local_data data; data.glob = &glob; data.maxgrad = *mgr; data.stop = stop; nlopt_result ret = nlopt_minimize(NLOPT_LOCAL_LBFGS, n, f_local, &data, box.lb.raw_data(), box.ub.raw_data(), x.raw_data(), &f, stop->minf_max, stop->ftol_rel, stop->ftol_abs, stop->xtol_rel, stop->xtol_abs, stop->maxeval - *(stop->nevals_p), stop->maxtime - stop->start); *mgr = data.maxgrad; T.xvals=x ; T.objval=f ; if (ret == NLOPT_MAXEVAL_REACHED || ret == NLOPT_MAXTIME_REACHED) return LS_MaxEvalTime; else if (ret > 0) return LS_New; else return LS_Out; // failure #else /* not using NLopt local optimizer ... use original STOgo BFGS code */ int k_max, info, outside = 0; int k, i, good_enough, iTmp ; double maxgrad, delta, f_new; double alpha, gamma, beta, d2, s2, nom, den, ro ; double nrm_sd, nrm_hn, snrm_hn, nrm_dl ; RVector g(n), h_sd(n), h_dl(n), h_n(n), x_new(n), g_new(n) ; RVector s(n),y(n),z(n),w(n) ; // Temporary vectors RMatrix B(n), H(n) ; // Hessian and it's inverse k_max = max_iter*n ; // Initially B and H are equal to the identity matrix B=0 ; H=0 ; for (i=0 ; ik_max) { #ifdef LS_DEBUG cout << "Maximum number of iterations reached\n" ; #endif info=LS_MaxIter ; break ; } // Update maximal gradient value maxgrad=max(maxgrad,normInf(g)) ; // Steepest descent, h_sd = -g copy(g,h_sd) ; scal(-1.0,h_sd) ; nrm_sd=norm2(h_sd) ; if (nrm_sd < epsilon) { // Stop criterion (gradient) fullfilled #ifdef LS_DEBUG cout << "Gradient small enough" << endl ; #endif good_enough = 1 ; break ; } // Compute Newton step, h_n = -H*g gemv('N',-1.0, H, g, 0.0, h_n) ; nrm_hn = norm2(h_n) ; if (nrm_hn < delta) { // Pure Newton step copy(h_n, h_dl) ; #ifdef LS_DEBUG cout << "[Newton step] " ; #endif } else { gemv('N',1.0,B,g,0.0,z) ; tmp=dot(g,z) ; if (tmp==0) { info = LS_Unstable ; break ; } alpha=(nrm_sd*nrm_sd)/tmp ; // Normalization (N38,eq. 3.30) scal(alpha,h_sd) ; nrm_sd=fabs(alpha)*nrm_sd ; if (nrm_sd >= delta) { gamma = delta/nrm_sd ; // Normalization (N38, eq. 3.33) copy(h_sd,h_dl) ; scal(gamma,h_dl) ; #ifdef LS_DEBUG cout << "[Steepest descent] " ; #endif } else { // Combination of Newton and SD steps d2 = delta*delta ; copy(h_sd,s) ; s2=nrm_sd*nrm_sd ; nom = d2 - s2 ; snrm_hn=nrm_hn*nrm_hn ; tmp = dot(h_n,s) ; den = tmp-s2 + sqrt((tmp-d2)*(tmp-d2)+(snrm_hn-d2)*(d2-s2)) ; if (den==0) { info = LS_Unstable ; break ; } // Normalization (N38, eq. 3.31) beta = nom/den ; copy(h_n,h_dl) ; scal(beta,h_dl) ; axpy((1-beta),h_sd,h_dl) ; #ifdef LS_DEBUG cout << "[Mixed step] " ; #endif } } nrm_dl=norm2(h_dl) ; //x_new = x+h_dl ; copy(x,x_new) ; axpy(1.0,h_dl,x_new) ; // Check if x_new is inside the box iTmp=box.OutsideBox(x_new, domain) ; if (iTmp == 1) { #ifdef LS_DEBUG cout << "x_new is outside the box " << endl ; #endif outside++ ; if (outside>max_outside_steps) { // Previous point was also outside, exit break ; } } else if (iTmp == 2) { #ifdef LS_DEBUG cout << " x_new is outside the domain" << endl ; #endif info=LS_Out ; break ; } else { outside=0 ; } // Compute the gain if (axis==-1) f_new=glob.ObjectiveGradient(x_new,g_new,OBJECTIVE_AND_GRADIENT); else { x_av(axis)=x_new(0); f_new=glob.ObjectiveGradient(x_av,g_av,OBJECTIVE_AND_GRADIENT); } IF_NLOPT_CHECK_EVALS; FC++; GC++; gemv('N',0.5,B,h_dl,0.0,z); ro = (f_new-f) / (dot(g,h_dl) + dot(h_dl,z)); // Quadratic model if (ro > 0.75) { delta = delta*2; } if (ro < 0.25) { delta = delta/3; } if (ro > 0) { // Update the Hessian and it's inverse using the BFGS formula #if 0 // changed by SGJ to compute OBJECTIVE_AND_GRADIENT above if (axis==-1) glob.ObjectiveGradient(x_new,g_new,GRADIENT_ONLY); else { x_av(axis)=x_new(0); glob.ObjectiveGradient(x_av,g_av,GRADIENT_ONLY); g_new(0)=g_av(axis); } GC++; IF_NLOPT_CHECK_EVALS; #else if (axis != -1) g_new(0)=g_av(axis); #endif // y=g_new-g copy(g_new,y); axpy(-1.0,g,y); // Check curvature condition alpha=dot(y,h_dl); if (alpha <= sqrt(MacEpsilon)*nrm_dl*norm2(y)) { #ifdef LS_DEBUG cout << "Curvature condition violated " ; #endif } else { // Update Hessian gemv('N',1.0,B,h_dl,0.0,z) ; // z=Bh_dl beta=-1/dot(h_dl,z) ; ger(1/alpha,y,y,B) ; ger(beta,z,z,B) ; // Update Hessian inverse gemv('N',1.0,H,y,0.0,z) ; // z=H*y gemv('T',1.0,H,y,0.0,w) ; // w=y'*H beta=dot(y,z) ; beta=(1+beta/alpha)/alpha ; // It should be possible to do this updating more efficiently, by // exploiting the fact that (h_dl*y'*H) = transpose(H*y*h_dl') ger(beta,h_dl,h_dl,H) ; ger(-1/alpha,z,h_dl,H) ; ger(-1/alpha,h_dl,w,H) ; } if (nrm_dl < norm2(x)*epsilon) { // Stop criterion (iteration progress) fullfilled #ifdef LS_DEBUG cout << "Progress is marginal" ; #endif good_enough = 1 ; } // Check if we are close to a stationary point located previously if (box.CloseToMin(x_new, &f_new, eps_cl)) { // Note that x_new and f_new may be overwritten on exit from CloseToMin #ifdef LS_DEBUG cout << "Close to a previously located stationary point, exiting" << endl; #endif info = LS_Old ; good_enough = 1 ; } // Update x, g and f copy(x_new,x) ; copy(g_new,g) ; f=f_new ; #ifdef LS_DEBUG cout << " x=" << x << endl ; #endif } else { #ifdef LS_DEBUG cout << "Step is no good, ro=" << ro << " delta=" << delta << endl ; #endif } } // wend // Make sure the routine returns correctly... // Check if last iterate is outside the boundary if (box.OutsideBox(x, domain) != 0) { info=LS_Out; f=DBL_MAX; } if (info == LS_Unstable) { cout << "Local search became unstable. No big deal but exiting anyway\n" ; exit(1); } *mgr=maxgrad ; T.xvals=x ; T.objval=f ; if (outside>0) return LS_Out ; else return info ; #endif } nlopt-2.6.1/src/algs/stogo/local.h000066400000000000000000000013721345435414600170030ustar00rootroot00000000000000/* Definitions of various variables used in the local search */ #ifndef LOCAL_H #define LOCAL_H #include "tools.h" #include "global.h" extern int FC, GC ; // Results of local search enum {LS_Unstable, LS_MaxIter, LS_Old, LS_New,LS_Out, LS_MaxEvalTime} ; const double delta_coef = 1.0/2.0; // Initialization of trust region const double epsilon = 1.0E-4 ; // Stopping criterion, var 1e-4 const int max_outside_steps=1 ; // Maximum number of steps outside the box const int max_iter=50 ; // Max iterations = max_iter*dim. of problem extern double MacEpsilon ; // min {x >= 0 : 1 + x > 1} int local(Trial &, TBox &, TBox &, double, double*, Global&, int, RCRVector #ifdef NLOPT_UTIL_H , nlopt_stopping *stop #endif ); #endif nlopt-2.6.1/src/algs/stogo/paper.pdf000066400000000000000000003233611345435414600173470ustar00rootroot00000000000000%PDF-1.4 % 63 0 obj <> endobj xref 63 46 0000000016 00000 n 0000001866 00000 n 0000001946 00000 n 0000002075 00000 n 0000002279 00000 n 0000002625 00000 n 0000003368 00000 n 0000003521 00000 n 0000003958 00000 n 0000011249 00000 n 0000011728 00000 n 0000012117 00000 n 0000012476 00000 n 0000012552 00000 n 0000012961 00000 n 0000016041 00000 n 0000016680 00000 n 0000017307 00000 n 0000017526 00000 n 0000017911 00000 n 0000018193 00000 n 0000018403 00000 n 0000024458 00000 n 0000024793 00000 n 0000025184 00000 n 0000025397 00000 n 0000027955 00000 n 0000028365 00000 n 0000028799 00000 n 0000029197 00000 n 0000029521 00000 n 0000030115 00000 n 0000030349 00000 n 0000030643 00000 n 0000030735 00000 n 0000031081 00000 n 0000031209 00000 n 0000032616 00000 n 0000037419 00000 n 0000043183 00000 n 0000045368 00000 n 0000045610 00000 n 0000046166 00000 n 0000046373 00000 n 0000048864 00000 n 0000001216 00000 n trailer <]>> startxref 0 %%EOF 108 0 obj<>stream xb```f````c``Ib`@ $AW] yNlV3:+EޘẀ`lWp5̴LI449kl  m<W;evƯ74:$P15z岕rKo'M R2XNحMہ@]E<"Xx (#SYy,*t9+L3>iGJ5p7kp^nFS$SO{?ڕbʼ@nb?y?R.xh Ш@* ^ju ._Z'JJJj@u4 .PVKKKG2vq  BRh( 4"сiiV+U ;EPe`r4NY@e @Z}xW(0hnPk]p2  "WqqyϹ¸tCcAM\M-L\2 _D>`>q!Qʅ [00'i& Yl8/v ` endstream endobj 64 0 obj<> endobj 65 0 obj<> endobj 66 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 67 0 obj<> endobj 68 0 obj<> endobj 69 0 obj<> endobj 70 0 obj<> endobj 71 0 obj<>stream HyPgƻfzfhn=Wʠn'za100  #àYt5$.1^.[?m?RZU<;0]Yb9#/&h6hwg=_b_dc/k1!0_8p9f:>w wyDDbuhT飯Y2e䱷-d+C<.yܽ;āt.ʃRt;^g %''M #ze XmVXlŸ_l$X:~hUZ[hJ9\Yo67G7Kӓ@C<=5EB t؜9Qx4M@ZU1ނpk\z֚FʚY! ݃wV&^FedU6C!B$ ~%"^-#Uzt F/?x^Ąicrlc|My" [D[qY~f6f#jE*RIOnl@84q ̀^(r3 AKkl㞱"[A =f g!b1ƻ>32;&,/4Z.B!MKxPd{I,ٲeR tZJmPJn@rEJB|mJާ]2p{r KЎMN4d(02S |(Li (,Յl/d Ss*SAbd= \ t^u)֨u*-3zA^(B_nB92Vt;*==ɜt$/w]TVNU 6f*5`#IWm "+FPBdZ`z}/+ y!PįvP@,Cf5ZNjo$Fd; `:U|AO'<$iIK%'Q[v52Te[{^m=&ooE2-ϋdV#ӧy)It{Y+|Y +؜󠷋=S{&\V˩`q)V+iw"[r!iL|RPZNԷp > -O~z?ZcfV ߊ|Vd@>7S4X~%g:Q[bio8 5*j:2Wj;.w;~Iw*mF$NR-ߙf}!"2C+\awa&<:xWwrvZLYSMqI Y9| :xFϙM3z ߛWUgjڗTz#`_6] !2m^ȑ¡;bZ`ӂy a'a8p7A#_mi {A.H32$~&^/3yںȬ#e4_]CgPqwF&n&+7v)آ|.)T,j'ҁPPP^ʴ67j# mfR"C~ǺYXo?6*\?{ @&$%\<ӃV35}<($,Ý9v)ؒRhcvHOFQ#t 869[Pc)YeC.fN[#eULu$ 6 )11*#ٺsr,n'둊@.Z "AE5%*ʄŻJF &hZKo Px2w,Cbn6ʃKvGxJe2,@,9h5q` =נﱅ'o4*+]g.RFE<&hq9D24,FBS2"F3Q5\h:~yy-hݿ޻ww}e3URns=/ 15/lVTov"g3:e'Ϟp12)'KeQچFeRzwۚnEa!'=vSK{Q Z)'QM٦t_7#м$qțSV73g.`.MH# 9&r6/dSYl6mk Y~^A"Mm+V^TVB[!L8vgK!mB&v/6}<.P.9F| ;~{nO׬-4' ;fJ.r9<_a@6dp0zqMB|m3-|ԷӲ~y(+AKIK"Vu`paqK󟜱7|$`& ݓ5IxJ`Wx/faa5!6Z|Nu^>R.MܚY7BYwځ}̃HROg؞qRq~э/h-an2Q6GPΕxL_N!Rn٧2QjFrL@\&~GشԼ2T!H+B%w[ 侬cc?#@ N)#'Z<pvҷ4اȄ\~ϭ^M4ߠZtܑ^;5d.d_\8ȇasPV+'| t31=3 6r*RaS!8#]:H`n"me_^A %|XU_:{_ara* YN_}9뒮Y~H>T? }DEM^H[hU}c RHWn]?wC?͌zUȊLQqScqpam lGYbdUt$1Z-)1:çp~[RICO@%N힀0@7HH20ShuȊjQOVnl v*h'8<{6}{C~7WGVaob;eȔ&P'IIOGUR]G%s=jcGtiHѐYCy\oJIC?bmaēh ^)!A)*[~F os3(8EiH)d ; ]{6~$d[S2PO{Eqa'hܭhoVYċxcD%HADcsf=1 [Ac%*9/AX?6b,OyBZ{ 9-\2/P/_kXq?]ۊiS&姣Sexo[*d)r)SynP̴B+@[^Er~~?|شpi|z`)4 $2T',Н󅃓1Ǫ\:onȋF˄ε6]0u_'ċHD?;=Rq2#L2}{kwîOHvƀ:Կ4^%6H-V$»!Kn;>\2E"6U &d`žk&ԚNuK94 gC~с_lskZkz6ƈ[hК$v uOn3'L ;btIVvh)-4ӠNc 3L#AVp\}/v9 Eihw|P~H@"X^r^H KИ-tU?Xh>ڍNo[g EJ#04};M$6#`:1p)?KRE VYª5G󣾒5R9[Gn y{*঒P`C-֤9,fib*Vbju"Aa *`CYqaX<kq(}`9&ީsp幆\)\KngR^ml8 huPYYv,h5<^Z)hw - Y|CMHQ,Qk5Y̶}Dlc~\qc;Sy X@dL._WT$#=hU6CULI&3<;irRs!8O߀0?7 .wzrdy%"*.>r5jח ӅeϮ@镝rNHF5N:w׍[8p\c2ǕWV3rWXP!P #?eH} ئ=I#I(8Zf[U a$$=D.hLWA< [ CdCF*O){+\٢I*X6BuQ~ֈm3t3r̼GgK-"UzD7;[Ξv0UxpE0Vu'E1/XKrY X;xqalA$^2 MD[:kY?%X&D,O=>.]=`:Qﯘҗ@)x&(LzHJlI%Unz =cMtBI+^疐M =1.-) M7Ek7P:⋌#%}rI\=z뼵[c@T@>LZT*+9.~@G?BVd_['߳$e7݄9L:00(\h=<'pC\mz D3ޕ$|_=s9X) Z nFyxՄw1;:sY4XDUaL)KZW lj-z@! ; 7L2GcdY|z RN}i*xslmAK!"AA/Eo0(-Ze }xwv77͕6~E!boGsFyuss9Sށp݄3 reaj &Fg{7'oU'XUNh]|ΪGq\tL NtJH*}D%}PV3!м?{r)rDqe!a0P% tss@HwAI!804 ٧lT] Vbd R SLo'\K]>S^LPM%#>c"BmTOg7l)5 q4Lt"Eť }>c0]]K_ '8Zعo~mvqm*Kֺm%jVݩtj߂yjgPt(QNE[,ʋ@z#&mt,wQ+569d> endobj 73 0 obj<>stream HT?o0w>ō:ؘ 1$Q &n#E*2dȷ:`w]CY&1aqP [Zw9py$TXl{Uw#iƽkA+B)UebEݘ/x󰕲""gę%2s +22rQ%3wvb@LBFaV&яXĹbq (}u"JH ?#^s ^s m>/`ș endstream endobj 74 0 obj<> endobj 75 0 obj<> endobj 76 0 obj<> endobj 77 0 obj<>stream HWIr )oQ) CA5bsuUp^7HNjY7/ooYÍyQb_6. zqыεvq_7o鳥ܨS>6SVݰϗaY;Y68g~KX;_X&}*e([CKު5ٲ0W?&SzAAshaXtљ"M;m}Mvȼmv$]4ЉE^b⧧c"l Y[n"֫\VmfBqڒ3$'`(;4hul3m-`%lqPm#-VZ 9nqfRDfyX=$seU΍y -$r%6zє$^ѝaی?ƨ2&xO6'Cqu~{!2$Xd sx GVj,0!LWE hZ*'^7CP&+pU,$EJD}.nm~d>긻ۭd0= >7X-:8٠}E_w[ ly؍yu웩ìgH.6@:D\\b=L6,á+1m?cJs׸/PmN}1$*=J:<xPaIrxv"[4iyRC0lq{?ו+e_}%[!m䅸JX+Hqu`S_B6{*g8b,b.H7HQ+pn~r&,RNCpAOSL`,N4\Bs@HSSF=W?2DCPY4:C(E2z:՜CsI.\&fl=Awh՚hWl!Q>?qd?x?m\ץRm-`r>'2ȑ"Ό-Ɩ/`2{d+U-#?F 8;4ۖv)!M'%KvCURHJ0%|MiT!ZҏB)\rA/. 4T |jr\} :u﫶D9OJfrl;/uuU&z}-Xe\׆W*n=ZtϷ~yXUa"'M28$PcVc֥sn"ır9ܡZ W'܉\;HԨTo^GRE:Wo՚jiÙq{lΪ+KC@/Xr_2@: liSkM= h_52K(ڃn>LS sj}K|=$r,Yj o<\.~6*yA]G.:o5SMݧ iʑYx%Q|I Ҥg37#*PnfBH_ |˘8I{@ MjN6eS"qub*,mc4Ffr8KX.1?k$.wz|WTB]/mO-I.J*)\Bs`kZ>,uu-Y)IP'9umOGJRjKIt`Fk2{^`LLӀ"A8Ex[ 41V2$ark拓;0itQpR ale4g/Fr,힜F5%fW@r~1C[B:·ET M-`x(Lqh3ꢉ?"eQD64z5i´ctx 2&&8=&DܼTG+s] a ث#xrpTrJ> L]xFޖpw7ԑ1cWvR2g-?~S %@xfi-&h hإ٣j:*22)*\gFMY0MXb'by \cTj#'3.k teT:dQ Wdñs a4&F*UHؖg<) $3sL*ڥ*evǞ!1B1SJUP |{ΟV[ y AǾ3YQ `E[#n3.VJƂ =Yes#;{;[:g;<_YT)yYXJ+ ;%!srJ乊D}Oj+]GaMNg. bg=[nvfۊ[۟KAEu違ծ0 w}dMzx-]H ѡܑL (T 05]iNEsWU. E>0QI-nǩ; 9orT*c/u05 2us_gKx /GFAxUSS/J)1'+'~/ %R8L+fǸ}-8KUۆz_SKXoHN9Gu17^=# rr`mg endstream endobj 78 0 obj<> endobj 79 0 obj<> endobj 80 0 obj<> endobj 81 0 obj<>stream HTMO0 >qǤ@ځ=MQQ:_a Տ3t55Bނ`z=/׃rB:8l7B]g-$_aX`/ޠV'Njs_8CӀ.c'Հ/v:bi<=#\6P.E*i;|RldxM,8\"2J5&(UIy Ƥ)Nw<=֊{h+ L"~Js%5.MTEr `}>x-&s{+w#/˾ϚC endstream endobj 82 0 obj<> endobj 83 0 obj<> endobj 84 0 obj<>stream HUip,Kv  ,J +`mjsN ]{k` , 'f$ ⦞dOնL˸3鏾yEGa8ǯX,kFUgωLY\ˊ%sC! О<D76krJs49o,),uF=-szvJܲ9U9ܢQ^[5?WS:P&RQ^[[V@ "Æc0 aql"İ$K`)AaY8*[K` |x,_{ _Cr|0L2IA Q%ѝd9fb̩رK֡-8÷ FJXp~dʨ^:2gcN2iٯ L-3Q)6TJQtU< d[K7,lpK{gm_0j:A%)M>ذYu+mu >s6,9eƚ`+ZlFvp"6{ }U^`1ؔ _#OvPP0]J3 uSU\'ڴ6xOtva-{, *MU$3IԧG4ZbZNPob%l\kPj$Chg%/xݒO oU`]HK oun;~͠AHM v\<Kn)2t4wĵ{Hu)\^d_I[SS2G~[;_YNpf/$/>:)j^[vo˟ Q;z^R9F1ZIϘ ng'.2/'%q%swlB$Z< V~Z7V4,DUV 'Dy,le 08o\ϵiJe/r3Jgk:?<*mke{Vk gmgY뺬]֊/*D)$HB {o7 y܄DȂR߻#:ZDZ:\gwq93D*`-77_f !29V&+/]/~;+åćxn[y"fYM7ŧ?KEv׹,ARf5=\{#p.¯H`X-D ?"ϰn.m7;K K3[ ZQeG .:׮4$K21&tFjgZ;iƁ֒[p*UM) cGS'R(qVIQXfwƥq?wpF+*!$A=[]פӃL-&eHFM0 vq9iT_b)DC&srZZvA1s>mN|=5nr7?C,~m{oڝf5,Qub |i96TH-ˉcFWRr?Zw0} v x>u} 0D*YLaN#2*H%ar(5~$`98DZ\ObWr"*G*uEe 6fnw 2ٳ&֙Xقat0d*n꯭ml ό9&Q I\WCTPJ"YIT߂ j"Nn0^:;qˊL.$!_o>WS6G5R")-QΝɹUl|KccQh!@/*)rD?{&,=ǿх}YIԝ4֔213ܒ%#\>w(6Wn(e\,Crnaeqh9Kfp>{~R8/z԰C-c*=F %{. +ِ1 ֱ)_K*=,Ḿړۼ[Xpnýe{QtCE Z(wI|v..efVM-=I|hE"P}# .AY,OFǻsge2dYȗrerņݘʈA1VZQ$t=  h"ޕbg'<@PINa0Vpʙ(%{c *uW7,h>ҹRYܫ /x i`^WЉ0`EbCL:GݨO铔* '*Cw,ٜXiUE1weSCݚpp8 S`tpDj(9_bqAp4Fow'"c]O 4"oMJGtJqK;b;&.)2D$ij L_!uGIPl4+1*`|AG[?^Xg 6.+06r kK*X%;} KJD`$ITR$쑟rok e ġ! ENΉ!Iqn-ay`-n6YLVDzlW4)G (৅lkSbޢp+y7qѺƮLU%@idtڴp$!>c(:|زdYJvulY6¶-!cl|ORRg0̈́6̏tgJW23ݿ}{UIYm78^}s|cȤ ފw]dl |2!')CMĿaW]U+,'>$Ӑ{\T*.R+&O$=}F$%B`4q(Z%lkzu(SUz8U!%|jwNir1FfGkGExq??3.@2#s\r Y"#EN3kʋT`^+ QXlgbS?RYl8gq'C7+g~ "jX%vLPS\@ݭ%>$ LC4 m"b!{]K~es\sܞhdM* puE ; 72X F2HKtR76mOP[&.ԭ]iiчǚX^p?>Ip&g.,No̝LR0[B1dTd#(<@e2uljf)Lo zq+.S2{ v  hL~̉{]Kmz7)8ǤUF[a y؟?.;h5GUm^5BCq?LR'3Tr%9B1 @]3ħt:;ZX48Qu:[^TKl٩)gmD+5fq[1sCtL:{ABYe^IxM52}z DVUr KJRg7bNMQ}+nE.IΎ:' _.c ,Zc*uEfLR[P@Y{}'VCuf΀K;P9$Ry =Pd;@Bt` !Z Ŕw ή&ayE5P[).+!z , r:i qOK J%b!*&R~T4u݅ Ы={᧮l[`;ï|B!oH endstream endobj 85 0 obj<> endobj 86 0 obj<>stream HTRn0{LՃH m$}I{w̒"criYfv5 k 77#.s8OWx A/-,0/>ck *a8/n!w^]n0؝ҏOO~fu  k}Q##wZ-tkLF*<<`I()HRDHDX2z4 DIRn!m:W?N'`O9o endstream endobj 87 0 obj<> endobj 88 0 obj<>stream HtU{PTeP&wͽ4>#+QɈƈ . ..]}oQ5V&i3v-j$^4:9s~ws$'!(l]͋rk(;3&^$v)V> O͚41S^demz+sD*euFvH"*Ji\Z)RIrJAyR*ᬟ}KJRVV)Je N*VHjLU*Tr\Z+jZQض*%e3*(KJIX"ϩ{Ƙ gaZʕYi*8qEZިL&pc(`hrF`vQ> po4ڬV7G @ Fa)i"V :U-2tP8fλү}ouTl `0X1NA9I0 _>X:!hQ$ go(oC.7夥>l~-ѝa;B@w @Y~.W0'}WBG4NK/M;&A?G)1tt%3s5X <_ ~x0x(8<va )Qj#1^|!`78 8 A8m A6.6Ity{a/.+MlM@$>-|cz"؏րv>_ hq=d" >Mh%h5X,p 2n"uMMl0 z-dB& fF7L4,?qWoF@߁z͸kk:<.2DAiƛN;h"6-fܟ~:DǾ҇G_Fyrڙvѱ[?\# 'B (>+ "bZQUo%_@Dp .ёصӷfNfƆ5Y{:/#+O}ҷ!_<{㯿ŗϨ?8Gr\&Jy>_93;%=Uk`VL|fq]%\U NY$X1]ӠdJ1G~ʝnxIU'8\\BZժ]OUoopG{Erp̛`:tt]/ŕne5aJmƲ&ȣ?R*޶bm)Y1s) mv#kzM-NC0N#uA^h#o8Gn7PxNw?/wt[kb?zz>H%%Vm*(wNϢpﭾ+#`ߎ,6Z'.D­ptU(Ovxmv5fY=J}2Qv~$]pBG*I讂p{n76QX-Fbq"/o 0o!mw;b"Fニ&R]uDh[QkaD)kZ V ৌ vz`5pxpvXDsڎSUFub DKMnyO;.t;wjO_ -N<&`;`&74茰]kUd?nѮD[[g ͸\<`i"fjP"n4zh> endobj 90 0 obj<> endobj 91 0 obj<> endobj 92 0 obj<> endobj 93 0 obj<>stream  PBIBHM+CMSY8(J_  mOHOT diasteriskmathprimenegationslashCopyright (C) 1997 American Mathematical Society. All Rights ReservedCMSY8060@ty_yys$h%(+oy}|},~y{|x$L$K~xr%|0t 1hqromcjF}~k (25}~~o:fhwPwu}}utts? endstream endobj 94 0 obj<> endobj 95 0 obj<>stream HT=o w~ǫ:媓2C͵;N!EWu?wv'Ǹ-'O*pަݫ&- ]'GN.787vȞ&8\ϯpFJЀpb⫙db-"p"FiFF\GmX*j@+-2We2gu*įik endstream endobj 96 0 obj<> endobj 97 0 obj<> endobj 98 0 obj<>stream endstream endobj 99 0 obj<>stream HkLSgi)ԍav3s:˜f.^-́zr;)ZRJ=ޠ])P8&ΠdsfY2%-veaE&;f#YOjCcsd :7~]"&ڤZ*FOFYl$,S?ki4NsK^g 9~E/&n{yni+"7A U6|QZRu;vVg7R1*yw?SB]4|E"w2j*B Lm<}>.3[X!eH*e@""pJ{K`f-侎6I0%f }Ez4Ss  p"s)8U5L206swqZ8 ҳ7/Ϥ'p,VgFl1䀑ՎkrH'} r$~SQIP_v m53Ξ_!a5 W҉ڏƣ!2VLˍK\(GP끾p"a}if2uyMzHGP{?)+2[c,1\1ggz PdVjO^HIWN~TǺQPߦܿЩ ,^!a{8ڕKK$ɾ>stream HUyPWf"Nƣ[&Z)o]We\ y3L ``@+6פAt<5zbv޿0hhؓS' #mX/+؝]3kظ7bVfޕVVɉ٤۵;l~̪Љ˜ŒǝU*Pi0pO?q`RYƌ-S 4}5ڏk,n=uZ<JyC`ؔe;7mqt'iz2q"Sj 4q73sp#.evmҾ3G{Yz+?g5(4jt%ku:=&Xdz,R m`(?juVY.P~P7>(6pmNHd/ (m¡v.#zB]/s7 C HTIy"BOO2Rt ==aUfwU|;dblj3yZFZy@LkQ@]iF'| 5 ЖXa6lŴyRA MCj<7nӃ)1b #'a7Ƥז <;uBYD+N_47@/^)Vz˵mWfvܞq6(l᫢i|nShcTl> E+E4Wf\#|UQMPC."jn(mVX3XNٙg3XC0E~I H23-wsw.rv[]QRV,OqaPwF#,V`nX[M %䠽&XPe 6T=N5~Zî,(X,.'X#{m le"UAX?֐DŽ'c[ C(qBG+u*؇Y!\S^EI}y4qJ^,XlBc?@z`IM|=?>s-nHߕ5d#َK&g9/5gy <b(IȲFY#L.+3CbLHAGV=GBoQ#=r@?IAuBkyAQW }DD-k䀶GIk@f:.dExTdYFySexܭ;u3R]ltAApL;2mAab'<߁sˬ8 PzIٗ֏.2ee[er6ԛߓC`p;{AKQJI]jKǥ.r 挺;˟|6T^rBA FkmW>]Qj+QnQ[Q(FC2l, #_ _!c98V؍;jn4 '&R9rn~ZhqSZ1['zfk29Kp nyMnc0F=8V)U j /~{*#U!ki7!KeiiEt;aXu g :/mBS4n1ۛw87˾Q/$QsoBE ZfgR+/-gW-΍e'&L4p2^]j>j?ΙZ|,OזTᄐ1*?1`uEG!7WRA;t=5iQCŠ=Fw=+3qٹ"xbnBkX++yEeRG⪑&-#$>R.*7yzs98an֙ܭ#4yVfP+ex$+v>~{ʕ9_>kDjjJGN{GNwk誻Q'J! V)*ID2o+aH#P&yIyMy;MLc>'--gqpn0AHjUuY{2ۏ>R@hHa7:~dhֻ ^q+T Tz)"2 nBpڴ ?;S=?cuJ@:iyO^pw$H-ssMx{Q'ݬZIa磑+6/W("ҘR*IXjTqO3lPDEY1a7kc8ζ4珡 /N%y.3`(o+iWl@'W8e> n -t5 i.D%iOBOۋk54q6?~ Pi"SWUw<,k먢u`V$o"A?VշWrlRXy\lVeg=,4L윿 ^> }čSQ <Nw;z/ܜ1^bXѬW%!Ժ1vIG ꐋ&L=1(SOb,Cɇx\7 q X U O ieKjX{GAR"-W>E)TU=FcW(1EMkt$%|VSb2 l ;JQ5Xs33_\gɭu"%}i2]'bn|6ڬБْn@'Fvp1ԭ0w1 Jt ȿUC3I1E020]qcg,,IQ!ы!phJՙɏM0Mv^S"E̟$'.{Gf>5gz V]x s=Xk^ނ.Ђ9p wsdNa:{]v7;n" }[263t_S=2L.(-cI 1S]`V^//]En^z+ҝ Eqm3+WLx:SX^Zr˶.+4}%㴻M޽,&$J:uWO#?q-sܘ7q k]ً'5{7kNsrp0epʅg5GdDpeeH"eg5,oI ؔ󣯯9qN5DvM>IneJOѝPhU/ɭ ]MAU5gήﮗ֒-vnݱc3ǫs̕ l(4vuյԖKW7NZR)v~s^sX ,bBz֙囦vϗ.̩il+[~SN.? Se@ endstream endobj 101 0 obj<>stream HdyPTWߣWZlDy%5HG 1NDA\A١AYҠ(4YAinEih#74n)udf0蘉9 8ʟ9;HBhG$)ZrO׮ 3$,9iwEphdŽ$WxUq;2nsK^I1dȌ1ICbCJt\Lz+1Q~<#]>&=F+foIHž$$$#1SJ̳#<b VJGs?Ibv/YPx8NB.N#m_g7YL/m[@/w8:;f;844ydSys3%"]\..|Tʹryl,8k [Am&t^S;ukaL,gॡĻ^bz?6SykZ^@?f6c2=qETfcT7xSpil8|ZTkA=U]E1L?ҥsA).ګ-K:z}{FҠlI\TRvM<4i6{mymn \nC$^PHb!#@ JB% חz ڷ[vx6ؗ7jVf*HO (XLiZT MTs B+Vb%C7%XEFSRRDkJ ,u_Z-&0 k"M>ȺMuŷoeN4w&5=恃8 \ ȇRemTBz!Si } VcGnhfLWrqU!u4KJb33S ye[y ; զE LVA}3uQ/ݜOA0J~ S!Hq i( ħL/~d[[s[;  i@Y<;*I8STit6MPc&x}0Cu!f`b_0ZU~JnLN\j8Q/0όRRRkQ/"$cb(`"K0ɧPFN0D9? )*|3/z[ הhѾ6a5[8]aѠlHPj]iu%[F>Fq@#͸=)^O9LO= σh'_eWg;1;UT:֘aj57\<;q/P?( hI4 $DWqyfǁsߍepCf/6q/6L49: *hxDb[7kXg|$ i~Ty{hW«wǵ,s[C?Rg[=y~x M;X, Z%%6+=}R e*&L?|kL_:b}<S{Rs5=^LaP3ʇAv ;<vGpA6d-LlŶ7LtGjKBZ|V !olCjqf,172XLG?@/窓tkid ^{46f;oc@3^Pk+Q,v_u,dl>XhdOv]53/ݨZyG ] d /(K)::!!:ڔ`L8a?۶q ?lΓj*V3*>u!K߿-AڔŪ"b]%JvƠ t UP4gzN1":W9HqcĘMZ$|lC(+ 5ڌ̫uyw0DZ hXD\X}ws]PY]QvELBmlQi RJK*6w8iͽ{~zwe^?|dC ]mNē*KY<3Z ~'h#  \Dp#9(~T9X3.?'=V7#dI q0L #aXM6[»D6j:XHԜrxӪ[m|Ns0"oDy:=ϙQzg]O5b>XG! $Sg$YaH:,qQIOsjʞէݖ!*0S S \IY܇tPP 2 [M)Rw^Ve ^Y9gGd: 1#\`0w 8%#*JD[4q`fFTvCI)EX)oě7ns2SUɕִ ;ᰉyMչrbZ1USk0AĝҜ&_%b& j4dRzNek,IZ7C{W%1-F xQOp,; ) ^^EoaRE{h/Af0Ηjk K /C^]&%|XJyyXɑdz,C5YBNSno^ts .NCZ\e\ko))+ߋ9Du#ܑ'8H2^s?M,hs&[Fbe|cinVpwV{p=̔Yx3KG 3sHeVȐfuVCU3|枇,p2xg1> A- {YC.d"ιDCkUcV9F4 ~>Axg0\v)w 5&0y;'LwWl9ZS}֓ Ωo+U, 6jC"VA}42dNHtínO(ME7+g{{# #ffUX+5n]sp:UDg 2kLJrHP#Lk\)qQ:vtRWj2\_Q_s+7\n"u񴧅ó.xS/&2N( 㹻ğWĚNdŇ L A7μPV|ǟa1D,'vଔqSO# +H=;;Y2'_`xj W=oMފX{G9xEN-L8mI.8&i{BwH]XCr mæqZ K/k A('{Q 0Q\3ٛx͡"ZIvCn֦< ]D&~v Fr'Ǻїc\:zU!jvPcdžoYMG?Z;,g:1Y@"c vѫ! ~<ɅxjsOIk+̦faTɒ5':)"%(t$F֋p-֫͢0滛(^[@ɗF[RkZf4q:|;EͪeOB@N Q7WV|UG8yx|:ӝ[&QUJVU] Plmd |KB*n'L61Lz̀qr>818X+yn~Ǔ˔i&4[r%aW.4c$|Ubr֕}ই1,O_-1ܣvrGĕrT3N$X`itUzWU" !7Wc&C¥^Q}[`+G՘yI.z`Ϛbv::HJ\X8M&KTH*2V2ah5=Q851;0gP*pXgBv"Zpj0{PP '|q:ӓ1'XTtc uu5xg*U([_]&ս9`0[ǐbDr*mL"a@eŏ])uTaRhaa8 2,!+`K˜tu9X*sg9iY9K;GqŸ n6 f4^%)BX?0ڡ'A-$QRt*Y8nn iq(?!nqH&38%z EX}}谯׿][gx endstream endobj 102 0 obj<>stream H}Pw9={IĪA#F,q^)/wppzǛP+eF%N/FIH1%L;}~~1[ i|}W[1R[lq,; e)_lp|z?YboltLoCR7V"# 'DIC(H&JVV&$HF%EfG 1l.`u6X-B0l&Lj.xtd!Aڝ/k{B&.&{qb-x!@[nTF8ƜSY3 YW0ܨ)'q"4]C)Nw>|yR-]{Ihhhp?^a̻)׶1˳ng]O!loOݲB/^D~6}VG1f/hƟ@6hfv3:TrO|T6*c5J}8W8Dy]޹7|bE 1,D`WZFҪՆqѪTr8o}xLW䅼3rCa( _>0`CtCdG#Y 0l8*7޸ǻ>WA99Ķ;֏Kc5USTy̕vl_Fl_ %~2`4nRyWnzk4 ,xGdǩ ˅£HNY/yIdi''.aƞv>@="f;i` *kKje*ڌvI j 0]6ୃ L1ZeEqSA>9_QV*8tHJe©]켐lb&sU< pNhs#w],*2LٙMEg+buRHL>@KccsR=s@lAT<)( vw?eUR !tȴփ]]Di-UXi\Uvn0$∮:/Iiti`Qχu!4R)پ_pn-&EuE>CJPK)h3anI;Su'ZcO9j1QpѿO)sOx#&x#w;-]Iq6~['c!ZAƨF\s-'&Nl9* ֥zayV?#9:;3/O`BQ8KؙԜ3ЭΣT1uL.?A11- OEh[ 3 Tr铈> @n$M'-?dΌO7Șd?ZDV5t,u+#NKt[b{몲7rG\2''|Q\+}¤#ƣX1YHRzNA gKRjY%^ 2Ջa"eyYyPA $7tnʭQ*2L-& WЕyZI)U r&jU7tZH]Q .吏Y7!uՕ ͕}#(sZUUT1oD|iĿͣVDf$?9Կ6"E vaPkwH$6O_1!p@ƅj`%jpNߠި1jW>x3=XøMFYRV  b;iqI (pαvU54\W:;ۑ#Q=2LG%]TR0^hÕF ?Ǜ endstream endobj 103 0 obj<> endobj 104 0 obj<>stream Hbd`ab`dd ptrv 4 f!"Ћ9 X?o'?~W.8G#s~AeQfzFcnjQfrbobIFjnb ZRQZZT .|߭ov>ߗH9k]#GÖ]ӥW̜hA͜Rޅ=ӧ嘴zR۳j[S'WM i-mɘ19B|Z&LZ$aꤞ] -m٥Rk'Z> endobj 106 0 obj<>stream H{PSW9YJn{{ӊJwk bc C B<"ܓ `<juԱZ:Sk-{.N٠;sf}|}󂰍QKLߠXϾw\9gAN?Dޞ836G|J+ҹaKCBVJfTi){ YF{FgԹkJii,G'K}%xVx<^o3ˋ0o<[_Ÿ1 f T1S~W*-`â"3ʦ~|M<+\ vZWLt)xifl 9)ܬ,O}᪣͆$@'eXM1m:@pmºF}fY0>T{Ni7ŀ J D؅^tDWJ+Vd5fR'0>z.OfiAqD#w|"Cj45v i>W͉yK}W=l: p$I8bʩgM@nԮ&sBgvࡘXa a}LsS'PSe81pyVjaq)MS䪈ؒ ^mj}NL6d:qoxnf3"Yc!Ah^T7G$l -Hnv<ΘF(&R=A{lzFF+n4KjXJykr?a?KhEӦ*Hz`LQGDįhkqkl)kiܭ.br2jv!ܰ!C&Ma"Cյ]V‚°]/F!I֮a߰='n#$}"j?TPSiUޤ<$E}'\r yd\F&H̡ >l@{:sqfaCv6*Hh{ʼnyG qXˊ#X ;Rw3pЃlwN QHV Ǡw|;aHp3Hՙ3:XZGs U~k[]cSm+Ir1n$ha䴑:N(fX;L@Qq ptl9jr5S5Ug% Vg{UTQ:3[evvă*u8F+ m2mW[TZh(rOJ&ۓ-bQDDyU%Zܜ'){̧gGg;I-pJRjO>ƅCGC#$OP#_ǘṿ^|uG>CH6$`w l2JP޸XY~c%0Ys+rH&OQhx:|(+/~iEXN`9>(yM'oGt^i_.`n"KWtRI̥e*5YYllskjچ$=8n ~(4>ic&%7>^"B3{P:~?qJwV%W$#ՑqSTi&MGV1h2#,*$ Cz) N,Vgj(WSy[뜯, nD Z:fZ; n6ڠ!yz.Wy˪+; xa Ö2Cǭ ]?G?=e7z;jm,l]Ʊ#S&꽴i6y1t^lE.?]-4Nx?UI%=@[sfWvbo SClp@K30D}=aVVX5H^Nwo YۧvK-=degg3fVWZ'R-V=B~U䅳V.)/ˍۚԖ#GAj%?DY'b*:eZwoԌJW~.a8qކL~&U; |g-bTXs.i9N.?* \+/(@d endstream endobj 107 0 obj<> endobj 1 0 obj<> endobj 2 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 3 0 obj<>stream HWˮ wI,2LA= ṠI!@~8u(:e`z:u߿V÷?G}zP*ʝӏ1+a$N𰉣8鱤Û946RAn"#t:UEVE:=-c#8TnqgkZmR2 繠+z`7y˒/4 ?yxß?˰'qGB#o]IJG֌aLaL oµ]i[eC3 +䇕->):)ph4uR;Uy İh8-t,yqYT|dQnBM WAS4Ə2QrJ\ gxV^WbNWeEvN(v nO%d? a\w"%QOތ.]_h`nFZ̡w7 tȌG8*@сc[d;3TS',[*~rꋒӄ,ïzO<}7عr[ě$/ƾ%ptw/ 7R}ے6#lS(PgM6 SX*%yfɖohh/7`W Ka/;WM fqc1^!$vH$PT}IF1<i!Uͼ!11Q |8W R6FSYV$Q`A zB@UL&V95I|Ň!υ ɓw!\ob bW o$< ax<253_NKJUȐJ-P4s8?DDt>TmՃuNمuRFLz6wP)[D*׎B W60 =C}n*JgQ75;I)\:O# d(yLoPb0fLaɍp? X&&ba6Fvm6&H\Ll]X|S^>vA-JCMՍSK|,9ŁY4%NEE !A~,]fg˔Msc7/b22S(8cgi)pVgntAmAIjA1.[k@,M N\4ݎ#'dd}?Uo![Pg 3`7W?vc.=_.MN[fp/ɀ.<as4)xgz hwjIdJ7Y7x8v8KS(-o:DdMqD Y ԭlزyx UVm4k@oJǔPiʑٜ{ũ2"^{c&23ZDɑB %tw2/*G6hkXYG?!P^";|,ChxlَuXJt16,7^2q+`LK0Ε/ hǚrs63jagY'$=28-{w:ɘp\B-O=js}fCe(&~J*Ylqa9'u[ƗzUsLʖ5F\"KDHٕ$o;A %ƹmH+`{҇g-~d T y75{wBewVŻYch~=cdi|:? 3 m.NJ5K0a^^E YHy+Fӹzr>U%Q=?ureByF:A2uF|2+( ".R<2WK3w0+)?w8bB fUԟ$%͌fᒢ ^Bvo{ݖr8OZ4J\ TQ?.OK,Jn"8^~;nU(Yca'u'~Fc"Z _p)Y"x|OlcVH8 b ', G< fM(; Qt;`/_W8O\Xa NR2ݏS?RZKt9THb6,a跔BN=?4)Y~|Iv=lOgaBɾeP 'Y!é ڍޭn\-4JD osݵ%{f%ݠK$"#]'[ \@-7 ps.ۣ/TRz&Diw].$}HEIFʍz`rg@, w0:QvL(Y9!xHSfj:"?dF#3 {Y{nr[PR "۶t.j+~B{_![x{dKsa] &ʧD"&T3A"#)5.vK?1m^/RJMyoEN_da,+BGq񧲸9[5F}| FЖK#\ǧO7 Z[YదCԶs m ?ac6 فD ޻(=JiUmQ1'e8fG X%mJ\-KU77u}GK[uH"iOBYa Q=|?Mqq s_vOUYN/ht[E=ϒd!n)E!a"<_> endstream endobj 4 0 obj<> endobj 5 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 6 0 obj<>stream HWnLWhY,N8 & @Y%f"@![UHZzǹ_ވ꧟DLnﮄ+0z= !Je'6ROxɹ;&Rt*ʆ2ֳ”-/-)8~ͼ=L5 ,ߤ _ l(12;s+'sdd; 4Syl;2W] "/un-%elUT7Pwl`kBE>?*dtJR&_gc EB#er <SJں)l3-w i-J/MQs\%uJ{xahTzadsm"ϑ+)C=KLMyXg)* Y74GJ䐙Wc4n%{.4I<;V"P6@TW PR( ɰngۺmAM h*K͹hJuۊv߬]KlQ1H4mFg oy+}hW d..r}(o(~t,^b,`LR!W:{$5vN4u"!l 2P;5BX;xᱲ 2$|ܤcsxkj~Xwg =<~(҈;@5ڐl[-=3ZQSjael IGN.]G(%+O.]p,)l`bN s/ ]Ly^|ȑ.ˍb볈2=-޶omSn됟B?➏|Ġ+-Ġ R9}zt ݩdSSI^ %]||t.hj5p Bv$Qn#1&~?jS$עGbQ^T߯M"jKD$: S}r ɀsjYi"/Hp8&faB/ P(W c+1V'S'f G-,pv0&tڻ]Bt93Uߖ3,ၮ>RCrv'bhw͆ۺ /&ȫggKz:g3HRIBGBؔ"ϣ!P}B?pmyĽj50̦ rݴ oՊtȬ^e6mXpj -6 ~Zbx`VC/VP+lc$b=GCbXLis7r؉F=S).<&bjF1H35[C_T~<P!+rI[61>!eZ,d̥/X%f4^Ѵ U.Z}5jËQ1T-3uX=4"(yf_hОPkuqֱ\}}T6ֲ8Njż8~j o^kcΟ@hwBk?3iK d,4KJ*QJgK6ȟ*ǀd;|:1X32EBPEtN6_Z/Zr0h2Ɍ,i+=IFg2Qf~=aj0:%sꮛ=D៌q/B9ʡضr m6U8wBCcjEB<6mC: ۮɍV4X4I2*P,7yAS|B=yȂ- oiS/*RAgD`"٬jgI[ԤK|ԣmvmfN+0x9fQ<@iӥtq.UG']hV*T`dMhWMo@8 įhK(z .iJUHyovױڦSY܍̓p|zzH+sB07qatbn`[2Gϭ5KX)5fEpA͸ty?;=N8F̵&S[ʌua*s.Lˁd.rHHuQp\kRJ(U]H|o"J'[v4Y?nWE@m>%nz~QS#<)]~?6xFˎ@jwr{@\|] MYW3nVp ."{re!PqDR6u6 2 Rױ 7h`\7/R&HYJ'[1oLebzZP>‚k;/* RO0}w?;<طݜA6CVx̒h~yqyf+6,$ҝ 6G%:q;?[kޡ@8LqMqqog4͵}}OX?_EV.+x 5ia^rvS"u%]+H@@+1%Es8d%si\'9T`v%$0;["MBD㪍CKroJO-07:~lRYEFog4oIWg| i!zϗ i |'87b^# endstream endobj 7 0 obj<> endobj 8 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 9 0 obj<>stream HWn Ĥk."Y~$ ^P-͸l@VùCMR< MVݺus}jxsQ H7>+k o7>BBn\䲐R~^M Mo~AM `.^_w,tiZk\t%>reCm:At)|fŠe+nJiZ&ow>.()ya +WnLѲ:;S2$st[B:Rͼ,]fuf %,eD}laJ'/]aKi8V!ūl,YRS(,/R x"7mg/Ji1zӼkn]vd}}wל9<3PbARb4 q9=]1F36${2VLI-,yQy(d dEۮ_7ss{Z (=jr5\Q#fOaV?^B_-YASUpA4])hs^odaܢ/ڗ.R_IP8n:&cLxTN6|?j`b_BUahB%6pLްu4u|]"^Z:h2F:qS)uQ7K8H#2-MĐo>&ݶ;B YBf]́?U+sR#$C5tH( ~CF࡭/\ J(:\5hG8 ylH}AzVzB/vݞFnLSt9E"\\f.;k1> 7]Fs fZ|tmJ 8]TC/,#2R{Yԉ"˭Fϳt>5:uNq?TnvOu}R{oKנbO>i/@%qU8s~&":V;#jQ1\+F"=4Q5y5!q}ß!b|DuZ|q D9plrn, Tp5!@v;49sT먐=AJ84 bdC@t0,#ZLT=X?LSR ,Iy&ey^E%9ҧb1@ )U74 m5W*~ߥ0Sl#ER;V:`] >dxSIwH-DJ}}rfp(7۫>`tCuE&%;X $< XR3<8 5(+}jM M`8h/1zTf6yġBg`/wxkP"]WGct}3Zbi2~,[tto; u4 "~׿C_8 zsHsa!N])Ɖl3)2&MlŔt&bSP5  31jL3Oe4=O=_qa^(k,U17X&Ȓ` ncHc6e LzO䨑|Okږ*}_g:x\kGE$5j P iģ+ј(zsy1 (9Yq[e|둛imaaC^gqBH4V#si)aX%mlOz[G\%uL|VӍ bA-I]ZC)&;cUAg<6))M.xS> 9qoJx24mx$Onp[=6ᚲXt @2 ܓ%<џ (rSް*fS_+󿨗? W6{cK!;ԙ nO4A1&mCz*Ǝz8z",HgM z8%%t}K+\=˜z:${\/ivX^_cT ΁z*%r/UDD%@>%2L>\" !KCUUxfEJrtR[j\i5Q$s񽮊7eŜFBf)ܬlF+$ЋF KÊݠumUJ"@sbLeac,~ ~Q5 JmZhZ$&/UD^A0gX;>*x?q vǺi!85h! [ 8C  [K[ؖ+i  }O1TEþ܋nȳZDdCEKO7×}$> endobj 11 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 12 0 obj<>stream HWێ@_f`+ ! X ȼ83 $r<7y Ω&/k,bߪNSwv-+)`Z?<+#¯]0rXbG+*vPi( V_^qč#F4cJ-0t5[U.8OꇕM-kK®xqG~ݮeWi29e\ULGT@'-~?uPyPc~3XYhrc~ Z\_S >+m+)Hڕ'b9YӜ2/@|Ko̍2\oT.aSV(m 8B9/mYH‹a8r޸6Sh4>}u GFrQasq'H;%\t- qhGj !D :ZcK; <IWM'=ymb4MhjbZV-ۨLG G! }rxTYpHj# ڮ=PE,iw),z5'1H Fې#".9nTJADxwJv7̓e̥ES #4TIihE5ԞI]h=λ4oz!X}Lm$wqJML+2 sp1Y k&*27ɂ(lklDuQN ߦȤn4\AD]ᨮemGF-T.]O|SΡm푦yDBr OfLj(}*@(s tX +,@¢E~/d@]uYm ^2(Cg`ƾOC@R+cƣL $PF6X.,҆LqGLՁ.B.~|`F]lFCHb`Ʒd'fj9T@UŸ%v]e >S,^'Rm(aMq lP ?s}T%hޡ.vGT* ̴+;_ԡnW%V9_[GvfsMH8y+j]Qlqa҈k|'C:n_vʨݑhR4:C] -0sN)&N njTnk:z1' _J2er~\Prz=[etb铫2Y$3 j15̱`=}+V Y}o&E17YK$JEiՠl3-OlGܠ)/k>x2}z%sR,ҥtb;#jEwȡ}/g(~&=Pf9fQ`35t6mrQ'TCMVTRmJkI(C*L ;H:H*\$qVMkb@'h%U*ðx"E*|[Ա̟+I2}em6]fSy ԫаhxfPfnD_0mԉbXR.q-sA'SfX2E493Գ9OSW")ȸ:=*Xf=q%|/d "\5)piCϾxɁ5CSUTt_8lƋigV+sCZMYP+۬z8p̩K59u00"LkWϱKoATCwԬ9q dT/,J n"I 57i:/i~sC]_ڧ]z]ԞtoNK?K$T[ qz*h0.˓_ҕ RNzqC\bKy CnyET ,\r lb@cpe |FR]U,P ?v;;vnη42-Qs1*!2g[nY#cK\ 'ĨDr@ONcЉ%Nb[w $־b?_ f-((ՏAhKXeBJwxpcܺZ~T9tX15BEY.}FiU,& * U_av3fD88Y>"&BcQ,-8޴Â$F8ƴ.Y)^$P3IE_2gPw]|2 c5 bxK&c|feS]ǩk(pvo0^U8R."514ShSRi3tXR![yƐji. lfn]q625H.q6'zs-Yb1FJ~Z6!%@GCxߊrOb.)a% "獑.DݳHHKd51H}e:vspw $ M@^bYzegm&Ra.q& x˭s77O4CtXs}}N):uS{GoxUA%WB1⣃< $ϕCi*7DJG)d}:]SlY؃y"$+E>= ,m!λmS4Plak"qK,پ{`"hqiA1E_i9DRˆ4SxdsJ6RE~X̖I,3G+ a@B:5E|mϿXjIa 11.x7lwFy!^a &4rZUAlWUҠ=ۏ; endstream endobj 13 0 obj<> endobj 14 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 15 0 obj<>stream HWnf -M>yi`6 @,nJ͙nRawd|I&:URd{QNGu}a}V+9}]ҿk_B᪼ZEYsC?׏W?g]UԎWWОvC2&b,lvw7n+HO[Ju66ۮ~|a+eHiN mrCW=پ Gϱ<\efrBt[|0?V5~̍%&Q{the :tJ Uvמr]'2vQ3H%"N$f,ًjE%N0QPٻ|*X ȓPGW$\XD2uIGTMwmjl&?-TWɊ``-!hlmNawHM|2τv;r>пٜ`7$#IV}kB9z .5л6xJMz+Gal;ݯd`9/X{I% }!ߍXy ,E3C l+lצなS{9I\QzΒTSt]2.N\PgsjlױC6WRmTX{{> ljwD3BDM#3g*I:ѓnW@YjT RE-ߨ|!d OK0 >)'߭s<{;m+)sI^Y*ʃ| WOVzԽ:tN :׎+0rOr%*AVGJBQ;^]1ouY,Hm,Ad*8[m|gQ7y:u'e>5A#UfmSS)DDj(plkPJyӮqu< l4vuvz0yꆈp%Np ܵdX2QjX3Ƅdfާ)Au)ɽ ˛i'&0x|+1fX#= n K/@Z7wDj8d< \\$`u<(.[bq4^~1mrBcubF);9]9.sTQ%0'a$3)(D"3(tZT83M5ad5q%O6J&Jڋ\ջ!+tw)3SLשQI1kfpW>μQO*)l)ZTDIAKX W7Hդ`@G@gIJ7W?(q 䛯gE(Y`pӟ/|j9T/ct|1X*xWM~.}́엥8ګe|kC{f od S/+|3ڋuL#=odvS$P*v Di_vV%| Kkoel@S@#hvA4Ed3;go, TfxY 460`6o7s$k/4tfe>ԕYH+2g &q-SH~!>Qz=ȝÖTXQKMRMtp]@Bv>Mx$ TT&N;0T\q > K2nY'lďNXfʌXH ]]'#KPؔexNBoXǓb3C ېV(+f/a,ŠXglp20LRrϼئK9:|n.n!5]ՅђdS>71VNyɈfl !׆#P0"5gzUc'f]10xl-uZۋ6?5}4cXcޥ!trJou=KyEqG4R3$%fB8K*w;JӦo K.F%/@%(I~ƽW1PU> jU-_-u,Q]ǹSkp * ;jcAyOaLFRH1az"ʠUn+ :AR eeUKpު&UI'͘oFMx~sX- lKyx'OJZ?,³0xtڨW"Mfc!?ߐeYlJ_'ZJEn7Z\rC_6ySNnA'=(&) hMډJ`tC2\:G #cB* [N_-w/ S&4)_ H8##ޤQISKo4QVj q.ԀO.,jIa2gW\|'%τz$@=z~!%5 H!Mر3؀#jv! UӼkc7 ( >++rY`ih3 E0ZaML)kHR5&)B,~*az)GՠQF^EwLk ,TY& zQYfڃ pnqRs#ANN[)ZztcԶ! '5~AcK |`eͮl?Y88`j\w }(0Pu|7ٽnh{V>m#d#*\Ѵ;s*e+ NZ~Kz61 S RZrnK ZH4 ş8׿˒bꨰJBQ 99Z9RL)~i%z&o*"ȮL"i&행CrC>lݜ#/q,|bB$}7 ^TsZvIbiI-Z祛Ezb \xxP\|vp9?Ջ"O^d/8~휁!0>jE1M$Ģ E ʑ/`1 endstream endobj 16 0 obj<> endobj 17 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 18 0 obj<>stream HWn;/yM60tLf dў%;2eaw:UIyH B$nթSpյ:7gM6\&\<\WE^Ey}竏rUnZ\gSnԏ7͍lnt%|V{/P fA-y|"n]U4dE^eGUf;.nJYYKs[6:n|,ilOղ-jzx?.OprBkγGV[}P{ 6{w=+G(,*M{-w: l6ÇZA;nr; t˺>p@+'O9[mt'yF!.Ղ<Ɂ0ߩ[[n0\]ԂI{D<\1|ޞ027a\FJqO?'!A<9jϭ XS4`r`6ʲ+ZĕYXE:!{S;~۴~N'8GІ_Z9N$A) N8{{[M)9:ћCn C>!Z˄WLQwO EI#kbo+OiU!]*U D&t \*o>xZ߃9};&7Ly>!(,OBP:Se ˦)A?1YX+JrH k&;q P J51"X1=Uy1 ,:+^=f1=²2[2躤Dأ W{n~"4r&.!x7S;p z`J˜1'eNH>*rY*Qfȣ;ζ q*BWJ:SUI) ?!7mv2Q*ċ.Vگ,i++W5۾aBCiEDGmeUJ;َ:.MΣ;!1IjQϨKũ8rt=Lnl9D+a. n5Z2n՜f&x04?J=xʲ=43J*H+Xx9?zfIS2)TrzNݟ/)ʡ;$k-d']Kt Fyc$A8nv, UybSG|1٠#:&?$2=(ڷĚhHI?4r2홷*-GcMRm[馒 K٦#@Dmi:5 ;YhA<&y}# R,6ti_>6w˷/ز;TO;Q4`R{u?%7!pQsxoNDNapI$5KHF!,onŽ_DK!I.z.$f2RG EI=ƨ{`l>NUYKAԓ1ʟ( Pc^ DzÇ]f"$K/LbAk #Q31AjZ jWF22z(sHގ!5eԡԌhW7ғz8~*S aP i JCAz_<LvKEx#~Ч1rVT&n"e1p:=>n[Fj5J>R~w}iMg^ԔtDo6LBN*?۝4X˞l[['@+Ϊv\kw2Q+b=r>^"']5McNkγ.ńy9)=j\*힒Ϋ nW},~=S M %|74T6WsL4 - #M[%, E"D endstream endobj 19 0 obj<> endobj 20 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 21 0 obj<>stream HWMsoc30v ` A.+ dkYQx_8)3d7">{Uy[somIҳ)뢬o} o7&/4Z<޼Wv}YyVS|3C_>d- ݧnީJ.LE7.V7Mըi仺O|SVx )0Nϓ@]z{{8]f2Ƈh|(ڶSGmQ7zQdAq2+W5/(o5SH=};1.=S58QjL:>\Z>qrfn mPVPjNv[ؚdcWL%L僄H)>sRxMEe;U^0ɍ'wFQDr:Io1t&\ϱQ f‰~{D9jD 6ɹ7~7\PtCȣTHxSO'l`PN{zkZtJ6p_W%Rkm:-G5%d#m hu =4uTքv̗t93b4-T`;{Sĸ7Ql,wAYpZ%%z ѓ]wD}1jeEiKF߮hH39xBnZ[4d7 Il ' -HѪo.= bQzlQxZ15ДW'm\p[-9HBw&/2ڷ]=aYYSN [u^rP> yā5Oi(T#2v7XmReD0'~FHjRj"XzSXWb ky4҄fͬiȑh@Uc}Ĵce5*>=3}*\N*@RU#T,> Z$nU[{kʧ^ ѣp.}flLSh䆪`_]lVXRoqC?a%bt+jzklU#%ihԆ;WRHAgN˹vp^4pEnѸ%8=.}[KУ#%Nؖ[+snxt-ZɩD{|E%vxjtS̓/[IۺK-%~{5?RȗDt|کFh(lk0h91"(oȕF`Xl}Ѯ1^E#I;:xtKHL;ZcsS\+|=Zzyl{-&ͬPUl5cFc'`p$$ֿ =4sFJ* -ײ]X+:c;sp(N/*;McXk+kj"{DA13 piݭR6YZ \;ٮ,էC=-y ڳMgݼS]Mhi$Go:Rld56~ˁ3$W-"`vn]YjX\|8 \Q0\Vא$+:F+ Z.F8v)9{$$p9!}g  MA)&YNL;/JL5FA+r?^\5Ro0lu7 {cL>F?FVf4 *!| xTaڸPk;ٌ~ܨݬsk?X"tlz*g4"t~T b9o:鮾KPnܞPpQT)S%6*eu0V$PVOmy c(VjϓXgZϿhb]r1쎊&]tg5O?P] Vq+J-Zx~beuvAkBS WgMAO6-ab/ 6u*/Jz F(j( &;Մ:@~ަ 9&]C,#ij`%UJ\> endobj 23 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 24 0 obj<>stream HVKo1~mq=c{lz!PorҦJҪI \Ì׻z[!@(5}=|丞> @ECEz5dֆm)c9AO9@>UuCQ JTd+ߧf5U\y/Rw-q*+߇V)\. DhE(c{"lQ;SZyڍ; "팭3u3gAeEû&-hDӬR*J[,Ŷ9w۬˂aX+|ĸie8Nf-Cڙ4@,y > endobj 26 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 27 0 obj<>stream HWn7W̪7hvhQ@qTn,|u %YcNx{sk-MUr\ѕ_LD\ͥ&gzw d1&LGDR~xpuy.)+5bĦe}84W+?&EHEH@ég;l i@;#%d ă1B~n-hUgARg!0@y '4C^=S ,,,g k`(_y%gq($,ZvuQ838hyu8#* yBM>fgN?'IQ~\4 LVK'UhҪ;QѶڤ+~O1ktT,PADm;K8S6~Ð3)~sm䅟؞>0`Hpaؤ5j!)1*Jǻt shZb*} ^{ĎSJSoaijg :}G{5 cWxe u_Q %:B 21C =TrE{L\|S253?ӕqןLJHJlΏ7zv!,`nb!HiI╝ӰlpPTB4-h첡V"}ؿt0m8p|* SY5-)J u`Drc&SjVLKG]~*PhзOD/I;IV~!y_cڞmRAȾx ,lG]`TL9$prL66l?wBKfh5QÖ)ޟmfe/!g.*W`glv)e1mh5^Ϛ $v-"0o.kfn=tk)]7s`j+;em~\8L+#ŝ { 2f֣x:_kL^^ 9`O& 8Cdۛ tB)_Pqq+MZ[Zj꽣)8`iĦ[Q0F8>'pa%<t5`Օ&D=.X(2 8{ BeTXyt[JAAiɶxD@LcimQLj{Aۃ4AoȏGs@S("rD&wr%w*{ ܆΂6 n]D=NWsJmtN]뜏#b\ 7m;.ke+`mvGim썸ҵ[`uṖ~[ҫ<΍(bD֮2;a"F(! i 'lq ,ޓ c~EkǕŰZkS'OAv`%fm͹G[Sa6(:uّYa?nkhKR#:YN&[Ȫ&{5Bw4B^<];DXC(:H;qJd!RތfРlss/ǝ ϐȘ>.M3xSRN|eT񛲄*W҆[[Nj$=jW*0(}U`YzPUX* ¯& NbT:!5wÃpf^ c7z1ܟ҄ImϠ endstream endobj 28 0 obj<> endobj 29 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 30 0 obj<>stream HWn 6Wc5-X7z o6C$?(8 9}f(ԃ*?L_<,h:"9^uτ>fX^ůG/ѩMZg:/Q})ju^ML]}^_ܯnŇq$OXݫޭ/wm]I >7=7r^s`[}tN`^Glq!c`>ӺRx"Oբ޶7~v.%s4-n- P8tH>OOСP9\_^rfrJQJD)g, dj JynņK@B- +$I ot&u]uȶYw6eVCqAmJ:똻~LE*YOaӃ$&$ؚ04&3FZJFCL ԕr%skN($!,3 K JX@qU nvD{hVFB.SQc#%b`%HgOLq0^( ;?ҶFf=:дc8Q>ʞ&eբۡU̴T+b0/Ui鐋Cd_ "ʀ\hmGzz@/L鑶 t \-3:![( 4½hb[}^_ܯn5F*(w>{ŁL8`= &X͉d ĻݝivAsMCuwO bRx"OS;0кx6'JDL| $rk['h-b˂]ҾUx2GxXuSluNzdm,hx0AWz=q't(.Ѓt`Z8͛`8.RajM:y)`MkYSyIjIsrj81j2y!h7> endobj 32 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 33 0 obj<>stream HWˎ6Kf4@E(0"xcIЯ(٤lYAX{xWb䥚v9Z9ÿA 3_glnV2ʘ \|]Wwt:^mVBrǂO#b6/9L*tMn؁{)R:IH., Kd_jhއme+|坴.`m‡LUt\Ҷ Qq{~!|Bb2~X9uڕ\Œ^/?$k'ۢ6u!!٫6/in7Lj8VUR կF2GVu 7E2G-?e<"ۈjj<1jo1zjQ>[ȱȴ cb:ٞ`6v^J4%v=E9bKn~ޯW7pEn?nn> J#$>{W"U3R4% [t%N'@3)B?,. $-,+$>RZgzk*N\N\2v'|8}&sCjuNT)/M:6 0Ba՝d-( [zAPz }_vH  >dNqm%%Qi/;SWvHE&jdզOiuvy|gW֦~R c0v jţy< <*/5T xkgJؘCDLwJi=$!!Y;vi;s"jTiS%*Ei©51 [~c@sPr(H,\9uN+!2ڥE\?E(82Rc/iRH&x\l:>&R4R}(+X+s-L9Ubsv9U{L^ccjB{dY88Cc 9vS}evn2 :eA0цyv=5IS*5?.,И`x肖@G}7p( .V;FjI|sX"%QI4C|Tn3.jpW$ݞ _X[g4\9Yo&AppYϞ/g. a+M0M܉_p(zgJSroF̤p‰{$ cjоu: Uo!ƜYE_ch⨌[G,ʉM_|Gsl IWDT/QXOT`4}~%RlЬ.HΟ(Eqpz1E@YK)2B}$&nS5jpة~0Zg6C{@^>Րyq Yc'`jV:lt-\U/!`' LPe F_D1EIAZ_`Jgi}:t0R(G:X'3xFafuSƉԫR$5*G r9Ek>dzq^p~ z )-"zjz@{@>' e3hr&v&8U&JQ3>bFX\> endobj 35 0 obj<>/Font<>/ProcSet[/PDF/Text/ImageB]/ExtGState<>>> endobj 36 0 obj<>stream HWˎE"W|$wUG`R&g0ۓ |[~sݶ'NAB(RU}=Ϟftťxz5֪YA+ Wn<]z4\~NF_LT;\M=+TU_.쪐v5Uf4L$֕ӤYFi\{\L6yiyi.U:W\\ykD &.AXM>(alU /vyW8ܰYSpk}߭nI.1n'-”}-jϤ 1ȑ[WhO1BI|y酌ȏX8z^ >HFg QKl]L16dbPIv `_ hU+SBʰ`l.u6U>>/J(վk^dV_)2$v{p+3vRqD-.6'ͮ9t0G*h$ֻ^XUH b@ ^lקl%>h["wByMVKW2p)#sy꧵GCEٺ9 W$A_6 Ќ1?Wg. OGႪx1lBja v<[^.zc"6!'w19e4ugBߖ'JjJPBHżtrR6B_o#{%`_ I嘱eW*{(cz#sB;U> 7 WIW@`vw\X@D+&7ثł $7`O# | ݀I'KO+ )]L0%h}O4胜V%E\,8E}\[UƠ]SS:%G@2}6O/SqVLL,û0 q:4Pnv9w^ٽ︭CDE>6gbi64!CkL dXOT$^:l[Vjy@EG%)0#ږtbpa?" dq=Z+ldX_C]BL;ߓRH;ae<ǴyNlV܇ XiRXܗ)sSMsEͮ$] 0x!H$YI҉J'M'ad <b,m^Arb 6VvGL{ ߠ 2Mge4\A@'L}Yi/Hh6zhŶUjH ;ahѩAnTdROVOFS7[ey I𒬐?Ȩb.uߥ ֘"#L{@JrgCmbMb@ GoMဓ!S>?bzTβn( u\L?ǍYomT a= 䎰e9]$߁.E[7;-LQTȤlٻ9j<nyA6WͲZUI& .+<\$C5OPJXrUw6 m>n#=o{q1p"?D`458EH ͡Qw#Zbߨ^F}rI %wNCH( MAM0U#U/=!]R5WUx})+`v01D|z| B%f endstream endobj 37 0 obj<> endobj 38 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 39 0 obj<>stream HWMs6WNCr$LK遱嘭D"}a%NL,..׿O˳f!˛3! o\p;J^.f3ts+|..y Yn ˚6Y,WLMAResկ}3Vo°jPL+ꃪ?L`\!Lieb:cX 儎pT7'՛*e nw6M4\`vQؓw\s-rXp z_{bI#c,O 5Zo #V(VM3r<@RdtPr-_bJH7-0yz 2dp.d(aqmr H9gu%:[%3/M9NhrbBtĈd4Pٕ%Ө3O]yQBHI`?*2O'ԅd)5%Iw#vRD̰DI֑6pCQcD͓O_7Vic呚6|kQrm7GjF@ iW5UbLZ7УHx^WPhv?CW\ H*ݸ'G?> ǹU[R#3Ԧs(!Јq,Yce?oij몺OM}mz?i38,Y]eJn* ݅g.qv&SuX]h3^5#u%]]1OD1()BVkA)AER:Z'ۮu!æwU>gjVPW D5*r& aJ | ?'}ivms7dI;n]wy`KntDJP6os(Z>g!Ge%@u]>`Vndu`S#WvUG~6DfE:nWMyCGKDIrң6K*j0E AX,Q:e%}T0 5w0 5M5 >BM-'"LLc]@r!ߴWĀCϨ4r6(ƽG oH<8pB`9lMErU17$]U@HW># !xӫ]pNՙ "EY(=$tlҲsZkd8}kJw^:ny6r}.Zc7]!0psD'ςÅFLi5G7؎(aj:;4,Bj@ D$d"w˳)NB endstream endobj 40 0 obj<> endobj 41 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 42 0 obj<>stream HWnF+)Jf3EEE ڢmJTR+ {Cn\sΝ{ynϾ03=ߜi]Vޛ[Ç P҄|}fg*l~ ⲯeSF5XVVNRW0VYg$:rxs2oSDD~ VؽFq$pC5u?ϿJ(go2UT_ 4RjMoq>Enwɾ MSv?9b^ˮ=_4;靨{Aȸ^/ /> T{e zD[%8狋S`N@ 'CK!bпᳩa9DdXKgi,X<^bs XWh ^mj|k"<ۺ!-WҚamE!gK9N:Ǒ!94w׬ݣ"7p8]!@ c9i,|p :\:eXpĄ zf!u}4vj7uA讓x9{<a'6S##o;^ZGPf0kq10{O,KpLeƻĚL6_ U``BR Yr'vI,(ylM!ha|Z>VR3m:@/e80IE?"Ye?Uc:(q\+iK0j`l`*q  S5|\QᕭO y?G;$''gO4xWH F鍃B- b2iY(Ql(nX A *A1X 8B\6 zXFyƂA,lG{^Yoe{ءK%(w>-!@*?J7Ȁ%~̻NC+|:l'D>WU@QWG T /uiL&'1\Tmu?*Dm̱Ŀ#FI=\ {}."!'3NVn.t0,mfrs U&MK-=kDIp`HÏ,]rL(elJϳƗ>_M|W T'8 íP^:N!i~l 4!u25:bʅU9y4.zj] ](:Q_,Wç ,̇n^ T+,gVk~ۦm6t)W_sݭM1}k1d#]GE=2x!G6}%> endobj 44 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 45 0 obj<>stream H|Wr }WLYZR[x+<-qB^L"UTf ~a?{srg̶ g/>zp}^Ow.fYfw)18ky2!Y&uے&|뒡jk؆d_ 'c23}Rw&14mj^>uqǁo*YgԖ5uak/CM8bnywf7fk3pN*) +2:xWO0^텞r#_$m;OKߞC{?H^SIowHK<38m =iR(Eg|a))%tK_uM= 9UFhD;[G#9;nE.^lV褐{eEv>[M mثl>}<ӝPGxDHI&#O(>~4 mhQVm *s~-j,nA8Ib76yC`ƭ^rCkA7𦾼zS C箝gƝ7eZ8LNpzON $g;Mk( yP65ā>bz2+̢Sx)8/-NݠoHGl QfB9A/ܥP(5I8~QAղjy ]FE;w`s}Z%0  gJbLS=~ UϠ*$"<@0 OtA"x~22 Ά_7ǿ'ћN(ſgmkH}gA,\$4!Kn}}0qS?s<.hO{ ܿ[/ ZlA2Y2f =lYt0YZ :6'X͈6Ad ̃~ij_ xI瑑 e70 >(^ZGĸV878 d2ǣL 0/DB`u3ߌ.N% ,),>ɀECVrvcC_ZُUrl=8IkAuXjI{ϻ"Xx=9jOb鿼ކ'lme|bi1@LI LޘuV,5Q&:lʘ؝tՉ׫ vR:(ilV I Z{QVlK/3"Y3p=g~=QՊ\oTFl8Wq*MY %s. Sլ؊SzpouFQjtISܕ*5(=x Vuf׳Kv*v I/ciwq*]Y}clIDq㢸Q9L'ÜoC!J$ݯzULǠT1_AE{0:jt|~ $0 endstream endobj 46 0 obj<> endobj 47 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 48 0 obj<>stream HWr8}W 9č-xl'd*V֖3DKKWd7OnPR${\e@w>}>ތ~͝Ù ;/oxZ:+Lu>Zӳ,ʲ1ݩOmBJ8=?Fh+EVYcOw^Uum6wN..YKCoū+jMa'lT1Kv7㌦8amV~%0UXuqF'ifn{v^^< 磷g=Y,IA$[F:T]K(.mqVMɧUF>D\4ӾOSєVB1zJ{=񚜿 iX?ֿ|EӴU^w_aN(|bUs"%ꉶ( Nq"s?"ӣ,T+Y Zz\S G!M[f<5L5%#{rr"ÞZ^\}QO҆@ Bu=eξeBrCTs Sv~{בp< 4 3RY4YPUB^U,u VwW %r=Euh5_#.Fٌ2@W=`T`嬈Q `Z`d`-3 dTg/W8!V Y!8Zb0lhgň&GQؔ'y &"˃Gx8͘Q>%-Qz%^I^r>gu_D}":GGEL̥n9%ssM\By jKzNLjFTtЂBWn-F [Vb;gޅp̪Cf5m>,as+"_?-e(>keay鴞qiFнlYlǡ#չ˔X3w$>>ќ&U܍G]gAw%*j+w%u))^g[GCgS"HB sq;T<2-? f`Q~cUZAPɈAMb1-h(zOT FNB]f %CL.Qr 4Ooup?Nir9ܶ[*BQɜ=#3C06k5٭{i;\rZd'b;3HIn@ nY83tPTps-w=Q*S3ľA3@kVHf,\c,Y?dL`P9~UnfPHo&YbIRqbc>L5^Q `CViuQ͕QG6M-sM2)U%aΥ?Oj1_=AJP ̙`/$X _, $sq{Q-}?,uBE5?e=b(C+"9ЍU>R7C䮚_:M]Q dpru84|^̔D}>ۑd 0r^<$ÆD-qHGU,)ׯoA[nW%AbDhA~X 3ϲndRgdhSK_sDլ%,$jUiWqNHjw!!A %wAW|HlDWRC&'(l"~vꨜF\X:HhŠKȬ"b1]jP$jրbq$+qEIQfI!?Q=5Z drf20ԈXُE:T-&A[}o1P%l̜vcP#m B7,Nfr'̲͖_Y1bB9s˄5nV+uW)+DKr0;_&uڝAKrIF~D:#T bLElE7ݭ~*Ȼm?ޭ{c9~z$*rkn>)2B5]6LnYJטs1:[ endstream endobj 49 0 obj<> endobj 50 0 obj<> endobj 51 0 obj<>stream HP[8]:/\gϽ:{lJ0E@Qlv?~' x{1rc B ELHUHeV>G-py)3(tA& CFԔ78C% V7:x$⌦&X5V{M-\O߳qKEJr zvoD[ofeLOGa2N+kQZT_L\kjvۘ'/ &貝ɻ+NM_b{s"JFD`b]gSHu5ݜ;?>:ԏp~[}20ă6Hs&W[N?7[G,"EyX88q;lĺˆ,iQ?Ò@VS!|!o?LJl>N4ٺMRSz? 1,a'W6rwc׾e].ߒinl>PQ6g[' WlMpI*bipVGKlh>뷄di3E[D8X&*ţh)Mq6d¶L!_1 o=Uc~~Zr]\[ς#"rG}4ը=6p~6G%8XVQL5=#S셶J!4j?o$eJʊU7 p km<ٝ\}`ϝ H=#nQq3x%XN 3(yk4c`,"*?73KLYjxQ2g KP~1r'~C{̝E<ɔNm}!e>k1$(QJc$l$roAViH(T@9cLL46A|v8nᨬeI T:!%7|w\חs:̂I-u~Q<İZy%5 J"N7(O֘ )#0h6z#u>璗_3 lA_ֽne3y}:;Ȓ̪a1]Yl'> endobj 56 0 obj<> endobj 57 0 obj<> endobj 58 0 obj<> endobj 59 0 obj<> endobj 60 0 obj<> endobj 61 0 obj<>stream Acrobat Distiller 7.0.5 (Windows) 2007-08-23T21:01:44+02:00 2007-08-23T21:01:44+02:00 dvips(k) 5.95a Copyright 2005 Radical Eye Software application/pdf paper.dvi uuid:95f26a86-9547-4033-bc7e-367a35527daa uuid:1bec38e8-e050-4f6c-9d4f-acc564f4b367 endstream endobj 62 0 obj<> endobj xref 0 63 0000000000 65535 f 0000049105 00000 n 0000049231 00000 n 0000049363 00000 n 0000053149 00000 n 0000053275 00000 n 0000053428 00000 n 0000057201 00000 n 0000057327 00000 n 0000057521 00000 n 0000061262 00000 n 0000061391 00000 n 0000061575 00000 n 0000065391 00000 n 0000065520 00000 n 0000065694 00000 n 0000070591 00000 n 0000070720 00000 n 0000070864 00000 n 0000074720 00000 n 0000074849 00000 n 0000075033 00000 n 0000078775 00000 n 0000078904 00000 n 0000079028 00000 n 0000079897 00000 n 0000080026 00000 n 0000080171 00000 n 0000082006 00000 n 0000082135 00000 n 0000082290 00000 n 0000084543 00000 n 0000084672 00000 n 0000084847 00000 n 0000086929 00000 n 0000087058 00000 n 0000087233 00000 n 0000089131 00000 n 0000089260 00000 n 0000089353 00000 n 0000091269 00000 n 0000091398 00000 n 0000091501 00000 n 0000093317 00000 n 0000093446 00000 n 0000093529 00000 n 0000096297 00000 n 0000096426 00000 n 0000096529 00000 n 0000099013 00000 n 0000099230 00000 n 0000099500 00000 n 0000101257 00000 n 0000101419 00000 n 0000101695 00000 n 0000102755 00000 n 0000102892 00000 n 0000102927 00000 n 0000102951 00000 n 0000103011 00000 n 0000103138 00000 n 0000103246 00000 n 0000106739 00000 n trailer <> startxref 116 %%EOF nlopt-2.6.1/src/algs/stogo/prog.cc000066400000000000000000000157111345435414600170200ustar00rootroot00000000000000/* A simple program to test the global optimizer. */ #include "global.h" #include "tools.h" #include "testfun.h" #define STRLEN_MAX 80 int main() { bool AVfail, AVflag; int testfnc, dim, axis, i; double AVbest; Pdom Dom; Pgrad Grad; Pobj Obj; cout << "Global Optimizer v0.1" << endl; cout << "1. Rosenbrock (min=0)" << endl; cout << "2. McCormick (min=-1.91)" << endl; cout << "3. Box & Betts (min=0)" << endl; cout << "4. Paviani (min=-45.7)" << endl; cout << "5. Extended Beale (min=0)" << endl; cout << "6. Three-hump Camel (min=0)" << endl; cout << "7. Jacobsen & Pedersen (min=3)" << endl; cout << "8. Poly1 (min=0)" << endl; cout << "9. Six-hump Camel (min=-1.03) " << endl; cout << "10. One-dimensional (min=-23.58)" << endl; cout << "11. Kowalik (min=0.0003075)" << endl; cout << "12. Hansen (min=-176.54)" << endl; cout << "13. Shubert (min=-24.06)" << endl; cout << "14. Griewank (min=0)" << endl; cout << "15. Levy4 (min=-21.502)" << endl; cout << "16. Levy5 (min=-11.504)" << endl; cout << "17. Levy6 (min=-11.504)" << endl; cout << "18. Levy7 (min=-11.504)" << endl; cout << "19. Rastrigin (min=0)" << endl; cout << "20. Trid" << endl; cout << "21. Perm(4,50)" << endl; cout << "22. Perm(4,0.5)" << endl; cout << "23. Powersum(8,18,44,114)" << endl; cout << "24. Schwefel (min=-12569.5)" << endl; cout << "25. Shekel (-10.0)" << endl; cout << endl << "Select test function :"; cin >> testfnc; switch (testfnc) { case 10: dim=1; Dom=Domain_OneDim; Obj=Objective_OneDim; Grad=Gradient_OneDim; break; case 1: dim=2; Dom=Domain_Rosenbrock; Obj=Objective_Rosenbrock; Grad=Gradient_Rosenbrock; break; case 8: dim=2; Dom=Domain_Poly1; Obj=Objective_Poly1; Grad=Gradient_Poly1; break; case 7: dim=2; Dom=Domain_Jacobsen; Obj=Objective_Jacobsen; Grad=Gradient_Jacobsen; break; case 6: dim=2; Dom=Domain_Camel3; Obj=Objective_Camel3; Grad=Gradient_Camel3; break; case 5: dim=2; Dom=Domain_Beale3; Obj=Objective_Beale3; Grad=Gradient_Beale3; break; case 4: dim=10; Dom=Domain_Paviani; Obj=Objective_Paviani; Grad=Gradient_Paviani; break; case 12: dim=2; Dom=Domain_Hansen; Obj=Objective_Hansen; Grad=Gradient_Hansen; break; case 13: dim=2; Dom=Domain_Shubert; Obj=Objective_Shubert; Grad=Gradient_Shubert; break; case 11: dim=4; Dom=Domain_Kowalik; Obj=Objective_Kowalik; Grad=Gradient_Kowalik; break; case 9: dim=2; Dom=Domain_Camel6; Obj=Objective_Camel6; Grad=Gradient_Camel6; break; case 2: dim=2; Dom=Domain_McCormick; Obj=Objective_McCormick; Grad=Gradient_McCormick; break; case 3: dim=3; Dom=Domain_BoxBetts; Obj=Objective_BoxBetts; Grad=Gradient_BoxBetts; break; case 14: dim=10; Dom=Domain_Griewank; Obj=Objective_Griewank; Grad=Gradient_Griewank; break; case 15: dim=4; Dom=Domain_Levy; Obj=Objective_Levy; Grad=Gradient_Levy; break; case 16: dim=5; Dom=Domain_Levy; Obj=Objective_Levy; Grad=Gradient_Levy; break; case 17: dim=6; Dom=Domain_Levy; Obj=Objective_Levy; Grad=Gradient_Levy; break; case 18: dim=7; Dom=Domain_Levy; Obj=Objective_Levy; Grad=Gradient_Levy; break; case 19: cout << "Enter problem dimension "; int rast_dim; cin >> rast_dim; dim=rast_dim; Dom=Domain_Rastrigin; Obj=Objective_Rastrigin; Grad=Gradient_Rastrigin; break; case 20: cout << "Enter problem dimension (two or larger) "; int trid_dim; cin >> trid_dim; dim=trid_dim; Dom=Domain_Trid; Obj=Objective_Trid; Grad=Gradient_Trid; break; case 21: dim=4; Dom=Domain_Perm; Obj=Objective_Perm_4_50; Grad=Gradient_Perm_4_50; break; case 22: dim=4; Dom=Domain_Perm; Obj=Objective_Perm_4_05; Grad=Gradient_Perm_4_05; break; case 23: dim=4; Dom=Domain_Powersum; Obj=Objective_Powersum; Grad=Gradient_Powersum; break; case 24: cout << "Enter problem dimension "; int schwef_dim; cin >> schwef_dim; dim=schwef_dim; Dom=Domain_Schwefel; Obj=Objective_Schwefel; Grad=Gradient_Schwefel; break; case 25: dim=4; Dom=Domain_Shekel; Obj=Objective_Shekel; Grad=Gradient_Shekel; break; default: cout << "Error : Function not defined" << endl; exit(1); } cout << "Dimension=" <> params.maxtime; if (params.maxtime<1) { cout << "Warning: time limit set to 1 second\n"; } params.maxeval = 0; cout << "Use factory settings (y/n) "; char str[STRLEN_MAX]; cin >> str; if (str[0]=='y') { params.det_pnts=2*dim+1; params.rnd_pnts=0; params.eps_cl=0.1; params.rshift=0.3; params.mu=1.0E-4; AVflag=FALSE; } else { cout << "Number of deterministic points "; cin >> params.det_pnts; cout << "Numer of stochastic points "; cin >> params.rnd_pnts; cout << "Radius of attraction "; cin >> params.eps_cl; cout << "Parameter rshift "; cin >> params.rshift; cout << "Parameter mu "; cin >> params.mu; cout << "Use the AV initialization (y/n) "; cin >> str; if (str[0]=='y') AVflag=TRUE; else AVflag=FALSE; } Global Problem(D,Obj, Grad, params); RVector x_av(dim); if (AVflag==TRUE) { cout << "Enter time limit for each coordinate direction (seconds) "; cin >> params.maxtime; if (params.maxtime<1) { cout << "Warning: time limit set to 1 second\n"; } params.maxeval = 0; params.det_pnts=3; TBox I(1); Global AV(I, Obj, Grad, params); x_av=0.0; AVfail=FALSE; for (axis=0; axis> stream x\Yqv6"g,LCTH-[VCzvqQX` ޙufUg. AouUVV_f۝XN^:~ݙLv?vߜàSbqNӳ1a1a_D؝:{b\|0oG`u_o-S h?%_Qf:>;Xc<&F5~Wj aC%mmy#.fygoM-n"OձRU}W)wEUWiprOT Yq %wGm?/w\>gQjIcAyG+cwdAY`RiZ[x36fJE>҄#ejjQ-pKs\_;t]C0"pS Ⱦ#@%51TB2eA.()RjvR.DQ); N,r1,U03H I5I&+@%/C 0l ؁*sq"b6aI`I, 5 p0Y8_JX2~쿁Al`2UZAYUw}G|_#ӻ`f ʅ:8u ;p"ek)}TwfI7@!Gך?݁-B#|0$VNzʮ갋X-Bf  nx]_3S4t_m+SK(їgt+{f)fSgT`<5;'URcCiTF&$܏ur+*SW9^Cfb6EN@U9d}IuJ3"2€]`O[t`FM{5#oxtD!AM̴M641"`#48#Alnư*$=n'_ 7ΐpz# E҄ٹF aX7+7]T~qx ~B-O.6jهKdiĈ:n#X 2lJV񸩒Fоrm37bU fkFjJ\P]XGT`dnJ'NFh .3?=r0T >@|+2𺷐 X011>sFR l g%_ҫ-RÑ| d #'ĝ _r3q2pS! hMGJwJ+\1.Ap۔74Q)grq$P,͖^1LeL0e30 bpU.UT)mBm `yW+C0GYWU'[C0Ċ 4)/ e@l5$ c$>:B=e5K+ zV #@=QgjD3$FgQX8_VMH $V̮NF' y Prv]X#5w8!i|z/2 7erAZ[ 6AQ H$`jCry&)*$0TCM5g4x (q/VҎbzlȪ= ר' Kp~8BaChݴ\ EiolK4Lj&ֈy"8ll?"pPL6Vra)k z.WIұ EVi"' .px(u5%J,B$ZC,-ʲs,I!ngg@Q'v17< `r"K kSQ΀VO{)EǔB]U1Ng )2S"n|ja#i$6KH;^ٍ`n`&3guN[\-lGkrcz% z4RE֪cͦ\TI|w],zUũ9R4AiIHGW5teM& qk{B#Y_JŝG5]ʚU+ʀU;?U:a "pګ>4$2B55r9vZد_­F3GVCflscW[٩]fiHELMBe8zj1w^ 2r*<&:!J{@ UZAeX\JY~f䦞 EYZR ~~oDNw-XRe!P838t&׾Mc!f ?tG]8eUYuiut +MP{wRΰlXkpS.4ҵY7Tɞx ;0ZGs5Ko3])3LuĹ<{[ky89vk9!\\;dk;̞ fy7"?OТ 6UTpeaiJ1BGP!*0ꩼ{7BJNUntz<8GCP*[Ibf-ʳEuܣ=<*8#Ĺ.Zݫ-[ޅG۠O)ESLN ؑwӜm!D=zj[ Uhull$"IHȸΎ|Cad32L/`f P -P ӊ CwƘ uYxBJABİ!QmyԴ!D秠ꏦgsC刏䋱-wؖx]ܦscc-bb#)Ir.)X!<nA|]UZEYWUT4 !~6Uxكʵ0NAkFۆ6n|c7X66.&[kr=t+ GSa- ks۵'YZB\r5GƟ8=x uy/"GՍӘ m¯  UZpD1:[oڱϗ4vҲ n[ \DLG㢤:W_w$ l0s{#ЊLrvu$RyYȊ0: ARLyks!b0i'Q2%agG>ޣ|,tM*$A%0W^Nz뺺z9оJ] ϋ=7LsmxaF#Ll~+|Y@g.I#4vu]GexK^4;+x&,ј! 00'96R?Ncny(VW\n\?p)SC@H5'BY7x4+!3' 1N;34̝ySq4|-U$^Y>#lm8۪<~t_u,뇟 .0&+q)-|(-3ǧ %L#;𴁔l7&~A<,{0~ܠ,j7ӍP{ |Zw%_ѳ-@bd&n{Ml@PT'!.e`oEM{2y`.bH],R5fvfy޵0g@t~JH훜 XٕkVi<[*O ®5]оhAX `sAs]^>;-vPVO @y, >E#:cƐN #*rh6m*jǐt1]J*ϥh.M,*7v)Ÿfv@lI )Hs&*\V$6YK l O+z3!rqS2!SLm AI_ZbgFB7f $+4PXKa?3rƻ·bW|rcH%Hz$**3?;F 3ܦ曆Rcht2 (X*mP@FM[: %ΊL9VԸ/^q 0}(p#alLib@F&+x춄:8\x׉8 M]穲2ޙBys\lm "U& l# ]/sƅM)'3mҒX pΐm҉(hHh3f gPLUnUP R6 r $dvC}k;F@IBUfn3sߒb{gow2$OwKOq'Ke.^}s۽yrv_}]d9bu ZC/2\!=+/T㭭^}=M.JAgE?{Q肯#:?6x^'SPf1R)ҰSJki@& yDB WhQZ_`!6Rt!, w^H2lӖϓFyG[`X?B+SJVS_yZ2y#]1h=u:Ԭ H�Mo{Bc%2 ȺT c#m#Pf =C}=&U1L8c3~[JxiH=g.endstream endobj 6 0 obj 5950 endobj 31 0 obj <> stream x\[\~_#6o3 (DnJV`&Ylק}C!ΜXʿ^\|y}!.\|!g/.?O)h"/khŗ.~l~űfvotb^ w8iTPA-i/LNsTu ,/xś{EfUa }R~̋ZZZ-juOQǘd2 jx5LzE}N{dv~KWBphS&  @h`֋P05~JLoZ+k)_y^6vB]8.pVF;h2gfw;@;x`P\3 *oxC9Ass2, {x gTab[DP:}}ETlHFo 5~?֤T7_r1>!zo$* g"Xw;HTrC}$7@ɸ8S# HtdW;" k5J`m2 t|$N\5? h g21/3|0ڳWmQ]l֟`2|+ -z"(Eiw&)ωY^,)zߍt̖Q* B{G_6.F:-9۽^dw"bܢ^zg%t5cԍՆ A:[;X>Q[fȞ}hey!t6Xb]K 8828GXAc@`E]1 лc!<&y2vD"apuPfDrݣP0p|W wMBVEV~f4a'Tg-2[ v~+o+:@]5L)=x$ I4 \2X(@HT&w J6 "" - b]zS920}^ 4p-4DyM7Qƥox~:3Y2q" A.gЄͪ:*WRqc-.PFpoQ!|Ӱ8uzeq*O)SяM ԓcF 8\BY쩙ۮw fz w@pO/~%")ϼ#nlP2JtrvRd UڭE,JJW/v&>"C2|40yJ# U˺O8Zpv8op)l_r" 1B-Db`Z/rNK&Jo9y;&֒}g3猈n Wň/YbAޑK|Mn(f1jEI04A Ot[SP HPRP \%[HEZY.|N. |k}"zAI6*v(dذ`1\}L`Xe9RT_$Zf2D*@лdl\II04>6 X7uI΢"P\QF0(tn`T\5J WQP|Tɠmal#TjуF;%- d1l`7yw&^"'^Ƚc! O,P.#$Ij1# a4CٖxLct"N2 =#$\xb7L8No I45ս x~OxyT݅xi1n`F$wsg`b 3OZ$3ngtoTtܤ5`.n/jQ9#1rwu$єp~hD6tghޣe'#JLd &n+eұwHn/jxCd6󤢛R A DtKvGUkv MSw#3"FL|QCA93ZSRMӚL ޗq%:5<&%p $CJcãs7%7z@AbW+#xٻ9Ub'ثbe/ZBOu92 ɸI OF\y5 ?_n$tnǦVm}Z@*WhL x):,sBڸ&AOʶկK_g7A[vr%q62unK jP:'+06DAxg Q;!1= Ņelo{XrÌ%#}4֕@%JSl=U80>1C ~DwxC&2Vu<ڮ ט,e;ܛMo t@ !WN' F] S X ])aro(/=OM`Qyi>$i!', ƿ0J Wb1j\ :B^ < ,!VmeܑO@0U/}PޓcδD7GrWT'X>$]k}M &=D\NjXd ɦsǯO0ӭ'Tc;ij;iHaw_6̇V)ᆫt>v #뼳י̢9apK`HC qVf 6VoGk^qDkC?cxܮ3Ѹ\ᛒ+˧~3}:j#5gL* GQmۋةsQ>]ظoYqhO჉}H6)bÒrF}`l`z}]%)O1s@?Ml# ¦8ւ 0b yXlZM~IiÓrcjkzЯ}/\0e|X:TUu4*wEnlmM0/`RqlŪnta yBrhwvɪm-pf,adpb%+֫juSvVg~P's~Rzsݸ9/jܵ; hK23űBȹe*E{.BޜҮ'rnsٹ,j*Vq>MTph_WU_S7YG@p)_H+Ⴞ3֠_Y~+}uk \t.+d9'`TZ /"cw~ MX| &>k?,Ӌ]abL¬ji <4L0a*mO2dpMR9K,WX< )kr7~cm8&m2x} ۯ'ަ»@c IDlǿ>ah6M3ٹsqFq2*}q!8iJΏ"vEϼzkm1N%!  [T+7;HhBzctɼ"1141CL=1V7o?Kll]2n+$LU~HTCxb`A 5(ypEbI~dڤc#uiV :&lz f+4[D0!U譟[dHjRQ,LOqXȽ? 托4J{vgv5xع=w[RW Ur|7> 0|L`oY8y,a=  1sn.ƨ 6*~Uv8FWTagBvqhM/a &{Qo-3:OC)W#iO †RTc D/lV}ҡ'ܠR)#g:CLl T~3ʇ2 %މqF8ѩN(8 塭uѓP[qdU3;3ԗB!KN`~z`]aSGѓf}Nx%|tR){HoY%ښJ(7:69Ջ6zph#bR=15ۮ;49DZ@BxBs\J]3{=tjK2 ?]]/Dendstream endobj 32 0 obj 5104 endobj 36 0 obj <> stream x=َ]q~yA4G/ rlG ?~HIJEf>UVwW{gDE!L^kηWէ察w%Vщf8,Lg S8p^ TZZXJZ{wx?L9O#ʜw#Xon:C9|CEŭC8BF++0nJY>"(9 B!A$4 㐝/@'[8e!A8gQifD%0g,Tk*YejeCnĜQ{')nxpJC8)pqSqN} ςSȈW_ΏE +Eaϋʿ y$O$AFC8VآLLIu!@PR=8cogNVfQDQ2$d6:3($Pg6LLGQUYtஈW75Qˆ@2mxJٻP'I|;Id'@aeI)$PyaF;!JjOQocMd$4soC0[&[ Mɫ.F6 K,FͤKVpU7։;hnnѬ7RwMdɰ 2`x^0TYdi޽X.+Î|aПP͋x[|D!ytڠD#JoɽK|'QgAU)P#凞BTN`GyK"DYkbWshf$`t* E l[ٿXNդޓgMM LQ%dř/B5p_@/=Ʃ0`収4+^%K)SRI .>ǧ :z3 G<tPN7/`+HD)Fe\܋(@@wx3b]ymd=*$=0aȢJmr7UxMm8G78ü+ /2.`+d dub&WlL&o28T~d́بHku*&>еS˥ ]Tp`[8BM0uKõ@Cfdc߮׻CO` YݞP6/faQlT80ubU=0:/4MoMdfW(Utrw :kPZZu:Zgѵ/Pk>(~5;Wݩb 6%x@5{Zg&|HnCF⺹0%<0CwfiBECoûqvԵA=RN\E &dd_JPƂIɕ%e]i%($nr(;c:֮jXQWOlD@ָ@'uGv4Nk% \v wrt#<^>d"@X=kp|0.n02ȃ(<]%6n)`d [g9V{b 9NK覢[j( 8Vh %FsʪU>iim44p."PٳȂg-(&ҁϳ;̸)(G_@+Lx"ҭ6p)󒡓9GnLCiMJF.P#1 Qt]M&n~} $""Mn.{8_WJd˧i;-:0T%<J>}@0K3޶vym,qP wh5 a$}HGOqaׁZ{ ՇKOc.)t#5}v{85yU#\5 '-mBt=k`g4ֺ!iem'Omߊ5i8!f̛ p- dNaK<)L$g+0 /`aQzU+R螰nwqvT뤩T@n2kO[T6zJLzor<`Ɖb_)}1ADŬ-{5{iu 0t~=1EST1ãOSY,%a>#uːHMMrfk2eK$#fVJńIZxGQEdb\59u{SkEtjIN''eHpfѝR5KеY)8}ȦW"+9y{`}l ~ .s&?Mſś4]Ode_6p8Dme2kʔWbH&&q,y#P|!;1Zv͆O݁ɐ |kdqT4U`f'a&LXҾ)-)gc/!'$W:AA$✕$܂fƓF3'lQ1VqN,pac2Y*օv)12|ΝX5ȐB"Sj^--lGXʻ4ωDq(M6.5,^[azt3~^2\`ekEάIc>bJ3?A>HƇdwdAe0O]:-'"u=\&aQO@dAęе_ukk9smև b<>p|CN>ɡ૜OXX6 ɪ&Fj3p?W= oK;)`8RIi>2~w1_D y>@ dݏMչq ȏFT7j_~EЂpe?74q,  V'&~[S&(e%ڥ,cz .P0ZeM4BM[mPx:*9-Ll9[xM̄>PʎRB:٫WROpEH (7N 9 \"V)f UjJ&Ub:vmCq,Rs}>4]J4-!5{/FXCk|*4@diTZs^/: ќV]Go" ;{afhIfP5)I[҃0;iI[Ġ9ii}׊_5^ k?H{T} yI-B%{@ h.KX=޵,bo:NbF<^JU pCz/4ƥkx`nhehG]q֦fwOIҶ.^9RCP,UToy[hq^T8 ̀j<96ܫsb+og)9 {t\Jﳱabʈfҷuxx߲Eػ+dgU2Prsj 2^R\#X ƨ\[tSvVu]XXl 2Yhh"v'"4kw%L{h+}:*9Ѝtz8йRމ;)|4*n  Hɮ`JP2`!!ݪMqN ;W_.mwtPȠ*O}@4s,6$e'B0qSqͮKb 1!`W MU-=Qbz$${&4#y/G'őpEk*QBjPbS|/" J?w-UGkTYə'] QwW|ؖ=zFnΙ[/p=|f8G1Ұ="6n b8/+xAx"S"ҦuCR#[;&x`>m Hl3T@̓fDh7d3mb;R3T9$Bif[UitڠŇ:b| `NU.9{q{Yr#]=K L9Ō{MK~ON2S^np#I;{1g/ө)bN UٚXUl,ɣ-~OułҊ涵iҒP:~j&ul*Λi@ĸBr8m`F"2@#伓Gp&IlļQ $%lREW[p BU7/*jݸG!z["z{SkDʔfrX},<•洝>l{Ey3YQ =ѓU@*3Mgy0@u'&[7@aO Z 6ƳC |WсՈ׷Xcɀv ԱJIu$j}->.aӸXb1{h]7nujoXN̰dztoStQMn茟O]}ky}}?׿'4(x )}J5Y>14͔XqyǺkV.d8Ɋَdm~=b.BDnMU~stT&0/Rqn˟ 8\WZck)lթAjx9DӮŠִP) ^dN}I]>J=v!.57Fcie }uXv{h9ms^ճyv0a\x❚8/3r\A߃ XmnY/1ߣ5Tk=-Ui20Y(9mtm4~ZO 쓴Puc2:ۛ_5cm,6^ꄢl7->Q&/.TR/Ԝ*0a: .G܍6quk ;:kԡϘH/bekDR0ǡ8E/͋:1g .> W`t+IZ]3՗>qΖ? 7^=g'Gr ;s%"DKs6㜿#Q>ض,(oه-;,HV0IIQ4՗;,_˹fL]#SBL-2폨l+^ _Gc OmN>zE.{+<#2%!/.JF0De{ՙڽ6+ccFRg9Va=NM- [kn)YqcE(Bɜbm'$vy90u;|_33yizq(?E#c қC JK EbK[ sVo/ɝe<IvȯMz$4*-)mBM⏒6%m]y퇍4|N>lݤ-;U؞,u81?Ьb ;reْi=K| *"zʫm&&`Q[*DK9~fgr ڀe~R<"w韑{5B'_3.} =.Ԙ-Ns?È=?gl֠;1 _V_1U< w/-_/…Ti&d{ZsǪRYGZG*[W #endstream endobj 37 0 obj 7542 endobj 43 0 obj <> stream x\Y]GR~x/Cj_,3aImmblz2kͪuvBY2rÕ?篟Oկ'?<邫W_E_)hy$-ݴkg^?opΞޜ|-6g:/0^ӷx߼gzN[uz~=_M9|қv-m!?-z%+"'ϛ0-7c`f70"Hڜ«䦵wWǷ#*o#IiyPyl:!ڴNTxzW@<1K e<=?lOϪXrpY%MY Rrh3|\Jpz Bhc/oN+v]oߧL>lB oA u+>xrs֫|]rQm SLw3ւl8a}0=`28kյ4&7x386iAߞ?y9N/xvPbhb6́FE~ۡm{aJP0Go DXsOUYE4ara3.ښ.A)]L"kӨtS:*@ѩFq *D2<)0ݪH郜M;̓j4%fAVy_ңj1En+-Cu~K A)MNˁ/Wj/B,9w N;M!|&H. eXu+ `sAS,/% em7>&ݝ/T y0NٔEJS Q]~iIt]3zĤ,Tk u"i 9Sߐg^L APOQozv|2 BE(l>:Gp۲IB>/vm/gr#(7QO!:H`XN0x+m20Cp୉5#4ZśʧaqQgL3ݥGbad3>6P+X#Χ:txE 5X&W(m"=*(HmŃ댤YVYO;Z,!ό S8jf WJ^1 ȎjHxۿ^d`~gA#787P 9ѵ޻:YOpbAћ?beBC mc'~S#MA 0Y!@{>S%4|r4(v#Vp۴|#ݥNdؐ-_=.dBZk6%/k=Pl6sz8'.4ćݕ#$GC(K2lx9ɣ>#XR6iO;^kji(>"P1R1ϊBu=xUw ,4_a]@.jŠ!ótQa 8`kJɆ#}.[ٮh2z;ft&MҸGgXk= Vڑ` R L،PRXBN0elZM[ >ˢ'0$ъ&ǩ5l6QZb̟x$2T\YkDDsD\WKSmY@vBDe`>(j~H;HLSe>L ny(a .Q*}c/0("I<*J93PROX˟7'eHK/ KEG!\c0oʼ gt ÅE4ǜoƑz.6%ؔuQ9IO?,ȹ@ug  {p@/ <-851X^GH!$šqh=<9Ϲazl0u FmdiLvJ j۟D7jΚ]CYrhY q<揥ⱚg[Rʂ"@ʔ}&4ЈEU0='j9i*#-TskՒSȩ2wM|Fz,ƜQUb3ӝ.ﺵWGdJ2 5FuuOQlq/m$6{Me ,ުWi_ݩ`I5qvI$M| | JeǑʏv4@]i:+ \;C|Hz?14|"Drfo[6F/08`7! `7p=@lI'7*)pu԰_I9+ ؝ ہ:o?ȱ.}&QJ8+;nyrʜ>b/SHL$"D;]D%3g`I# hqKTilIW7hj+(xLv:8K)e^Tpd|#k(/cz꿝EbًI*HV9Lh| /^:qM :ӌH DӪ?R߇e(- zWKXayM;5ƀṗC Z?RU(R;:Dz;u?K bdZm0 i- X]STHs?- <8|>^J.Pk83eY^K-_$ CKplNO_Y%tQ:Tm=MZuh܆l4䡻}< %?. >L;%<;|@4k>->L /m>";͑tڂ;FXg5Q4;uc,y 4&[ҁA`vt)a@O!n  {%DnZ灑Z 攁E=-%L-M3@ ,Q"_#D)z.1 Qk:ѸXN ahih k&p`tnOCH4W`ղ僱{Q^b:=5ݙq$B\-T_sC}쫯q^Oi|VZ+( qorC1ֳظOl$΅`Q9mJuAq.ލ`K풽M_ ;FfMRj:Z .jTq r}_p,z, {m:֤*m]r~uƐE~pU$4{?HTPu94+x:Pa#XXc%+~B&]Ui_)蠘<0Pta+.-cD}p3ccD,<3b-S_EM=>DITN6j̔Dvi#m%B>{bl |48Ve [Ј7*$.mbHYq:祄 >Yn l5ȗ3l=JXfCq\v3}xH1p m82 ߦvi ; ]9(A`?27WݛYxJvliOhUݾDաnր>'L_Bz#X@'c- ^Ք )ʄsnbV𠽅E*C?=mq)i$N+>ESE|D< U}))aG8<eL:ڕp &{*vh%u@pX"ؖ4mN|GmPqҌ|22g\!:<%/K>+ frҾ\iِEBJq/LQUhaڧ Dckh^KMȅVg`-<~"7Xܰ^FwIʭʸv~l{#i7 $$X C Eв #Bh?)p4;wlfdZ|YHK pyd n ~*(+8xPxl]#19mZ'H]VZX оkrIR"⵹&ca?XW,3K!c%)QrIŻt,k AIgd֭+^¢K.m1Y[хz`w+fKWfa)]N `Ȃ$1 rWԢ@01q׺Ça'j^>Ow/&g$'@uo|* N=@LL_2|}?>PkߵJ AQB~7B%2 Z>X(mӗq]qwN,k-70!rGfC. x U~ܚS1=sRI`폿ƔBwk]IeKNng<)wizJg/p׽ δoW}2[cKRcR҂۴ʵ$2e=[&d#|JG9xp qGbU>lkn[4a^=&ߗYsMIU5JG{aJ|2}Nendstream endobj 44 0 obj 5842 endobj 48 0 obj <> stream x\Y ~_3)OyS8KޤReAK+YRb)>Okw.Jn6 |>x9Or?~.//~/&!/1EzZ\Z7K̤6Ϸ;1ygD>fᡫ<'x^ >}Sg Okg~ުXev7OV;oeRnlwrV9O tnm@|XO'i6%HX<ÏAl^O^yy_L&]~C~ 18Fy:.+WewmRv #[9.2q 3K O+9F)|pYz3TMZ2R9}QqRJ9!Bv@L Qf> i%իOGS@[Qkh=}|S{5cq@<˪2 B$: *%W/7TYltk1ߠä^/= ѡ'xà~6 pziŞ$1§2rl_?@=(w3r,vƊjRFiXH&(Ãfy+$ 'f,(]IS kDw^EYm̛zQS>LF 0ip&o9#GEJPy8TMy8`''8u@MoA2~EF˕"FHb O{Ig#<<NTn`+=Yvmj /HMi<&Mm>'2\ſgO>&H gMjqU"ѕ#6 o$Hp4Zw_#A2zEjr% oeys?E@F6.z陬sU:+7_C~Bz N#Ԃ燅#``dﺮ͎ *lqhFΊ8,W+޶YΚ3Âw=PMcU YFHu͐OFJiw/NC4=S7CV)@,kRnr+t26#< DT!ǰ2*tXZ\\D"ՇxЌ!4]?q D -P`(fbsz >D@ E~R`ROPnQ@2m cKm[Q{Xޭ1J p`tCE%N< q*pᄩ%%A2 ɵd0p-Kx%}؂qiu0;9K?pܱ꫆r -,0.eݝȶ(Aq2*\[CgtO :m98O$=SS/%{ZGIaF{h܇t| l]5ޱ0Hkm(#7 F! hGft'39ƠBŢt X<ګe`/2ƉkLtl(|б0+ 5:lAdKgwclQZdoB=OxfLT ˄B|G`JmJ7sҚsIWm |[Yrݍ:1an3,5|aRo8S"06$hb\=ﬦ+̡%S:O;e)>8SAst~ h쩫{y=*n'#RFVYe([AX<ut[jR>b)TJ8/\)[Ȁ`wJ2{vӫ6=rAa_iMg w(qёKrRN\{,XC|khDJ. +^v%;ȣ{@@8F&Lդ=nݝPkl39W>Y{8?+aŌ//:rc))Lڵj-;Q!-^k-TG00ɤar,jm_.#DzhZGf]D0@ve'(TP$Eъ09Ҕe>ߖ4k?"]} pL/6zY[_FJ ޺[:مY `׶be#y/[@}OUR4D@g;nmq >h4Rzk·Dyi_."9J8'+ 箮._t#,-+zԭTָɑY_fmV\W܃) :8i7<%/ύg R]8A2(;YO% N3UV[~@0 > 1'Fr)n&5G }> W0 hb"gb +dƅ)sʰlX:ryGO V(A#zݪ-þ KkMƋ}*t7ZX ݐ=y\Lw'D#CJv)qng IijŴa0Yţ'@]=?T^4D yvpI5xM} Gv֡PC4͙t;ǗJm \GH|b``Oh0 :/3zGfj <.UscFPPPs D"M9na2&5y )"l!&\-ޒz8N0Uw5/-؀G)O7A"FI n9@@guӃVrJDAtk ݏ=5CO% 28\gfxWW?qendstream endobj 49 0 obj 3831 endobj 53 0 obj <> stream x\Y\ŕs~ӗܗ!`քAFFB\O=VA8p2f;K"{}+q'W2 .^_| R.Zu}*ϖ/khW?o⤐j^/iv?o ۽V/{'|ܽߨH =+"=Wڇݻ=5 .}eؽŵ{xp7:b??o^tIQÈ8 eҴ<>TOwqqqBe:Y`k h]vH` h +arFL[ q^-Q ewKJXf1*Η5!J2?EubTyb梅 [y8491Y0 lp'o,Ts6m@]pIBѨjϯ< "uNd;/=r6[$O!W"_U i\t}B 2M&P'؊me9.WvG]仇5qW&-(#Z [Ղ/iMg [[X 7'Dydzߌ{W-0BEcgqm;M'[Y/|v@QMWI L{}Cw/k`'6PW4*#4%s+h2mD u3#`?;~ּ嫮<|*8Z:oQ䢵nhGWIؔv } ˂\c|*J(H18\x1.灞2:AM+ӗn#t",X ngYY( m_u }tPӮP?X~ OzRH7iO^2$ <9gGjٱ: fjDÈu,>V*E#. q+-I;0odó*WO[!1H +WT804#G x[NI$|rS|mL+`̠ceM v0I֐wk6Qӕ yft1靄XL.LJ*~3j65HH,pn&"K4Cv ]tI@y۞a~n HKRH* 8V6 9C\j$ïpbђR<=x_"ohH6[DUJfY4p_*8W+k+xH{߰, LJw__}?}'w/atkxN(stFbQȢ %ߗyb׉buھEq_Yϋv5 :xR s%;m,GdWGe +:~ZepUпgj1jph}!h/{)Wb+"F-a>&\<.HJ1ר<+F8ɵATЊv1)SChJvߵ}aj7LNlHy.Ze6#R*g5A8 Kp)&\ߟ  :7gVz) d_P .H߸zs0.biƤl{kL Xv ,kPMNA|͔iK")Fw7;p|Soa<Ī4|/: 1My(.K@p|zi?v@$)pLP*V3k8XFXGQwM4m])Y L}HŬje5JsgV=؛*Yd܄bi,XILRf"#1q9g ՠW_Ch|R9Бz滳{^ :2ts= ̹{ApRnJPtӣܷHbC*vG4Pۯa)}W}(Rk%xyTqa3jn6Ca%83E CNJ{G}0{3ldYUa}uC|h:`* Jլp) RGxo}mf.̶=Z쯥N ~jj +ߍMPቯP|/;XI`w JIp~64If;Ar1'f!M*PEw- V+([S 6.VzċUY"V6 @j$1-8졛ܩg4 rU )Iڞy*H^*!Gn]!YʴR F"&*J-{r4xzV#շc{x6X1pVGʡEywk.&4}29ҋ!WyIh_+玅H=NjW'J Rl}Tz _JAS"G`s_bk72] ;EolDIɕtJBq٦GUNѢz&2IpCYOb{M6YoꇻKm#Xu!w [HEMjrBJʑ#7)ߍk\^J_om24:&ݫ[m R&Qs€J -9`UdvIXftk\](9z'>;l|:Ơ?}.Q-XoHJyG<_k~, FdkI4į\nl A+AjG{Lk|̉%x5$]ѳk*&2eVn<0A>_D]ڎ{ilc5*T>eR0 cK(՚KEg.k;DC46XR\$%):p {9mH*(+:pwc5ݥ!p =y˲!OҐy@5PS[ ~[%Kkؔ8GO"k~ߓ8SY{hcb_"b*5 @iN1eVhNmJ>!B`_E(< 5b|P₯<6 V$h $B:5T,f}b`TuBbv#c[J:NVrM%B).6 0;EW"~|봏6 - rRev oD'*m:GsǴ\ʿ-;z8S*m![՗ӷzu&rnMI sY GotӲuBȻ_"AẬ=1ŭNI+9ږ/Ԍex7puBfCkOxý^"6U)yќGo*)TK:\-r X@h#|z5ޟN>z7o}Cj2)NL7耜h 37^AU㼧+>h#3Ȱqww_vg[gWvaNTI-97b^S6/":OG$I>Cl%ץ~m`H T:7n~{zQL˿d3䘲?ru,#.XT z4 Ѽϳ vm `GvĔ!R:E}[6P OJָ%)d>v|qOZ endstream endobj 54 0 obj 5180 endobj 58 0 obj <> stream x\[sToޥ_L!&e'ƥWy@@ t̙3g\X=gn_w3K6%'w~gl {xer>xt[󥱃[Z _ZzވA)VƯN`Z7l0 ZY~"=ybof슻ӵZA Nz9ӹOq([=ɭ/CY ]& XH֥V`H)8'l4Wz{2k\'Os:UXB~V…+ F"D~]k=0 mb Zb+xW;[/}dzstR0]9_L'U&9hёB,I1Iňh Z ^0MxF-@JWz|^/+"$lTSZ4i$ĵ24Eߵ7ل&>܄EI(Y? I.oh`'ŐvԒκyY8$ /HQKo|۠B)Pw?npX|+PӌaYb|J}VnDj#¤Q@$09)d}YzOAF K)Ҩ%X;֮'|dVyVO*W_l=x1k`6vy5^m"ƘVDk/Q`بs ., MBWf6RAc٧w݅]mpvtҨݗPJ/n*,H=]i&f^V iWa$uW D~/ʍQ?}0"@4e5]u[k)+?ф95ƐeнfTEiJ^fܘ̓<|R;Փxb2fuAbku{SW x!WB[^\@ 0>;YD$r|}+9~GՏ8 EO9?=IQy>0lR> Fp! <9,.LZz4VD@y; DuQ6R|-`;HHpɝy>[rъ 6VEa.def_7h@yjʌ5Z\y~:h%X'yy`2xѮsG#S1d|mrMQ㛿Eeݸ`|{%hr&*gyXLM2)hth' vy>6U䎔OFqOON 2S˄/z(,uRL{&(7_ORa4QWL Tx8X\&I)(|NIKU:)ID2QSsg#F0XyRaa9)ȀF?֎/>w0h+ܑOz3X,]KPOPܤGKiN[RIpރŝ/ߟ_<]y;%xO%8(0q/kWkʉ(ѽtQ4B5W}Pfrӄ K?O]$huʛ/%n蘲s%h1?T\7FqÛ$z-M b}\*];]#0C /ʹMҀ [ȩM׉e=ޣÞp€erTAX5t910zM,8FN<דT:+)륭v{"h=dO *o ZUI d:;"Ӵ@qGf]˭./|;u-& pkrVW/DsW}%>Sx؞m%۟ܯg} i^'8?# 5+p<. a-Y VY`ѩ`fO[lRFA))q2ts^y:l:OFOT,eRb'@\ AA(Np5NQJ1͇ƞfݟLPDKԶRVosר+uIh9īn`б{1ܓ5qOOɩnh^[?{*ɿ&\VnwbԤȴJA~>9O}W{HRJŗoχfO@4A尳K*8Zr3TCXi jAk^5vC|:s=߃xʏ!l-#^ZN^Tc29Wdz9nI &PʴX&^ݐzl< ǐB/N >~>Oh[g3#6$spTNde/fqm@ܨ;/STlgVV&EaxmձO()KA`s='SSȨoƙtMKx׍N >o+!}sE/%K3W菛 E(&닲l5^A3f,]Z#:WpS%(3𨬨]F#D q;H͠`!;$^,SoysCȇ,zdDu1l L}W1Ma'aKr #$zlw]J۝&q䪸`:Y;\5,6IԈvk&[z 4؞Fh Sx?m8$`ˉ!pP1S&˳2Y,iN9yt屦 Iݰm/jަ5L!H{u/3"Ɂb\zz@qSf"TupU썓U p/u EvqJe".agN 'ʣtq􌨘x1[{mi۽6 -E1*Qg7r^~ ird2Ip~a,)تx=<\u2> stream x\Y7r?ݶXthwő(!E3q&P>fv(iuWD_~v"v+|{۽j}uӕowOo"_!`|;s, ~{_OH;? b. pZЛ+jA.Aj=ߴWtZvݗj1V '-R_6x3 C'fzqĖ "wM Żtju!լRg+<=cD_ՑAfemoJ Ń܂vPq0kޞCT֞VVk! Q]Ux6^=7 (Ќ(^`I ~ITp-n ly9!/^Aߕ^7qvEpr+R7ߥi7uwmл3JE]䙃*fF l~)AeuZKl\`zCґ^4S(:J,v+)<ȯjfqЛ׻j)AKi$cd+Td+(+ fً ;mw_pBՒLhKs6XmLl#QQ\Qwma0[M`ADx7mqd:4 sS,jRN^u1Q,YWc66xۏ8zTFgI>tP6A;Yp -\@eǏ*x>\( UM$koANA d!oᣆ)\ v%%G 1"$fh%" B0" P^Q1fxpvuC(Ft7Iɸq-#ڈvB'G8AXQׇlX  Ձ>4g|׹|+Ф_V+\WtXT= G+b(1Ƹ[jP+YJ.U8 h-ԶpY/]@~Dx^nu<1Mx:~U׸=2Wg"젴Ti*OMJ@ˬì\=7x8 h.. OX|ߴ4mbeќ~ssO;eczP̂gWO~çﮞi'+~z7WyLXrQ1S.fV?C Z+Xsm3v1fo3_ˊ4l`yawOmᾆ+D6Ŏ#% 0}2O[Tn1[+$% tov7늒Zf?Zŀr%\rgA~XkXl͜py-aMj0W( ڍ K J&*~/ΎKUg2K$bI.)~5SD9?}cحhVzYv/Jom_OE)I CY(6Tm><[z[7$KuDݗ #R5L:>AOKI_}R+Ç&-F"5ڣkeqġip ,APYTflb^wME!p'}yRʪV$DYO3K >#&n[;eZa"9!A.`~؝$b*×yo3 6Eܴ bi3sI`08HLv. vkTՙ [U`Sux.0m_!*\ Y`u4ЀP < 5]Xڍ렶-@IVi2Ϛ@$)5kiAib,9 hWx  j,XtFL4$)N!n$?`UAZ'W=KCdO֢aá(3WWH#GbuLj`Oc "*;UQN:*:Q, kh=hQ|\%쩂!ȗm։=nR7ơf[*zZ", ܉կ\+'A7;Тdh.Mp] 4&)<ҙ8I*"Fr@ݻT3zl0/,Q9Zb Y>,ʉkov+=,T`MPIT vVH%a(cr6ϘM3eK|C@Aq> r=7Sl1G.x 6K%-/o;3_#Zfӷ')y!b䉎䔣X;ig/JZHuB>ٌ0GR ' 61%)o3 j#A2?xU)ݰ7e+GeN/S8vY>{_mv'VA@$P@r`~hRң q&gyKk0L' ժ\kʅZY> uT3v8jmWGȆ uM%"΀.?ѻ^Rf ZFrDE[V;ܬVU,J`[rUpT":-kZRfn~ŵ4IN8iOJLwk&xڎ3fhaUJFSVGɛmr:R;0lr{k=_ H&h4qhIm%YmO+I괺KBMp:(ūnbIkZ{ PMKtL.I}xSw Q6ʉ G'-K,ּ[2.%I%I!so-#_]K_Б[,3BDb)W`Iqj8ZEi:镊s"'%bR~HݎnReb!{>asjndKdW0Hܧ[Oz´5N"pf3!P,MLɚHeb- Mtwd0G&GdRn<6i%)8Ghɱ'],QBbO!&WuBê 1U$e)eG| 797aҪ5*T]]ʓAig ;& /ӠȦ+`Jx?f6tgbNo6k"]кMO7` Lz?7Dģ >=Por5ۛ,q=2RP1{%hQ$ոORuH=-=3J`P5VWn>9>d<:XOM"ۉ@1Uٲ 3㙦腻{T7ͺI ܱqhlasOjeΞ)(:# {~> DyH<'14ZSҮ4R~)L$5ӆ{mӥ@9vt"j\*K[ ZkpiΩ=*6> PX^O޵'&DM*9rG܃[^;SCjQ¡_p^4{UOx Pj1Ũ2+_Uux/Yi|5!r\+[OqM2̴Ƌ!;9v>MXw {n-nni4*} W=$7K9I7[_+Ж*+!vҁ9@@`w' Թ"̟ڱ’\[`ܙHcJN?]-eHt\yTmM /WFr> stream x\[qF?8g/^^\|! g^KBly~~ 6ypl ^ΆOWrVǧW܍=JIY/қTm*#Wf5⎏.ؔs{JKr-;1ǿ^Q~7)  ¼C;2= 즭KޭΤWiB1.u~O&gh'[Lh%^{MY_ׅЛ>\_F[xGm.G YMxd/R%#!SRnAjNq x8GYg'/(Oa~fy=4*Ղ +sjoۤLCՋK_ʓmȥG7iӉL.B,GU ̽/"$u Wh}[`D 0% <_tĂ+veWeu e2Y/޺RTn%}Jo*7JET/h3V3*V? 0;xfNb2+Dw%qP(R˓E;V ~6 >G-wIOm0K£/\U ƂQ:\ʉ*CLMk@tQÔV?i:7Tv\ ˴t&#d$48Ck$dj$r "LixheT^ .k>E ODuҔ\)Li:~ cZ ..hYR]^p;86O# FŸ鞧nt TWqRܹye/[$[o6E]|W3a%?t$p\ Z`qϒCH޻8征IJԆDFp(02OhPalb~/#ku hUՙy>ڔuQJ-?s4 ӆM֐)!Kټ%. ߉{#ߞ#f᎚ NzUU&ezFMWT+ y%SݍU/L1UU:Y_0WAa~~ _T%)J̲ Ƣ2t`7atPaKf6! THP[胬 IΐA4iH/yB"FYa4Z}!`?"ftpĉH+6=OרYV-J c({ҽ=QEK0 OCRb-l1*Tcl)*W#NӀuUE2G2`kOӣ7U4j6 Nճ;CئgS 8OeG I 7Q@mZltW'z\^#z|pp-F0a[m:u ݫPja>^* "n4 3($8+{&̜~v`@NIv?t҄*$ L 鄧2y.Rᐉp7GB`+1b8W=|^#'@ (PW搑}$8,@}WEKfODKP =zJF]>z2$K_}ׂ^ thj"i$Ӷs /Mq8KQ փn[S<1BYh&#uЦ ğO GK*/ph 8lАk NŠc]0A-D49KQ i VrB`wBx>Cg A'?MT(Ujrdx^cEZD}p西BMHфS,`lUAJ 1J.&5)#h+lF9/ܗ*&qZ{ iI͘PukcarIOrpM{օxI]/+Y ԑM9RtT6;qCfGw9CDiO?=T.d'05tأH֬Nq\SpsZò{T|@3̀7m45D1,@DrnG}mXý OӊpE/0 :p]+_X`p)NG|>p(vW1b~4>NcfK7\>Rk]ND1QJCT3' ӌW[?6E#?#CE}c#Gou[+/47~+.Mޗ$@%XƟ@jx:%;9( D59}9SOL>MpAq'<=D~}DX,bЫrm_n17ƨ7r*BDJj,Т9%؎$+u,ɱ%=='`Di>YEdit@guan^,BE%aR}bK %Nä̬d[`,Rqº"CQD5Z! qzGrh ^.F3z +ͻnLe+D-4[ORdը:-;bBwpJ̚XjF>$ܤZqܶH aQm\!(qɺ`cEl`}!tI/j.TS 6K9ޫJ?,cszp KI'C(Hֈٛ>ejw 3e[VBb4W1OaL,WS 8hU`v ֌ iHcF3h|r*(-"$2v№# tq}z/@TAی,NBR 1}`wWh'[74f6KjֻsT1x-{=ۧKl9^1؞wY`w<&MX;=}o~9 5䦅'0SOu ahb#?'16s2WND9^ft`'g BΈrH=W;wAeD'Ӊo[{DCSbZ.ӄG,=ODo\PK ?U*'džsFI ?9yʡEؼj=ɴg~=]ZqDlA#ʙ~ą>5JXq&J2ˣ$휬FƬ ohLg(Zt.hVl򾞡CCn AtuԋhdRFi&%\ܓpV,H8Q&5]{;v^(.2NRV-c y}C,t;Ԇ^YGµK9I0XN@s Dzs[}爫*Θfrӭٯf=rYn*:Ji)YYxr[TZcvVխݎ? _ NոۯiSPOϢF!id4sm{X +jwp砐tّ L9sD'l[>GMTly}US7锤 I916'Dns΃oփ\1"O·7h廙TCw*ƹXGseE[OonǠD05vt2КT`h ' qQMQſC Ħbgh:Kϙ.2e.oo`cw8ջ;uum``d{zC ^ZhƒYV]ѳ$/.m`Yn`(9;)]Kfg{fƊꝌv݊I#qMy2"1O0'`6$DbS ͖\Yh>Z\Sn`d`[.t\㴀ĦVW-ͷs "B7E9\TCljaeۗqD^Z.v DdGA񮫟vP٭, brNO}]F ^!JSqBűΟH {b%1&~_M\+W `7ۆ姖?&z}3>V,8U?h `\үJx}0sŒݹSSZ3R|7mB zZɌH.B"RUg?/|> Q<3 8=v<t`47O-ͅ@Vr?W-n8(8͖9:6Bhhtktʒx!d+% ZC>7M/;1.]|=@a>>?7~ zÿ\{^1v84u+?Tr6MNDAƊa ʰ߱H`:$T၇w~ ՝4ř0Kf+_hrlWl{7o'UŘ4{=:]5ȥ9d]ܲ||QiKwN|.g~y5_|u/z$Ȓˈ"BF4]/endstream endobj 69 0 obj 5553 endobj 73 0 obj <> stream x\I[+s$SħrG$ZceקkArFT.sH>,^.E\/.` {"~"Ob ȋGŅ V_8e~^.iv7񕑻'W{(eyt 'ZD0]ܯKpr5| Ӈz1*WkڽKxG[v뢃J2p@:>wA{?( ka,S: fcyU?||?EZOpuARe5DV:|y^Bi!sn^Ƨ*t<T($<#臰WX |YX|T(H4}tGdME=Ov,(Yn)Y B *GRrQ3M1#h<,>'3ݎ߶>;nM8Qnwx;Bhq^!]zPԪdWMoӀsQN-`zvQKnT='ux.>-O=WUDMΔvJC)_}: hQnz Nj{J+Q0UNxU XJ7%yoa ޛEX׍Dgxn1Գ!'=" օ _ Ne+/]>nP_ de]o~Rv61>kѪӵgE]=f9sȑJ 6=C4h U @%0.|- !~1.^KOq3Z8K(} `U*k^'+UU* 4ھdO ǕQBLWt*bۜ QιWd$cU/fiĨܠB34mm| wS)\.}pЇP;KaE[99AE40>9e7cŞ>@ oRԂ~IA&>@{_Rc@瘼A/VBn Ǫ)ufj* [(5Bցm[X3$Sk]+CzTgW;3cBqBc0aɪ =wQ(rJ1JU »iew4߬=fţÙe}m@J:/{ptCd[R'BӺ(r[OQ^Y >}Q/'A-NnYk52j\M!&#q31f_~1构 OZrw1qMi3,=&mvߦ ,7L[!2t&2jwKX㳹%Kun`]L[TQQM"5gSmw[3;%wc]o<BnfLoDWڝxioqyE0yQ=@rT lfPOwI菲a[H;Ky X|t@K+6Jl}g{Mb-b}7`,>eBVc:JM3֬[q/IQOYFţFA e& I,ۈ<4 ! \x"ku ZTnS! F)ӇN-r+o jĘ+* [aӝ N&%A\jC M+Z8N&M9L^~$Q$b%I?7,P)(77Ap:$]%PdỐ6>Zڈ~%_0 b1!b1Z\]oB&ܛ 9M!$4XUacoIGѼ [y`z/@)W)ڧ [n$waDQIjB*tӐ`ji\If x?] ;߂Ԩ밼$p m.J-*&62- `nBC$ƊyԵ,s\Q_f(PSQuƼORs5o@?荳1c i#zNxAzg$栢 ([W 5 $^UF>* ԙ4V&a1s. u9֨Oq>TF?_k2aL%Y9?V\?V*y&36@2I27/YZEgn=ƹu.兝&7ӥ|{u}3ċIqvmup[@5vm>Bh=cU\2DfVCڢu9X"dwdbpx"!fa+?h 8#QvV7A[A̓CB2!IIjْ @~R%&ޞSϭl mc`ղ/\D~Z>uVEA39m:> stream x\[\q?b6h~%' lGR8퇕(E_V٥VI`Ȝ9U}u 6y/|% =J/_>|Isr֪ã^M/r|v-7;^kl _%1(c=?>M(ڔS.?V.5&6gյެV_oa x_^ևϮ׆[lx=z(VtЧ:4#$7qt T__x+<>rN>0$qd:>62w%;Zջm`7?Uoxq 1hCz1tMΦp{:WQ>EMd:9Oަ/%0rd ~-?Vi}D!:{]aL öAf0YiG{A8g4,e?^ii We?tlzxOmo.yѢM"k20B! 3L5 Cs 7wJ+"D<~rq1\l!:*HƗZo.I¿kQBOۊRu|+90#U 5o5J eB$Qԁ+Ϯ;h^8(= ?7_]烼z_>w'~u'4Gp4G C74kHOOHG뜙|ۀl׭7^)%7a()ب4 +H Um"$99!W*t#_vv9/ۣYꑁA7 WvP -v?]M.6.YjYQSlpf`;]+FXid:A#,3jɓr7(ڹK6v6+$,~ݾ|EX߷=ՄBDHK`鋌4HVl=4ko1ûmhޓ DvU@:5xH8w8:64 gR*Ϣʇ|c8$'0{F U Y۾,5ʌ pRޞ)[R;*,[ aG>VT Hm@!2I I+^Z_a3z >0V(7A&~٠zcsԅi7j jpyWD;ͺJ+1yToZ)Br 6i7+9/XĬpmXCx5 %}9…b= 8AKiu#/,Lr ~X~tnڣg ?{9o{\u({e{owK wD#FUM})Ƨ^_(+3$;fg>o dcPV]ltj/V&#Ho9/戩@of+%cY5 @+g0Nwɠ̟ ,@=cN\AR:l̅P԰F8ƒ  !j1`:kmrDuO~Zlj_bUf(I2Cx+( ]7ATPzcXoT'pE#M}ۗVex0$h3즚$FB=s1(Z+(pd< p0zo5QŪ[ O0P!Pins>8RR+jS76!g"`yʗ'm)I) nNꯓg4( gȾʔv˲߅l w(‘jCW1ŁLmiK4 [(o(Yep]t Q:c"{a2.Jpt;""4jXw;3k(t3] _c`z0.v9WK0&*ꗋ]b tIweb?EXiP c)ZV(R4$_CJ25'W{ia7X{8L 22s#d̾M7#0iMѺrcm7|27vn ^Mpℾ#rF;?: c{{Q`)1YzgEļ%M*uЍM,GΕi]rqؓAU`0Km`SAc0"Q[eGj&P W-1?%tV-&zV,y@V4U/8 {F{ψ;ڻ-bܦ#lt(9*^e{HfhnM)#4͓748|9^$9#2hL B<&na3~,s?dj{;) +GZn K"R~O@;j3tS9fM?HBf8YQ]un0H>ѓ}`Xq5DAT15.D>C+^VV9'@wJmNevƩJFMx3㦜\Io5\s*J0`\`{9fK;!8$+-$@2 -gD s1\lQԐ:q LjHBh)ƒ2LfagQwfH@Q2c~/iΛQ_bҩ3HF$s@@giBNTO"1+,\&jO"g$m6؅h!)~H3JgfXeS(VweLcsƷH>(j2JP<٤ήy(d(}$U˪}5զLҘBmӀ'9x*&R6|f&i${]Z"(hNL~.a:]@V6T 4m!VKy#G[< % "#3Dz<{42eSqkeظ Pc% \U nC4w2ke9dg,M~wug={ ܧ>9rUl̽~eqXy)WF.mxݻZ8"[C4 OFYУEc F!-Sx8R80M8T d\>Ayki u!ZLYƘ.*LhꚍSs]ňbΤ+21`yd;'r_Y)Vƻb d.~0ZNq/ع)G|E2|ڸg]7sK/\g.$;R)WrIɫpDV/;& ⾹3N\ s s {b)#K}qɝJc wYm$X*J 8G g1Z7b& `B(mXY]Y~]u]X<s_~5DSY<2)g|=Yv1CgͩbЙ=zR B5izrƃdE旍ܣq O:(,Rj8@W ų8J .ʺN"5m 4 sm"{9i{co/Pm  ;ߐQFC;ՍLV 6yd'h_o;]8kkƫ7)#: L:|Š;W"`HX1vx7-.l`ř'{9wx 1;㑂EBPVXn` fyH1 _4 C@A!iqKP N:;ѣz4* moQ]a`u1w 9&iws 鐥K.Rq۔hzZ~nA R :#y8,TOᭂ$V=Ɣ_Jt2 }8"{\#m/rݫ*s/ M٬'[Ϛ Ф4-/ͼ9<.6lB࿜Hlkz<wHOJ[>KyPW["^ᝒNêoA.WU4~fL@$іVx8?fXQfOˇGH6 :1Fc y@<8#u=l^12]dI$TmuH/RZ0IL4~ 4/4ZO*f1~#+wօn.Fn/nx,H #qA*D / xwsAUx:ވĜF`nqa2SzMȁ&xکK3gwU}tOsЌ~bhNLr떆Bm\ 5c'pZ\sc#J$bޥn7}xLd xWT@ ?")g[a 3<2ӣO9n6XIxIrEXLߍw6J`'\TId~)V)%lUcB ʃ  vXendstream endobj 79 0 obj 5843 endobj 87 0 obj <> stream x\[~w#*꜔*ȭHB&//kp~}%ͨ%= P.s4_3)ԙ?'~0=}O >=\}xJ>;v<|,' ܾ)(gBڠwRx ^Gvbb=LnO|ӻUN.*o…Wg_IԽhB{Ly0! -g ؖ wYMRuFFxxi^v^Z:_/T"I}GRa@ lg؞n"mXzK zF]8-}<vp&`DHg Fz䭬Uv@z;K~QJFt*JV>*  ΆmϐJiq\%9~/c?ߝ3yf"qPQ AYa4%jd2k:]!!Zꩪ]M+3 B?黽"yS|& =jzQSm{m3B/٠$E::#T[27 …Yʀv+ᕞy ૽k@rUngxOk͋U16f LiQd}vbLfb$^T ӨmUy`&v d#i]3ʕkIלlTfjxԻu>A^]IRgeYhAe(tI׳5d,2l 5 ú^vS l/jkT(({^6O,#HPv4VY֨m ׆Fw 8@+8lLX 2()5wv94†tܹ> EhbN_kŠN#AdŪ|/,N^zuE*PJ$f/VU(4mp:ɂ{͚w\z tl+azPuWShB_uZ bƧxL0eU ىwD0]8+Z g6ą"Z ,@ ?CTefx7Unѫza1+P/ՊYu0k1WX$9ngl/"eҪD[z<BP‚SASw5D f} c+gPix&2uWB,8 aWQ+%x"zklKف݄f(|孔gi&mMa=mFh(>U#\~+307PgjR,_"E8.)yM"pH.ѓ8F7j/5~u#&ϖySj2Fiՙ¢$ ^{{u0 Lb T./FXj<`CkYcY|)=SAh3Lh.[pJ[3q(tN 8ƃD7K6DMEq;0x7( бx 6Փ^yTPfM&}X=8 +V29+%F<g\•R\R 3rwYDW=5̆:x%Biլ[qQ^ uxjp-_>M`F+`y>ftRG٘{+D-W"L\*i$P(͏Nɠtu b0ejǚ)p)rd]ktM*'Q½Hɺ ,e>ɑmH1(v7)Ukm W|%5Y7|vބY TsoK;x>$b:{E̢W'WF+T {SjAw Ɓ-#, DWWk\57I@*>We!C+M^ןUS=وzf) ?Z1bU6Cq9Q3 zb-8e" Bg TyG2Z7˽˅Bm%KM,;"zF0 ރ vI[`T_ɘ)b4ԶwE<4&lOt[&*ao"7lKֳ5[a񇰹(jA,٘ߙ׳kM8vOeB[-S4?,:9.69ⲐFem7F,k+]DywQLa-?=M>=$!,O$ކT,X( Y!U/ 'Bf.ѕnYsFIm: KMrRY9IYFMFeˊ)̜CNjLS i~`#lC9+1B+F_ _!G!/AЇ5wD;Cеb_)}^ǭ/!QH\B!p@>a=jG:HFpr#PVW'ΔdU'Lֈ@̷fmlVHU/ j~WaNnϸe^s񩰁HR#P q0#LӒyIsGzD]!ĭߚdO&nw ռ;/ryڋ#!3N1HNF> 1b&P<;oLo.XrHOVfjbZsVU4sdimˆJ16ʧ}}wZhgolꃕ$0T̢"yXIڨɄ1 #iMlFf&y>C3;Ա)^eUPNAhދh@>p`6*^-ܻk\*WdH?|M2F>Ӷy$[vWe=揦$1__x%]>ۭ$LiJ??1+C]QIh\P0z4rnǔ,c83hƳK{M=mB Ѯށ t%FaFWN\`pR"׌h{+rl% /R d)RZ)~DzYKވii2A,b,ECVޱ2ܾ[]b޼Q=PgoMBg)Xou|m <%j~z+}PB"lsnyOj#<)jB@덆T i viQ%[Y xdS^,BзPNeJ, O"{q~'zXdrmάegzVLq&ZeMVzb6cGW^Zuy+;W,Ԙ5掅X!2 NG6saf |4 Az\-Ccvك2[s~ld(Tk)YTҦ)ʅ֐r>yMX[/+r:őwݹ]/)GهjL⛈ϙ Qm}an"ybeT-?Um u nj_&C;.34$RSsEjW}*K l}gjVtk->]VH$_WĵN&;Ac`5W1Y޷}[eE( .yE"; "&mB@hdp$CA9\a׎J8v9N! /m(>` )>,gg!dZ,70. yXbb?q<.R@ZB9>xC 7_1AɏTl7iA H Ih<8p|&5 r4GQ88, @@u?/Ku;h͝='q-MS"GG GTRBD ! R@!j բ.?,kizƣV”ȗwughɃ'4`͂?f568tEeu>#شNHаtflq7] ##d{3qOѝ,sZ I s@vCt7{?$tendstream endobj 88 0 obj 4547 endobj 92 0 obj <> stream x]Yq~#3LoI;iXZ@ X8(Cޙuf]=# g˫++>yywճտ¿z|Z܋o+c7we$|ޟo'_Gi#?>«?]ۣڬ*}%(Ɣw䍷Ǔ4f36_?Ie7|x0F1*>!-?G~HkO= %W[K;*?|Lk)%/W./7װ|yuxy۸3n Y36VbEL Ϗs{RM()eGyW͡ƯӆN~0X]x 74Oã|% KMPgtv tȟl^ԡPdmdx$)Qզ"uV&3v9qTO+ ȿVnF; `SHBJGEIyIW`@'0ͼtDϦ f)3SxM像& hTryX^a8qjH%27}4<&u(Rm ) @-F4>l$|{7_pê`8,v_xL>XQ#jwag94׏,X#9# w;;?5e,&k̷ɤMj}ebW!`*cr)z7Z^E'<5zAB̗) `DAAHeVqߨĿG e`6u'roR-$.xĥlj2 ᅛZRpXLFf#Jҷ O w!S@Qmޏj/S&K lVf$.HT~^2$%)k -V7@*t&[ DT S':q9J( qed{ |myxt/*g0)P%jyRS8P$\Ge줜ߜWA(4iBzpA&#'.U5|)nׅɫBBoy%M< rY6%-"NmrC!7qw\wќqUހ`^*D;&Jd ʪRTuKBg`8 ï(,&ȥW.Q}:b[UyS!(j!2֛T1*Mi!P(n&3>>iTӄC(&2 DAyÉ@u81b 62󆯃(Ec*!Ũ$3hj:'wAb]qR.bZi:%`<e6z K;<֪>HTգ-zsΖM>Z(p +֜*=I1a%E ab\[Ru17dPaiM~C\n'QkrsK8Y3T`)XbsA- w ʀ ֙474N$Jhռ;4wW 7SsE -5:Y(4@ FDH |P$r@ZTmZp'.ɔ)PM<ФP6,DV}:8QĨ"9QdTSJ,Ğ@7.Oa9@~f9zqAG}\(oέ;j]%_ fP~iaZԘzp*5m`-M"j@^7:S7K\) rT:\lY)is9,hNg3.;cx)i;ZqVq׼'njSx\܄@2戁{H=kW,\)ia4F H̖ ;٫ VA`4& ƴu#4nOLRܖЄQkRhm]Ҝ>RRrj4\cN>;%pI;f2I ~^ia}&*NWshrO MRF78I F}&3dQE]& Ye_,Usd%ST"E0&2RsFOɴZK"=1%uT#c 0%4- iGLU=ji\mĊ!i^gIBa ~+w]@+MN1:A'8j&PXVe{Y )z~ܥLM7%H7ͨ_s'y>cB ^!N mX/Oׁ Oؘ&hk!"M]SJ=X,4iV'V yݙq'ZA ?~+=,3 뻀k5]d0Fvχ2IXI&r;IbxH9Hf}/zX2+-4*V$IN< t\Ygs27x}3 mg'@ctTY|@K=o UӠƳ2&r"!*j0Fbu$(ݩ(? )RQq;+w<4p#_ U]nj"_a'E &>~ǬByXU07񹺖OlTL oUѝT #vǨWh5~ D@,A Qc7ΈԚW3P%U*D3@!O] E+lD ٦06VEAVh./0)62CGN=[A͛|~e$Rm E%ݢ *V1Imnuy2lm0GνtQrN#rچ(^FnF| i -*e6G5\f?3^$ƈuUXE:\L{hy^;RbkY# vVM Xt BY*DɻMdUr'"yzGF] }PFrÞS5A5oIr^U>  :mJcϞ^C;w!Hi; )qϼ/s1NiSHXԧCqHYd`K0.,*PhLMg,B_26v"qVaEUwźAVc &ii957 po"hf XA;픛!@1n;(9S;}!n&${ 9vz|B_+Ёފ}=nEp9/$Qb`.^d"%<-Ieи V䤌hoGxSiϵ. 6=4)*yYeM`cWg"4ړ&LAigwmh+зj²BUPA ,rX;h&!h~!j)}yP8×}++Bb5sGk>ސЕeV>i^ōvyQv9W{:l ^_X߇[m(90w¬CG1hnf\cEiۨ:%1`sҧ85+ZbY%E6-O%= и.!r(p"1Al #OU}2L;p1 ̌ցܻu#w y8 5ȹ> ϖ6oIqIUûPH cV8-7ŝ}0뚋|T}k9"8Z!G ϒ=  m.5Ce@cˌTHc6mtl_-nnмNYX*c arMTwq9ɟ6ykXR&NͶ`\ J̴[;&;xݽDM=,KP$O$ebj,Q[y&%m,"F4/5E`z9_u*֒`/gL,;M dj>+sI^&G2m+ox eaɼa#62.W V5m@M$4TBjuy 9%{5zI: lƫA.8 iہ6zB_X% EMi_r`WÞ^s/%Z >CEtc&m A|/V-Bm-$mtu{KHd"f5 e{0R@,LJ"֍4lԂۻ8 cO~}k}cZ[2Zcgಸ4Z"' C} K nQ K DGֶTŀ͏(n%DEoH9Ce8^}S$){H5 *t^xntVy>.w. 0XGS E1}p ~(?"8#Mz3/WׯyKmqLgSoK ,ț1gSۛTGxIwϽsj|D͇zoCp葷:I6fͳTj &!:|RƦVqF?|[t9ߪtm תGBubYn Y?}iC&JLpIt-Y(.51z-X&QZ_zHͩQQ!uy7[U| Obciᅠ(o_BzDtT|]4X{;$as_3AM.pM;70mD_`VUyUƏdTTr Gjks^аKLM⨗ {+㝚'xKg<헗r=\?) E/ H|kdԬVUWڢAmnE%ރK]hxΏ/~J~]oatK[2''xq&_U.E*"}Fx0e?12j$1 }{M<", {Ռ/tt?T3({m934~ے7T.39,v0X^ٿ˜ʛr[g ^%n|ޖZi_|]P.Jk[-wx a2&'3endstream endobj 93 0 obj 6214 endobj 97 0 obj <> stream xYMsoVN3)-]Q؊؛Kd"R}^cNUphݯ_P{I? w;vow*.n1*%sz|+8aftRxWax9b > ZhoF*Bn[=#NÛ2[Ezl9FQ>uVvHAKwhE bl ?sF8l¨!阆O`ީ@2)H#L0eO]Q:i%}NBk_qlҫ> h@1lǾAx "Aj2$ͫ-u&,ˮfDՖZo~ Y &a'ߎZx}|"B%o|{lY̑,5T xxuL8T@$U|jhN0W([;ײ+A?dsu+ Ƕ=@W쨹.%S8&=Ofn]"’h2/@Ѕ3:3n=X5vt6?+ HwB wp20=NQ9Ψ`M=""LnaH-R*C"i~;nGʳ5MAy|F$M(NTրHY|a8D6r6}rG&*yC3M j?#L'ն~{EJM j2l:P̢ʁ`_!PfxL[Q1|COj6q6M?>( G!^{iwFrv& e&.T&=KLK^4ƾ| ~\[r)Bۼ\zU᝔ aH[h=cJu>zr:_W~!^0IK0][ S҅]z{!-I1Avw [lXnޝIN$2䁭Ww/[+.bObnX, q^bF{Pb\MQHIfB zEr6n^GKbmWIExo,؞'1alB+׼ŭClͺ z?6 ś#%M7gۢu[/VqVeh'?kPgy1i Z@/Aޑ}Nszձ[@aЬp,0zn}q)N}[(>wkEOsTnzL8 t c'߭o⟌2 1=緻ӶaT}Q/0qF7.-[vzp7!I{el;Ԗ eErcr?;8AwA¼FUย3߻w k٣CŲgTA-7*&w20(endstream endobj 98 0 obj 2217 endobj 4 0 obj <> /Contents 5 0 R >> endobj 30 0 obj <> /Contents 31 0 R >> endobj 35 0 obj <> /Contents 36 0 R >> endobj 42 0 obj <> /Contents 43 0 R >> endobj 47 0 obj <> /Contents 48 0 R >> endobj 52 0 obj <> /Contents 53 0 R >> endobj 57 0 obj <> /Contents 58 0 R >> endobj 62 0 obj <> /Contents 63 0 R >> endobj 67 0 obj <> /Contents 68 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 86 0 obj <> /Contents 87 0 R >> endobj 91 0 obj <> /Contents 92 0 R >> endobj 96 0 obj <> /Contents 97 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 30 0 R 35 0 R 42 0 R 47 0 R 52 0 R 57 0 R 62 0 R 67 0 R 72 0 R 77 0 R 86 0 R 91 0 R 96 0 R ] /Count 14 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 28 0 obj <> endobj 29 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 40 0 obj <> endobj 41 0 obj <> endobj 45 0 obj <> endobj 46 0 obj <> endobj 50 0 obj <> endobj 51 0 obj <> endobj 55 0 obj <> endobj 56 0 obj <> endobj 60 0 obj <> endobj 61 0 obj <> endobj 65 0 obj <> endobj 66 0 obj <> endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 84 0 obj <> endobj 85 0 obj <> endobj 89 0 obj <> endobj 90 0 obj <> endobj 94 0 obj <> endobj 95 0 obj <> endobj 99 0 obj <> endobj 100 0 obj <> endobj 16 0 obj <> endobj 114 0 obj <> endobj 14 0 obj <> endobj 115 0 obj <>stream x]An EƲJlM0D^#,rL!=>#w,?iy)uHvRo~+Y>@pAc(5Dj}hߥssT=*^P؍ "='n'::FT:p2h uQqnE'TXh@5ꯞϗJUflFe>/i)[y]LY|Dwb endstream endobj 12 0 obj <> endobj 116 0 obj <> endobj 10 0 obj <> endobj 117 0 obj <> endobj 82 0 obj <> endobj 118 0 obj <> endobj 8 0 obj <> endobj 80 0 obj <> endobj 38 0 obj <> endobj 26 0 obj <> endobj 24 0 obj <> endobj 119 0 obj <> endobj 22 0 obj <> endobj 120 0 obj <>stream x]O1 y@C(KdhU1&bA }I:t8K结ϲ. >)laIH0Y( cY6Qj V̛C馮`i)HMӵuI{`tUh(%ZJ7smZL `(FS# endstream endobj 20 0 obj <> endobj 121 0 obj <> endobj 18 0 obj <> endobj 17 0 obj <> endobj 101 0 obj <>stream xXyxSUڿip~[eSEDZ *e/[YѴiM4}Ofi蒖ҖR(Pv* ⠢6~3'vNhGGٚ<9o9E,kŠ<wNt+`\"&[̆?кZ&sE1_~AE#+M]tSˊy}% (uSi>^xa겢ԍ_nWTy<~ AXS-}yiފ痿Xo([TobXJ,$f뉕,bMH,!6#D2$XCˉZb3&(\41 $- I nι i%w~b&'?6uM?CS Ocz_YĔ?N@HBD}v19V@H3?@`V*ffV+!E$qtt3'6ڗl`"jZA>I`rRZvF϶,btk<[13hESFsYk%jb)/7Hy+bҁ }(.?s _Li/B$@Cjj`hRW/d*hE<_Vjwvֻz;e8[=b">8r->]J=mH .$BH ǨA4˝4Ĵ?[镀+\z#x8kFgAE 5.A s7>٠3A PGjb, #4(~]^Ʌ/ΠHdt9}NgAX,N%h:vq Xd rJt Ju:VCw8"b3itցf&sVFo%EkCz(f*GQ,BZ%0 xA+!7hB+t f/ 2HqnqDL3Gvu Rt-؝{D6 Q:JjSÛ;𑊘 1Ϣf9wnt ҿ{ %hz]bfF\ ZzÉD_ ,]V82 -ӽcL"Xuɰ4 Jk}3 VL|WHvimvw?J6ѮҖx4Es?z5핌ZZy:9JZZZW?׺r\#k6<L+ؕ k?2v%6Qq? _Gv6zI-T;mAh$z_z7YуcUY4Z^^|)ȍp m pw#e'!2r~LBFvq78h7ڎx埙OwČ|6.d?ѥ_L9~D0Y -x`eG7Fpv, Jp_{o;`S3!p*4z?inړ]' &\+"Utvⶉgp d@ %#_WNoN05&D}at4. \kMf:ͼOG}?>ҷNosZ 6z`toPkie5ڵ3y1q0d' ~sa4]-RU @@֦pu{.l\.<|:7A8;#S.iy6?6x-zl`g3o$%~Dh'Aۢ=*$Ja4!իC V{(l=vPp%E&5@㛟wR{t<}_xǞc f<Iiώ߁UմEA4aP;VۅRZ@Y88|4 FaKJk8{ K+VEE,mAoA)Ջ戊iަ_W7̴^Z-%Зt[4o΢*(Θu=؆Xl ߉Ucn4Ͱj5 mcHXƘC3{KL@+.~yͱY5&UUnߵrź!Mx%}s{߹xbNQԅfresc6EZWք_& '7gǢle'rTnO/&A_XV_)nbUj<.҅G%RFzYLP*-M!I܎%1K\Bv=rxk5zTFr}Md&0$ֿg@B4CU3MP`V*`'.]|9lrR`2XHuBhmL655OQh6ݔ/P_qqɻytePlY^ݨ0}0tw?;n~h(a0bݍ[:<0!b()6ltJ} ]!|W>PWF!Om-kk Y/sJK|%` ~}3/iF;,NJ3ܠ`cupjK v{.~4Uzkm@ k=~s\Onrh+u[ʑVMWS]{nh޼;(l/oouLxgG{Y'E6uN[SBU3Bvp{VvxDzᔨ+˩I<aXL%1&^AuƿM&m;h ۺc.1/Ttc{ Z9K*Y9 6e['RPo@`,h5Nľlߑ].PU2W4 u%P#.* O9|O Oj)j>H}iUDQ4;(h< !m=FOv(dQ,"F[5Aѱª2@ev8(;3FVWeVDG-j-4!6#4uXG?cE"a :>ڃ5VA]N5u1Q7&ZIiKM <d.rNM:T`}!{ʹ endstream endobj 15 0 obj <> endobj 102 0 obj <>stream xW Tg*I)QpAK\OԼg . MVmK,@@ ļhD_fԘcf2&q b1s{g_}NW{-Q;1,r^~ P'y HO=4Wuˈ /pڋe}ynM Osg{,xC&culpDhb g$Z?zϠ;$ؒbZ;q0i/i):m4C#dܗ ȓV ١uрCvB7!%;9fhA'-[>,\q5O]}0Cv"&d5CftE_tQ,1[4l]<x2 pr\C /-"dCO82⻩87 _(4c'C68誒0VSd1d5qHd@:=l[+4m=[H)PYvvBz Oq%Un=n& cTOJh NJA"0#Z8cYjxZT}3Ou+=)dkN<|Cկpmy,5YEGnN,? G0L>%Q>\]o#K%bPSnm<#V_Iw=5O2x8 'e鐵ݒ%-]D-<-8T枴5U6v(&yZi,jV}0J'p NL&/8#N*"qNq;Ӂe:"ZӚ_#hS@ Qr{b.3wA2ܘZ[Tv5{Q^\I~Cŭ!Zų8/$^3YܱӔv`kG RiɜkvFu3 w1 RlE(/|~#ɸO/?КM O>R[{v(Q3$&C!Ł4 7E3EHi)- Y~h1.{뫕bСe0jfrJ8@Nkƍ3KHϮgu4,bPFˈ=Pxe*y<_,3J4eĖo)M&2_LjȖYв% 9pyX1ʒ|2$JRTVh*=] R)o " [VV ?l*Xos3xHOUO!qo{G+iY. *_1ړxŽMAJc3:8]?Qmj F#~bzchoPOvmFcue8~R 8;/#bʰH룒ca>ݕiI;*8c"dO39ίbX lSa˜2W뵖 A&! ܨQ4Ji=;Z=~%ʜ\oV,Xwag ' !% =_F{%`U)*hCf$–;~#Tƅ )Djzr?5ϗ!{D2pd9@_#8IVR(5.A}h͐ |{\*k5&b=[V+R rż<RTG-tΩ4yS4Ԩa'ԛ!R\7]8t{ڬ3tuC6#A"?)9&ݦyN犩oU_\퀿qN&s44NE٢Ŗӝ6N5oA'h-sT4y/Q-'QAmM p =0&h"LcA1}L~ꣵtNoL-D"?xc Ŷ֫Pg#8shfc>~13֢I;!mR5X-W]n^WxB3F,[l8RXW}ɮ/[Ogy3RӤ鯂'5ydM ȖiZ䪼犄-Dy%?> F<}KDKX=<:׉eC ga)),UZs ;@tQϮru>Vl\W7J( endstream endobj 13 0 obj <> endobj 103 0 obj <>stream xUPTcqoR5h l%Q2EM]X`Ov/@&!ӚN;q:FB'KL{;s>{DzAѢ=MrҸR5) \4F9HdZЩʛ[t*yCFlViѮ]ҽMJ^+SJ+eFI Z9J*CPK1jFԭP77h5JZ\Ǩ2AjU+o)e-#S|FS`:5aL0M-*J%nV2ucLUW8Tj* O4Or͝'-$dI&=~"҈ YEȫiEixzuX5¶,΁q~H,@ܼCbtlhhd xG X#}4> 砫Yoi9hV샠Srq PW"'>*AYIÞi= Pq_qi*[RV5S=5e8z,57AaO;QJ$*srLaCT}#n^|ss^"H'nni @#~{PMWP'A}i180va `p((/ `gB]+p]y]c?4ʽ%kzE1#Csv^$/?wg w2ZuEP>=L;Ѭ;8&-Ⴥ _oNTm +'ʆ&\\sqCm\KM֊߭L6x +tL5h@ݯS+hܧ1r.)W@p[?چ Σ4'Ƅ"mއ?MtVė'ԺTb]_>[Xoٌ6za3:g"A/{hL$1#{R5<_C m EhR8 q>wGik%6g|P-w5uXl ;]4wtUm}G) THMkoo2:-V'rܾ3Sf>pB%D㘨pUZ=^nK֐f:VA;>L _D$|QZdլmm`tTG՗. #C##, n*:zXc{4Qo0cF x?Z{v,lTqkf`?6ۏ@rMa혛Z@O=B%3n3ҋckLǗ endstream endobj 11 0 obj <> endobj 104 0 obj <>stream xyXTGj`X v,i0*e2m;3 EPXcM4IL4j$C6$<g{}׻Q]P"Hf ? Ԗh=гk`;~7Pbn_J,-Z=G;ۉӧ; :ym#?ۮ ~vaEPo/G;y:zy(Z|^s@A.+Z(ta~k߱nIN祑El0r;vnj2a3'Lm?i2;e=zm6}F5JP+t]jZE-Sé"j&5ASZ}jZBMޡdʎZO-P rj*5H9Q)j,ZA9R(bnTwՓEuzS}` Q7)RPHj@YS2jeC zPkIF&/D!wY- nj5VVIJ \6[Uw>=%u{}F {s/;m-~yg`NuT< v۷\5D*}nmaC:wan C#6aD'-Fgϋ۬"4pbT<,qd{\Y"LgdFzG^M\ nW'r7 "*WqQ+waqi}V=P RØi]zCAdc x!4 !."Tu(,hkfp _"ec3t⛼,*!=!] 52M0Zr AFvI(U`Ũ"%BgSYFLk\ ɂ5‚ӐGv]݆F T1H.<*/:&B!n9qJ)9l!"(W# :llt? Ӓ"l^r`OXf,JRwb#%>F7zKe8l #jm8Z/NU斣 vF|}ձ]d/>oAƌk73J'Vt-1z"+3Q73 4)J2&pWYyaayyY#8ms|1'k<_S/ı^}%C1!%?n={2k`+wΛQCАKŤ l. ="-E)r1tHMx8S* FV/Xr {Ӧt$3QgzЦqI])Fc^UMPTN<\˟Q(ÄO~eBzxeB=9ܿtƝ{҄oBTN(,6Uo36 (۞G笩N&F Vׅd*o ̢GkP6Vn)!DX&(J/g*I%l0_Ȱh$("ˆ3ȇ, ]dW2^ڻ?IQ#yJeU{oHk08Г5R~á#I(3oHp0CHNID njh}@n3-2Wur޸];䃉'yؼpdC6OZpNU :N50rPFK`:T2@_PظX-o؝% J_>?0(]=KʀT`rP )4ΟѢ璎`U wKEHNIs?~ozc`x8,6=ʢ".h/4ȫ?X Ž v_)`>ϻgJ,RZr,h'lšڌ䣪u̸\wE(\SZFo3y2R&b4og+##ʣk+K9]J!SJyi( {|WMFO?ݘz.0WOM+S9bjTٝEHUXܒ\7 ݣ 6Zؔfpîz~_cl؁=R9^/$9Ҫ[v Pt,sI TP1:^{K>/bz+4"&x4 N[<9ђ\VDi$}Owx7Вʚr Fuy5U2K)) |Gp)D} B i?D[<\>ϪGPL$ScT i7~g$?fd/I`|i;@ʛigeIJYؾC=f6zAɼ B@(+$*QqB"){$u&8/dab~,*-A9'R [`raLs)@F(&@+ [돆_ qze.d@>Jv&h*fAIp+gZt& `r`1(&.&22ZaA D{_J >Y"3l "2D)##m'~ rN߫aW mNrXr7QzxbHz {g?*XL/8ly0O0=Ecn?Md #y|KMFv7~*UeM13*‚|\t3 ׁ4ً$ͥ[EBC425g$4AZHV)QN6 `" l#O|1 k \ˌkqnjB'oo,A6xpoCaշ'+ת~ʼnɉ4>lnGr Ǿp /] ӱ5vi'֜FN&-%-YѫtJHa}ae'dM%Yb ;RnfQ6,h57k-15<[ƺ[&V7 g@$SͰ:-% 2l P\ 1(јP7L x P_i&"bM]+~ڥ/Ey6:SFó❄/Ju&mY:uYS=;4|_@>A!|W{1hVԳۧp"fCd-XS;V*5 ln?69rܶlӄ.,pZ"YF1ʴ}U R]3:UDŽ#{Q𿲺dx%& ( JC֭O\X,*<8$*Du}feQ}} RAS4Z4;LĠYBrt^?΅82p=~{YJZ4>]QٹY@}"f9RMQ􇑧to31+:ΞbФݹ2Dtt4._(cQt&?7@hW4()LȉS+!1}GSuyPxFA㩸 YZ]2%wfR4t]X]Tdr8UWlexi c^m*vYB[E9(Oj9/v[f ETDUMBk@Em|XZd%{گ&I>GGHG :Ly:^Vx)P*/lgI*<3)'?5/;Y'<=e-g[e |zL{7ÂXqSԭA}EK2 \#mB7: w}onXagZr` Fg̯_w㤝8z|{8`w)G! ܄|ZQѥcB==V2%o "}+_,"5BxEX t\h&@L{1N$U'-z:2n%L@p!62_Ji/~y}:+旣YlDN+9q B vTPY"S)~>#2,~gH5U쮎* LԀV͕\n=x//?eޚeVA7ߣ׃KƇ$1Z%_6.ZeeJ`8oo /&~yq*N}3=jފIݡ)C5^~`\RKѼ ̼I6)[$5$$qJ '>VNj߽|<^b{aUM:(zZ4eb^B,fM+Iq[y\%)53Et5ZcD9Fѳ*oWquZRiC D`X[Qɩ$A.)>JGCJA檛ޟdy\5^!ndџ4Z C^X=}L:3] !h̀ }1 bSنѿ?i}-~;;HuGg,JG}Z%\7l /(*0>6֘At>Fͻߌ1'P!E}ev9J4%V*UV'>~\gI7ŻU7>_ 7Ph51!+{epj<<ؖs&0%yFۤꯞ,2W/ dle8ƽ@*!o*gLA:m cFiWyҀsk6[AAfnjBm,9_0Όg ~~~\NN{ea>3ْH>,J8\| +\Vg/WEW9fNX6U5yhG.X>eeԺ.]O4$8xWLQ{ ٠T^Olp63rͩAKv5a8pesqU>0 LX{̤NRtI2s׌$^翽% m3䫖-Juh^;:4 nXkf a!^$DH/d@ R&EA,d?9a#s-0_wڠ:&`FTo/.Es%d*Lj LӽI9ׄ+ P`{{pݻ:{v3fyg/P{ endstream endobj 83 0 obj <> endobj 105 0 obj <>stream xcd`ab`dddwu041~H3a!-C5eBw``adtv/,L(QpT04WpM-LNSM,HM,rr3SK*sr@:RSRS ;)槤d$V2000F00v107?B+ɰ|(  k[oܲ6!޳ɽ}${ZI)(cwgS:6?|Z+%lyeV]c ?|nnl=W|>컸vqqTpnļ >숃 endstream endobj 9 0 obj <> endobj 106 0 obj <>stream xViPgf$ZɆ""hŀE((8yAnpRYXcYCr.k4*يǮ#ƤT_U<4MQ4M3^iemPku8)ɾ{ouJA>~ۼ ,Jŋ+UI1aa)ѪܠQhܕ+━@U*i*yjou|Bj*I鯎T%(etw*`纤(ߔp7%@Q(Wj=CyP'ZM͢6QR卑7Dr_Kg<;> 3GlkFs)gvQ`XegV_V?rA[\EMI \"+Bj9/ԗqg.e٠ &$ &83~e3h #<:Gq~F\EiGiVXy~ .4|mDeDb tB?9x_mJ{E5A/!HF^U=WYgr<)T}YЙ!c:-5 x&(>"[/ITdY`]+ 7 >ܐFC,$ޤŃgM'{b&FwHm@Bz{h 85C aS7-F.%]ɾ".@v90  '8lCqN'ʙ ܯחXul"6zJA/(-&\hxHc3]Q`YƏ=m;`0N lb%$.o`6_Z*W}oyky56mN]$nښ7S/G?u+!]2$6]Mu!>1Dw>YN\ !!8%E U /:298SK7AӝMPnZfȘϞ/*{ K4+LGZ"#%&?aT߳rGjlk(\B9cnH-HLṋi.o5Ƭص2:W!~U36I՗ic_e ]<ݧ@3wk]S~_|qJe” ˪̫m4FD%CQU-_x8*Wp(*Ց=[#`+=Y Nfp()A7TBsc3w?Hcxch"3}:ڛ *^d}6nx LespU1G]Llv$J/(q +譼8W Y/kUxY.d⮺}|ަ.Dz.67 )FO(_h]=2Ji@쑻xuf듰=lwe=hcc}G&YfMcJj&%UJkinZ2pl1p ZlX=ha:<8!^)YUo[0erocXUy8*FC-mӪӋ ub?H9%%hVPq讀 to!m5n@vmB~V86 C6n9Qk%>tK//g>"}M}o:&:i, 'Ӕm `=6d0Hl'b/q;pvȮxQk4X\?2zM*9nGͅX1Qҋ5ׄm.t+,0Gk)2E"NАLHDbC"'f/7H`3 \ VfGaF4PduDQZ֐ endstream endobj 81 0 obj <> endobj 107 0 obj <>stream xcd`ab`dddw 141U~H3a!#>nn}7n]O'9(3=DAYS\17(391O7$#57QOL-SpQ(VJ-N-*KM윟[PZZZk ]?T>0}C?4}_*:cu59ݵϱewgg)Qwd>ߗN4iZ '=UybS7GMe}Y֩-߷ocKCkwdYr={zM䫟!S~WNb?u[2(^O endstream endobj 39 0 obj <> endobj 108 0 obj <>stream xcd`ab`dddu 1T~H3a!sO]nnu? ~%_PYQᬩ`hiiZXX('gT)8(t+u-(-I-ROI-c```65b`bc;!a#$-L k~^}>[]S V͑ž`euedm{ؽuoX1}<f4;[d<3gw/ZT]#d~,3Dg-ʔdjʁ22P5|/y}ٳ=cq|V[7QԦ Vڸ?^nŕsKtsmcd7ob ݝE?V|wga(ohmWKg}ϟ;qr\,y8O>d endstream endobj 27 0 obj <> endobj 109 0 obj <>stream xVkTg h%m'Z训"Bk=0K2o]nI  ڭeK"j[koa;={3g朙oyyx<裂%wsIbEBLTצ(D^2}Td"+H*VǎWR^dbE2a3ғc2dSeBpbiTB ۉma0?-l+揽c6, c˰ l; [mܰ\h]ێǝf:2\7⏈^.G]vs{?sxS2dT6^M>!@p.VB:TzB PAZX>2 p(.u1$#`7-/+317KM@ jm%f&i.w]@qUYqV=CH<)lE>ɚp PRMoh+b4#B'W. \. v (q6i{fMq+H&Bxg}U$ſ()rc ja#M,B^d5|u{씷X}p"ЌZVvٺ\h:Х'rMt|L5g>3y,- b 4r'u$-cnAbxtCP8)٬u3ZY{gDMuc,`y|&rFn !02"L)C'o8xtNI5 [A PG$bbTnFq@u+8[d'8;{UV ړ#!3Y$+|0 zXDFt]Hxkqy"tAxyh t}4l<jbV6сѷ Z=i t]ӰS l89 }6;9fCota.pR.׉>z.w!v$ RDc HPZhfw+,OP O}O65qR։uRD&ЃX;+n/=yH$\u|7*B&|јO*|I&vك~\!9o3~^pރue yٺC:d8; 樲# B;7c@TΌƞNbmIi>lċx=*U8*DyDK"v?0]q9{G`Hտ]`LK :N4ޒ Me7K<8x;>gfH`c!}̩*ȩY iUƆPwB_X|t~\'Nh ^GWn_|ۤ<|zS؃\'"a @(-9!30Z*ZZ͑k"3)0rY/L71Z6}rAGٴkh¿!ZC.G*\e BtH1ui뀸744ܱCQ/j?^TIHК< JuuY]q}%6-"7:j*PزWu =$pb[ږ=C>܆ܑ˓m6QM[a3'S-P5F gsw*Ip 9u;19.wJ[I" rE4<rʋ:`Cmݩm~/_K:%ĖDOfYn!%R.` *NbMY6`vV 8qpKe*Q)LbҁEgv"׎ [4z,Vs۾sHfC+'Ch|ƾ6*$[g_nte؆s%.~G~:iS?N!?f3z si.GUrZ M_)>.d- LJ&Yl<.XP*FSmb'ӿ8:]~BnSɡiu% Jjz|說8z<_E!טs4)$/4X;yuQ_(vne)S7S/(h=gKQão AOm&ug^wgeR@P) Ge4 >.rlNmHNNMMNnHmnnhh0BκG*G|*NcaH )x.Z*J.qΆG 9J;.OȦ113deYZ_srP?Ra!It9 7ؒi#jɭ60 %:/2VJlM;iȫJ(,-,{+7b&Шόp>¾ X )x|jõ%5m7.T!@*0B) UzO%v' sGyot=U` gf@ cj٣{x]=t)ܯA" cz0]:"ߪ$Q( nQ aI kSZ׺[/jl+obۢ8\CvcҚv p_qy:* }wF}q 0G Oȿ%[7-COyd4ј bBkPޯ&z:slsD(7!)/A@jW$=E.Ii8\RF̣lc J.e%l.uu2a?d endstream endobj 25 0 obj <> endobj 110 0 obj <>stream xcd`ab`ddds 4T~H3a!G*k7s7 ~n)_PYQᬩ`hiiZXX('gT)8(t+mv-(-I-ROI-K,33g dX|3O2~Vtir̬[([`wf7m[Y䶞nɊim3[kmmh뮔^9or_朗reU6gV3'V}[Y5o_Iϝ9vbk|ˆ 8J_[x*{00? endstream endobj 23 0 obj <> endobj 111 0 obj <>stream xXyxSe?!m8 TEFe˪ "(;-]钐MfONsf޴)mӍPlyqsqfӹ3_ڂ8ayG} @ 04|٬فo'^(ka5<\8tqQ41B(|B,[6a©f͝Ƅc ;"S&F$G&HI˞>ὤ abRc1C{4Y#*1}{);BHWbV.j<%i k/X.+9ji bXI,"/UbbxIL$ˆ%,bXJL&‰eīb-1XG!^&D(x@ D(1׉"XG##. !oDe#CG!GQԨ HӘycGՇL~tģǕ㢞'>!)xGJK?34e`[^Vp_o|v㟁6xE[+Y̓J#?Mڱf Hj|=K;E!;R6L'5N((d-VQ_ ݆TzWj:qv^DN[_UZJGG$nˈHt98DUh|]M[u\XT-UEO!'t?&g#5AnjHӈZ0MFJ \[npxϚ HڡyLI-[ v3g0N7zmTɊ@@J~1ݨF%(w{]eVujtqYsU_%ӳ WV[|??e⩕c7Xl:&Y-|Wdj48wy/o"C.L1f4e(Q@ |2~ SefSA "~jtH jsa5p롁aEa2+C381&Xm<+:1=ř ARGd5K3Z=Cvi!w 8h }yz?`#DG#/WWzE7'xlCH(ѵU=2?Zӟ`4_t*49SA_RxPO)%KZRNT׶5 *L^'=UM$,S 9k%C> tLH('Z7(\e&(@mޭ*=@.IeuJ+|2M=ӅەV!~A+<+QO{j њ*^lc 4~/tvtj/W+Sx Siz*ͬx)ʊ:K^!VY :jF49ݳS&ڤ +_r$.[_-Mf N$.Hy u;j 4|5 j=8kA__ϕ(z;k>,,PU~gktzlB*5diLAZ|yACv.(qh9?$`OGoo9 P\UC Y1Up1 [*b׭IόGI `sC&w0DgYrPxZh\wl۪yz"hR¯~,h-\kgs64aKHC5hMUa?L&yo5(E\O 0J<{Mrʋ޼Fw,_\X?ͯi_ЗwC@r@BjД_!4xf%!^^-,֚@tAdY+köZ` I JKm4iiiYsFud r-0ɼao栁nVcd؀㜴90vK~v#]A^IC(&Eν}í$+A*VyMިWS :*/ܭIѢaJFX!QEo#ټVdҕ35,Ls(ܫA/Fp!D'E1&BDXvfͷ?R{Z9hp}Cs%yxۢ;WfkEmf~{jmByb"td0D16Ӡ 矉 c!Lc|[tޡf뤌1)B ɇ \DeN 䛢ӈuظ14$``` Ur Uf)X$8Ph&`p`$-Jpu%Y1V-/Jk9Q-)-jYbnI_KiNn/SE`rhtGb0Uqb Kڢ촼2^y D~Ҍë?:ҽnTI1 $.wbHS)IiW\ҹkJڝ+r-s`= .mwcv1GϘ & y?]):ʕ*2*I9K:Tw{hUm9T|#EN^"7ehF Eѝ9pE'g99zlGU!?HgdHJy1Vd8T°WГ,U~D܆* ^FWM؇Go-*d8t5Unt2ԏõރgc"@5<3.$ϙ_Vgs͋3Ac ҀN!2*qA|7~"ׯCw1ߗ_!o}8in m :nD$.VMiT ;gG(2 Fb4~'~@W p6jrrnx#Th[9<-mWs7Cy>M.l/0qxv8*0kT`li̜+e.rkMhҟ|uc>ą<-I3Қ } prp'qEO>x+dD8Zm4^Ϳ_vdmI4]ÉBգetXG E ~x PXU9 E^08V&V~$Ctc!0{P .SP#ǹ$pt?K.{, 1b![eS17*OhuK@TV : KeCyplh@n+,Βgi86H rq~8/+/ ֛/&3]&YYRzH9&Y&$ 6tZmU'{$:@i! r%~`|TH?u>'z: Fĺds*hIekW4+;[zȊ윥 q{jm}-TSZ k?-B|P :qBnlMnFחvA}kdQ{ J#?N#XFcRrkSM0*:|j24ysV&ܿa9CkMEe6gH(eהVٯ>[gGgTgD`:X( 6L4J). C0+mR _4#0~)gjOaTi"N.i Ebes"gqL+/z=WBq>/Ɓpwʆ(Y.jJڳxIfHn+-׫ؔޡM V _ > g];:k(GjV& g%L_^h,+3;9Nmo<T h5 ޽sPX+BԋL~l` DOYT / ŝק9sIҜMTJƅR957#7> endobj 112 0 obj <>stream xcd`ab`ddds TH3a!;xnn?4 ~!V_PYQᬩ`hiiZXX('gT)8(t+v-(-I-ROI-K,33RӁ$g0000110v1v30322ͺI؁aR7e{K*VvO;}&Oʹi3&vع$CƬڽs:wKVvr4[iݔvh}uMŌ֩U|~x7׵vWHk{{˔˺v/M?24i*:izwwǴu-u-rh!0~I3&/id\Owa`0 endstream endobj 19 0 obj <> endobj 113 0 obj <>stream xUmh[eǟd鵆:|{ V'ڑumfMh^zs&5M6I{41MLt:֢Sd8A!̉;98;? N:pozQZQF+C;@|8~1N$t63  L{G~r~!ba9n7esx鹷`zX9فu6}g9Fo`9+BHe=j2#jG0D-1Dl+& m[<:]!On%n*q/>Қ bZ?y!=a.3$Ȟ+Ѡ?B9:,T(,Iٵ˸&:yAIkάAxϰD*(SeZ*K幇=[H/ÇzS2{5)T*R-tk"*s 1SYoo儜2bqe]jRd״C0-g0KΙً7ױb k-@v׵3{Vb.&fSTukcc|kFE9Cy$ͩ>eGV4T5Pɉ* endstream endobj 122 0 obj <>stream GPL Ghostscript 8.54 PDF Writer 98-04.dvi endstream endobj 2 0 obj <>endobj xref 0 123 0000000000 65535 f 0000074943 00000 n 0000117978 00000 n 0000074792 00000 n 0000072469 00000 n 0000000015 00000 n 0000006035 00000 n 0000075009 00000 n 0000079246 00000 n 0000101337 00000 n 0000078332 00000 n 0000092164 00000 n 0000077686 00000 n 0000089984 00000 n 0000077002 00000 n 0000086274 00000 n 0000076588 00000 n 0000081803 00000 n 0000081582 00000 n 0000115508 00000 n 0000081206 00000 n 0000114727 00000 n 0000080566 00000 n 0000109090 00000 n 0000080328 00000 n 0000108401 00000 n 0000079967 00000 n 0000105165 00000 n 0000075050 00000 n 0000075080 00000 n 0000072637 00000 n 0000006055 00000 n 0000011231 00000 n 0000075209 00000 n 0000075239 00000 n 0000072799 00000 n 0000011252 00000 n 0000018866 00000 n 0000079786 00000 n 0000104381 00000 n 0000075315 00000 n 0000075345 00000 n 0000072969 00000 n 0000018887 00000 n 0000024801 00000 n 0000075454 00000 n 0000075484 00000 n 0000073131 00000 n 0000024822 00000 n 0000028725 00000 n 0000075560 00000 n 0000075590 00000 n 0000073293 00000 n 0000028746 00000 n 0000033998 00000 n 0000075655 00000 n 0000075685 00000 n 0000073463 00000 n 0000034019 00000 n 0000037473 00000 n 0000075794 00000 n 0000075824 00000 n 0000073633 00000 n 0000037494 00000 n 0000042902 00000 n 0000075889 00000 n 0000075919 00000 n 0000073803 00000 n 0000042923 00000 n 0000048548 00000 n 0000075984 00000 n 0000076014 00000 n 0000073973 00000 n 0000048569 00000 n 0000053255 00000 n 0000076079 00000 n 0000076109 00000 n 0000074135 00000 n 0000053276 00000 n 0000059191 00000 n 0000079595 00000 n 0000103751 00000 n 0000078999 00000 n 0000100671 00000 n 0000076174 00000 n 0000076204 00000 n 0000074305 00000 n 0000059212 00000 n 0000063831 00000 n 0000076313 00000 n 0000076343 00000 n 0000074467 00000 n 0000063852 00000 n 0000070138 00000 n 0000076419 00000 n 0000076449 00000 n 0000074629 00000 n 0000070159 00000 n 0000072448 00000 n 0000076503 00000 n 0000076533 00000 n 0000082085 00000 n 0000086593 00000 n 0000090310 00000 n 0000092700 00000 n 0000100896 00000 n 0000101589 00000 n 0000103970 00000 n 0000104598 00000 n 0000105433 00000 n 0000108645 00000 n 0000109422 00000 n 0000114992 00000 n 0000115728 00000 n 0000076914 00000 n 0000077384 00000 n 0000078090 00000 n 0000078864 00000 n 0000079147 00000 n 0000080472 00000 n 0000080976 00000 n 0000081471 00000 n 0000116656 00000 n trailer << /Size 123 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 118168 %%EOF nlopt-2.6.1/src/algs/stogo/testfun.h000066400000000000000000000330071345435414600174010ustar00rootroot00000000000000#ifndef TESTFUN_H #define TESTFUN_H #include "linalg.h" #include "tools.h" #include "stogo_config.h" const double pi=fabs(acos(-1.)); /* The Matrix a and vector c are needed in the Shekel function */ static double a[10][4]={ { 4,4,4,4 } , { 1,1,1,1 } , { 8,8,8,8 } , { 6,6,6,6 } , { 3,7,3,7 } , { 2,9,2,9 } , { 5,5,3,3 } , { 8,1,8,1 } , { 6,2,6,2 } , {7,3.6,7,3.6} }; static double c[10]= { .1 , .2 , .2 , .4 , .4 , .6 , .3, .7 , .5 , .5 }; void Domain_Shekel(RTBox box) { box.lb=0.0 ; box.ub=10.0 ; } double Objective_Shekel(RCRVector x) { int n=x.GetLength() ; double R=0.0, S; for(int i=0;i<10;i++) { S=0; for(int j=0;j=0) grad(i)=-( sin(sqrt(x(i)))+sqrt(x(i))/2.0*cos(sqrt(x(i))) ); else grad(i)=-( sin(sqrt(-x(i)))+sqrt(-x(i))/2.0*cos(sqrt(-x(i))) ); } } /******* Difficult multimodal problem, PERM(n) *********/ void Domain_Perm(RTBox box) { int n=(box.lb).GetLength(); box.lb=double(-n) ; box.ub=double(n) ; } double ObjPerm(RCRVector x, double beta) { int n=x.GetLength(); double s1=0.0; for (int k=1; k<=n ; k++) { double s2=0.0; for (int i=1 ; i<=n; i++) // s2+=(i^k+beta)*((x(i-1)/i)^k-1); s2+=(pow(1.0*i,1.0*k)+beta)*(pow(x(i-1)/i,1.0*k)-1) ; s1+=s2*s2; } return s1; } void GradPerm(RCRVector x, RVector &grad, double beta) { int n=x.GetLength(); for (int j=1 ; j<=n ; j++) { double s1=0.0; for (int k=1 ; k<=n ; k++) { double s2=0.0; for (int i=1 ; i<=n; i++) // s2+=(i^k+beta)*((x(i-1)/i)^k-1); s2+=(pow(1.0*i,1.0*k)+beta)*(pow(x(i-1)/i,1.0*k)-1); // s1+=2*s2*(j^k+beta)/(x(j-1)*j^k)*k*x(j-1)^k; s1+=2*s2*(pow(1.0*j,1.0*k)+beta)/pow(1.0*j,1.0*k)*k*pow(x(j-1),k-1.0); } grad(j-1)=s1; } } double Objective_Perm_4_50(RCRVector x) { return ObjPerm(x,50); } void Gradient_Perm_4_50(RCRVector x, RVector &grad) { GradPerm(x,grad,50); } double Objective_Perm_4_05(RCRVector x) { return ObjPerm(x,0.5); } void Gradient_Perm_4_05(RCRVector x, RVector &grad) { GradPerm(x,grad,0.5); } /******************* Powersum **************/ void Domain_Powersum(RTBox box) { box.lb=0.0 ; box.ub=4.0 ; } double Objective_Powersum(RCRVector x) { int n=x.GetLength(); double b[]={8,18,44,114}; double s1=0.0; for (int k=1 ; k<=n ; k++) { double s2=0.0; for (int i=1 ; i<=n ; i++) s2+=pow(x(i-1),1.0*k); s1+=pow(s2-b[k-1],2.0); } return s1; } void Gradient_Powersum(RCRVector x, RVector &grad) { int n=x.GetLength(); double b[]={8,18,44,114}; for (int j=0 ; j #include #include "stogo_config.h" #include "tools.h" Trial::Trial():xvals(0) { objval=DBL_MAX; } Trial::Trial(int n):xvals(n) { objval=DBL_MAX; } Trial::Trial(RCTrial tr):xvals(tr.xvals) { objval=tr.objval ; } RCTrial Trial::operator=(RCTrial tr) { xvals=tr.xvals ; objval=tr.objval ; return *this ; } ostream & operator << (ostream & os, const Trial & T) { os << T.xvals << " " << "(" << T.objval << ")" << endl ; return os; } /********************* Vanilla Box **********************/ VBox::VBox():lb(0),ub(0) {} // Constructor VBox::VBox(int n):lb(n),ub(n) {} // Constructor VBox::VBox(RCVBox box):lb(box.lb), ub(box.ub) {} // Constructor RCVBox VBox::operator=(RCVBox box) { // Copy: Box1=Box2 lb=box.lb; ub=box.ub; return *this; } int VBox::GetDim() { return lb.GetLength(); } double VBox::Width(int i) { // Returns the width of the i-th interval, i between [0,...,dim-1] return ub(i)-lb(i); } void VBox::Midpoint(RCRVector x) { // Returns the midpoint of Box in x int n=GetDim(); for (int i=0 ; i::const_iterator TBox::FirstTrial() { return TList.begin(); } list::const_iterator TBox::LastTrial() { return TList.end(); } void TBox::GetTrial(list::const_iterator itr, Trial &T) { T.xvals=(*itr).xvals; T.objval=(*itr).objval; } void TBox::ClearBox() { TList.erase(TList.begin(), TList.end()); minf=DBL_MAX; } bool TBox::CloseToMin(RVector &vec, double *objval, double eps_cl) { // Returns TRUE if 'vec' is close to some of the trials in the box, // in this case, 'vec' and 'objval' are overwritten by the Trial data // otherwise 'vec' and 'objval' are not affected. // // Here "close" means norm2(T - some trial in box)<=eps_cl // // NB It might be better to accept Trial as argument instead of vector int n=GetDim(); RVector x(n), y(n); list::const_iterator itr; for ( itr = TList.begin(); itr != TList.end(); ++itr ) { y=vec ; // NB Should be possible to avoid this copying x=(*itr).xvals; axpy(-1,x,y); if (norm2(y)<=eps_cl) { vec=x; *objval=(*itr).objval; return TRUE; } } return FALSE; } unsigned int TBox::NStationary() { // Returns the number of trials in a box return TList.size() ; } void TBox::split(RTBox B1, RTBox B2) { list::const_iterator itr; double w,m,tmp; double fm1=DBL_MAX, fm2=DBL_MAX; int i, k, ns; int n=GetDim(); B1.lb=lb; B1.ub=ub; B2.lb=lb; B2.ub=ub; w=LongestSide(&i); ns=TList.size(); switch (ns) { case 0: case 1: // Bisection w=ub(i)-lb(i); // Length of interval m=lb(i)+w/2; // Midpoint B1.ub(i)=m; B2.lb(i)=m; break; default: // More elaborate split when there are more than one trials in B // See Serguies and Kaj's tech. report, page 11 // Compute the center point of all stationary points RVector center(n), x(n), dispers(n); center=0; dispers=0; for ( itr = TList.begin(); itr != TList.end(); ++itr ) axpy(1.0, (*itr).xvals, center); scal((double)(1.0/ns),center); // Compute the relative deviations for ( itr = TList.begin(); itr != TList.end(); ++itr ) { for (k = 0; ktmp) { tmp=dispers(k);i=k; } } B1.ub(i)=center(i) ; B2.lb(i)=center(i); break; } // Split the set of trials accordingly for ( itr = TList.begin(); itr != TList.end(); ++itr ) { if ( B1.InsideBox((*itr).xvals) ) { fm1=min(fm1,(*itr).objval); B1.AddTrial(*itr); } else { B2.AddTrial(*itr); fm2=min(fm2,(*itr).objval); } } // Set minf of B1 and B2 B1.minf=fm1 ; B2.minf=fm2; } void TBox::dispTrials() { // Display information about box #ifdef KCC copy(TList.begin(), TList.end(), ostream_iterator(cout)); #else copy(TList.begin(), TList.end(), ostream_iterator(cout)); #endif } ostream & operator << (ostream & os, const TBox & B) { int n=(B.lb).GetLength() ; for (int i=0 ; itmp ) { tmp=ub(i)-lb(i); j=i; } *idx=j; return tmp; } double TBox::ClosestSide(RCRVector x) { // Returns the shortest distance from point X to the box B. // Warning: The output of this functon is nonsense if the // point X lies outside B. Should we try to detect this case? double dist, tmp ; int n=GetDim(); dist=DBL_MAX; for (int i=0 ; iub(j)) { isect=0; break; } } } copy(z,tmpV); axpy(-1.0,x,tmpV); // tmpV=z-x if (isect==1 && dot(tmpV,h)>0) { done=TRUE; break; } } i++; } return done; } double TBox::LowerBound(double maxgrad) { // Lower bound estimation double lb=minf ; double f1,f2,est ; list::const_iterator itr1,itr2 ; int n=GetDim(); RVector x1(n), x2(n) ; #ifndef LB2 for ( itr1 = TList.begin(); itr1 != TList.end(); ++itr1 ) { itr2=itr1 ; while (++itr2 != TList.end()) { x1=(*itr1).xvals ; f1=(*itr1).objval ; x2=(*itr2).xvals ; f2=(*itr2).objval ; axpy(-1.0,x2,x1) ; // x1=x1-x2 est=0.5*(f1+f2-maxgrad*norm2(x1)) ; lb=min(lb,est) ; // cout << "est=" << est << " x1=" << x1 << " x2=" << x2 << endl ; } } #endif #ifdef LB2 for ( itr1 = TList.begin(); itr1 != TList.end(); ++itr1 ) { // Use also max distance to border x1=(*itr1).xvals; f1=(*itr1).objval; est=f1-FarthestSide(x1)*maxgrad; lb=min(lb,est); } #endif return lb ; } nlopt-2.6.1/src/algs/stogo/tools.h000066400000000000000000000057321345435414600170550ustar00rootroot00000000000000 // Various datastructures and functions used by the global optimizer #ifndef TOOLS_H #define TOOLS_H #include #include #include #include #include #include "linalg.h" #ifndef FALSE const int FALSE=(1==0); // boolean FALSE #endif #ifndef FALSE const int TRUE=(1==1); // boolean TRUE #endif typedef const class Trial CTrial; typedef CTrial& RCTrial; typedef CTrial* PCTrial; class Trial{ public: RVector xvals; double objval; Trial(); Trial(int); Trial(RCTrial); // Copy constructor RCTrial operator=(RCTrial) ; // assignment operator friend ostream & operator << (ostream &, RCTrial) ; }; class TrialGT : public unary_function // Predicate for Trial (needed for remove_if) { public: explicit TrialGT(double val) : _val(val) {} bool operator()(Trial& foo) { return foo.objval > _val; } private: double _val; }; typedef class VBox& RVBox; typedef const class VBox CVBox; typedef CVBox* PCVBox; typedef CVBox& RCVBox; class VBox{ public: RVector lb, ub; VBox(); // Construct a box VBox(int); VBox(RCVBox); // Copy constructor RCVBox operator=(RCVBox); // assignment operator int GetDim(); // Returns the dimension of the box double Width(int) ; // Returns the width of the i-th interval void Midpoint(RCRVector); // Returns the midpoint friend ostream & operator << (ostream &, const VBox &); }; typedef class TBox& RTBox; typedef const class TBox CTBox; typedef CTBox* PCTBox; typedef CTBox& RCTBox; class TBox: public VBox { public: double minf; // Smallest function value found so far list TList; // List of trials TBox(); // Construct a box TBox(int); TBox(RCTBox); // Copy constructor RCTBox operator=(RCTBox); // assignment operator double GetMin(); // Returns 'minf' bool EmptyBox(); // Returns TRUE if Box contains no trials void AddTrial(RCTrial); // Add a trial to the (back of) box void RemoveTrial(Trial &); // Remove a trial from the (back of) box void GetLastTrial(Trial &); // Return a trial from the back of the box list::const_iterator FirstTrial(); list::const_iterator LastTrial(); void GetTrial(list::const_iterator, Trial&); void ClearBox(); bool CloseToMin(RVector&, double*, double); unsigned int NStationary(); // Returns the number of stationary points void split(RTBox, RTBox); // Split a box void dispTrials(); bool InsideBox(RCRVector); int OutsideBox(RCRVector, RCTBox); double ShortestSide(int*); // Returns the shortest side double LongestSide(int*); // Returns the longest side double ClosestSide(RCRVector x); double FarthestSide(RCRVector x); bool Intersection(RCRVector, RCRVector, RCRVector); double LowerBound(double); bool operator<(const TBox & x) const {return (minf>x.minf);} friend ostream & operator << (ostream &, const TBox &); }; #endif nlopt-2.6.1/src/algs/stogo/tst.cc000066400000000000000000000025451345435414600166640ustar00rootroot00000000000000#include #include "global.h" #include "tools.h" #include "linalg.h" #include "tools.h" #include "stogo_config.h" void Domain_Mine(RTBox box) { box.lb=-3.0 ; box.ub=3.0; } static int cnt = 0; double Objective_Mine(RCRVector xy) { double x = xy(0); double y = xy(1); double f = ((x*x)*(4-2.1*(x*x)+((x*x)*(x*x))/3) + x*y + (y*y)*(-4+4*(y*y))); printf("feval:, %d, %g, %g, %g\n", ++cnt, x,y, f); return f; } void Gradient_Mine(RCRVector xy, RVector &grad) { double x = xy(0); double y = xy(1); grad(0) = /* df/dx */ ((2*x)*(4-2.1*(x*x)+((x*x)*(x*x))/3) + (x*x)*(-4.2*x+4*(x*(x*x))/3) + y); grad(1) = /* df/dy */ (x + (2*y)*(-4+4*(y*y)) + (y*y)*(8*(y))); } int main(int argc, char **argv) { int dim=2; Pdom Dom=Domain_Mine; Pobj Obj=Objective_Mine; Pgrad Grad=Gradient_Mine; GlobalParams params; params.det_pnts=2*dim+1; params.rnd_pnts=0; params.eps_cl=0.1; params.rshift=0.3; params.mu=1.0E-4; params.maxtime=0; params.maxeval = argc < 2 ? 100 : atoi(argv[1]); TBox D(dim); Dom(D); Global Problem(D,Obj, Grad, params); RVector dummyvec(dim); Problem.Search(-1, dummyvec); cout << "Minimizers found\n"; Problem.DispMinimizers(); cout << "dummyvec: " << dummyvec << "\n"; double val = Problem.OneMinimizer(dummyvec); cout << "one minimizer: " << val << ": " << dummyvec << "\n"; } nlopt-2.6.1/src/algs/stogo/tstc.c000066400000000000000000000020441345435414600166560ustar00rootroot00000000000000#include #include #include "stogo.h" /* has two global minima at (0.09,-0.71) and (-0.09,0.71), plus 4 additional local minima */ static int cnt=0; double tst_obj(int n, const double *xy, double *g, void *unused) { double x, y, f; x = xy[0]; y = xy[1]; f = ((x*x)*(4-2.1*(x*x)+((x*x)*(x*x))/3) + x*y + (y*y)*(-4+4*(y*y))); printf("feval:, %d, %g, %g, %g\n", ++cnt, x,y, f); if (g) { g[0] = /* df/dx */ ((2*x)*(4-2.1*(x*x)+((x*x)*(x*x))/3) + (x*x)*(-4.2*x+4*(x*(x*x))/3) + y); g[1] = /* df/dy */ (x + (2*y)*(-4+4*(y*y)) + (y*y)*(8*(y))); } return f; } int main(int argc, char **argv) { int n = 2; double x[2], l[2], u[2]; long int maxits = 0, maxtim = 0; int info; double minf; maxits = argc < 2 ? 100 : atoi(argv[1]); l[0] = -3; l[1] = -3; u[0] = 3; u[1] = 3; info = stogo_minimize(n, tst_obj, NULL, x, &minf, l, u, maxits, maxtim); printf("min f = %g at (%g,%g) after %d evals, return value %d\n", minf, x[0], x[1], cnt, info); return EXIT_SUCCESS; } nlopt-2.6.1/src/algs/subplex/000077500000000000000000000000001345435414600160645ustar00rootroot00000000000000nlopt-2.6.1/src/algs/subplex/README000066400000000000000000000024751345435414600167540ustar00rootroot00000000000000"Subplex" gradient-free minimization code, based on a variant of Nelder-Mead simplex by Tom Rowan. http://www.netlib.org/opt/subplex.tgz T. Rowan, "Functional Stability Analysis of Numerical Algorithms", Ph.D. thesis, Department of Computer Sciences, University of Texas at Austin, 1990. This code was downloaded from Netlib.org, converted via f2c, and then cleaned up a bit by Steven G. Johnson (stevenj@alum.mit.edu) for use with libctl. Unfortunately, neither Netlib nor the Subplex source code contain any explicit indication of the copyright/license status of the code, and I was unable to contact the author. However, it is listed as "public domain" by the Starlink astronomical software review (http://star-www.rl.ac.uk/star/docs/sun194.htx/node151.html). The original README file describes the algorithm as: Subplex is a subspace-searching simplex method for the unconstrained optimization of general multivariate functions. Like the Nelder-Mead simplex method it generalizes, the subplex method is well suited for optimizing noisy objective functions. The number of function evaluations required for convergence typically increases only linearly with the problem size, so for most applications the subplex method is much more efficient than the simplex method. nlopt-2.6.1/src/algs/subplex/subplex.c000066400000000000000000001466411345435414600177260ustar00rootroot00000000000000/* Downloaded from http://www.netlib.org/opt/subplex.tgz README file for SUBPLEX NAME subplex - subspace-searching simplex method for unconstrained optimization DESCRIPTION Subplex is a subspace-searching simplex method for the unconstrained optimization of general multivariate functions. Like the Nelder-Mead simplex method it generalizes, the subplex method is well suited for optimizing noisy objective functions. The number of function evaluations required for convergence typically increases only linearly with the problem size, so for most applications the subplex method is much more efficient than the simplex method. INSTALLATION To build subplex on UNIX systems, edit the Makefile as necessary and type: make This will create a linkable library named subplex.a and a demonstration executable named demo. EXAMPLE To run subplex on a simple objective function type: demo < demo.in To run subplex on other problems, edit a copy of the sample driver demo.f as necessary. AUTHOR Tom Rowan Oak Ridge National Laboratory Mathematical Sciences Section P.O. Box 2008, Bldg. 6012 Oak Ridge, TN 37831-6367 Phone: (423) 574-3131 Fax : (423) 574-0680 Email: na.rowan@na-net.ornl.gov REFERENCE T. Rowan, "Functional Stability Analysis of Numerical Algorithms", Ph.D. thesis, Department of Computer Sciences, University of Texas at Austin, 1990. COMMENTS Please send comments, suggestions, or bug reports to na.rowan@na-net.ornl.gov. */ #include #include #include #include #include "subplex.h" typedef double doublereal; typedef int logical; typedef int integer; #define TRUE_ 1 #define FALSE_ 0 typedef subplex_func D_fp; #define MAX2(a,b) ((a) > (b) ? (a) : (b)) #define MIN2(a,b) ((a) < (b) ? (a) : (b)) /****************************************************************************/ /****************************************************************************/ /* dasum.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static doublereal dasum_(integer *n, doublereal *dx, integer *incx) { /* System generated locals */ integer i__1; doublereal ret_val, d__1, d__2, d__3, d__4, d__5, d__6; /* Local variables */ integer i__, m; doublereal dtemp; integer ix, mp1; /* takes the sum of the absolute values. */ /* uses unrolled loops for increment equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified to correct problem with negative increment, 8/21/90. */ /* Parameter adjustments */ --dx; /* Function Body */ ret_val = 0.; dtemp = 0.; if (*n <= 0) { return ret_val; } if (*incx == 1) { goto L20; } /* code for increment not equal to 1 */ ix = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dtemp += (d__1 = dx[ix], fabs(d__1)); ix += *incx; /* 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__1 = m; for (i__ = 1; i__ <= i__1; ++i__) { dtemp += (d__1 = dx[i__], fabs(d__1)); /* L30: */ } if (*n < 6) { goto L60; } L40: mp1 = m + 1; i__1 = *n; for (i__ = mp1; i__ <= i__1; i__ += 6) { dtemp = dtemp + (d__1 = dx[i__], fabs(d__1)) + (d__2 = dx[i__ + 1], fabs(d__2)) + (d__3 = dx[i__ + 2], fabs(d__3)) + (d__4 = dx[i__ + 3], fabs(d__4)) + (d__5 = dx[i__ + 4], fabs(d__5)) + (d__6 = dx[i__ + 5], fabs(d__6)); /* L50: */ } L60: ret_val = dtemp; return ret_val; } /* dasum_ */ /* daxpy.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int daxpy_(integer *n, doublereal *da, doublereal *dx, integer *incx, doublereal *dy, integer *incy) { /* System generated locals */ integer i__1; /* Local variables */ integer 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. */ /* 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 = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*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_ */ /* dcopy.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int dcopy_(integer *n, const doublereal *dx, integer *incx, doublereal *dy, integer *incy) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, m, ix, iy, mp1; /* copies a vector, x, to a vector, y. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ if (*n <= 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 = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dy[iy] = dx[ix]; ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = *n % 7; if (m == 0) { goto L40; } i__1 = m; for (i__ = 1; i__ <= i__1; ++i__) { dy[i__] = dx[i__]; /* L30: */ } if (*n < 7) { return 0; } L40: mp1 = m + 1; i__1 = *n; for (i__ = mp1; i__ <= i__1; i__ += 7) { dy[i__] = dx[i__]; dy[i__ + 1] = dx[i__ + 1]; dy[i__ + 2] = dx[i__ + 2]; dy[i__ + 3] = dx[i__ + 3]; dy[i__ + 4] = dx[i__ + 4]; dy[i__ + 5] = dx[i__ + 5]; dy[i__ + 6] = dx[i__ + 6]; /* L50: */ } return 0; } /* dcopy_ */ /* dscal.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int dscal_(integer *n, doublereal *da, doublereal *dx, integer *incx) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, m, ix, mp1; /* scales a vector by a constant. */ /* uses unrolled loops for increment equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified to correct problem with negative increment, 8/21/90. */ /* Parameter adjustments */ --dx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1) { goto L20; } /* code for increment not equal to 1 */ ix = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dx[ix] = *da * dx[ix]; ix += *incx; /* L10: */ } return 0; /* code for increment 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__) { dx[i__] = *da * dx[i__]; /* L30: */ } if (*n < 5) { return 0; } L40: mp1 = m + 1; i__1 = *n; for (i__ = mp1; i__ <= i__1; 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_ */ /* dist.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static doublereal dist_(integer *n, doublereal *x, doublereal *y) { /* System generated locals */ integer i__1; doublereal ret_val, d__1; /* Local variables */ integer i__; doublereal scale, absxmy, sum; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* dist calculates the distance between the points x,y. */ /* input */ /* n - number of components */ /* x - point in n-space */ /* y - point in n-space */ /* local variables */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --y; --x; /* Function Body */ absxmy = (d__1 = x[1] - y[1], fabs(d__1)); if (absxmy <= 1.) { sum = absxmy * absxmy; scale = 1.; } else { sum = 1.; scale = absxmy; } i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { absxmy = (d__1 = x[i__] - y[i__], fabs(d__1)); if (absxmy <= scale) { /* Computing 2nd power */ d__1 = absxmy / scale; sum += d__1 * d__1; } else { /* Computing 2nd power */ d__1 = scale / absxmy; sum = sum * (d__1 * d__1) + 1.; scale = absxmy; } /* L10: */ } ret_val = scale * sqrt(sum); return ret_val; } /* dist_ */ /* calcc.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Table of constant values */ static doublereal c_b3 = 0.; static integer c__0 = 0; static integer c__1 = 1; static doublereal c_b7 = 1.; static int calcc_(integer *ns, doublereal *s, integer *ih, integer * inew, logical *updatc, doublereal *c__) { /* System generated locals */ integer s_dim1, s_offset, i__1; doublereal d__1; /* Local variables */ integer i__, j; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* calcc calculates the centroid of the simplex without the */ /* vertex with highest function value. */ /* input */ /* ns - subspace dimension */ /* s - double precision work space of dimension .ge. */ /* ns*(ns+3) used to store simplex */ /* ih - index to vertex with highest function value */ /* inew - index to new point */ /* updatc - logical switch */ /* = .true. : update centroid */ /* = .false. : calculate centroid from scratch */ /* c - centroid of the simplex without vertex with */ /* highest function value */ /* output */ /* c - new centroid */ /* local variables */ /* subroutines and functions */ /* blas */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --c__; s_dim1 = *ns; s_offset = 1 + s_dim1 * 1; s -= s_offset; /* Function Body */ if (*updatc) { if (*ih == *inew) { return 0; } i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { c__[i__] += (s[i__ + *inew * s_dim1] - s[i__ + *ih * s_dim1]) / * ns; /* L10: */ } } else { dcopy_(ns, &c_b3, &c__0, &c__[1], &c__1); i__1 = *ns + 1; for (j = 1; j <= i__1; ++j) { if (j != *ih) { daxpy_(ns, &c_b7, &s[j * s_dim1 + 1], &c__1, &c__[1], &c__1); } /* L20: */ } d__1 = 1. / *ns; dscal_(ns, &d__1, &c__[1], &c__1); } return 0; } /* calcc_ */ /* order.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int order_(integer *npts, doublereal *fs, integer *il, integer *is, integer *ih) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, j, il0; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* order determines the indices of the vertices with the */ /* lowest, second highest, and highest function values. */ /* input */ /* npts - number of points in simplex */ /* fs - double precision vector of function values of */ /* simplex */ /* il - index to vertex with lowest function value */ /* output */ /* il - new index to vertex with lowest function value */ /* is - new index to vertex with second highest */ /* function value */ /* ih - new index to vertex with highest function value */ /* local variables */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --fs; /* Function Body */ il0 = *il; j = il0 % *npts + 1; if (fs[j] >= fs[*il]) { *ih = j; *is = il0; } else { *ih = il0; *is = j; *il = j; } i__1 = il0 + *npts - 2; for (i__ = il0 + 1; i__ <= i__1; ++i__) { j = i__ % *npts + 1; if (fs[j] >= fs[*ih]) { *is = *ih; *ih = j; } else if (fs[j] > fs[*is]) { *is = j; } else if (fs[j] < fs[*il]) { *il = j; } /* L10: */ } return 0; } /* order_ */ /* partx.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Common Block Declarations */ static struct { doublereal alpha, beta, gamma, delta, psi, omega; integer nsmin, nsmax, irepl, ifxsw; doublereal bonus, fstop; integer nfstop, nfxe; doublereal fxstat[4], ftest; logical minf, initx, newx; } usubc_; #define usubc_1 usubc_ static int partx_(integer *n, integer *ip, doublereal *absdx, integer *nsubs, integer *nsvals) { /* System generated locals */ integer i__1; /* Local variables */ static integer i__, nleft, nused; static doublereal as1max, gapmax, asleft, as1, as2; static integer ns1, ns2; static doublereal gap; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* partx partitions the vector x by grouping components of */ /* similar magnitude of change. */ /* input */ /* n - number of components (problem dimension) */ /* ip - permutation vector */ /* absdx - vector of magnitude of change in x */ /* nsvals - integer array dimensioned .ge. int(n/nsmin) */ /* output */ /* nsubs - number of subspaces */ /* nsvals - integer array of subspace dimensions */ /* common */ /* local variables */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --absdx; --ip; --nsvals; /* Function Body */ *nsubs = 0; nused = 0; nleft = *n; asleft = absdx[1]; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { asleft += absdx[i__]; /* L10: */ } L20: if (nused < *n) { ++(*nsubs); as1 = 0.; i__1 = usubc_1.nsmin - 1; for (i__ = 1; i__ <= i__1; ++i__) { as1 += absdx[ip[nused + i__]]; /* L30: */ } gapmax = -1.; i__1 = MIN2(usubc_1.nsmax,nleft); for (ns1 = usubc_1.nsmin; ns1 <= i__1; ++ns1) { as1 += absdx[ip[nused + ns1]]; ns2 = nleft - ns1; if (ns2 > 0) { if (ns2 >= ((ns2 - 1) / usubc_1.nsmax + 1) * usubc_1.nsmin) { as2 = asleft - as1; gap = as1 / ns1 - as2 / ns2; if (gap > gapmax) { gapmax = gap; nsvals[*nsubs] = ns1; as1max = as1; } } } else { if (as1 / ns1 > gapmax) { nsvals[*nsubs] = ns1; return 0; } } /* L40: */ } nused += nsvals[*nsubs]; nleft = *n - nused; asleft -= as1max; goto L20; } return 0; } /* partx_ */ /* sortd.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int sortd_(integer *n, doublereal *xkey, integer *ix) { /* System generated locals */ integer i__1; /* Local variables */ integer ixip1, i__, ilast, iswap, ifirst, ixi; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* sortd uses the shakersort method to sort an array of keys */ /* in decreasing order. The sort is performed implicitly by */ /* modifying a vector of indices. */ /* For nearly sorted arrays, sortd requires O(n) comparisons. */ /* for completely unsorted arrays, sortd requires O(n**2) */ /* comparisons and will be inefficient unless n is small. */ /* input */ /* n - number of components */ /* xkey - double precision vector of keys */ /* ix - integer vector of indices */ /* output */ /* ix - indices satisfy xkey(ix(i)) .ge. xkey(ix(i+1)) */ /* for i = 1,...,n-1 */ /* local variables */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --ix; --xkey; /* Function Body */ ifirst = 1; iswap = 1; ilast = *n - 1; L10: if (ifirst <= ilast) { i__1 = ilast; for (i__ = ifirst; i__ <= i__1; ++i__) { ixi = ix[i__]; ixip1 = ix[i__ + 1]; if (xkey[ixi] < xkey[ixip1]) { ix[i__] = ixip1; ix[i__ + 1] = ixi; iswap = i__; } /* L20: */ } ilast = iswap - 1; i__1 = ifirst; for (i__ = ilast; i__ >= i__1; --i__) { ixi = ix[i__]; ixip1 = ix[i__ + 1]; if (xkey[ixi] < xkey[ixip1]) { ix[i__] = ixip1; ix[i__ + 1] = ixi; iswap = i__; } /* L30: */ } ifirst = iswap + 1; goto L10; } return 0; } /* sortd_ */ /* newpt.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int newpt_(integer *ns, doublereal *coef, doublereal *xbase, doublereal *xold, logical *new__, doublereal *xnew, logical *small) { /* System generated locals */ integer i__1; /* Local variables */ integer i__; logical eqold; doublereal xoldi; logical eqbase; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* newpt performs reflections, expansions, contractions, and */ /* shrinkages (massive contractions) by computing: */ /* xbase + coef * (xbase - xold) */ /* The result is stored in xnew if new .eq. .true., */ /* in xold otherwise. */ /* use : coef .gt. 0 to reflect */ /* coef .lt. 0 to expand, contract, or shrink */ /* input */ /* ns - number of components (subspace dimension) */ /* coef - one of four simplex method coefficients */ /* xbase - double precision ns-vector representing base */ /* point */ /* xold - double precision ns-vector representing old */ /* point */ /* new - logical switch */ /* = .true. : store result in xnew */ /* = .false. : store result in xold, xnew is not */ /* referenced */ /* output */ /* xold - unchanged if new .eq. .true., contains new */ /* point otherwise */ /* xnew - double precision ns-vector representing new */ /* point if new .eq. .true., not referenced */ /* otherwise */ /* small - logical flag */ /* = .true. : coincident points */ /* = .false. : otherwise */ /* local variables */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --xold; --xbase; --xnew; /* Function Body */ eqbase = TRUE_; eqold = TRUE_; if (*new__) { i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { xnew[i__] = xbase[i__] + *coef * (xbase[i__] - xold[i__]); eqbase = eqbase && xnew[i__] == xbase[i__]; eqold = eqold && xnew[i__] == xold[i__]; /* L10: */ } } else { i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { xoldi = xold[i__]; xold[i__] = xbase[i__] + *coef * (xbase[i__] - xold[i__]); eqbase = eqbase && xold[i__] == xbase[i__]; eqold = eqold && xold[i__] == xoldi; /* L20: */ } } *small = eqbase || eqold; return 0; } /* newpt_ */ /* start.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int start_(integer *n, doublereal *x, doublereal *step, integer *ns, integer *ips, doublereal *s, logical *small) { /* System generated locals */ integer s_dim1, s_offset, i__1; /* Local variables */ integer i__, j; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* start creates the initial simplex for simplx minimization. */ /* input */ /* n - problem dimension */ /* x - current best point */ /* step - stepsizes for corresponding components of x */ /* ns - subspace dimension */ /* ips - permutation vector */ /* output */ /* s - first ns+1 columns contain initial simplex */ /* small - logical flag */ /* = .true. : coincident points */ /* = .false. : otherwise */ /* local variables */ /* subroutines and functions */ /* blas */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --ips; --step; --x; s_dim1 = *ns; s_offset = 1 + s_dim1 * 1; s -= s_offset; /* Function Body */ i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { s[i__ + s_dim1] = x[ips[i__]]; /* L10: */ } i__1 = *ns + 1; for (j = 2; j <= i__1; ++j) { dcopy_(ns, &s[s_dim1 + 1], &c__1, &s[j * s_dim1 + 1], &c__1); s[j - 1 + j * s_dim1] = s[j - 1 + s_dim1] + step[ips[j - 1]]; /* L20: */ } /* check for coincident points */ i__1 = *ns + 1; for (j = 2; j <= i__1; ++j) { if (s[j - 1 + j * s_dim1] == s[j - 1 + s_dim1]) { goto L40; } /* L30: */ } *small = FALSE_; return 0; /* coincident points */ L40: *small = TRUE_; return 0; } /* start_ */ /* fstats.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int fstats_(doublereal *fx, integer *ifxwt, logical *reset) { /* System generated locals */ doublereal d__1, d__2, d__3; /* Local variables */ static doublereal fscale; static integer nsv; static doublereal f1sv; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* fstats modifies the common /usubc/ variables nfxe,fxstat. */ /* input */ /* fx - most recent evaluation of f at best x */ /* ifxwt - integer weight for fx */ /* reset - logical switch */ /* = .true. : initialize nfxe,fxstat */ /* = .false. : update nfxe,fxstat */ /* common */ /* local variables */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ if (*reset) { usubc_1.nfxe = *ifxwt; usubc_1.fxstat[0] = *fx; usubc_1.fxstat[1] = *fx; usubc_1.fxstat[2] = *fx; usubc_1.fxstat[3] = 0.; } else { nsv = usubc_1.nfxe; f1sv = usubc_1.fxstat[0]; usubc_1.nfxe += *ifxwt; usubc_1.fxstat[0] += *ifxwt * (*fx - usubc_1.fxstat[0]) / usubc_1.nfxe; usubc_1.fxstat[1] = MAX2(usubc_1.fxstat[1],*fx); usubc_1.fxstat[2] = MIN2(usubc_1.fxstat[2],*fx); /* Computing MAX */ d__1 = fabs(usubc_1.fxstat[1]), d__2 = fabs(usubc_1.fxstat[2]), d__1 = MAX2(d__1,d__2); fscale = MAX2(d__1,1.); /* Computing 2nd power */ d__1 = usubc_1.fxstat[3] / fscale; /* Computing 2nd power */ d__2 = (usubc_1.fxstat[0] - f1sv) / fscale; /* Computing 2nd power */ d__3 = (*fx - usubc_1.fxstat[0]) / fscale; usubc_1.fxstat[3] = fscale * sqrt(((nsv - 1) * (d__1 * d__1) + nsv * ( d__2 * d__2) + *ifxwt * (d__3 * d__3)) / (usubc_1.nfxe - 1)); } return 0; } /* fstats_ */ /* evalf.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ /* Common Block Declarations */ static struct { doublereal fbonus, sfstop, sfbest; logical new__; } isubc_; #define isubc_1 isubc_ static logical c_true = TRUE_; static logical c_false = FALSE_; static int evalf_(D_fp f,void*fdata, integer *ns, integer *ips, doublereal *xs, integer *n, doublereal *x, doublereal *sfx, integer *nfe) { /* System generated locals */ integer i__1; /* Local variables */ static integer i__; static doublereal fx; static logical newbst; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* evalf evaluates the function f at a point defined by x */ /* with ns of its components replaced by those in xs. */ /* input */ /* f - user supplied function f(n,x) to be optimized */ /* ns - subspace dimension */ /* ips - permutation vector */ /* xs - double precision ns-vector to be mapped to x */ /* n - problem dimension */ /* x - double precision n-vector */ /* nfe - number of function evaluations */ /* output */ /* sfx - signed value of f evaluated at x */ /* nfe - incremented number of function evaluations */ /* common */ /* local variables */ /* subroutines and functions */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --ips; --xs; --x; /* Function Body */ i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { x[ips[i__]] = xs[i__]; /* L10: */ } usubc_1.newx = isubc_1.new__ || usubc_1.irepl != 2; fx = (*f)(*n, &x[1], fdata); if (usubc_1.irepl == 0) { if (usubc_1.minf) { *sfx = fx; } else { *sfx = -fx; } } else if (isubc_1.new__) { if (usubc_1.minf) { *sfx = fx; newbst = fx < usubc_1.ftest; } else { *sfx = -fx; newbst = fx > usubc_1.ftest; } if (usubc_1.initx || newbst) { if (usubc_1.irepl == 1) { fstats_(&fx, &c__1, &c_true); } usubc_1.ftest = fx; isubc_1.sfbest = *sfx; } } else { if (usubc_1.irepl == 1) { fstats_(&fx, &c__1, &c_false); fx = usubc_1.fxstat[usubc_1.ifxsw - 1]; } usubc_1.ftest = fx + isubc_1.fbonus * usubc_1.fxstat[3]; if (usubc_1.minf) { *sfx = usubc_1.ftest; isubc_1.sfbest = fx; } else { *sfx = -usubc_1.ftest; isubc_1.sfbest = -fx; } } ++(*nfe); return 0; } /* evalf_ */ /* simplx.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int simplx_(D_fp f, void *fdata, integer *n, doublereal *step, integer * ns, integer *ips, nlopt_stopping *stop, logical *cmode, doublereal *x, doublereal *fx, integer *nfe, doublereal *s, doublereal *fs, integer * iflag) { /* System generated locals */ integer s_dim1, s_offset, i__1; doublereal d__1, d__2; /* Local variables */ static integer inew; static integer npts; static integer i__, j; static integer icent; static logical small; static integer itemp; static doublereal fc, fe; static integer ih, il; static doublereal fr; static integer is; static logical updatc; static doublereal dum, tol; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* simplx uses the Nelder-Mead simplex method to minimize the */ /* function f on a subspace. */ /* input */ /* f - function to be minimized, declared external in */ /* calling routine */ /* n - problem dimension */ /* step - stepsizes for corresponding components of x */ /* ns - subspace dimension */ /* ips - permutation vector */ /* maxnfe - maximum number of function evaluations */ /* cmode - logical switch */ /* = .true. : continuation of previous call */ /* = .false. : first call */ /* x - starting guess for minimum */ /* fx - value of f at x */ /* nfe - number of function evaluations */ /* s - double precision work array of dimension .ge. */ /* ns*(ns+3) used to store simplex */ /* fs - double precision work array of dimension .ge. */ /* ns+1 used to store function values of simplex */ /* vertices */ /* output */ /* x - computed minimum */ /* fx - value of f at x */ /* nfe - incremented number of function evaluations */ /* iflag - error flag */ /* = -1 : maxnfe exceeded */ /* = 0 : simplex reduced by factor of psi */ /* = 1 : limit of machine precision */ /* = 2 : reached fstop */ /* common */ /* local variables */ /* subroutines and functions */ /* blas */ /* fortran */ /* ----------------------------------------------------------- */ /* Parameter adjustments */ --x; --step; --fs; s_dim1 = *ns; s_offset = 1 + s_dim1 * 1; s -= s_offset; --ips; /* Function Body */ if (*cmode) { goto L50; } npts = *ns + 1; icent = *ns + 2; itemp = *ns + 3; updatc = FALSE_; start_(n, &x[1], &step[1], ns, &ips[1], &s[s_offset], &small); if (small) { *iflag = 1; return 0; } if (usubc_1.irepl > 0) { isubc_1.new__ = FALSE_; evalf_((D_fp)f,fdata, ns, &ips[1], &s[s_dim1 + 1], n, &x[1], &fs[1], nfe); *(stop->nevals_p)++; } else { fs[1] = *fx; } isubc_1.new__ = TRUE_; i__1 = npts; for (j = 2; j <= i__1; ++j) { evalf_((D_fp)f, fdata,ns, &ips[1], &s[j * s_dim1 + 1], n, &x[1], &fs[j], nfe); *(stop->nevals_p)++; /* L10: */ } il = 1; order_(&npts, &fs[1], &il, &is, &ih); tol = usubc_1.psi * dist_(ns, &s[ih * s_dim1 + 1], &s[il * s_dim1 + 1]); /* main loop */ L20: calcc_(ns, &s[s_offset], &ih, &inew, &updatc, &s[icent * s_dim1 + 1]); updatc = TRUE_; inew = ih; /* reflect */ newpt_(ns, &usubc_1.alpha, &s[icent * s_dim1 + 1], &s[ih * s_dim1 + 1], & c_true, &s[itemp * s_dim1 + 1], &small); if (small) { goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[itemp * s_dim1 + 1], n, &x[1], &fr, nfe); *(stop->nevals_p)++; if (fr < fs[il]) { /* expand */ d__1 = -usubc_1.gamma; newpt_(ns, &d__1, &s[icent * s_dim1 + 1], &s[itemp * s_dim1 + 1], & c_true, &s[ih * s_dim1 + 1], &small); if (small) { goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[ih * s_dim1 + 1], n, &x[1], &fe, nfe); *(stop->nevals_p)++; if (fe < fr) { fs[ih] = fe; } else { dcopy_(ns, &s[itemp * s_dim1 + 1], &c__1, &s[ih * s_dim1 + 1], & c__1); fs[ih] = fr; } } else if (fr < fs[is]) { /* accept reflected point */ dcopy_(ns, &s[itemp * s_dim1 + 1], &c__1, &s[ih * s_dim1 + 1], &c__1); fs[ih] = fr; } else { /* contract */ if (fr > fs[ih]) { d__1 = -usubc_1.beta; newpt_(ns, &d__1, &s[icent * s_dim1 + 1], &s[ih * s_dim1 + 1], & c_true, &s[itemp * s_dim1 + 1], &small); } else { d__1 = -usubc_1.beta; newpt_(ns, &d__1, &s[icent * s_dim1 + 1], &s[itemp * s_dim1 + 1], &c_false, &dum, &small); } if (small) { goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[itemp * s_dim1 + 1], n, &x[1], &fc, nfe); *(stop->nevals_p)++; /* Computing MIN */ d__1 = fr, d__2 = fs[ih]; if (fc < MIN2(d__1,d__2)) { dcopy_(ns, &s[itemp * s_dim1 + 1], &c__1, &s[ih * s_dim1 + 1], & c__1); fs[ih] = fc; } else { /* shrink simplex */ i__1 = npts; for (j = 1; j <= i__1; ++j) { if (j != il) { d__1 = -usubc_1.delta; newpt_(ns, &d__1, &s[il * s_dim1 + 1], &s[j * s_dim1 + 1], &c_false, &dum, &small); if (small) { goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[j * s_dim1 + 1], n, &x[1], &fs[j], nfe); *(stop->nevals_p)++; } /* L30: */ } } updatc = FALSE_; } order_(&npts, &fs[1], &il, &is, &ih); /* check termination */ L40: if (usubc_1.irepl == 0) { *fx = fs[il]; } else { *fx = isubc_1.sfbest; } L50: if (nlopt_stop_forced(stop)) *iflag = -20; else if (*fx < stop->minf_max) *iflag = 2; else if (nlopt_stop_evals(stop)) *iflag = -1; else if (nlopt_stop_time(stop)) *iflag = -10; else if (dist_(ns, &s[ih * s_dim1 + 1], &s[il * s_dim1 + 1]) <= tol || small) *iflag = 0; else goto L20; /* end main loop, return best point */ i__1 = *ns; for (i__ = 1; i__ <= i__1; ++i__) { x[ips[i__]] = s[i__ + il * s_dim1]; /* L60: */ } return 0; } /* simplx_ */ /* subopt.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int subopt_(integer *n) { /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* subopt sets options for subplx. */ /* input */ /* n - problem dimension */ /* common */ /* subroutines and functions */ /* fortran */ /* ----------------------------------------------------------- */ /* *********************************************************** */ /* simplex method strategy parameters */ /* *********************************************************** */ /* alpha - reflection coefficient */ /* alpha .gt. 0 */ usubc_1.alpha = 1.; /* beta - contraction coefficient */ /* 0 .lt. beta .lt. 1 */ usubc_1.beta = .5; /* gamma - expansion coefficient */ /* gamma .gt. 1 */ usubc_1.gamma = 2.; /* delta - shrinkage (massive contraction) coefficient */ /* 0 .lt. delta .lt. 1 */ usubc_1.delta = .5; /* *********************************************************** */ /* subplex method strategy parameters */ /* *********************************************************** */ /* psi - simplex reduction coefficient */ /* 0 .lt. psi .lt. 1 */ usubc_1.psi = .25; /* omega - step reduction coefficient */ /* 0 .lt. omega .lt. 1 */ usubc_1.omega = .1; /* nsmin and nsmax specify a range of subspace dimensions. */ /* In addition to satisfying 1 .le. nsmin .le. nsmax .le. n, */ /* nsmin and nsmax must be chosen so that n can be expressed */ /* as a sum of positive integers where each of these integers */ /* ns(i) satisfies nsmin .le. ns(i) .ge. nsmax. */ /* Specifically, */ /* nsmin*ceil(n/nsmax) .le. n must be true. */ /* nsmin - subspace dimension minimum */ usubc_1.nsmin = MIN2(2,*n); /* nsmax - subspace dimension maximum */ usubc_1.nsmax = MIN2(5,*n); /* *********************************************************** */ /* subplex method special cases */ /* *********************************************************** */ /* nelder-mead simplex method with periodic restarts */ /* nsmin = nsmax = n */ /* *********************************************************** */ /* nelder-mead simplex method */ /* nsmin = nsmax = n, psi = small positive */ /* *********************************************************** */ /* irepl, ifxsw, and bonus deal with measurement replication. */ /* Objective functions subject to large amounts of noise can */ /* cause an optimization method to halt at a false optimum. */ /* An expensive solution to this problem is to evaluate f */ /* several times at each point and return the average (or max */ /* or min) of these trials as the function value. subplx */ /* performs measurement replication only at the current best */ /* point. The longer a point is retained as best, the more */ /* accurate its function value becomes. */ /* The common variable nfxe contains the number of function */ /* evaluations at the current best point. fxstat contains the */ /* mean, max, min, and standard deviation of these trials. */ /* irepl - measurement replication switch */ /* irepl = 0, 1, or 2 */ /* = 0 : no measurement replication */ /* = 1 : subplx performs measurement replication */ /* = 2 : user performs measurement replication */ /* (This is useful when optimizing on the mean, */ /* max, or min of trials is insufficient. Common */ /* variable initx is true for first function */ /* evaluation. newx is true for first trial at */ /* this point. The user uses subroutine fstats */ /* within his objective function to maintain */ /* fxstat. By monitoring newx, the user can tell */ /* whether to return the function evaluation */ /* (newx = .true.) or to use the new function */ /* evaluation to refine the function evaluation */ /* of the current best point (newx = .false.). */ /* The common variable ftest gives the function */ /* value that a new point must beat to be */ /* considered the new best point.) */ usubc_1.irepl = 0; /* ifxsw - measurement replication optimization switch */ /* ifxsw = 1, 2, or 3 */ /* = 1 : retain mean of trials as best function value */ /* = 2 : retain max */ /* = 3 : retain min */ usubc_1.ifxsw = 1; /* Since the current best point will also be the most */ /* accurately evaluated point whenever irepl .gt. 0, a bonus */ /* should be added to the function value of the best point */ /* so that the best point is not replaced by a new point */ /* that only appears better because of noise. */ /* subplx uses bonus to determine how many multiples of */ /* fxstat(4) should be added as a bonus to the function */ /* evaluation. (The bonus is adjusted automatically by */ /* subplx when ifxsw or minf is changed.) */ /* bonus - measurement replication bonus coefficient */ /* bonus .ge. 0 (normally, bonus = 0 or 1) */ /* = 0 : bonus not used */ /* = 1 : bonus used */ usubc_1.bonus = 1.; /* nfstop = 0 : f(x) is not tested against fstop */ /* = 1 : if f(x) has reached fstop, subplx returns */ /* iflag = 2 */ /* = 2 : (only valid when irepl .gt. 0) */ /* if f(x) has reached fstop and */ /* nfxe .gt. nfstop, subplx returns iflag = 2 */ usubc_1.nfstop = 0; /* fstop - f target value */ /* Its usage is determined by the value of nfstop. */ /* minf - logical switch */ /* = .true. : subplx performs minimization */ /* = .false. : subplx performs maximization */ usubc_1.minf = TRUE_; return 0; } /* subopt_ */ /* setstp.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static double d_sign(doublereal *x, doublereal *y) { return copysign(*x, *y); } static int setstp_(integer *nsubs, integer *n, doublereal *deltax, doublereal *step) { /* System generated locals */ integer i__1; doublereal d__1, d__2, d__3; /* Builtin functions */ /* double d_sign(doublereal *, doublereal *); */ /* Local variables */ static integer i__; static doublereal stpfac; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* setstp sets the stepsizes for the corresponding components */ /* of the solution vector. */ /* input */ /* nsubs - number of subspaces */ /* n - number of components (problem dimension) */ /* deltax - vector of change in solution vector */ /* step - stepsizes for corresponding components of */ /* solution vector */ /* output */ /* step - new stepsizes */ /* common */ /* local variables */ /* subroutines and functions */ /* blas */ /* fortran */ /* ----------------------------------------------------------- */ /* set new step */ /* Parameter adjustments */ --step; --deltax; /* Function Body */ if (*nsubs > 1) { /* Computing MIN */ /* Computing MAX */ d__3 = dasum_(n, &deltax[1], &c__1) / dasum_(n, &step[1], &c__1); d__1 = MAX2(d__3,usubc_1.omega), d__2 = 1. / usubc_1.omega; stpfac = MIN2(d__1,d__2); } else { stpfac = usubc_1.psi; } dscal_(n, &stpfac, &step[1], &c__1); /* reorient simplex */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { if (deltax[i__] != 0.) { step[i__] = d_sign(&step[i__], &deltax[i__]); } else { step[i__] = -step[i__]; } /* L10: */ } return 0; } /* setstp_ */ /* subplx.f -- translated by f2c (version 19991025). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ static int subplx_(D_fp f, void *fdata, integer *n, nlopt_stopping *stop, integer *mode, const doublereal *scale, doublereal *x, doublereal *fx, integer *nfe, doublereal *work, integer *iwork, integer *iflag) { /* Initialized data */ static doublereal bnsfac[6] /* was [3][2] */ = { -1.,-2.,0.,1.,0.,2. }; /* System generated locals */ integer i__1; doublereal d__1, d__2, d__3, d__4, d__5, d__6; /* Local variables */ static integer i__; static logical cmode; static integer istep; static doublereal xpscl; static integer nsubs, ipptr; static integer isptr; static integer ns, insfnl, ifsptr; static integer insptr; static integer istptr; static doublereal scl, dum; static integer ins; static doublereal sfx, sfx_old, *x_old; /* Coded by Tom Rowan */ /* Department of Computer Sciences */ /* University of Texas at Austin */ /* subplx uses the subplex method to solve unconstrained */ /* optimization problems. The method is well suited for */ /* optimizing objective functions that are noisy or are */ /* discontinuous at the solution. */ /* subplx sets default optimization options by calling the */ /* subroutine subopt. The user can override these defaults */ /* by calling subopt prior to calling subplx, changing the */ /* appropriate common variables, and setting the value of */ /* mode as indicated below. */ /* By default, subplx performs minimization. */ /* input */ /* f - user supplied function f(n,x) to be optimized, */ /* declared external in calling routine */ /* n - problem dimension */ /* tol - relative error tolerance for x (tol .ge. 0.) */ /* maxnfe - maximum number of function evaluations */ /* mode - integer mode switch with binary expansion */ /* (bit 1) (bit 0) : */ /* bit 0 = 0 : first call to subplx */ /* = 1 : continuation of previous call */ /* bit 1 = 0 : use default options */ /* = 1 : user set options */ /* scale - scale and initial stepsizes for corresponding */ /* components of x */ /* (If scale(1) .lt. 0., */ /* abs(scale(1)) is used for all components of x, */ /* and scale(2),...,scale(n) are not referenced.) */ /* x - starting guess for optimum */ /* work - double precision work array of dimension .ge. */ /* 2*n + nsmax*(nsmax+4) + 1 */ /* (nsmax is set in subroutine subopt. */ /* default: nsmax = min(5,n)) */ /* iwork - integer work array of dimension .ge. */ /* n + int(n/nsmin) */ /* (nsmin is set in subroutine subopt. */ /* default: nsmin = min(2,n)) */ /* output */ /* x - computed optimum */ /* fx - value of f at x */ /* nfe - number of function evaluations */ /* iflag - error flag */ /* = -2 : invalid input */ /* = -1 : maxnfe exceeded */ /* = 0 : tol satisfied */ /* = 1 : limit of machine precision */ /* = 2 : fstop reached (fstop usage is determined */ /* by values of options minf, nfstop, and */ /* irepl. default: f(x) not tested against */ /* fstop) */ /* iflag should not be reset between calls to */ /* subplx. */ /* common */ /* local variables */ /* subroutines and functions */ /* blas */ /* fortran */ /* data */ /* Parameter adjustments */ --x; --scale; --work; --iwork; x_old = work; work += *n; /* Function Body */ /* ----------------------------------------------------------- */ if (*mode % 2 == 0) { /* first call, check input */ if (*n < 1) { goto L120; } if (scale[1] >= 0.) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xpscl = x[i__] + scale[i__]; if (xpscl == x[i__]) { goto L120; } /* L10: */ } } else { scl = fabs(scale[1]); i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xpscl = x[i__] + scl; if (xpscl == x[i__]) { goto L120; } /* L20: */ } } if (*mode / 2 % 2 == 0) { subopt_(n); } else { if (usubc_1.alpha <= 0.) { goto L120; } if (usubc_1.beta <= 0. || usubc_1.beta >= 1.) { goto L120; } if (usubc_1.gamma <= 1.) { goto L120; } if (usubc_1.delta <= 0. || usubc_1.delta >= 1.) { goto L120; } if (usubc_1.psi <= 0. || usubc_1.psi >= 1.) { goto L120; } if (usubc_1.omega <= 0. || usubc_1.omega >= 1.) { goto L120; } if (usubc_1.nsmin < 1 || usubc_1.nsmax < usubc_1.nsmin || *n < usubc_1.nsmax) { goto L120; } if (*n < ((*n - 1) / usubc_1.nsmax + 1) * usubc_1.nsmin) { goto L120; } if (usubc_1.irepl < 0 || usubc_1.irepl > 2) { goto L120; } if (usubc_1.ifxsw < 1 || usubc_1.ifxsw > 3) { goto L120; } if (usubc_1.bonus < 0.) { goto L120; } if (usubc_1.nfstop < 0) { goto L120; } } /* initialization */ istptr = *n + 1; isptr = istptr + *n; ifsptr = isptr + usubc_1.nsmax * (usubc_1.nsmax + 3); insptr = *n + 1; if (scale[1] > 0.) { dcopy_(n, &scale[1], &c__1, &work[1], &c__1); dcopy_(n, &scale[1], &c__1, &work[istptr], &c__1); } else { dcopy_(n, &scl, &c__0, &work[1], &c__1); dcopy_(n, &scl, &c__0, &work[istptr], &c__1); } i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { iwork[i__] = i__; /* L30: */ } *nfe = 0; usubc_1.nfxe = 1; if (usubc_1.irepl == 0) { isubc_1.fbonus = 0.; } else if (usubc_1.minf) { isubc_1.fbonus = bnsfac[usubc_1.ifxsw - 1] * usubc_1.bonus; } else { isubc_1.fbonus = bnsfac[usubc_1.ifxsw + 2] * usubc_1.bonus; } if (usubc_1.nfstop == 0) { isubc_1.sfstop = 0.; } else if (usubc_1.minf) { isubc_1.sfstop = usubc_1.fstop; } else { isubc_1.sfstop = -usubc_1.fstop; } usubc_1.ftest = 0.; cmode = FALSE_; isubc_1.new__ = TRUE_; usubc_1.initx = TRUE_; evalf_((D_fp)f, fdata, &c__0, &iwork[1], &dum, n, &x[1], &sfx, nfe); *(stop->nevals_p)++; usubc_1.initx = FALSE_; } else { /* continuation of previous call */ if (*iflag == 2) { if (usubc_1.minf) { isubc_1.sfstop = usubc_1.fstop; } else { isubc_1.sfstop = -usubc_1.fstop; } cmode = TRUE_; goto L70; } else if (*iflag == -1) { cmode = TRUE_; goto L70; } else if (*iflag == 0) { cmode = FALSE_; goto L90; } else { return 0; } } /* subplex loop */ L40: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { work[i__] = (d__1 = work[i__], fabs(d__1)); /* L50: */ } sortd_(n, &work[1], &iwork[1]); partx_(n, &iwork[1], &work[1], &nsubs, &iwork[insptr]); dcopy_(n, &x[1], &c__1, &work[1], &c__1); ins = insptr; insfnl = insptr + nsubs - 1; ipptr = 1; /* simplex loop */ sfx_old = sfx; memcpy(&x_old[1], &x[1], sizeof(doublereal) * *n); L60: ns = iwork[ins]; L70: simplx_((D_fp)f, fdata, n, &work[istptr], &ns, &iwork[ipptr], stop, &cmode, &x[1], &sfx, nfe, &work[isptr], &work[ifsptr], iflag); cmode = FALSE_; if (*iflag != 0) { goto L110; } if (ins < insfnl) { ++ins; ipptr += ns; goto L60; } /* end simplex loop */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { work[i__] = x[i__] - work[i__]; /* L80: */ } /* check termination */ if (nlopt_stop_ftol(stop, sfx, sfx_old)) { *iflag = 20; goto L110; } if (nlopt_stop_x(stop, &x[1], &x_old[1])) { *iflag = 0; goto L110; } L90: istep = istptr; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MAX */ d__4 = (d__2 = work[i__], fabs(d__2)), d__5 = (d__1 = work[istep], fabs( d__1)) * usubc_1.psi; /* Computing MAX */ d__6 = (d__3 = x[i__], fabs(d__3)); if (MAX2(d__4,d__5) / MAX2(d__6,1.) > stop->xtol_rel) { setstp_(&nsubs, n, &work[1], &work[istptr]); goto L40; } ++istep; /* L100: */ } /* end subplex loop */ *iflag = 0; L110: if (usubc_1.minf) { *fx = sfx; } else { *fx = -sfx; } return 0; /* invalid input */ L120: *iflag = -2; return 0; } /* subplx_ */ /****************************************************************************/ /****************************************************************************/ /* front-end for subplex routines */ /* Wrapper around f2c'ed subplx_ routine, for multidimensinal unconstrained optimization: Parameters: f: function f(n,x,fdata) to be optimized n: problem dimension minf: (output) value of f at minimum x[n]: (input) starting guess position, (output) computed minimum fdata: data pointer passed to f old args: tol: relative error tolerance for x maxnfe: maximum number of function evaluations minf_max, use_minf_max: if use_minf_max, stop when f <= minf_max new args: nlopt_stopping *stop (stopping criteria) scale[n]: (input) scale & initial stepsizes for components of x (if *scale < 0, |*scale| is used for all components) Return value: = -2 : invalid input = -10 : maxtime exceeded = -1 : maxevals exceeded = 0 : tol satisfied = 1 : limit of machine precision = 2 : fstop reached (fstop usage is determined by values of options minf, nfstop, and irepl. default: f(x) not tested against fstop) = 20 : ftol reached = -200 : out of memory */ int nlopt_subplex(subplex_func f, double *minf, double *x, int n, void *fdata, nlopt_stopping *stop, const double *scale) { int mode = 0, *iwork, nsmax, nsmin, errflag, nfe; double *work; nsmax = MIN2(5,n); nsmin = MIN2(2,n); work = (double*) malloc(sizeof(double) * (3*n + nsmax*(nsmax+4) + 1)); if (!work) return -200; iwork = (int*) malloc(sizeof(int) * (n + n/nsmin + 1)); if (!iwork) { free(work); return -200; } subplx_(f,fdata, &n, stop, &mode, scale, x, minf, &nfe, work, iwork, &errflag); free(iwork); free(work); return errflag; } nlopt-2.6.1/src/algs/subplex/subplex.h000066400000000000000000000006271345435414600177240ustar00rootroot00000000000000#ifndef SUBPLEX_H #define SUBPLEX_H #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef double (*subplex_func)(int n, const double *x, void *func_data); extern int nlopt_subplex(subplex_func f, double *minf, double *x, int n, void *fdata, nlopt_stopping *stop, const double *scale); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/api/000077500000000000000000000000001345435414600142255ustar00rootroot00000000000000nlopt-2.6.1/src/api/CMakeLists.txt000066400000000000000000000065221345435414600167720ustar00rootroot00000000000000 # install man if (UNIX) install (FILES nlopt.3 nlopt_minimize.3 nlopt_minimize_constrained.3 DESTINATION ${INSTALL_MAN_DIR}/man3) endif () # generate nlopt.f from nlopt.h enums if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/nlopt.f) file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/nlopt.f "") file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/nlopt.h NLOPT_H_LINES REGEX " NLOPT_[A-Z0-9_]+") set (i 0) foreach (NLOPT_H_LINE ${NLOPT_H_LINES}) if (NOT NLOPT_H_LINE MATCHES "NLOPT_NUM_") string (REGEX REPLACE ".*NLOPT_([A-Z0-9_]+).*" "\\1" ENUM_STRING ${NLOPT_H_LINE}) string (REGEX REPLACE ".*NLOPT_[A-Z0-9_]+ = (-?[0-9]+).*" "\\1" ENUM_VAL ${NLOPT_H_LINE}) if (ENUM_VAL MATCHES "^-?[0-9]+$") set (i ${ENUM_VAL}) endif () set (ENUM_LINE " integer NLOPT_${ENUM_STRING}\n parameter (NLOPT_${ENUM_STRING}=${i})\n") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.f "${ENUM_LINE}") # https://public.kitware.com/Bug/print_bug_page.php?bug_id=8996 if (i MATCHES "^-") math (EXPR i "1 ${i}") else () math (EXPR i "${i} + 1") endif () endif () endforeach () endif () # generate nlopt.hpp from nlopt-in.hpp if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp) file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp "") file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/nlopt-in.hpp NLOPT_HPP_LINES) foreach (NLOPT_HPP_LINE ${NLOPT_HPP_LINES}) list(LENGTH NLOPT_HPP_LINE line_len) # handling trailing backlashes in "file (STRINGS" is a little tricky if (line_len VERSION_LESS 8) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp "${NLOPT_HPP_LINE}\n") else () set (prev_inst FALSE) foreach(NLOPT_HPP_SUBLINE ${NLOPT_HPP_LINE}) # test is we need to add the eaten semicolon if (NLOPT_HPP_SUBLINE MATCHES "\\)$" OR NLOPT_HPP_SUBLINE MATCHES "return") set (new_inst TRUE) else () set (new_inst FALSE) endif () if (NOT prev_inst) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp "${NLOPT_HPP_SUBLINE}") if (new_inst) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp ";") endif () list (FIND NLOPT_HPP_LINE "${NLOPT_HPP_SUBLINE}" index) math (EXPR index "${index} + 1") list (LENGTH NLOPT_HPP_LINE total) if (NOT index STREQUAL total) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp " \\") endif () file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp "\n") endif () set (prev_inst ${new_inst}) endforeach () endif () if (NLOPT_HPP_LINE MATCHES "GEN_ENUMS_HERE") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp " enum algorithm {\n") file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/nlopt.h NLOPT_H_LINES REGEX " NLOPT_[A-Z0-9_]+") foreach (NLOPT_H_LINE ${NLOPT_H_LINES}) string (REGEX REPLACE "NLOPT_" "" ENUM_LINE ${NLOPT_H_LINE}) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp "${ENUM_LINE}\n") if (NLOPT_H_LINE MATCHES "NLOPT_NUM_ALGORITHMS") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp " };\n enum result {\n") elseif (NLOPT_H_LINE MATCHES "NLOPT_MAXTIME_REACHED") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt.hpp " };\n") endif () endforeach () endif () endforeach () endif () nlopt-2.6.1/src/api/deprecated.c000066400000000000000000000157371345435414600165060ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include "nlopt.h" /*************************************************************************/ nlopt_algorithm nlopt_local_search_alg_deriv = NLOPT_LD_MMA; nlopt_algorithm nlopt_local_search_alg_nonderiv = NLOPT_LN_COBYLA; int nlopt_local_search_maxeval = -1; /* no maximum by default */ void NLOPT_STDCALL nlopt_get_local_search_algorithm(nlopt_algorithm * deriv, nlopt_algorithm * nonderiv, int *maxeval) { *deriv = nlopt_local_search_alg_deriv; *nonderiv = nlopt_local_search_alg_nonderiv; *maxeval = nlopt_local_search_maxeval; } void NLOPT_STDCALL nlopt_set_local_search_algorithm(nlopt_algorithm deriv, nlopt_algorithm nonderiv, int maxeval) { nlopt_local_search_alg_deriv = deriv; nlopt_local_search_alg_nonderiv = nonderiv; nlopt_local_search_maxeval = maxeval; } /*************************************************************************/ int nlopt_stochastic_population = 0; int NLOPT_STDCALL nlopt_get_stochastic_population(void) { return nlopt_stochastic_population; } void NLOPT_STDCALL nlopt_set_stochastic_population(int pop) { nlopt_stochastic_population = pop <= 0 ? 0 : (unsigned) pop; } /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_minimize_econstrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data_, ptrdiff_t fc_datum_size, int p, nlopt_func_old h, void *h_data_, ptrdiff_t h_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, double htol_rel, double htol_abs, int maxeval, double maxtime) { char *fc_data = (char *) fc_data_; char *h_data = (char *) h_data_; nlopt_opt opt; nlopt_result ret; int i; if (n < 0 || m < 0 || p < 0) return NLOPT_INVALID_ARGS; opt = nlopt_create(algorithm, (unsigned) n); if (!opt) return NLOPT_INVALID_ARGS; ret = nlopt_set_min_objective(opt, (nlopt_func) f, f_data); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } for (i = 0; i < m; ++i) { ret = nlopt_add_inequality_constraint(opt, (nlopt_func) fc, fc_data + i * fc_datum_size, 0.0); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } } (void) htol_rel; /* unused */ for (i = 0; i < p; ++i) { ret = nlopt_add_equality_constraint(opt, (nlopt_func) h, h_data + i * h_datum_size, htol_abs); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } } ret = nlopt_set_lower_bounds(opt, lb); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_upper_bounds(opt, ub); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_stopval(opt, minf_max); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_ftol_rel(opt, ftol_rel); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_ftol_abs(opt, ftol_abs); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_xtol_rel(opt, xtol_rel); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } if (xtol_abs) ret = nlopt_set_xtol_abs(opt, xtol_abs); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_maxeval(opt, maxeval); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_set_maxtime(opt, maxtime); if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } ret = nlopt_optimize(opt, x, minf); nlopt_destroy(opt); return ret; } /* don't emit inner deprecated warnings */ #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__==3 && __GNUC_MINOR__ > 0)) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif nlopt_result NLOPT_STDCALL nlopt_minimize_constrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) { return nlopt_minimize_econstrained(algorithm, n, f, f_data, m, fc, fc_data, fc_datum_size, 0, NULL, NULL, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, ftol_rel, ftol_abs, maxeval, maxtime); } nlopt_result NLOPT_STDCALL nlopt_minimize(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) { return nlopt_minimize_constrained(algorithm, n, f, f_data, 0, NULL, NULL, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, maxeval, maxtime); } nlopt-2.6.1/src/api/f77api.c000066400000000000000000000121421345435414600154660ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include "nlopt.h" /*-----------------------------------------------------------------------*/ /* wrappers around f77 procedures */ typedef void (*nlopt_f77_func) (double *val, const int *n, const double *x, double *gradient, const int *need_gradient, void *func_data); typedef void (*nlopt_f77_mfunc) (const int *m, double *val, const int *n, const double *x, double *gradient, const int *need_gradient, void *func_data); typedef struct { nlopt_f77_func f; nlopt_f77_mfunc mf; void *f_data; } f77_func_data; static void *free_f77_func_data(void *p) { free(p); return NULL; } static void *dup_f77_func_data(void *p) { void *pnew = (void *) malloc(sizeof(f77_func_data)); if (pnew) memcpy(pnew, p, sizeof(f77_func_data)); return pnew; } static double f77_func_wrap_old(int n, const double *x, double *grad, void *data) { f77_func_data *d = (f77_func_data *) data; double val; int need_gradient = grad != 0; d->f(&val, &n, x, grad, &need_gradient, d->f_data); return val; } static double f77_func_wrap(unsigned n, const double *x, double *grad, void *data) { f77_func_data *d = (f77_func_data *) data; int ni = (int) n; double val; int need_gradient = grad != 0; d->f(&val, &ni, x, grad, &need_gradient, d->f_data); return val; } static void f77_mfunc_wrap(unsigned m, double *result, unsigned n, const double *x, double *grad, void *data) { f77_func_data *d = (f77_func_data *) data; int mi = (int) m; int ni = (int) n; int need_gradient = grad != 0; d->mf(&mi, result, &ni, x, grad, &need_gradient, d->f_data); } /*-----------------------------------------------------------------------*/ #define F77_GET(name,NAME,T) NLOPT_EXTERN(void) F77_(nlo_get_##name,NLO_GET_##NAME)(T *val, nlopt_opt *opt) { *val = (T) nlopt_get_##name(*opt); } #define F77_SET(name,NAME,T) NLOPT_EXTERN(void) F77_(nlo_set_##name,NLO_SET_##NAME)(int *ret, nlopt_opt *opt, T *val) { *ret = (int) nlopt_set_##name(*opt, *val); } #define F77_GETSET(name,NAME,T) F77_GET(name,NAME,T) F77_SET(name,NAME,T) #define F77_GETA(name,NAME,T) NLOPT_EXTERN(void) F77_(nlo_get_##name,NLO_GET_##NAME)(int *ret, nlopt_opt *opt, T *val) { *ret = (int) nlopt_get_##name(*opt, val); } #define F77_SETA(name,NAME,T) NLOPT_EXTERN(void) F77_(nlo_set_##name,NLO_SET_##NAME)(int *ret, nlopt_opt *opt, T *val) { *ret = (int) nlopt_set_##name(*opt, val); } #define F77_GETSETA(name,NAME,T) F77_GETA(name,NAME,T) F77_SETA(name,NAME,T) F77_SET(name##1,NAME##1,T) /*-----------------------------------------------------------------------*/ /* rather than trying to detect the Fortran name-mangling scheme with autoconf, we just include wrappers with all common name-mangling schemes ... this avoids problems and also allows us to work with multiple Fortran compilers on the same machine. Since the Fortran wrapper functions are so small, the library bloat of including them multiple times is negligible and seems well worth the benefit. */ # define F77CALL(a, A) F77(a, A) /* name + underscore is by far the most common (gfortran, g77, Intel, ...) */ # define F77(a, A) a ## _ # include "f77funcs.h" /* also include g77 convention of name + double underscore for identifiers containing underscores */ # define F77_(a, A) a ## __ # include "f77funcs_.h" # undef F77_ /* AIX and HPUX use just the lower-case name */ # undef F77 # define F77(a, A) a # include "f77funcs.h" /* Old Cray Unicos, as well as several Windows Fortran compilers (Digital/Compaq/HP Visual Fortran and Intel Fortran) use all-uppercase name */ /* Digital/Compaq/HP Visual Fortran, Intel Fortran. stdcall attribute is apparently required to adjust for calling conventions (callee pops stack in stdcall). See also: http://msdn.microsoft.com/library/en-us/vccore98/html/_core_mixed.2d.language_programming.3a_.overview.asp */ # undef F77 # undef F77CALL # define F77(a, A) NLOPT_STDCALL A # define F77CALL(a, A) A # include "f77funcs.h" nlopt-2.6.1/src/api/f77funcs.h000066400000000000000000000114331345435414600160420ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__==3 && __GNUC_MINOR__ > 0)) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif /* Fortran API wrappers, using the F77 macro defined in f77api.c. This header file is #included one or more times from f77api.c in order to define verions of the Fortran API for various compilers. In homage to Fortran 77, we stick with 6-character subroutine names. The return value of the function is converted into the first argument of the subroutine. */ /* nlopt_minimize_constrained */ void F77(nloptc, NLOPTC) (int *info, const int *algorithm, const int *n, nlopt_f77_func f, void *f_data, const int *m, nlopt_f77_func fc, char *fc_data, char *fc_second_datum, const double *lb, const double *ub, double *x, double *minf, const double *minf_max, const double *ftol_rel, const double *ftol_abs, const double *xtol_rel, const double *xtol_abs, const int *have_xtol_abs, const int *maxeval, const double *maxtime) { f77_func_data d, *dc; int i; d.f = f; d.f_data = f_data; if (*m < 0) { *info = NLOPT_INVALID_ARGS; return; } dc = (f77_func_data *) malloc(sizeof(f77_func_data) * *m); if (*m > 0 && !dc) { *info = NLOPT_OUT_OF_MEMORY; return; } for (i = 0; i < *m; ++i) { dc[i].f = fc; dc[i].f_data = fc_data + i * (fc_second_datum - fc_data); } *info = nlopt_minimize_constrained((nlopt_algorithm) * algorithm, *n, f77_func_wrap_old, &d, *m, f77_func_wrap_old, dc, sizeof(f77_func_data), lb, ub, x, minf, *minf_max, *ftol_rel, *ftol_abs, *xtol_rel, *have_xtol_abs ? xtol_abs : 0, *maxeval, *maxtime); if (dc) free(dc); } /* nlopt_minimize */ void F77(nloptm, NLOPTM) (int *info, const int *algorithm, const int *n, nlopt_f77_func f, void *f_data, const double *lb, const double *ub, double *x, double *minf, const double *minf_max, const double *ftol_rel, const double *ftol_abs, const double *xtol_rel, const double *xtol_abs, const int *have_xtol_abs, const int *maxeval, const double *maxtime) { int m = 0; F77CALL(nloptc, NLOPTC) (info, algorithm, n, f, f_data, &m, 0, 0, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, have_xtol_abs, maxeval, maxtime); } void F77(nlosr, NLOSR) (const int *seed) { nlopt_srand((unsigned long) *seed); } void F77(nlosrt, NLOSRT) (void) { nlopt_srand_time(); } void F77(nloptv, NLOPTV) (int *major, int *minor, int *bugfix) { nlopt_version(major, minor, bugfix); } void F77(nlogls, NLOGLS) (int *ideriv, int *inonderiv, int *maxeval) { nlopt_algorithm deriv, nonderiv; nlopt_get_local_search_algorithm(&deriv, &nonderiv, maxeval); *ideriv = deriv; *inonderiv = nonderiv; } void F77(nlosls, NLOSLS) (int *ideriv, int *inonderiv, int *maxeval) { nlopt_algorithm deriv = (nlopt_algorithm) * ideriv; nlopt_algorithm nonderiv = (nlopt_algorithm) * inonderiv; nlopt_set_local_search_algorithm(deriv, nonderiv, *maxeval); } void F77(nlogsp, NLOGSP) (int *pop) { *pop = nlopt_get_stochastic_population(); } void F77(nlossp, NLOSSP) (const int *pop) { nlopt_set_stochastic_population(*pop); } #define F77_(name,NAME) F77(name,NAME) # include "f77funcs_.h" #undef F77_ nlopt-2.6.1/src/api/f77funcs_.h000066400000000000000000000150531345435414600162030ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* Fortran API wrappers, using the F77 macro defined in f77api.c. This header file is #included one or more times from f77api.c in order to define verions of the Fortran API for various compilers. All of the functions in this file have underscores in their names, which means that they are treated differently for name-mangling (thank you, g77 and f2c) than names without underscores. The return value of a function is converted to the first argument of a subroutine. */ NLOPT_EXTERN(void) F77_(nlo_create, NLO_CREATE) (nlopt_opt * opt, int *alg, int *n) { if (*n < 0) *opt = NULL; else { *opt = nlopt_create((nlopt_algorithm) * alg, (unsigned) *n); nlopt_set_munge(*opt, free_f77_func_data, dup_f77_func_data); } } NLOPT_EXTERN(void) F77_(nlo_copy, NLO_COPY) (nlopt_opt * nopt, nlopt_opt * opt) { *nopt = nlopt_copy(*opt); } NLOPT_EXTERN(void) F77_(nlo_destroy, NLO_DESTROY) (nlopt_opt * opt) { nlopt_destroy(*opt); } NLOPT_EXTERN(void) F77_(nlo_optimize, NLO_OPTIMIZE) (int *ret, nlopt_opt * opt, double *x, double *optf) { *ret = (int) nlopt_optimize(*opt, x, optf); } NLOPT_EXTERN(void) F77_(nlo_set_min_objective, NLO_SET_MIN_OBJECTIVE) (int *ret, nlopt_opt * opt, nlopt_f77_func f, void *f_data) { f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->f = f; d->f_data = f_data; *ret = (int) nlopt_set_min_objective(*opt, f77_func_wrap, d); } NLOPT_EXTERN(void) F77_(nlo_set_max_objective, NLO_SET_MAX_OBJECTIVE) (int *ret, nlopt_opt * opt, nlopt_f77_func f, void *f_data) { f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->f = f; d->f_data = f_data; *ret = (int) nlopt_set_max_objective(*opt, f77_func_wrap, d); } F77_GET(algorithm, ALGORITHM, int) F77_GET(dimension, DIMENSION, int) F77_GETSETA(lower_bounds, LOWER_BOUNDS, double) F77_GETSETA(upper_bounds, UPPER_BOUNDS, double) NLOPT_EXTERN(void) F77_(nlo_remove_inequality_constraints, NLO_REMOVE_INEQUALITY_CONSTRAINTS) (int *ret, nlopt_opt * opt) { *ret = (int) nlopt_remove_inequality_constraints(*opt); } NLOPT_EXTERN(void) F77_(nlo_add_inequality_constraint, NLO_ADD_INEQUALITY_CONSTRAINT) (int *ret, nlopt_opt * opt, nlopt_f77_func fc, void *fc_data, double *tol) { f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->f = fc; d->f_data = fc_data; *ret = (int) nlopt_add_inequality_constraint(*opt, f77_func_wrap, d, *tol); } NLOPT_EXTERN(void) F77_(nlo_add_inequality_mconstraint, NLO_ADD_INEQUALITY_MCONSTRAINT) (int *ret, nlopt_opt * opt, int *m, nlopt_f77_mfunc mfc, void *mfc_data, double *tol) { f77_func_data *d; if (*m < 0) { *ret = (int) NLOPT_INVALID_ARGS; return; } if (*m == 0) { *ret = (int) NLOPT_SUCCESS; return; } d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->mf = mfc; d->f_data = mfc_data; *ret = (int) nlopt_add_inequality_mconstraint(*opt, (unsigned) *m, f77_mfunc_wrap, d, tol); } NLOPT_EXTERN(void) F77_(nlo_remove_equality_constraints, NLO_REMOVE_EQUALITY_CONSTRAINTS) (int *ret, nlopt_opt * opt) { *ret = (int) nlopt_remove_equality_constraints(*opt); } NLOPT_EXTERN(void) F77_(nlo_add_equality_constraint, NLO_ADD_EQUALITY_CONSTRAINT) (int *ret, nlopt_opt * opt, nlopt_f77_func fc, void *fc_data, double *tol) { f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->f = fc; d->f_data = fc_data; *ret = (int) nlopt_add_equality_constraint(*opt, f77_func_wrap, d, *tol); } NLOPT_EXTERN(void) F77_(nlo_add_equality_mconstraint, NLO_ADD_EQUALITY_MCONSTRAINT) (int *ret, nlopt_opt * opt, int *m, nlopt_f77_mfunc mfc, void *mfc_data, double *tol) { f77_func_data *d; if (*m < 0) { *ret = (int) NLOPT_INVALID_ARGS; return; } if (*m == 0) { *ret = (int) NLOPT_SUCCESS; return; } d = (f77_func_data *) malloc(sizeof(f77_func_data)); if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } d->mf = mfc; d->f_data = mfc_data; *ret = (int) nlopt_add_equality_mconstraint(*opt, (unsigned) *m, f77_mfunc_wrap, d, tol); } F77_GETSET(stopval, STOPVAL, double) F77_GETSET(ftol_rel, FTOL_REL, double) F77_GETSET(ftol_abs, FTOL_ABS, double) F77_GETSET(xtol_rel, XTOL_REL, double) F77_GETSETA(xtol_abs, XTOL_ABS, double) F77_GETSET(maxeval, MAXEVAL, int) F77_GET(numevals, NUMEVALS, int) F77_GETSET(maxtime, MAXTIME, double) F77_GETSET(force_stop, FORCE_STOP, int) NLOPT_EXTERN(void) F77_(nlo_force_stop, NLO_FORCE_STOP) (int *ret, nlopt_opt * opt) { *ret = (int) nlopt_force_stop(*opt); } F77_SET(local_optimizer, LOCAL_OPTIMIZER, nlopt_opt) F77_GETSET(population, POPULATION, unsigned) F77_GETSET(vector_storage, vector_storage, unsigned) F77_SETA(default_initial_step, DEFAULT_INITIAL_STEP, double) F77_SETA(initial_step, INITIAL_STEP, double) F77_SET(initial_step1, INITIAL_STEP1, double) NLOPT_EXTERN(void) F77_(nlo_get_initial_step, NLO_GET_INITIAL_STEP) (int *ret, nlopt_opt * opt, const double *x, double *dx) { *ret = (int) nlopt_get_initial_step(*opt, x, dx); } nlopt-2.6.1/src/api/general.c000066400000000000000000000135631345435414600160160ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include "nlopt-internal.h" /*************************************************************************/ void NLOPT_STDCALL nlopt_version(int *major, int *minor, int *bugfix) { *major = MAJOR_VERSION; *minor = MINOR_VERSION; *bugfix = BUGFIX_VERSION; } /*************************************************************************/ static const char nlopt_algorithm_names[NLOPT_NUM_ALGORITHMS][256] = { "DIRECT (global, no-derivative)", "DIRECT-L (global, no-derivative)", "Randomized DIRECT-L (global, no-derivative)", "Unscaled DIRECT (global, no-derivative)", "Unscaled DIRECT-L (global, no-derivative)", "Unscaled Randomized DIRECT-L (global, no-derivative)", "Original DIRECT version (global, no-derivative)", "Original DIRECT-L version (global, no-derivative)", #ifdef NLOPT_CXX "StoGO (global, derivative-based)", "StoGO with randomized search (global, derivative-based)", #else "StoGO (NOT COMPILED)", "StoGO randomized (NOT COMPILED)", #endif "original L-BFGS code by Nocedal et al. (NOT COMPILED)", "Limited-memory BFGS (L-BFGS) (local, derivative-based)", "Principal-axis, praxis (local, no-derivative)", "Limited-memory variable-metric, rank 1 (local, derivative-based)", "Limited-memory variable-metric, rank 2 (local, derivative-based)", "Truncated Newton (local, derivative-based)", "Truncated Newton with restarting (local, derivative-based)", "Preconditioned truncated Newton (local, derivative-based)", "Preconditioned truncated Newton with restarting (local, derivative-based)", "Controlled random search (CRS2) with local mutation (global, no-derivative)", "Multi-level single-linkage (MLSL), random (global, no-derivative)", "Multi-level single-linkage (MLSL), random (global, derivative)", "Multi-level single-linkage (MLSL), quasi-random (global, no-derivative)", "Multi-level single-linkage (MLSL), quasi-random (global, derivative)", "Method of Moving Asymptotes (MMA) (local, derivative)", "COBYLA (Constrained Optimization BY Linear Approximations) (local, no-derivative)", "NEWUOA unconstrained optimization via quadratic models (local, no-derivative)", "Bound-constrained optimization via NEWUOA-based quadratic models (local, no-derivative)", "Nelder-Mead simplex algorithm (local, no-derivative)", "Sbplx variant of Nelder-Mead (re-implementation of Rowan's Subplex) (local, no-derivative)", "Augmented Lagrangian method (local, no-derivative)", "Augmented Lagrangian method (local, derivative)", "Augmented Lagrangian method for equality constraints (local, no-derivative)", "Augmented Lagrangian method for equality constraints (local, derivative)", "BOBYQA bound-constrained optimization via quadratic models (local, no-derivative)", "ISRES evolutionary constrained optimization (global, no-derivative)", "Augmented Lagrangian method (needs sub-algorithm)", "Augmented Lagrangian method for equality constraints (needs sub-algorithm)", "Multi-level single-linkage (MLSL), random (global, needs sub-algorithm)", "Multi-level single-linkage (MLSL), quasi-random (global, needs sub-algorithm)", "Sequential Quadratic Programming (SQP) (local, derivative)", "CCSA (Conservative Convex Separable Approximations) with simple quadratic approximations (local, derivative)", "ESCH evolutionary strategy", #ifdef NLOPT_CXX11 "AGS (global, no-derivative)" #else "AGS (NOT COMPILED)" #endif }; const char *NLOPT_STDCALL nlopt_algorithm_name(nlopt_algorithm a) { if (((int) a) < 0 || a >= NLOPT_NUM_ALGORITHMS) return "UNKNOWN"; return nlopt_algorithm_names[a]; } /*************************************************************************/ /* get thread id, if possible, for use in nlopt_srand_time to ensure that different threads have a different default seed even if they are called simultaneously */ #if defined(_WIN32) || defined(__WIN32__) # include # define my_gettid GetCurrentThreadId #elif defined(HAVE_GETTID_SYSCALL) # include # include # define my_gettid() syscall(SYS_gettid) #elif defined(HAVE_GETPID) # include # include # define my_gettid getpid #else # define my_gettid() (0) #endif /*************************************************************************/ static THREADLOCAL int nlopt_srand_called = 0; void NLOPT_STDCALL nlopt_srand(unsigned long seed) { nlopt_srand_called = 1; nlopt_init_genrand(seed); } void NLOPT_STDCALL nlopt_srand_time(void) { nlopt_srand(nlopt_time_seed() + (unsigned long) my_gettid() * 314159); } void nlopt_srand_time_default(void) { if (!nlopt_srand_called) nlopt_srand_time(); } /*************************************************************************/ nlopt-2.6.1/src/api/nlopt-in.hpp000066400000000000000000000473541345435414600165130ustar00rootroot00000000000000/* Copyright (c) 2007-2011 Massachusetts Institute of Technology * * 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. */ // C++ style wrapper around NLopt API // nlopt.hpp is AUTOMATICALLY GENERATED from nlopt-in.hpp - edit the latter! #ifndef NLOPT_HPP #define NLOPT_HPP #include #include #include #include #include #include #include // convenience overloading for below (not in nlopt:: since has nlopt_ prefix) inline nlopt_result nlopt_get_initial_step(const nlopt_opt opt, double *dx) { return nlopt_get_initial_step(opt, (const double *) NULL, dx); } namespace nlopt { ////////////////////////////////////////////////////////////////////// // nlopt::* namespace versions of the C enumerated types // AUTOMATICALLY GENERATED, DO NOT EDIT // GEN_ENUMS_HERE ////////////////////////////////////////////////////////////////////// typedef nlopt_func func; // nlopt::func synoynm typedef nlopt_mfunc mfunc; // nlopt::mfunc synoynm // alternative to nlopt_func that takes std::vector // ... unfortunately requires a data copy typedef double (*vfunc)(const std::vector &x, std::vector &grad, void *data); ////////////////////////////////////////////////////////////////////// // NLopt-specific exceptions (corresponding to error codes): class roundoff_limited : public std::runtime_error { public: roundoff_limited() : std::runtime_error("nlopt roundoff-limited") {} }; class forced_stop : public std::runtime_error { public: forced_stop() : std::runtime_error("nlopt forced stop") {} }; ////////////////////////////////////////////////////////////////////// class opt { private: nlopt_opt o; void mythrow(nlopt_result ret) const { switch (ret) { case NLOPT_FAILURE: throw std::runtime_error(get_errmsg() ? get_errmsg() : "nlopt failure"); case NLOPT_OUT_OF_MEMORY: throw std::bad_alloc(); case NLOPT_INVALID_ARGS: throw std::invalid_argument(get_errmsg() ? get_errmsg() : "nlopt invalid argument"); case NLOPT_ROUNDOFF_LIMITED: throw roundoff_limited(); case NLOPT_FORCED_STOP: throw forced_stop(); default: break; } } typedef struct { opt *o; mfunc mf; func f; void *f_data; vfunc vf; nlopt_munge munge_destroy, munge_copy; // non-NULL for SWIG wrappers } myfunc_data; // free/destroy f_data in nlopt_destroy and nlopt_copy, respectively static void *free_myfunc_data(void *p) { myfunc_data *d = (myfunc_data *) p; if (d) { if (d->f_data && d->munge_destroy) d->munge_destroy(d->f_data); delete d; } return NULL; } static void *dup_myfunc_data(void *p) { myfunc_data *d = (myfunc_data *) p; if (d) { void *f_data; if (d->f_data && d->munge_copy) { f_data = d->munge_copy(d->f_data); if (!f_data) return NULL; } else f_data = d->f_data; myfunc_data *dnew = new myfunc_data; if (dnew) { *dnew = *d; dnew->f_data = f_data; } return (void*) dnew; } else return NULL; } // nlopt_func wrapper that catches exceptions static double myfunc(unsigned n, const double *x, double *grad, void *d_) { myfunc_data *d = reinterpret_cast(d_); try { return d->f(n, x, grad, d->f_data); } catch (std::bad_alloc&) { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; } catch (std::invalid_argument&) { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; } catch (roundoff_limited&) { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; } catch (forced_stop&) { d->o->forced_stop_reason = NLOPT_FORCED_STOP; } catch (...) { d->o->forced_stop_reason = NLOPT_FAILURE; } d->o->force_stop(); // stop gracefully, opt::optimize will re-throw return HUGE_VAL; } // nlopt_mfunc wrapper that catches exceptions static void mymfunc(unsigned m, double *result, unsigned n, const double *x, double *grad, void *d_) { myfunc_data *d = reinterpret_cast(d_); try { d->mf(m, result, n, x, grad, d->f_data); return; } catch (std::bad_alloc&) { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; } catch (std::invalid_argument&) { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; } catch (roundoff_limited&) { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; } catch (forced_stop&) { d->o->forced_stop_reason = NLOPT_FORCED_STOP; } catch (...) { d->o->forced_stop_reason = NLOPT_FAILURE; } d->o->force_stop(); // stop gracefully, opt::optimize will re-throw for (unsigned i = 0; i < m; ++i) result[i] = HUGE_VAL; } std::vector xtmp, gradtmp, gradtmp0; // scratch for myvfunc // nlopt_func wrapper, using std::vector static double myvfunc(unsigned n, const double *x, double *grad, void *d_){ myfunc_data *d = reinterpret_cast(d_); try { std::vector &xv = d->o->xtmp; if (n) std::memcpy(&xv[0], x, n * sizeof(double)); double val=d->vf(xv, grad ? d->o->gradtmp : d->o->gradtmp0, d->f_data); if (grad && n) { std::vector &gradv = d->o->gradtmp; std::memcpy(grad, &gradv[0], n * sizeof(double)); } return val; } catch (std::bad_alloc&) { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; } catch (std::invalid_argument&) { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; } catch (roundoff_limited&) { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; } catch (forced_stop&) { d->o->forced_stop_reason = NLOPT_FORCED_STOP; } catch (...) { d->o->forced_stop_reason = NLOPT_FAILURE; } d->o->force_stop(); // stop gracefully, opt::optimize will re-throw return HUGE_VAL; } void alloc_tmp() { if (xtmp.size() != nlopt_get_dimension(o)) { xtmp = std::vector(nlopt_get_dimension(o)); gradtmp = std::vector(nlopt_get_dimension(o)); } } result last_result; double last_optf; nlopt_result forced_stop_reason; public: // Constructors etc. opt() : o(NULL), xtmp(0), gradtmp(0), gradtmp0(0), last_result(nlopt::FAILURE), last_optf(HUGE_VAL), forced_stop_reason(NLOPT_FORCED_STOP) {} ~opt() { nlopt_destroy(o); } opt(algorithm a, unsigned n) : o(nlopt_create(nlopt_algorithm(a), n)), xtmp(0), gradtmp(0), gradtmp0(0), last_result(nlopt::FAILURE), last_optf(HUGE_VAL), forced_stop_reason(NLOPT_FORCED_STOP) { if (!o) throw std::bad_alloc(); nlopt_set_munge(o, free_myfunc_data, dup_myfunc_data); } opt(const opt& f) : o(nlopt_copy(f.o)), xtmp(f.xtmp), gradtmp(f.gradtmp), gradtmp0(0), last_result(f.last_result), last_optf(f.last_optf), forced_stop_reason(f.forced_stop_reason) { if (f.o && !o) throw std::bad_alloc(); } opt& operator=(opt const& f) { if (this == &f) return *this; // self-assignment nlopt_destroy(o); o = nlopt_copy(f.o); if (f.o && !o) throw std::bad_alloc(); xtmp = f.xtmp; gradtmp = f.gradtmp; last_result = f.last_result; last_optf = f.last_optf; forced_stop_reason = f.forced_stop_reason; return *this; } // Do the optimization: result optimize(std::vector &x, double &opt_f) { if (o && nlopt_get_dimension(o) != x.size()) throw std::invalid_argument("dimension mismatch"); forced_stop_reason = NLOPT_FORCED_STOP; nlopt_result ret = nlopt_optimize(o, x.empty() ? NULL : &x[0], &opt_f); last_result = result(ret); last_optf = opt_f; if (ret == NLOPT_FORCED_STOP) mythrow(forced_stop_reason); mythrow(ret); return last_result; } // variant mainly useful for SWIG wrappers: std::vector optimize(const std::vector &x0) { std::vector x(x0); last_result = optimize(x, last_optf); return x; } result last_optimize_result() const { return last_result; } double last_optimum_value() const { return last_optf; } // accessors: algorithm get_algorithm() const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); return algorithm(nlopt_get_algorithm(o)); } const char *get_algorithm_name() const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); return nlopt_algorithm_name(nlopt_get_algorithm(o)); } unsigned get_dimension() const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); return nlopt_get_dimension(o); } // Set the objective function void set_min_objective(func f, void *f_data) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_set_min_objective(o, myfunc, d)); // d freed via o } void set_min_objective(vfunc vf, void *f_data) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_set_min_objective(o, myvfunc, d)); // d freed via o alloc_tmp(); } void set_max_objective(func f, void *f_data) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_set_max_objective(o, myfunc, d)); // d freed via o } void set_max_objective(vfunc vf, void *f_data) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_set_max_objective(o, myvfunc, d)); // d freed via o alloc_tmp(); } // for internal use in SWIG wrappers -- variant that // takes ownership of f_data, with munging for destroy/copy void set_min_objective(func f, void *f_data, nlopt_munge md, nlopt_munge mc) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_set_min_objective(o, myfunc, d)); // d freed via o } void set_max_objective(func f, void *f_data, nlopt_munge md, nlopt_munge mc) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_set_max_objective(o, myfunc, d)); // d freed via o } // Nonlinear constraints: void remove_inequality_constraints() { nlopt_result ret = nlopt_remove_inequality_constraints(o); mythrow(ret); } void add_inequality_constraint(func f, void *f_data, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol)); } void add_inequality_constraint(vfunc vf, void *f_data, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_inequality_constraint(o, myvfunc, d, tol)); alloc_tmp(); } void add_inequality_mconstraint(mfunc mf, void *f_data, const std::vector &tol) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_inequality_mconstraint(o, tol.size(), mymfunc, d, tol.empty() ? NULL : &tol[0])); } void remove_equality_constraints() { nlopt_result ret = nlopt_remove_equality_constraints(o); mythrow(ret); } void add_equality_constraint(func f, void *f_data, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol)); } void add_equality_constraint(vfunc vf, void *f_data, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_equality_constraint(o, myvfunc, d, tol)); alloc_tmp(); } void add_equality_mconstraint(mfunc mf, void *f_data, const std::vector &tol) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL; d->munge_destroy = d->munge_copy = NULL; mythrow(nlopt_add_equality_mconstraint(o, tol.size(), mymfunc, d, tol.empty() ? NULL : &tol[0])); } // For internal use in SWIG wrappers (see also above) void add_inequality_constraint(func f, void *f_data, nlopt_munge md, nlopt_munge mc, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol)); } void add_equality_constraint(func f, void *f_data, nlopt_munge md, nlopt_munge mc, double tol=0) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol)); } void add_inequality_mconstraint(mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc, const std::vector &tol) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_add_inequality_mconstraint(o, tol.size(), mymfunc, d, tol.empty() ? NULL : &tol[0])); } void add_equality_mconstraint(mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc, const std::vector &tol) { myfunc_data *d = new myfunc_data; if (!d) throw std::bad_alloc(); d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL; d->munge_destroy = md; d->munge_copy = mc; mythrow(nlopt_add_equality_mconstraint(o, tol.size(), mymfunc, d, tol.empty() ? NULL : &tol[0])); } #define NLOPT_GETSET_VEC(name) \ void set_##name(double val) { \ mythrow(nlopt_set_##name##1(o, val)); \ } \ void get_##name(std::vector &v) const { \ if (o && nlopt_get_dimension(o) != v.size()) \ throw std::invalid_argument("dimension mismatch"); \ mythrow(nlopt_get_##name(o, v.empty() ? NULL : &v[0])); \ } \ std::vector get_##name() const { \ if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \ std::vector v(nlopt_get_dimension(o)); \ get_##name(v); \ return v; \ } \ void set_##name(const std::vector &v) { \ if (o && nlopt_get_dimension(o) != v.size()) \ throw std::invalid_argument("dimension mismatch"); \ mythrow(nlopt_set_##name(o, v.empty() ? NULL : &v[0])); \ } NLOPT_GETSET_VEC(lower_bounds) NLOPT_GETSET_VEC(upper_bounds) // stopping criteria: #define NLOPT_GETSET(T, name) \ T get_##name() const { \ if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \ return nlopt_get_##name(o); \ } \ void set_##name(T name) { \ mythrow(nlopt_set_##name(o, name)); \ } NLOPT_GETSET(double, stopval) NLOPT_GETSET(double, ftol_rel) NLOPT_GETSET(double, ftol_abs) NLOPT_GETSET(double, xtol_rel) NLOPT_GETSET_VEC(xtol_abs) NLOPT_GETSET(int, maxeval) int get_numevals() const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); return nlopt_get_numevals(o); } NLOPT_GETSET(double, maxtime) NLOPT_GETSET(int, force_stop) void force_stop() { set_force_stop(1); } const char *get_errmsg() const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); return nlopt_get_errmsg(o); } // algorithm-specific parameters: void set_local_optimizer(const opt &lo) { nlopt_result ret = nlopt_set_local_optimizer(o, lo.o); mythrow(ret); } NLOPT_GETSET(unsigned, population) NLOPT_GETSET(unsigned, vector_storage) NLOPT_GETSET_VEC(initial_step) void set_default_initial_step(const std::vector &x) { nlopt_result ret = nlopt_set_default_initial_step(o, x.empty() ? NULL : &x[0]); mythrow(ret); } void get_initial_step(const std::vector &x, std::vector &dx) const { if (o && (nlopt_get_dimension(o) != x.size() || nlopt_get_dimension(o) != dx.size())) throw std::invalid_argument("dimension mismatch"); nlopt_result ret = nlopt_get_initial_step(o, x.empty() ? NULL : &x[0], dx.empty() ? NULL : &dx[0]); mythrow(ret); } std::vector get_initial_step_(const std::vector &x) const { if (!o) throw std::runtime_error("uninitialized nlopt::opt"); std::vector v(nlopt_get_dimension(o)); get_initial_step(x, v); return v; } }; #undef NLOPT_GETSET #undef NLOPT_GETSET_VEC ////////////////////////////////////////////////////////////////////// inline void srand(unsigned long seed) { nlopt_srand(seed); } inline void srand_time() { nlopt_srand_time(); } inline void version(int &major, int &minor, int &bugfix) { nlopt_version(&major, &minor, &bugfix); } inline int version_major() { int major, minor, bugfix; nlopt_version(&major, &minor, &bugfix); return major; } inline int version_minor() { int major, minor, bugfix; nlopt_version(&major, &minor, &bugfix); return minor; } inline int version_bugfix() { int major, minor, bugfix; nlopt_version(&major, &minor, &bugfix); return bugfix; } inline const char *algorithm_name(algorithm a) { return nlopt_algorithm_name(nlopt_algorithm(a)); } ////////////////////////////////////////////////////////////////////// } // namespace nlopt #endif /* NLOPT_HPP */ nlopt-2.6.1/src/api/nlopt-internal.h000066400000000000000000000115201345435414600173430ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef NLOPT_INTERNAL_H #define NLOPT_INTERNAL_H #include "nlopt.h" #include "nlopt-util.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /*********************************************************************/ struct nlopt_opt_s { nlopt_algorithm algorithm; /* the optimization algorithm (immutable) */ unsigned n; /* the dimension of the problem (immutable) */ nlopt_func f; void *f_data; /* objective function to minimize */ nlopt_precond pre; /* optional preconditioner for f (NULL if none) */ int maximize; /* nonzero if we are maximizing, not minimizing */ double *lb, *ub; /* lower and upper bounds (length n) */ unsigned m; /* number of inequality constraints */ unsigned m_alloc; /* number of inequality constraints allocated */ nlopt_constraint *fc; /* inequality constraints, length m_alloc */ unsigned p; /* number of equality constraints */ unsigned p_alloc; /* number of inequality constraints allocated */ nlopt_constraint *h; /* equality constraints, length p_alloc */ nlopt_munge munge_on_destroy, munge_on_copy; /* hack for wrappers */ /* stopping criteria */ double stopval; /* stop when f reaches stopval or better */ double ftol_rel, ftol_abs; /* relative/absolute f tolerances */ double xtol_rel, *xtol_abs; /* rel/abs x tolerances */ int maxeval; /* max # evaluations */ int numevals; /* number of evaluations */ double maxtime; /* max time (seconds) */ int force_stop; /* if nonzero, force a halt the next time we try to evaluate the objective during optimization */ /* when local optimization is used, we need a force_stop in the parent object to force a stop in child optimizations */ struct nlopt_opt_s *force_stop_child; /* algorithm-specific parameters */ nlopt_opt local_opt; /* local optimizer */ unsigned stochastic_population; /* population size for stochastic algs */ double *dx; /* initial step sizes (length n) for nonderivative algs */ unsigned vector_storage; /* max subspace dimension (0 for default) */ void *work; /* algorithm-specific workspace during optimization */ char *errmsg; /* description of most recent error */ }; /*********************************************************************/ extern void nlopt_srand_time_default(void); /* init the rand. seed only if unset */ /*********************************************************************/ /* global defaults set by deprecated API: */ extern nlopt_algorithm nlopt_local_search_alg_deriv; extern nlopt_algorithm nlopt_local_search_alg_nonderiv; extern int nlopt_local_search_maxeval; extern unsigned nlopt_stochastic_population; /*********************************************************************/ #define RETURN_ERR(err, opt, msg) do { \ nlopt_set_errmsg(opt, msg); \ return err; \ } while (0) extern const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 2, 3))) #endif ; extern void nlopt_unset_errmsg(nlopt_opt opt); /*********************************************************************/ #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* NLOPT_INTERNAL_H */ nlopt-2.6.1/src/api/nlopt.3000066400000000000000000000665401345435414600154600ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 Massachusetts Institute of Technology .\" .\" Copying and distribution of this file, with or without modification, .\" are permitted in any medium without royalty provided the copyright .\" notice and this notice are preserved. .\" .TH NLOPT 3 2007-08-23 "MIT" "NLopt programming manual" .SH NAME nlopt \- Nonlinear optimization library .SH SYNOPSIS .nf .B #include .sp .BI "nlopt_opt " "opt" " = nlopt_create(" "algorithm" , " n" ); .BI "nlopt_set_min_objective(" "opt" , " f" , " f_data" ); .BI "nlopt_set_ftol_rel(" "opt" , " tol"); .BI "..." .BI "nlopt_optimize(" "opt" , " x " , " &opt_f" ); .BI "nlopt_destroy(" "opt" ); .sp The "..." indicates any number of calls to NLopt functions, below, to set parameters of the optimization, constraints, and stopping criteria. Here, \fBnlopt_set_ftol_rel\fR is merely an example of a possible stopping criterion. You should link the resulting program with the linker flags \-lnlopt \-lm on Unix. .fi .SH DESCRIPTION NLopt is a library for nonlinear optimization. It attempts to minimize (or maximize) a given nonlinear objective function .I f of .I n design variables, using the specified .IR algorithm , possibly subject to linear or nonlinear constraints. The optimum function value found is returned in \fIopt_f\fR (type double) with the corresponding design variable values returned in the (double) array .I x of length .IR n . The input values in .I x should be a starting guess for the optimum. .sp The parameters of the optimization are controlled via the object .I opt of type .BR nlopt_opt , which is created by the function .B nlopt_create and disposed of by .BR nlopt_destroy . By calling various functions in the NLopt library, one can specify stopping criteria (e.g., a relative tolerance on the objective function value is specified by .BR nlopt_set_ftol_rel ), upper and/or lower bounds on the design parameters .IR x , and even arbitrary nonlinear inequality and equality constraints. .sp By changing the parameter .I algorithm among several predefined constants described below, one can switch easily between a variety of minimization algorithms. Some of these algorithms require the gradient (derivatives) of the function to be supplied via .IR f , and other algorithms do not require derivatives. Some of the algorithms attempt to find a global optimum within the given bounds, and others find only a local optimum. Most of the algorithms only handle the case where there are no nonlinear constraints. The NLopt library is a wrapper around several free/open-source minimization packages, as well as some new implementations of published optimization algorithms. You could, of course, compile and call these packages separately, and in some cases this will provide greater flexibility than is available via NLopt. However, depending upon the specific function being optimized, the different algorithms will vary in effectiveness. The intent of NLopt is to allow you to quickly switch between algorithms in order to experiment with them for your problem, by providing a simple unified interface to these subroutines. .SH OBJECTIVE FUNCTION The objective function is specified by calling one of: .sp .BI " nlopt_result nlopt_set_min_objective(nlopt_opt " "opt" , .br .BI " nlopt_func " "f" , .br .BI " void* " "f_data" ); .br .BI " nlopt_result nlopt_set_max_objective(nlopt_opt " "opt" , .br .BI " nlopt_func " "f" , .br .BI " void* " "f_data" ); .sp depending on whether one wishes to minimize or maximize the objective function .IR f , respectively. The function .I f should be of the form: .sp .BI " double f(unsigned " "n" , .br .BI " const double* " "x" , .br .BI " double* " "grad" , .br .BI " void* " "f_data" ); .sp The return value should be the value of the function at the point .IR x , where .I x points to an array of length .I n of the design variables. The dimension .I n is identical to the one passed to .BR nlopt_create . .sp In addition, if the argument .I grad is not NULL, then .I grad points to an array of length .I n which should (upon return) be set to the gradient of the function with respect to the design variables at .IR x . That is, .IR grad[i] should upon return contain the partial derivative df/dx[i], for 0 <= i < n, if .I grad is non-NULL. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the .I grad argument will always be NULL and need never be computed. (For algorithms that do use gradient information, however, .I grad may still be NULL for some calls.) .sp The .I f_data argument is the same as the one passed to .B nlopt_set_min_objective or .BR nlopt_set_max_objective , and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from void* by a typecast.) .SH BOUND CONSTRAINTS Most of the algorithms in NLopt are designed for minimization of functions with simple bound constraints on the inputs. That is, the input vectors x[i] are constrainted to lie in a hyperrectangle lb[i] <= x[i] <= ub[i] for 0 <= i < n. These bounds are specified by passing arrays .I lb and .I ub of length .I n to one or both of the functions: .sp .BI " nlopt_result nlopt_set_lower_bounds(nlopt_opt " "opt" , .br .BI " const double* " "lb" ); .br .BI " nlopt_result nlopt_set_upper_bounds(nlopt_opt " "opt" , .br .BI " const double* " "ub" ); .sp If a lower/upper bound is not set, the default is no bound (unconstrained, i.e. a bound of infinity); it is possible to have lower bounds but not upper bounds or vice versa. Alternatively, the user can call one of the above functions and explicitly pass a lower bound of \-HUGE_VAL and/or an upper bound of +HUGE_VAL for some design variables to make them have no lower/upper bound, respectively. (HUGE_VAL is the standard C constant for a floating-point infinity, found in the math.h header file.) .sp Note, however, that some of the algorithms in NLopt, in particular most of the global-optimization algorithms, do not support unconstrained optimization and will return an error if you do not supply finite lower and upper bounds. .sp For convenience, the following two functions are supplied in order to set the lower/upper bounds for all design variables to a single constant (so that you don't have to fill an array with a constant value): .sp .BI " nlopt_result nlopt_set_lower_bounds1(nlopt_opt " "opt" , .br .BI " double " "lb" ); .br .BI " nlopt_result nlopt_set_upper_bounds1(nlopt_opt " "opt" , .br .BI " double " "ub" ); .sp .SH NONLINEAR CONSTRAINTS Several of the algorithms in NLopt (MMA and ORIG_DIRECT) also support arbitrary nonlinear inequality constraints, and some also allow nonlinear equality constraints (COBYLA, SLSQP, ISRES, and AUGLAG). For these algorithms, you can specify as many nonlinear constraints as you wish by calling the following functions multiple times. .sp In particular, a nonlinear inequality constraint of the form \fIfc\fR(\fIx\fR) <= 0, where the function .I fc is of the same form as the objective function described above, can be specified by calling: .sp .BI " nlopt_result nlopt_add_inequality_constraint(nlopt_opt " "opt" , .br .BI " nlopt_func " "fc" , .br .BI " void* " "fc_data" , .br .BI " double " "tol" ); .sp Just as for the objective function, .I fc_data is a pointer to arbitrary user data that will be passed through to the .I fc function whenever it is called. The parameter .I tol is a tolerance that is used for the purpose of stopping criteria only: a point .I x is considered feasible for judging whether to stop the optimization if \fIfc\fR(\fIx\fR) <= \fItol\fR. A tolerance of zero means that NLopt will try not to consider any \fIx\fR to be converged unless .I fc is strictly non-positive; generally, at least a small positive tolerance is advisable to reduce sensitivity to rounding errors. A nonlinear equality constraint of the form \fIh\fR(\fIx\fR) = 0, where the function .I h is of the same form as the objective function described above, can be specified by calling: .sp .BI " nlopt_result nlopt_add_equality_constraint(nlopt_opt " "opt" , .br .BI " nlopt_func " "h" , .br .BI " void* " "h_data" , .br .BI " double " "tol" ); .sp Just as for the objective function, .I h_data is a pointer to arbitrary user data that will be passed through to the .I h function whenever it is called. The parameter .I tol is a tolerance that is used for the purpose of stopping criteria only: a point .I x is considered feasible for judging whether to stop the optimization if |\fIh\fR(\fIx\fR)| <= \fItol\fR. For equality constraints, a small positive tolerance is strongly advised in order to allow NLopt to converge even if the equality constraint is slightly nonzero. .sp (For any algorithm listed as "derivative-free" below, the .I grad argument to \fIfc\fR or \fIh\fR will always be NULL and need never be computed.) .sp To remove all of the inequality and/or equality constraints from a given problem \fIopt\fR, you can call the following functions: .sp .BI " nlopt_result nlopt_remove_inequality_constraints(nlopt_opt " "opt" ); .br .BI " nlopt_result nlopt_remove_equality_constraints(nlopt_opt " "opt" ); .SH ALGORITHMS The .I algorithm parameter specifies the optimization algorithm (for more detail on these, see the README files in the source-code subdirectories), and can take on any of the following constant values. .sp Constants with .B _G{N,D}_ in their names refer to global optimization methods, whereas .B _L{N,D}_ refers to local optimization methods (that try to find a local optimum starting from the starting guess .IR x ). Constants with .B _{G,L}N_ refer to non-gradient (derivative-free) algorithms that do not require the objective function to supply a gradient, whereas .B _{G,L}D_ refers to derivative-based algorithms that require the objective function to supply a gradient. (Especially for local optimization, derivative-based algorithms are generally superior to derivative-free ones: the gradient is good to have .I if you can compute it cheaply, e.g. via an adjoint method.) .sp The algorithm specified for a given problem .I opt is returned by the function: .sp .BI " nlopt_algorithm nlopt_get_algorithm(nlopt_opt " "opt" ); .sp The available algorithms are: .TP .B NLOPT_GN_DIRECT_L Perform a global (G) derivative-free (N) optimization using the DIRECT-L search algorithm by Jones et al. as modified by Gablonsky et al. to be more weighted towards local search. Does not support unconstrainted optimization. There are also several other variants of the DIRECT algorithm that are supported: .BR NLOPT_GN_DIRECT , which is the original DIRECT algorithm; .BR NLOPT_GN_DIRECT_L_RAND , a slightly randomized version of DIRECT-L that may be better in high-dimensional search spaces; .BR NLOPT_GN_DIRECT_NOSCAL , .BR NLOPT_GN_DIRECT_L_NOSCAL , and .BR NLOPT_GN_DIRECT_L_RAND_NOSCAL , which are versions of DIRECT where the dimensions are not rescaled to a unit hypercube (which means that dimensions with larger bounds are given more weight). .TP .B NLOPT_GN_ORIG_DIRECT_L A global (G) derivative-free optimization using the DIRECT-L algorithm as above, along with .B NLOPT_GN_ORIG_DIRECT which is the original DIRECT algorithm. Unlike .B NLOPT_GN_DIRECT_L above, these two algorithms refer to code based on the original Fortran code of Gablonsky et al., which has some hard-coded limitations on the number of subdivisions etc. and does not support all of the NLopt stopping criteria, but on the other hand it supports arbitrary nonlinear inequality constraints. .TP .B NLOPT_GD_STOGO Global (G) optimization using the StoGO algorithm by Madsen et al. StoGO exploits gradient information (D) (which must be supplied by the objective) for its local searches, and performs the global search by a branch-and-bound technique. Only bound-constrained optimization is supported. There is also another variant of this algorithm, .BR NLOPT_GD_STOGO_RAND , which is a randomized version of the StoGO search scheme. The StoGO algorithms are only available if NLopt is compiled with C++ code enabled, and should be linked via \-lnlopt_cxx instead of \-lnlopt (via a C++ compiler, in order to link the C++ standard libraries). .TP .B NLOPT_LN_NELDERMEAD Perform a local (L) derivative-free (N) optimization, starting at .IR x , using the Nelder-Mead simplex algorithm, modified to support bound constraints. Nelder-Mead, while popular, is known to occasionally fail to converge for some objective functions, so it should be used with caution. Anecdotal evidence, on the other hand, suggests that it works fairly well for some cases that are hard to handle otherwise, e.g. noisy/discontinuous objectives. See also .B NLOPT_LN_SBPLX below. .TP .B NLOPT_LN_SBPLX Perform a local (L) derivative-free (N) optimization, starting at .IR x , using an algorithm based on the Subplex algorithm of Rowan et al., which is an improved variant of Nelder-Mead (above). Our implementation does not use Rowan's original code, and has some minor modifications such as explicit support for bound constraints. (Like Nelder-Mead, Subplex often works well in practice, even for noisy/discontinuous objectives, but there is no rigorous guarantee that it will converge.) .TP .B NLOPT_LN_PRAXIS Local (L) derivative-free (N) optimization using the principal-axis method, based on code by Richard Brent. Designed for unconstrained optimization, although bound constraints are supported too (via the inefficient method of returning +Inf when the constraints are violated). .TP .B NLOPT_LD_LBFGS Local (L) gradient-based (D) optimization using the limited-memory BFGS (L-BFGS) algorithm. (The objective function must supply the gradient.) Unconstrained optimization is supported in addition to simple bound constraints (see above). Based on an implementation by Luksan et al. .TP .B NLOPT_LD_VAR2 Local (L) gradient-based (D) optimization using a shifted limited-memory variable-metric method based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. .B NLOPT_LD_VAR2 uses a rank-2 method, while .B .B NLOPT_LD_VAR1 is another variant using a rank-1 method. .TP .B NLOPT_LD_TNEWTON_PRECOND_RESTART Local (L) gradient-based (D) optimization using an LBFGS-preconditioned truncated Newton method with steepest-descent restarting, based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. There are several other variants of this algorithm: .B NLOPT_LD_TNEWTON_PRECOND (same without restarting), .B NLOPT_LD_TNEWTON_RESTART (same without preconditioning), and .B NLOPT_LD_TNEWTON (same without restarting or preconditioning). .TP .B NLOPT_GN_CRS2_LM Global (G) derivative-free (N) optimization using the controlled random search (CRS2) algorithm of Price, with the "local mutation" (LM) modification suggested by Kaelo and Ali. .TP .B NLOPT_GN_ISRES Global (G) derivative-free (N) optimization using a genetic algorithm (mutation and differential evolution), using a stochastic ranking to handle nonlinear inequality and equality constraints as suggested by Runarsson and Yao. .TP \fBNLOPT_G_MLSL_LDS\fR, \fBNLOPT_G_MLSL\fR Global (G) optimization using the multi-level single-linkage (MLSL) algorithm with a low-discrepancy sequence (LDS) or pseudorandom numbers, respectively. This algorithm executes a low-discrepancy or pseudorandom sequence of local searches, with a clustering heuristic to avoid multiple local searches for the same local optimum. The local search algorithm must be specified, along with termination criteria/tolerances for the local searches, by \fInlopt_set_local_optimizer\fR. (This subsidiary algorithm can be with or without derivatives, and determines whether the objective function needs gradients.) .TP \fBNLOPT_LD_MMA\fR, \fBNLOPT_LD_CCSAQ\fR Local (L) gradient-based (D) optimization using the method of moving asymptotes (MMA), or rather a refined version of the algorithm as published by Svanberg (2002). (NLopt uses an independent free-software/open-source implementation of Svanberg's algorithm.) CCSAQ is a related algorithm from Svanberg's paper which uses a local quadratic approximation rather than the more-complicated MMA model; the two usually have similar convergence rates. The .B NLOPT_LD_MMA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear inequality (not equality) constraints as described above. .TP .B NLOPT_LD_SLSQP Local (L) gradient-based (D) optimization using sequential quadratic programming and BFGS updates, supporting arbitrary nonlinear inequality and equality constraints, based on the code by Dieter Kraft (1988) adapted for use by the SciPy project. Note that this algorithm uses dense-matrix methods requiring O(\fIn\fR^2) storage and O(\fIn\fR^3) time, making it less practical for problems involving more than a few thousand parameters. .TP .B NLOPT_LN_COBYLA Local (L) derivative-free (N) optimization using the COBYLA algorithm of Powell (Constrained Optimization BY Linear Approximations). The .B NLOPT_LN_COBYLA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear inequality/equality constraints as described above. .TP .B NLOPT_LN_NEWUOA Local (L) derivative-free (N) optimization using a variant of the NEWUOA algorithm of Powell, based on successive quadratic approximations of the objective function. We have modified the algorithm to support bound constraints. The original NEWUOA algorithm is also available, as .BR NLOPT_LN_NEWUOA , but this algorithm ignores the bound constraints .I lb and .IR ub , and so it should only be used for unconstrained problems. Mostly superseded by BOBYQA. .TP .B NLOPT_LN_BOBYQA Local (L) derivative-free (N) optimization using the BOBYQA algorithm of Powell, based on successive quadratic approximations of the objective function, supporting bound constraints. .TP .B NLOPT_AUGLAG Optimize an objective with nonlinear inequality/equality constraints via an unconstrained (or bound-constrained) optimization algorithm, using a gradually increasing "augmented Lagrangian" penalty for violated constraints. Requires you to specify another optimization algorithm for optimizing the objective+penalty function, using \fInlopt_set_local_optimizer\fR. (This subsidiary algorithm can be global or local and with or without derivatives, but you must specify its own termination criteria.) A variant, \fBNLOPT_AUGLAG_EQ\fR, only uses the penalty approach for equality constraints, while inequality constraints are handled directly by the subsidiary algorithm (restricting the choice of subsidiary algorithms to those that can handle inequality constraints). .SH STOPPING CRITERIA Multiple stopping criteria for the optimization are supported, as specified by the functions to modify a given optimization problem .BR opt . The optimization halts whenever any one of these criteria is satisfied. In some cases, the precise interpretation of the stopping criterion depends on the optimization algorithm above (although we have tried to make them as consistent as reasonably possible), and some algorithms do not support all of the stopping criteria. .sp Important: you do not need to use all of the stopping criteria! In most cases, you only need one or two, and can omit the remainder (all criteria are disabled by default). .TP .BI "nlopt_result nlopt_set_stopval(nlopt_opt " "opt" , .br .BI " double " stopval ); .sp Stop when an objective value of at least .I stopval is found: stop minimizing when a value <= \fIstopval\fR is found, or stop maximizing when a value >= \fIstopval\fR is found. (Setting \fIstopval\fR to \-HUGE_VAL for minimizing or +HUGE_VAL for maximizing disables this stopping criterion.) .TP .BI "nlopt_result nlopt_set_ftol_rel(nlopt_opt " "opt" , .br .BI " double " tol ); .sp Set relative tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the function value by less than .I tol multiplied by the absolute value of the function value. (If there is any chance that your optimum function value is close to zero, you might want to set an absolute tolerance with .B nlopt_set_ftol_abs as well.) Criterion is disabled if \fItol\fR is non-positive. .TP .BI "nlopt_result nlopt_set_ftol_abs(nlopt_opt " "opt" , .br .BI " double " tol ); .sp Set absolute tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the function value by less than .IR tol . Criterion is disabled if \fItol\fR is non-positive. .TP .BI "nlopt_result nlopt_set_xtol_rel(nlopt_opt " "opt" , .br .BI " double " tol ); .sp Set relative tolerance on design variables: stop when an optimization step (or an estimate of the optimum) changes every design variable by less than .I tol multiplied by the absolute value of the design variable. (If there is any chance that an optimal design variable is close to zero, you might want to set an absolute tolerance with .B nlopt_set_xtol_abs as well.) Criterion is disabled if \fItol\fR is non-positive. .TP .BI "nlopt_result nlopt_set_xtol_abs(nlopt_opt " "opt" , .br .BI " const double* " tol ); .sp Set absolute tolerances on design variables. \fItol\fR is a pointer to an array of length .I n giving the tolerances: stop when an optimization step (or an estimate of the optimum) changes every design variable .IR x [i] by less than .IR tol [i]. .sp For convenience, the following function may be used to set the absolute tolerances in all \fIn\fR design variables to the same value: .sp .BI " nlopt_result nlopt_set_xtol_abs1(nlopt_opt " "opt" , .br .BI " double " tol ); .sp Criterion is disabled if \fItol\fR is non-positive. .TP .BI "nlopt_result nlopt_set_maxeval(nlopt_opt " "opt" , .br .BI " int " maxeval ); .sp Stop when the number of function evaluations exceeds .IR maxeval . (This is not a strict maximum: the number of function evaluations may exceed .I maxeval slightly, depending upon the algorithm.) Criterion is disabled if \fImaxeval\fR is non-positive. .TP .BI "nlopt_result nlopt_set_maxtime(nlopt_opt " "opt" , .br .BI " double " maxtime ); .sp Stop when the optimization time (in seconds) exceeds .IR maxtime . (This is not a strict maximum: the time may exceed .I maxtime slightly, depending upon the algorithm and on how slow your function evaluation is.) Criterion is disabled if \fImaxtime\fR is non-positive. .SH RETURN VALUE Most of the NLopt functions return an enumerated constant of type .BR nlopt_result , which takes on one of the following values: .SS Successful termination (positive return values): .TP .B NLOPT_SUCCESS Generic success return value. .TP .B NLOPT_STOPVAL_REACHED Optimization stopped because .I stopval (above) was reached. .TP .B NLOPT_FTOL_REACHED Optimization stopped because .I ftol_rel or .I ftol_abs (above) was reached. .TP .B NLOPT_XTOL_REACHED Optimization stopped because .I xtol_rel or .I xtol_abs (above) was reached. .TP .B NLOPT_MAXEVAL_REACHED Optimization stopped because .I maxeval (above) was reached. .TP .B NLOPT_MAXTIME_REACHED Optimization stopped because .I maxtime (above) was reached. .SS Error codes (negative return values): .TP .B NLOPT_FAILURE Generic failure code. .TP .B NLOPT_INVALID_ARGS Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera). .TP .B NLOPT_OUT_OF_MEMORY Ran out of memory. .TP .B NLOPT_ROUNDOFF_LIMITED Halted because roundoff errors limited progress. .TP .B NLOPT_FORCED_STOP Halted because the user called \fBnlopt_force_stop\fR(\fIopt\fR) on the optimization's \fBnlopt_opt\fR object \fIopt\fR from the user's objective function. .SH LOCAL OPTIMIZER Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local optimization. You can change the local search algorithm and its tolerances by calling: .sp .BI " nlopt_result nlopt_set_local_optimizer(nlopt_opt " "opt" , .br .BI " const nlopt_opt " "local_opt" ); .sp Here, \fIlocal_opt\fR is another \fBnlopt_opt\fR object whose parameters are used to determine the local search algorithm and stopping criteria. (The objective function, bounds, and nonlinear-constraint parameters of \fIlocal_opt\fR are ignored.) The dimension \fIn\fR of \fIlocal_opt\fR must match that of \fIopt\fR. .sp This function makes a copy of the \fIlocal_opt\fR object, so you can freely destroy your original \fIlocal_opt\fR afterwards. .SH INITIAL STEP SIZE For derivative-free local-optimization algorithms, the optimizer must somehow decide on some initial step size to perturb \fIx\fR by when it begins the optimization. This step size should be big enough that the value of the objective changes significantly, but not too big if you want to find the local optimum nearest to \fIx\fR. By default, NLopt chooses this initial step size heuristically from the bounds, tolerances, and other information, but this may not always be the best choice. .sp You can modify the initial step size by calling: .sp .BI " nlopt_result nlopt_set_initial_step(nlopt_opt " "opt" , .br .BI " const double* " "dx" ); .sp Here, \fIdx\fR is an array of length \fIn\fR containing the (nonzero) initial step size for each component of the design parameters \fIx\fR. For convenience, if you want to set the step sizes in every direction to be the same value, you can instead call: .sp .BI " nlopt_result nlopt_set_initial_step1(nlopt_opt " "opt" , .br .BI " double " "dx" ); .SH STOCHASTIC POPULATION Several of the stochastic search algorithms (e.g., CRS, MLSL, and ISRES) start by generating some initial "population" of random points \fIx\fR. By default, this initial population size is chosen heuristically in some algorithm-specific way, but the initial population can by changed by calling: .sp .BI " nlopt_result nlopt_set_population(nlopt_opt " "opt" , .br .BI " unsigned " "pop" ); .sp (A \fIpop\fR of zero implies that the heuristic default will be used.) .SH PSEUDORANDOM NUMBERS For stochastic optimization algorithms, we use pseudorandom numbers generated by the Mersenne Twister algorithm, based on code from Makoto Matsumoto. By default, the seed for the random numbers is generated from the system time, so that they will be different each time you run the program. If you want to use deterministic random numbers, you can set the seed by calling: .sp .BI " void nlopt_srand(unsigned long " "seed" ); .sp Some of the algorithms also support using low-discrepancy sequences (LDS), sometimes known as quasi-random numbers. NLopt uses the Sobol LDS, which is implemented for up to 1111 dimensions. .SH AUTHORS Written by Steven G. Johnson. .PP Copyright (c) 2007-2014 Massachusetts Institute of Technology. .SH "SEE ALSO" nlopt_minimize(3) nlopt-2.6.1/src/api/nlopt.h000066400000000000000000000343511345435414600155400ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef NLOPT_H #define NLOPT_H #include /* for ptrdiff_t and size_t */ /* Change 0 to 1 to use stdcall convention under Win32 */ #if 0 && (defined(_WIN32) || defined(__WIN32__)) # if defined(__GNUC__) # define NLOPT_STDCALL __attribute__((stdcall)) # elif defined(_MSC_VER) || defined(_ICC) || defined(_STDCALL_SUPPORTED) # define NLOPT_STDCALL __stdcall # else # define NLOPT_STDCALL # endif #else # define NLOPT_STDCALL #endif /* for Windows compilers, you should add a line #define NLOPT_DLL when using NLopt from a DLL, in order to do the proper Windows importing nonsense. */ #if defined(NLOPT_DLL) && (defined(_WIN32) || defined(__WIN32__)) && !defined(__LCC__) /* annoying Windows syntax for calling functions in a DLL */ # if defined(NLOPT_DLL_EXPORT) # define NLOPT_EXTERN(T) extern __declspec(dllexport) T NLOPT_STDCALL # else # define NLOPT_EXTERN(T) extern __declspec(dllimport) T NLOPT_STDCALL # endif #else # define NLOPT_EXTERN(T) extern T NLOPT_STDCALL #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef double (*nlopt_func) (unsigned n, const double *x, double *gradient, /* NULL if not needed */ void *func_data); typedef void (*nlopt_mfunc) (unsigned m, double *result, unsigned n, const double *x, double *gradient, /* NULL if not needed */ void *func_data); /* A preconditioner, which preconditions v at x to return vpre. (The meaning of "preconditioning" is algorithm-dependent.) */ typedef void (*nlopt_precond) (unsigned n, const double *x, const double *v, double *vpre, void *data); typedef enum { /* Naming conventions: NLOPT_{G/L}{D/N}_* = global/local derivative/no-derivative optimization, respectively *_RAND algorithms involve some randomization. *_NOSCAL algorithms are *not* scaled to a unit hypercube (i.e. they are sensitive to the units of x) */ NLOPT_GN_DIRECT = 0, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_DIRECT_L_NOSCAL, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_ORIG_DIRECT, NLOPT_GN_ORIG_DIRECT_L, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, NLOPT_LD_LBFGS_NOCEDAL, NLOPT_LD_LBFGS, NLOPT_LN_PRAXIS, NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_RESTART, NLOPT_LD_TNEWTON_PRECOND, NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_GN_CRS2_LM, NLOPT_GN_MLSL, NLOPT_GD_MLSL, NLOPT_GN_MLSL_LDS, NLOPT_GD_MLSL_LDS, NLOPT_LD_MMA, NLOPT_LN_COBYLA, NLOPT_LN_NEWUOA, NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NELDERMEAD, NLOPT_LN_SBPLX, NLOPT_LN_AUGLAG, NLOPT_LD_AUGLAG, NLOPT_LN_AUGLAG_EQ, NLOPT_LD_AUGLAG_EQ, NLOPT_LN_BOBYQA, NLOPT_GN_ISRES, /* new variants that require local_optimizer to be set, not with older constants for backwards compatibility */ NLOPT_AUGLAG, NLOPT_AUGLAG_EQ, NLOPT_G_MLSL, NLOPT_G_MLSL_LDS, NLOPT_LD_SLSQP, NLOPT_LD_CCSAQ, NLOPT_GN_ESCH, NLOPT_GN_AGS, NLOPT_NUM_ALGORITHMS /* not an algorithm, just the number of them */ } nlopt_algorithm; NLOPT_EXTERN(const char *) nlopt_algorithm_name(nlopt_algorithm a); typedef enum { NLOPT_FAILURE = -1, /* generic failure code */ NLOPT_INVALID_ARGS = -2, NLOPT_OUT_OF_MEMORY = -3, NLOPT_ROUNDOFF_LIMITED = -4, NLOPT_FORCED_STOP = -5, NLOPT_SUCCESS = 1, /* generic success code */ NLOPT_STOPVAL_REACHED = 2, NLOPT_FTOL_REACHED = 3, NLOPT_XTOL_REACHED = 4, NLOPT_MAXEVAL_REACHED = 5, NLOPT_MAXTIME_REACHED = 6 } nlopt_result; #define NLOPT_MINF_MAX_REACHED NLOPT_STOPVAL_REACHED NLOPT_EXTERN(void) nlopt_srand(unsigned long seed); NLOPT_EXTERN(void) nlopt_srand_time(void); NLOPT_EXTERN(void) nlopt_version(int *major, int *minor, int *bugfix); /*************************** OBJECT-ORIENTED API **************************/ /* The style here is that we create an nlopt_opt "object" (an opaque pointer), then set various optimization parameters, and then execute the algorithm. In this way, we can add more and more optimization parameters (including algorithm-specific ones) without breaking backwards compatibility, having functions with zillions of parameters, or relying non-reentrantly on global variables.*/ struct nlopt_opt_s; /* opaque structure, defined internally */ typedef struct nlopt_opt_s *nlopt_opt; /* the only immutable parameters of an optimization are the algorithm and the dimension n of the problem, since changing either of these could have side-effects on lots of other parameters */ NLOPT_EXTERN(nlopt_opt) nlopt_create(nlopt_algorithm algorithm, unsigned n); NLOPT_EXTERN(void) nlopt_destroy(nlopt_opt opt); NLOPT_EXTERN(nlopt_opt) nlopt_copy(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_optimize(nlopt_opt opt, double *x, double *opt_f); NLOPT_EXTERN(nlopt_result) nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data); NLOPT_EXTERN(nlopt_result) nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data); NLOPT_EXTERN(nlopt_result) nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); NLOPT_EXTERN(nlopt_result) nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); NLOPT_EXTERN(nlopt_algorithm) nlopt_get_algorithm(const nlopt_opt opt); NLOPT_EXTERN(unsigned) nlopt_get_dimension(const nlopt_opt opt); NLOPT_EXTERN(const char *) nlopt_get_errmsg(nlopt_opt opt); /* constraints: */ NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds(nlopt_opt opt, const double *lb); NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds1(nlopt_opt opt, double lb); NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bound(nlopt_opt opt, int i, double lb); NLOPT_EXTERN(nlopt_result) nlopt_get_lower_bounds(const nlopt_opt opt, double *lb); NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bounds(nlopt_opt opt, const double *ub); NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bounds1(nlopt_opt opt, double ub); NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bound(nlopt_opt opt, int i, double ub); NLOPT_EXTERN(nlopt_result) nlopt_get_upper_bounds(const nlopt_opt opt, double *ub); NLOPT_EXTERN(nlopt_result) nlopt_remove_inequality_constraints(nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol); NLOPT_EXTERN(nlopt_result) nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol); NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol); NLOPT_EXTERN(nlopt_result) nlopt_remove_equality_constraints(nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func h, void *h_data, double tol); NLOPT_EXTERN(nlopt_result) nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func h, nlopt_precond pre, void *h_data, double tol); NLOPT_EXTERN(nlopt_result) nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc h, void *h_data, const double *tol); /* stopping criteria: */ NLOPT_EXTERN(nlopt_result) nlopt_set_stopval(nlopt_opt opt, double stopval); NLOPT_EXTERN(double) nlopt_get_stopval(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_ftol_rel(nlopt_opt opt, double tol); NLOPT_EXTERN(double) nlopt_get_ftol_rel(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_ftol_abs(nlopt_opt opt, double tol); NLOPT_EXTERN(double) nlopt_get_ftol_abs(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_rel(nlopt_opt opt, double tol); NLOPT_EXTERN(double) nlopt_get_xtol_rel(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_abs1(nlopt_opt opt, double tol); NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_abs(nlopt_opt opt, const double *tol); NLOPT_EXTERN(nlopt_result) nlopt_get_xtol_abs(const nlopt_opt opt, double *tol); NLOPT_EXTERN(nlopt_result) nlopt_set_maxeval(nlopt_opt opt, int maxeval); NLOPT_EXTERN(int) nlopt_get_maxeval(const nlopt_opt opt); NLOPT_EXTERN(int) nlopt_get_numevals(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_maxtime(nlopt_opt opt, double maxtime); NLOPT_EXTERN(double) nlopt_get_maxtime(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_force_stop(nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_force_stop(nlopt_opt opt, int val); NLOPT_EXTERN(int) nlopt_get_force_stop(const nlopt_opt opt); /* more algorithm-specific parameters */ NLOPT_EXTERN(nlopt_result) nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt); NLOPT_EXTERN(nlopt_result) nlopt_set_population(nlopt_opt opt, unsigned pop); NLOPT_EXTERN(unsigned) nlopt_get_population(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_vector_storage(nlopt_opt opt, unsigned dim); NLOPT_EXTERN(unsigned) nlopt_get_vector_storage(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_default_initial_step(nlopt_opt opt, const double *x); NLOPT_EXTERN(nlopt_result) nlopt_set_initial_step(nlopt_opt opt, const double *dx); NLOPT_EXTERN(nlopt_result) nlopt_set_initial_step1(nlopt_opt opt, double dx); NLOPT_EXTERN(nlopt_result) nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx); /* the following are functions mainly designed to be used internally by the Fortran and SWIG wrappers, allow us to tel nlopt_destroy and nlopt_copy to do something to the f_data pointers (e.g. free or duplicate them, respectively) */ typedef void *(*nlopt_munge) (void *p); NLOPT_EXTERN(void) nlopt_set_munge(nlopt_opt opt, nlopt_munge munge_on_destroy, nlopt_munge munge_on_copy); typedef void *(*nlopt_munge2) (void *p, void *data); NLOPT_EXTERN(void) nlopt_munge_data(nlopt_opt opt, nlopt_munge2 munge, void *data); /*************************** DEPRECATED API **************************/ /* The new "object-oriented" API is preferred, since it allows us to gracefully add new features and algorithm-specific options in a re-entrant way, and we can automatically assume reasonable defaults for unspecified parameters. */ /* Where possible (e.g. for gcc >= 3.1), enable a compiler warning for code that uses a deprecated function */ #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__==3 && __GNUC_MINOR__ > 0)) # define NLOPT_DEPRECATED __attribute__((deprecated)) #else # define NLOPT_DEPRECATED #endif typedef double (*nlopt_func_old) (int n, const double *x, double *gradient, /* NULL if not needed */ void *func_data); NLOPT_EXTERN(nlopt_result) nlopt_minimize(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; NLOPT_EXTERN(nlopt_result) nlopt_minimize_constrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; NLOPT_EXTERN(nlopt_result) nlopt_minimize_econstrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, int p, nlopt_func_old h, void *h_data, ptrdiff_t h_datum_size, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, /* out: minimum */ double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, double htol_rel, double htol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; NLOPT_EXTERN(void) nlopt_get_local_search_algorithm(nlopt_algorithm * deriv, nlopt_algorithm * nonderiv, int *maxeval) NLOPT_DEPRECATED; NLOPT_EXTERN(void) nlopt_set_local_search_algorithm(nlopt_algorithm deriv, nlopt_algorithm nonderiv, int maxeval) NLOPT_DEPRECATED; NLOPT_EXTERN(int) nlopt_get_stochastic_population(void) NLOPT_DEPRECATED; NLOPT_EXTERN(void) nlopt_set_stochastic_population(int pop) NLOPT_DEPRECATED; /*********************************************************************/ #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/api/nlopt_minimize.3000066400000000000000000000427611345435414600173600ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 Massachusetts Institute of Technology .\" .\" Copying and distribution of this file, with or without modification, .\" are permitted in any medium without royalty provided the copyright .\" notice and this notice are preserved. .\" .TH NLOPT_MINIMIZE 3 2007-08-23 "MIT" "NLopt programming manual" .SH NAME nlopt_minimize \- Minimize a multivariate nonlinear function .SH SYNOPSIS .nf .B #include .sp .BI "nlopt_result nlopt_minimize(nlopt_algorithm " "algorithm" , .br .BI " int " "n" , .BI " nlopt_func " "f" , .BI " void* " "f_data" , .BI " const double* " "lb" , .BI " const double* " "ub" , .BI " double* " "x" , .BI " double* " "minf" , .BI " double " "minf_max" , .BI " double " "ftol_rel" , .BI " double " "ftol_abs" , .BI " double " "xtol_rel" , .BI " const double* " "xtol_abs" , .BI " int " "maxeval" , .BI " double " "maxtime" ); .sp You should link the resulting program with the linker flags -lnlopt -lm on Unix. .fi .SH DESCRIPTION .BR nlopt_minimize () attempts to minimize a nonlinear function .I f of .I n design variables using the specified .IR algorithm . The minimum function value found is returned in .IR minf , with the corresponding design variable values returned in the array .I x of length .IR n . The input values in .I x should be a starting guess for the optimum. The inputs .I lb and .I ub are arrays of length .I n containing lower and upper bounds, respectively, on the design variables .IR x . The other parameters specify stopping criteria (tolerances, the maximum number of function evaluations, etcetera) and other information as described in more detail below. The return value is a integer code indicating success (positive) or failure (negative), as described below. .PP By changing the parameter .I algorithm among several predefined constants described below, one can switch easily between a variety of minimization algorithms. Some of these algorithms require the gradient (derivatives) of the function to be supplied via .IR f , and other algorithms do not require derivatives. Some of the algorithms attempt to find a global minimum within the given bounds, and others find only a local minimum. .PP The .B nlopt_minimize function is a wrapper around several free/open-source minimization packages. as well as some new implementations of published optimization algorithms. You could, of course, compile and call these packages separately, and in some cases this will provide greater flexibility than is available via the .B nlopt_minimize interface. However, depending upon the specific function being minimized, the different algorithms will vary in effectiveness. The intent of .B nlopt_minimize is to allow you to quickly switch between algorithms in order to experiment with them for your problem, by providing a simple unified interface to these subroutines. .SH OBJECTIVE FUNCTION .BR nlopt_minimize () minimizes an objective function .I f of the form: .sp .BI " double f(int " "n" , .br .BI " const double* " "x" , .br .BI " double* " "grad" , .br .BI " void* " "f_data" ); .sp The return value should be the value of the function at the point .IR x , where .I x points to an array of length .I n of the design variables. The dimension .I n is identical to the one passed to .BR nlopt_minimize (). .sp In addition, if the argument .I grad is not NULL, then .I grad points to an array of length .I n which should (upon return) be set to the gradient of the function with respect to the design variables at .IR x . That is, .IR grad[i] should upon return contain the partial derivative df/dx[i], for 0 <= i < n, if .I grad is non-NULL. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the .I grad argument will always be NULL and need never be computed. (For algorithms that do use gradient information, however, .I grad may still be NULL for some calls.) .sp The .I f_data argument is the same as the one passed to .BR nlopt_minimize (), and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from void* by a typecast.) .sp .SH CONSTRAINTS Most of the algorithms in NLopt are designed for minimization of functions with simple bound constraints on the inputs. That is, the input vectors x[i] are constrainted to lie in a hyperrectangle lb[i] <= x[i] <= ub[i] for 0 <= i < n, where .I lb and .I ub are the two arrays passed to .BR nlopt_minimize (). .sp However, a few of the algorithms support partially or totally unconstrained optimization, as noted below, where a (totally or partially) unconstrained design variable is indicated by a lower bound equal to -Inf and/or an upper bound equal to +Inf. Here, Inf is the IEEE-754 floating-point infinity, which (in ANSI C99) is represented by the macro INFINITY in math.h. Alternatively, for older C versions you may also use the macro HUGE_VAL (also in math.h). .sp With some of the algorithms, especially those that do not require derivative information, a simple (but not especially efficient) way to implement arbitrary nonlinear constraints is to return Inf (see above) whenever the constraints are violated by a given input .IR x . More generally, there are various ways to implement constraints by adding "penalty terms" to your objective function, which are described in the optimization literature. A much more efficient way to specify nonlinear constraints is provided by the .BR nlopt_minimize_constrained () function (described in its own manual page). .SH ALGORITHMS The .I algorithm parameter specifies the optimization algorithm (for more detail on these, see the README files in the source-code subdirectories), and can take on any of the following constant values. Constants with .B _G{N,D}_ in their names refer to global optimization methods, whereas .B _L{N,D}_ refers to local optimization methods (that try to find a local minimum starting from the starting guess .IR x ). Constants with .B _{G,L}N_ refer to non-gradient (derivative-free) algorithms that do not require the objective function to supply a gradient, whereas .B _{G,L}D_ refers to derivative-based algorithms that require the objective function to supply a gradient. (Especially for local optimization, derivative-based algorithms are generally superior to derivative-free ones: the gradient is good to have .I if you can compute it cheaply, e.g. via an adjoint method.) .TP .B NLOPT_GN_DIRECT_L Perform a global (G) derivative-free (N) optimization using the DIRECT-L search algorithm by Jones et al. as modified by Gablonsky et al. to be more weighted towards local search. Does not support unconstrainted optimization. There are also several other variants of the DIRECT algorithm that are supported: .BR NLOPT_GN_DIRECT , which is the original DIRECT algorithm; .BR NLOPT_GN_DIRECT_L_RAND , a slightly randomized version of DIRECT-L that may be better in high-dimensional search spaces; .BR NLOPT_GN_DIRECT_NOSCAL , .BR NLOPT_GN_DIRECT_L_NOSCAL , and .BR NLOPT_GN_DIRECT_L_RAND_NOSCAL , which are versions of DIRECT where the dimensions are not rescaled to a unit hypercube (which means that dimensions with larger bounds are given more weight). .TP .B NLOPT_GN_ORIG_DIRECT_L A global (G) derivative-free optimization using the DIRECT-L algorithm as above, along with .B NLOPT_GN_ORIG_DIRECT which is the original DIRECT algorithm. Unlike .B NLOPT_GN_DIRECT_L above, these two algorithms refer to code based on the original Fortran code of Gablonsky et al., which has some hard-coded limitations on the number of subdivisions etc. and does not support all of the NLopt stopping criteria, but on the other hand supports arbitrary nonlinear constraints as described above. .TP .B NLOPT_GD_STOGO Global (G) optimization using the StoGO algorithm by Madsen et al. StoGO exploits gradient information (D) (which must be supplied by the objective) for its local searches, and performs the global search by a branch-and-bound technique. Only bound-constrained optimization is supported. There is also another variant of this algorithm, .BR NLOPT_GD_STOGO_RAND , which is a randomized version of the StoGO search scheme. The StoGO algorithms are only available if NLopt is compiled with C++ enabled, and should be linked via -lnlopt_cxx (via a C++ compiler, in order to link the C++ standard libraries). .TP .B NLOPT_LN_NELDERMEAD Perform a local (L) derivative-free (N) optimization, starting at .IR x , using the Nelder-Mead simplex algorithm, modified to support bound constraints. Nelder-Mead, while popular, is known to occasionally fail to converge for some objective functions, so it should be used with caution. Anecdotal evidence, on the other hand, suggests that it works fairly well for discontinuous objectives. See also .B NLOPT_LN_SBPLX below. .TP .B NLOPT_LN_SBPLX Perform a local (L) derivative-free (N) optimization, starting at .IR x , using an algorithm based on the Subplex algorithm of Rowan et al., which is an improved variant of Nelder-Mead (above). Our implementation does not use Rowan's original code, and has some minor modifications such as explicit support for bound constraints. (Like Nelder-Mead, Subplex often works well in practice, even for discontinuous objectives, but there is no rigorous guarantee that it will converge.) Nonlinear constraints can be crudely supported by returning +Inf when the constraints are violated, as explained above. .TP .B NLOPT_LN_PRAXIS Local (L) derivative-free (N) optimization using the principal-axis method, based on code by Richard Brent. Designed for unconstrained optimization, although bound constraints are supported too (via the inefficient method of returning +Inf when the constraints are violated). .TP .B NLOPT_LD_LBFGS Local (L) gradient-based (D) optimization using the limited-memory BFGS (L-BFGS) algorithm. (The objective function must supply the gradient.) Unconstrained optimization is supported in addition to simple bound constraints (see above). Based on an implementation by Luksan et al. .TP .B NLOPT_LD_VAR2 Local (L) gradient-based (D) optimization using a shifted limited-memory variable-metric method based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. .B NLOPT_LD_VAR2 uses a rank-2 method, while .B .B NLOPT_LD_VAR1 is another variant using a rank-1 method. .TP .B NLOPT_LD_TNEWTON_PRECOND_RESTART Local (L) gradient-based (D) optimization using an LBFGS-preconditioned truncated Newton method with steepest-descent restarting, based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. There are several other variants of this algorithm: .B NLOPT_LD_TNEWTON_PRECOND (same without restarting), .B NLOPT_LD_TNEWTON_RESTART (same without preconditioning), and .B NLOPT_LD_TNEWTON (same without restarting or preconditioning). .TP .B NLOPT_GN_CRS2_LM Global (G) derivative-free (N) optimization using the controlled random search (CRS2) algorithm of Price, with the "local mutation" (LM) modification suggested by Kaelo and Ali. .TP \fBNLOPT_GD_MLSL_LDS\fR, \fBNLOPT_GN_MLSL_LDS\fR Global (G) derivative-based (D) or derivative-free (N) optimization using the multi-level single-linkage (MLSL) algorithm with a low-discrepancy sequence (LDS). This algorithm executes a quasi-random (LDS) sequence of local searches, with a clustering heuristic to avoid multiple local searches for the same local minimum. The local search uses the derivative/nonderivative algorithm set by .I nlopt_set_local_search_algorithm (currently defaulting to .I NLOPT_LD_MMA and .I NLOPT_LN_COBYLA for derivative/nonderivative searches, respectively). There are also two other variants, \fBNLOPT_GD_MLSL\fR and \fBNLOPT_GN_MLSL\fR, which use pseudo-random numbers (instead of an LDS) as in the original MLSL algorithm. .TP .B NLOPT_LD_MMA Local (L) gradient-based (D) optimization using the method of moving asymptotes (MMA), or rather a refined version of the algorithm as published by Svanberg (2002). (NLopt uses an independent free-software/open-source implementation of Svanberg's algorithm.) The .B NLOPT_LD_MMA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear constraints via the .BR nlopt_minimize_constrained () function. .TP .B NLOPT_LN_COBYLA Local (L) derivative-free (N) optimization using the COBYLA algorithm of Powell (Constrained Optimization BY Linear Approximations). The .B NLOPT_LN_COBYLA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear constraints via the .BR nlopt_minimize_constrained () function. .TP .B NLOPT_LN_NEWUOA_BOUND Local (L) derivative-free (N) optimization using a variant of the the NEWUOA algorithm of Powell, based on successive quadratic approximations of the objective function. We have modified the algorithm to support bound constraints. The original NEWUOA algorithm is also available, as .BR NLOPT_LN_NEWUOA , but this algorithm ignores the bound constraints .I lb and .IR ub , and so it should only be used for unconstrained problems. .SH STOPPING CRITERIA Multiple stopping criteria for the optimization are supported, as specified by the following arguments to .BR nlopt_minimize (). The optimization halts whenever any one of these criteria is satisfied. In some cases, the precise interpretation of the stopping criterion depends on the optimization algorithm above (although we have tried to make them as consistent as reasonably possible), and some algorithms do not support all of the stopping criteria. .TP .B minf_max Stop when a function value less than or equal to .I minf_max is found. Set to -Inf or NaN (see constraints section above) to disable. .TP .B ftol_rel Relative tolerance on function value: stop when an optimization step (or an estimate of the minimum) changes the function value by less than .I ftol_rel multiplied by the absolute value of the function value. (If there is any chance that your minimum function value is close to zero, you might want to set an absolute tolerance with .I ftol_abs as well.) Disabled if non-positive. .TP .B ftol_abs Absolute tolerance on function value: stop when an optimization step (or an estimate of the minimum) changes the function value by less than .IR ftol_abs . Disabled if non-positive. .TP .B xtol_rel Relative tolerance on design variables: stop when an optimization step (or an estimate of the minimum) changes every design variable by less than .I xtol_rel multiplied by the absolute value of the design variable. (If there is any chance that an optimal design variable is close to zero, you might want to set an absolute tolerance with .I xtol_abs as well.) Disabled if non-positive. .TP .B xtol_abs Pointer to an array of length .I n giving absolute tolerances on design variables: stop when an optimization step (or an estimate of the minimum) changes every design variable .IR x [i] by less than .IR xtol_abs [i]. Disabled if non-positive, or if .I xtol_abs is NULL. .TP .B maxeval Stop when the number of function evaluations exceeds .IR maxeval . (This is not a strict maximum: the number of function evaluations may exceed .I maxeval slightly, depending upon the algorithm.) Disabled if non-positive. .TP .B maxtime Stop when the optimization time (in seconds) exceeds .IR maxtime . (This is not a strict maximum: the time may exceed .I maxtime slightly, depending upon the algorithm and on how slow your function evaluation is.) Disabled if non-positive. .SH RETURN VALUE The value returned is one of the following enumerated constants. .SS Successful termination (positive return values): .TP .B NLOPT_SUCCESS Generic success return value. .TP .B NLOPT_MINF_MAX_REACHED Optimization stopped because .I minf_max (above) was reached. .TP .B NLOPT_FTOL_REACHED Optimization stopped because .I ftol_rel or .I ftol_abs (above) was reached. .TP .B NLOPT_XTOL_REACHED Optimization stopped because .I xtol_rel or .I xtol_abs (above) was reached. .TP .B NLOPT_MAXEVAL_REACHED Optimization stopped because .I maxeval (above) was reached. .TP .B NLOPT_MAXTIME_REACHED Optimization stopped because .I maxtime (above) was reached. .SS Error codes (negative return values): .TP .B NLOPT_FAILURE Generic failure code. .TP .B NLOPT_INVALID_ARGS Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera). .TP .B NLOPT_OUT_OF_MEMORY Ran out of memory. .SH PSEUDORANDOM NUMBERS For stochastic optimization algorithms, we use pseudorandom numbers generated by the Mersenne Twister algorithm, based on code from Makoto Matsumoto. By default, the seed for the random numbers is generated from the system time, so that they will be different each time you run the program. If you want to use deterministic random numbers, you can set the seed by calling: .sp .BI " void nlopt_srand(unsigned long " "seed" ); .sp Some of the algorithms also support using low-discrepancy sequences (LDS), sometimes known as quasi-random numbers. NLopt uses the Sobol LDS, which is implemented for up to 1111 dimensions. .BR maxeval . .SH AUTHORS Written by Steven G. Johnson. .PP Copyright (c) 2007 Massachusetts Institute of Technology. .SH "SEE ALSO" nlopt_minimize_constrained(3) nlopt-2.6.1/src/api/nlopt_minimize_constrained.3000066400000000000000000000504561345435414600217510ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 Massachusetts Institute of Technology .\" .\" Copying and distribution of this file, with or without modification, .\" are permitted in any medium without royalty provided the copyright .\" notice and this notice are preserved. .\" .TH NLOPT_MINIMIZE_CONSTRAINED 3 2007-08-23 "MIT" "NLopt programming manual" .SH NAME nlopt_minimize_constrained \- Minimize a multivariate nonlinear function subject to nonlinear constraints .SH SYNOPSIS .nf .B #include .sp .BI "nlopt_result nlopt_minimize_constrained(nlopt_algorithm " "algorithm" , .br .BI " int " "n" , .BI " nlopt_func " "f" , .BI " void* " "f_data" , .BI " int " "m" , .BI " nlopt_func " "fc" , .BI " void* " "fc_data" , .BI " ptrdiff_t " "fc_datum_size" , .BI " const double* " "lb" , .BI " const double* " "ub" , .BI " double* " "x" , .BI " double* " "minf" , .BI " double " "minf_max" , .BI " double " "ftol_rel" , .BI " double " "ftol_abs" , .BI " double " "xtol_rel" , .BI " const double* " "xtol_abs" , .BI " int " "maxeval" , .BI " double " "maxtime" ); .sp You should link the resulting program with the linker flags -lnlopt -lm on Unix. .fi .SH DESCRIPTION .BR nlopt_minimize_constrained () attempts to minimize a nonlinear function .I f of .I n design variables, subject to .I m nonlinear constraints described by the function .I fc (see below), using the specified .IR algorithm . The minimum function value found is returned in .IR minf , with the corresponding design variable values returned in the array .I x of length .IR n . The input values in .I x should be a starting guess for the optimum. The inputs .I lb and .I ub are arrays of length .I n containing lower and upper bounds, respectively, on the design variables .IR x . The other parameters specify stopping criteria (tolerances, the maximum number of function evaluations, etcetera) and other information as described in more detail below. The return value is a integer code indicating success (positive) or failure (negative), as described below. .PP By changing the parameter .I algorithm among several predefined constants described below, one can switch easily between a variety of minimization algorithms. Some of these algorithms require the gradient (derivatives) of the function to be supplied via .IR f , and other algorithms do not require derivatives. Some of the algorithms attempt to find a global minimum within the given bounds, and others find only a local minimum. Most of the algorithms only handle the case where .I m is zero (no explicit nonlinear constraints); the only algorithms that currently support positive .I m are .B NLOPT_LD_MMA and .BR NLOPT_LN_COBYLA . .PP The .B nlopt_minimize_constrained function is a wrapper around several free/open-source minimization packages, as well as some new implementations of published optimization algorithms. You could, of course, compile and call these packages separately, and in some cases this will provide greater flexibility than is available via the .B nlopt_minimize_constrained interface. However, depending upon the specific function being minimized, the different algorithms will vary in effectiveness. The intent of .B nlopt_minimize_constrained is to allow you to quickly switch between algorithms in order to experiment with them for your problem, by providing a simple unified interface to these subroutines. .SH OBJECTIVE FUNCTION .BR nlopt_minimize_constrained () minimizes an objective function .I f of the form: .sp .BI " double f(int " "n" , .br .BI " const double* " "x" , .br .BI " double* " "grad" , .br .BI " void* " "f_data" ); .sp The return value should be the value of the function at the point .IR x , where .I x points to an array of length .I n of the design variables. The dimension .I n is identical to the one passed to .BR nlopt_minimize_constrained (). .sp In addition, if the argument .I grad is not NULL, then .I grad points to an array of length .I n which should (upon return) be set to the gradient of the function with respect to the design variables at .IR x . That is, .IR grad[i] should upon return contain the partial derivative df/dx[i], for 0 <= i < n, if .I grad is non-NULL. Not all of the optimization algorithms (below) use the gradient information: for algorithms listed as "derivative-free," the .I grad argument will always be NULL and need never be computed. (For algorithms that do use gradient information, however, .I grad may still be NULL for some calls.) .sp The .I f_data argument is the same as the one passed to .BR nlopt_minimize_constrained (), and may be used to pass any additional data through to the function. (That is, it may be a pointer to some caller-defined data structure/type containing information your function needs, which you convert from void* by a typecast.) .sp .SH BOUND CONSTRAINTS Most of the algorithms in NLopt are designed for minimization of functions with simple bound constraints on the inputs. That is, the input vectors x[i] are constrainted to lie in a hyperrectangle lb[i] <= x[i] <= ub[i] for 0 <= i < n, where .I lb and .I ub are the two arrays passed to .BR nlopt_minimize_constrained (). .sp However, a few of the algorithms support partially or totally unconstrained optimization, as noted below, where a (totally or partially) unconstrained design variable is indicated by a lower bound equal to -Inf and/or an upper bound equal to +Inf. Here, Inf is the IEEE-754 floating-point infinity, which (in ANSI C99) is represented by the macro INFINITY in math.h. Alternatively, for older C versions you may also use the macro HUGE_VAL (also in math.h). .sp With some of the algorithms, especially those that do not require derivative information, a simple (but not especially efficient) way to implement arbitrary nonlinear constraints is to return Inf (see above) whenever the constraints are violated by a given input .IR x . More generally, there are various ways to implement constraints by adding "penalty terms" to your objective function, which are described in the optimization literature. A much more efficient way to specify nonlinear constraints is described below, but is only supported by a small subset of the algorithms. .SH NONLINEAR CONSTRAINTS The .B nlopt_minimize_constrained function also allows you to specify .I m nonlinear constraints via the function .IR fc , where .I m is any nonnegative integer. However, nonzero .I m is currently only supported by the .B NLOPT_LD_MMA and .B NLOPT_LN_COBYLA algorithms below. .sp In particular, the nonlinear constraints are of the form \fIfc\fR(\fIx\fR) <= 0, where the function .I fc is of the same form as the objective function described above: .sp .BI " double fc(int " "n" , .br .BI " const double* " "x" , .br .BI " double* " "grad" , .br .BI " void* " "fc_datum" ); .sp The return value should be the value of the constraint at the point .IR x , where the dimension .I n is identical to the one passed to .BR nlopt_minimize_constrained (). As for the objective function, if the argument .I grad is not NULL, then .I grad points to an array of length .I n which should (upon return) be set to the gradient of the function with respect to .IR x . (For any algorithm listed as "derivative-free" below, the .I grad argument will always be NULL and need never be computed.) .sp The .I fc_datum argument is based on the .I fc_data argument passed to .BR nlopt_minimize_constrained (), and may be used to pass any additional data through to the function, and is used to distinguish between different constraints. .sp In particular, the constraint function .I fc will be called (at most) .I m times for each .IR x , and the i-th constraint (0 <= i < .IR m ) will be passed an .I fc_datum argument equal to .I fc_data offset by i * .IR fc_datum_size . For example, suppose that you have a data structure of type "foo" that describes the data needed by each constraint, and you store the information for the constraints in an array "foo data[m]". In this case, you would pass "data" as the .I fc_data parameter to .BR nlopt_minimize_constrained , and "sizeof(foo)" as the .I fc_datum_size parameter. Then, your .I fc function would be called .I m times for each point, and be passed &data[0] through &data[m-1] in sequence. .SH ALGORITHMS The .I algorithm parameter specifies the optimization algorithm (for more detail on these, see the README files in the source-code subdirectories), and can take on any of the following constant values. Constants with .B _G{N,D}_ in their names refer to global optimization methods, whereas .B _L{N,D}_ refers to local optimization methods (that try to find a local minimum starting from the starting guess .IR x ). Constants with .B _{G,L}N_ refer to non-gradient (derivative-free) algorithms that do not require the objective function to supply a gradient, whereas .B _{G,L}D_ refers to derivative-based algorithms that require the objective function to supply a gradient. (Especially for local optimization, derivative-based algorithms are generally superior to derivative-free ones: the gradient is good to have .I if you can compute it cheaply, e.g. via an adjoint method.) .TP .B NLOPT_GN_DIRECT_L Perform a global (G) derivative-free (N) optimization using the DIRECT-L search algorithm by Jones et al. as modified by Gablonsky et al. to be more weighted towards local search. Does not support unconstrainted optimization. There are also several other variants of the DIRECT algorithm that are supported: .BR NLOPT_GN_DIRECT , which is the original DIRECT algorithm; .BR NLOPT_GN_DIRECT_L_RAND , a slightly randomized version of DIRECT-L that may be better in high-dimensional search spaces; .BR NLOPT_GN_DIRECT_NOSCAL , .BR NLOPT_GN_DIRECT_L_NOSCAL , and .BR NLOPT_GN_DIRECT_L_RAND_NOSCAL , which are versions of DIRECT where the dimensions are not rescaled to a unit hypercube (which means that dimensions with larger bounds are given more weight). .TP .B NLOPT_GN_ORIG_DIRECT_L A global (G) derivative-free optimization using the DIRECT-L algorithm as above, along with .B NLOPT_GN_ORIG_DIRECT which is the original DIRECT algorithm. Unlike .B NLOPT_GN_DIRECT_L above, these two algorithms refer to code based on the original Fortran code of Gablonsky et al., which has some hard-coded limitations on the number of subdivisions etc. and does not support all of the NLopt stopping criteria, but on the other hand supports arbitrary nonlinear constraints as described above. .TP .B NLOPT_GD_STOGO Global (G) optimization using the StoGO algorithm by Madsen et al. StoGO exploits gradient information (D) (which must be supplied by the objective) for its local searches, and performs the global search by a branch-and-bound technique. Only bound-constrained optimization is supported. There is also another variant of this algorithm, .BR NLOPT_GD_STOGO_RAND , which is a randomized version of the StoGO search scheme. The StoGO algorithms are only available if NLopt is compiled with C++ enabled, and should be linked via -lnlopt_cxx (via a C++ compiler, in order to link the C++ standard libraries). .TP .B NLOPT_LN_NELDERMEAD Perform a local (L) derivative-free (N) optimization, starting at .IR x , using the Nelder-Mead simplex algorithm, modified to support bound constraints. Nelder-Mead, while popular, is known to occasionally fail to converge for some objective functions, so it should be used with caution. Anecdotal evidence, on the other hand, suggests that it works fairly well for discontinuous objectives. See also .B NLOPT_LN_SBPLX below. .TP .B NLOPT_LN_SBPLX Perform a local (L) derivative-free (N) optimization, starting at .IR x , using an algorithm based on the Subplex algorithm of Rowan et al., which is an improved variant of Nelder-Mead (above). Our implementation does not use Rowan's original code, and has some minor modifications such as explicit support for bound constraints. (Like Nelder-Mead, Subplex often works well in practice, even for discontinuous objectives, but there is no rigorous guarantee that it will converge.) Nonlinear constraints can be crudely supported by returning +Inf when the constraints are violated, as explained above. .TP .B NLOPT_LN_PRAXIS Local (L) derivative-free (N) optimization using the principal-axis method, based on code by Richard Brent. Designed for unconstrained optimization, although bound constraints are supported too (via the inefficient method of returning +Inf when the constraints are violated). .TP .B NLOPT_LD_LBFGS Local (L) gradient-based (D) optimization using the limited-memory BFGS (L-BFGS) algorithm. (The objective function must supply the gradient.) Unconstrained optimization is supported in addition to simple bound constraints (see above). Based on an implementation by Luksan et al. .TP .B NLOPT_LD_VAR2 Local (L) gradient-based (D) optimization using a shifted limited-memory variable-metric method based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. .B NLOPT_LD_VAR2 uses a rank-2 method, while .B .B NLOPT_LD_VAR1 is another variant using a rank-1 method. .TP .B NLOPT_LD_TNEWTON_PRECOND_RESTART Local (L) gradient-based (D) optimization using an LBFGS-preconditioned truncated Newton method with steepest-descent restarting, based on code by Luksan et al., supporting both unconstrained and bound-constrained optimization. There are several other variants of this algorithm: .B NLOPT_LD_TNEWTON_PRECOND (same without restarting), .B NLOPT_LD_TNEWTON_RESTART (same without preconditioning), and .B NLOPT_LD_TNEWTON (same without restarting or preconditioning). .TP .B NLOPT_GN_CRS2_LM Global (G) derivative-free (N) optimization using the controlled random search (CRS2) algorithm of Price, with the "local mutation" (LM) modification suggested by Kaelo and Ali. .TP \fBNLOPT_GD_MLSL_LDS\fR, \fBNLOPT_GN_MLSL_LDS\fR Global (G) derivative-based (D) or derivative-free (N) optimization using the multi-level single-linkage (MLSL) algorithm with a low-discrepancy sequence (LDS). This algorithm executes a quasi-random (LDS) sequence of local searches, with a clustering heuristic to avoid multiple local searches for the same local minimum. The local search uses the derivative/nonderivative algorithm set by .I nlopt_set_local_search_algorithm (currently defaulting to .I NLOPT_LD_MMA and .I NLOPT_LN_COBYLA for derivative/nonderivative searches, respectively). There are also two other variants, \fBNLOPT_GD_MLSL\fR and \fBNLOPT_GN_MLSL\fR, which use pseudo-random numbers (instead of an LDS) as in the original MLSL algorithm. .TP .B NLOPT_LD_MMA Local (L) gradient-based (D) optimization using the method of moving asymptotes (MMA), or rather a refined version of the algorithm as published by Svanberg (2002). (NLopt uses an independent free-software/open-source implementation of Svanberg's algorithm.) The .B NLOPT_LD_MMA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear constraints as described above. .TP .B NLOPT_LN_COBYLA Local (L) derivative-free (N) optimization using the COBYLA algorithm of Powell (Constrained Optimization BY Linear Approximations). The .B NLOPT_LN_COBYLA algorithm supports both bound-constrained and unconstrained optimization, and also supports an arbitrary number (\fIm\fR) of nonlinear constraints as described above. .TP .B NLOPT_LN_NEWUOA Local (L) derivative-free (N) optimization using a variant of the the NEWUOA algorithm of Powell, based on successive quadratic approximations of the objective function. We have modified the algorithm to support bound constraints. The original NEWUOA algorithm is also available, as .BR NLOPT_LN_NEWUOA , but this algorithm ignores the bound constraints .I lb and .IR ub , and so it should only be used for unconstrained problems. .SH STOPPING CRITERIA Multiple stopping criteria for the optimization are supported, as specified by the following arguments to .BR nlopt_minimize_constrained (). The optimization halts whenever any one of these criteria is satisfied. In some cases, the precise interpretation of the stopping criterion depends on the optimization algorithm above (although we have tried to make them as consistent as reasonably possible), and some algorithms do not support all of the stopping criteria. .sp Important: you do not need to use all of the stopping criteria! In most cases, you only need one or two, and can set the remainder to values where they do nothing (as described below). .TP .B minf_max Stop when a function value less than or equal to .I minf_max is found. Set to -Inf or NaN (see constraints section above) to disable. .TP .B ftol_rel Relative tolerance on function value: stop when an optimization step (or an estimate of the minimum) changes the function value by less than .I ftol_rel multiplied by the absolute value of the function value. (If there is any chance that your minimum function value is close to zero, you might want to set an absolute tolerance with .I ftol_abs as well.) Disabled if non-positive. .TP .B ftol_abs Absolute tolerance on function value: stop when an optimization step (or an estimate of the minimum) changes the function value by less than .IR ftol_abs . Disabled if non-positive. .TP .B xtol_rel Relative tolerance on design variables: stop when an optimization step (or an estimate of the minimum) changes every design variable by less than .I xtol_rel multiplied by the absolute value of the design variable. (If there is any chance that an optimal design variable is close to zero, you might want to set an absolute tolerance with .I xtol_abs as well.) Disabled if non-positive. .TP .B xtol_abs Pointer to an array of length .I n giving absolute tolerances on design variables: stop when an optimization step (or an estimate of the minimum) changes every design variable .IR x [i] by less than .IR xtol_abs [i]. Disabled if non-positive, or if .I xtol_abs is NULL. .TP .B maxeval Stop when the number of function evaluations exceeds .IR maxeval . (This is not a strict maximum: the number of function evaluations may exceed .I maxeval slightly, depending upon the algorithm.) Disabled if non-positive. .TP .B maxtime Stop when the optimization time (in seconds) exceeds .IR maxtime . (This is not a strict maximum: the time may exceed .I maxtime slightly, depending upon the algorithm and on how slow your function evaluation is.) Disabled if non-positive. .SH RETURN VALUE The value returned is one of the following enumerated constants. .SS Successful termination (positive return values): .TP .B NLOPT_SUCCESS Generic success return value. .TP .B NLOPT_MINF_MAX_REACHED Optimization stopped because .I minf_max (above) was reached. .TP .B NLOPT_FTOL_REACHED Optimization stopped because .I ftol_rel or .I ftol_abs (above) was reached. .TP .B NLOPT_XTOL_REACHED Optimization stopped because .I xtol_rel or .I xtol_abs (above) was reached. .TP .B NLOPT_MAXEVAL_REACHED Optimization stopped because .I maxeval (above) was reached. .TP .B NLOPT_MAXTIME_REACHED Optimization stopped because .I maxtime (above) was reached. .SS Error codes (negative return values): .TP .B NLOPT_FAILURE Generic failure code. .TP .B NLOPT_INVALID_ARGS Invalid arguments (e.g. lower bounds are bigger than upper bounds, an unknown algorithm was specified, etcetera). .TP .B NLOPT_OUT_OF_MEMORY Ran out of memory. .SH PSEUDORANDOM NUMBERS For stochastic optimization algorithms, we use pseudorandom numbers generated by the Mersenne Twister algorithm, based on code from Makoto Matsumoto. By default, the seed for the random numbers is generated from the system time, so that they will be different each time you run the program. If you want to use deterministic random numbers, you can set the seed by calling: .sp .BI " void nlopt_srand(unsigned long " "seed" ); .sp Some of the algorithms also support using low-discrepancy sequences (LDS), sometimes known as quasi-random numbers. NLopt uses the Sobol LDS, which is implemented for up to 1111 dimensions. .SH AUTHORS Written by Steven G. Johnson. .PP Copyright (c) 2007-2014 Massachusetts Institute of Technology. .SH "SEE ALSO" nlopt_minimize(3) nlopt-2.6.1/src/api/optimize.c000066400000000000000000000753231345435414600162430ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include "nlopt-internal.h" /*********************************************************************/ #include "praxis.h" #include "direct.h" #ifdef NLOPT_CXX #include "stogo.h" #endif #ifdef NLOPT_CXX11 #include "ags.h" #endif #include "cdirect.h" #include "luksan.h" #include "crs.h" #include "mlsl.h" #include "mma.h" #include "cobyla.h" #include "newuoa.h" #include "neldermead.h" #include "auglag.h" #include "bobyqa.h" #include "isres.h" #include "esch.h" #include "slsqp.h" /*********************************************************************/ static double f_bound(int n, const double *x, void *data_) { int i; nlopt_opt data = (nlopt_opt) data_; double f; /* some methods do not support bound constraints, but support discontinuous objectives so we can just return Inf for invalid x */ for (i = 0; i < n; ++i) if (x[i] < data->lb[i] || x[i] > data->ub[i]) return HUGE_VAL; f = data->f((unsigned) n, x, NULL, data->f_data); return (nlopt_isnan(f) || nlopt_isinf(f) ? HUGE_VAL : f); } static double f_noderiv(int n, const double *x, void *data_) { nlopt_opt data = (nlopt_opt) data_; return data->f((unsigned) n, x, NULL, data->f_data); } static double f_direct(int n, const double *x, int *undefined, void *data_) { nlopt_opt data = (nlopt_opt) data_; double *work = (double *) data->work; double f; unsigned i, j; f = data->f((unsigned) n, x, NULL, data->f_data); ++data->numevals; *undefined = nlopt_isnan(f) || nlopt_isinf(f); if (nlopt_get_force_stop(data)) return f; for (i = 0; i < data->m && !*undefined; ++i) { nlopt_eval_constraint(work, NULL, data->fc + i, (unsigned) n, x); if (nlopt_get_force_stop(data)) return f; for (j = 0; j < data->fc[i].m; ++j) if (work[j] > 0) *undefined = 1; } return f; } /*********************************************************************/ /* get min(dx) for algorithms requiring a scalar initial step size */ static nlopt_result initial_step(nlopt_opt opt, const double *x, double *step) { unsigned freedx = 0, i; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } *step = HUGE_VAL; for (i = 0; i < opt->n; ++i) if (*step > fabs(opt->dx[i])) *step = fabs(opt->dx[i]); if (freedx) { free(opt->dx); opt->dx = NULL; } return NLOPT_SUCCESS; } /*********************************************************************/ /* return true if [lb,ub] is finite in every dimension (n dimensions) */ static int finite_domain(unsigned n, const double *lb, const double *ub) { unsigned i; for (i = 0; i < n; ++i) if (nlopt_isinf(ub[i] - lb[i])) return 0; return 1; } /*********************************************************************/ /* wrapper functions, only for derivative-free methods, that eliminate dimensions with lb == ub. (The gradient-based methods should handle this case directly, since they operate on much larger vectors where I am loathe to make copies unnecessarily.) */ typedef struct { nlopt_func f; nlopt_mfunc mf; void *f_data; unsigned n; /* true dimension */ double *x; /* scratch vector of length n */ double *grad; /* optional scratch vector of length n */ const double *lb, *ub; /* bounds, of length n */ } elimdim_data; static void *elimdim_makedata(nlopt_func f, nlopt_mfunc mf, void *f_data, unsigned n, double *x, const double *lb, const double *ub, double *grad) { elimdim_data *d = (elimdim_data *) malloc(sizeof(elimdim_data)); if (!d) return NULL; d->f = f; d->mf = mf; d->f_data = f_data; d->n = n; d->x = x; d->lb = lb; d->ub = ub; d->grad = grad; return d; } static double elimdim_func(unsigned n0, const double *x0, double *grad, void *d_) { elimdim_data *d = (elimdim_data *) d_; double *x = d->x; const double *lb = d->lb, *ub = d->ub; double val; unsigned n = d->n, i, j; (void) n0; /* unused */ for (i = j = 0; i < n; ++i) { if (lb[i] == ub[i]) x[i] = lb[i]; else /* assert: j < n0 */ x[i] = x0[j++]; } val = d->f(n, x, grad ? d->grad : NULL, d->f_data); if (grad) { /* assert: d->grad != NULL */ for (i = j = 0; i < n; ++i) if (lb[i] != ub[i]) grad[j++] = d->grad[i]; } return val; } static void elimdim_mfunc(unsigned m, double *result, unsigned n0, const double *x0, double *grad, void *d_) { elimdim_data *d = (elimdim_data *) d_; double *x = d->x; const double *lb = d->lb, *ub = d->ub; unsigned n = d->n, i, j; (void) n0; /* unused */ (void) grad; /* assert: grad == NULL */ for (i = j = 0; i < n; ++i) { if (lb[i] == ub[i]) x[i] = lb[i]; else /* assert: j < n0 */ x[i] = x0[j++]; } d->mf(m, result, n, x, NULL, d->f_data); } /* compute the eliminated dimension: number of dims with lb[i] != ub[i] */ static unsigned elimdim_dimension(unsigned n, const double *lb, const double *ub) { unsigned n0 = 0, i; for (i = 0; i < n; ++i) n0 += lb[i] != ub[i] ? 1U : 0; return n0; } /* modify v to "shrunk" version, with dimensions for lb[i] == ub[i] elim'ed */ static void elimdim_shrink(unsigned n, double *v, const double *lb, const double *ub) { unsigned i, j; if (v) for (i = j = 0; i < n; ++i) if (lb[i] != ub[i]) v[j++] = v[i]; } /* inverse of elimdim_shrink */ static void elimdim_expand(unsigned n, double *v, const double *lb, const double *ub) { unsigned i, j; if (v && n > 0) { j = elimdim_dimension(n, lb, ub) - 1; for (i = n - 1; i > 0; --i) { if (lb[i] != ub[i]) v[i] = v[j--]; else v[i] = lb[i]; } if (lb[0] == ub[0]) v[0] = lb[0]; } } /* given opt, create a new opt with equal-constraint dimensions eliminated */ static nlopt_opt elimdim_create(nlopt_opt opt) { nlopt_opt opt0; nlopt_munge munge_copy_save = opt->munge_on_copy; double *x, *grad = NULL; unsigned i; opt->munge_on_copy = 0; /* hack: since this is an internal copy, we can leave it un-munged; see issue #26 */ opt0 = nlopt_copy(opt); opt->munge_on_copy = munge_copy_save; if (!opt0) return NULL; x = (double *) malloc(sizeof(double) * opt->n); if (opt->n && !x) { nlopt_destroy(opt0); return NULL; } if (opt->algorithm == NLOPT_GD_STOGO || opt->algorithm == NLOPT_GD_STOGO_RAND) { grad = (double *) malloc(sizeof(double) * opt->n); if (opt->n && !grad) goto bad; } opt0->n = elimdim_dimension(opt->n, opt->lb, opt->ub); elimdim_shrink(opt->n, opt0->lb, opt->lb, opt->ub); elimdim_shrink(opt->n, opt0->ub, opt->lb, opt->ub); elimdim_shrink(opt->n, opt0->xtol_abs, opt->lb, opt->ub); elimdim_shrink(opt->n, opt0->dx, opt->lb, opt->ub); opt0->munge_on_destroy = opt0->munge_on_copy = NULL; opt0->f = elimdim_func; opt0->f_data = elimdim_makedata(opt->f, NULL, opt->f_data, opt->n, x, opt->lb, opt->ub, grad); if (!opt0->f_data) goto bad; for (i = 0; i < opt->m; ++i) { opt0->fc[i].f = opt0->fc[i].f ? elimdim_func : NULL; opt0->fc[i].mf = opt0->fc[i].mf ? elimdim_mfunc : NULL; opt0->fc[i].f_data = elimdim_makedata(opt->fc[i].f, opt->fc[i].mf, opt->fc[i].f_data, opt->n, x, opt->lb, opt->ub, NULL); if (!opt0->fc[i].f_data) goto bad; } for (i = 0; i < opt->p; ++i) { opt0->h[i].f = opt0->h[i].f ? elimdim_func : NULL; opt0->h[i].mf = opt0->h[i].mf ? elimdim_mfunc : NULL; opt0->h[i].f_data = elimdim_makedata(opt->h[i].f, opt->h[i].mf, opt->h[i].f_data, opt->n, x, opt->lb, opt->ub, NULL); if (!opt0->h[i].f_data) goto bad; } return opt0; bad: free(grad); free(x); nlopt_destroy(opt0); return NULL; } /* like nlopt_destroy, but also frees elimdim_data */ static void elimdim_destroy(nlopt_opt opt) { unsigned i; if (!opt) return; free(((elimdim_data *) opt->f_data)->x); free(((elimdim_data *) opt->f_data)->grad); free(opt->f_data); opt->f_data = NULL; for (i = 0; i < opt->m; ++i) { free(opt->fc[i].f_data); opt->fc[i].f_data = NULL; } for (i = 0; i < opt->p; ++i) { free(opt->h[i].f_data); opt->h[i].f_data = NULL; } nlopt_destroy(opt); } /* return whether to use elimdim wrapping. */ static int elimdim_wrapcheck(nlopt_opt opt) { if (!opt) return 0; if (elimdim_dimension(opt->n, opt->lb, opt->ub) == opt->n) return 0; switch (opt->algorithm) { case NLOPT_GN_DIRECT: case NLOPT_GN_DIRECT_L: case NLOPT_GN_DIRECT_L_RAND: case NLOPT_GN_DIRECT_NOSCAL: case NLOPT_GN_DIRECT_L_NOSCAL: case NLOPT_GN_DIRECT_L_RAND_NOSCAL: case NLOPT_GN_ORIG_DIRECT: case NLOPT_GN_ORIG_DIRECT_L: case NLOPT_GN_CRS2_LM: case NLOPT_LN_PRAXIS: case NLOPT_LN_COBYLA: case NLOPT_LN_NEWUOA: case NLOPT_LN_NEWUOA_BOUND: case NLOPT_LN_BOBYQA: case NLOPT_LN_NELDERMEAD: case NLOPT_LN_SBPLX: case NLOPT_GN_ISRES: case NLOPT_GN_ESCH: case NLOPT_GN_AGS: case NLOPT_GD_STOGO: case NLOPT_GD_STOGO_RAND: return 1; default: return 0; } } /*********************************************************************/ #define POP(defaultpop) (opt->stochastic_population > 0 ? opt->stochastic_population : (nlopt_stochastic_population > 0 ? nlopt_stochastic_population : (defaultpop))) /* unlike nlopt_optimize() below, only handles minimization case */ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) { const double *lb, *ub; nlopt_algorithm algorithm; nlopt_func f; void *f_data; unsigned n, i; int ni; nlopt_stopping stop; if (!opt || !x || !minf || !opt->f || opt->maximize) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL args to nlopt_optimize_"); /* reset stopping flag */ nlopt_set_force_stop(opt, 0); opt->force_stop_child = NULL; /* copy a few params to local vars for convenience */ n = opt->n; ni = (int) n; /* most of the subroutines take "int" arg */ lb = opt->lb; ub = opt->ub; algorithm = opt->algorithm; f = opt->f; f_data = opt->f_data; if (n == 0) { /* trivial case: no degrees of freedom */ *minf = opt->f(n, x, NULL, opt->f_data); return NLOPT_SUCCESS; } *minf = HUGE_VAL; /* make sure rand generator is inited */ nlopt_srand_time_default(); /* default is non-deterministic */ /* check bound constraints */ for (i = 0; i < n; ++i) if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i]) { nlopt_set_errmsg(opt, "bounds %d fail %g <= %g <= %g", i, lb[i], x[i], ub[i]); return NLOPT_INVALID_ARGS; } stop.n = n; stop.minf_max = opt->stopval; stop.ftol_rel = opt->ftol_rel; stop.ftol_abs = opt->ftol_abs; stop.xtol_rel = opt->xtol_rel; stop.xtol_abs = opt->xtol_abs; opt->numevals = 0; stop.nevals_p = &(opt->numevals); stop.maxeval = opt->maxeval; stop.maxtime = opt->maxtime; stop.start = nlopt_seconds(); stop.force_stop = &(opt->force_stop); stop.stop_msg = &(opt->errmsg); switch (algorithm) { case NLOPT_GN_DIRECT: case NLOPT_GN_DIRECT_L: case NLOPT_GN_DIRECT_L_RAND: if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return cdirect(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); case NLOPT_GN_DIRECT_NOSCAL: case NLOPT_GN_DIRECT_L_NOSCAL: case NLOPT_GN_DIRECT_L_RAND_NOSCAL: if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); case NLOPT_GN_ORIG_DIRECT: case NLOPT_GN_ORIG_DIRECT_L: { direct_return_code dret; if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); opt->work = malloc(sizeof(double) * nlopt_max_constraint_dim(opt->m, opt->fc)); if (!opt->work) return NLOPT_OUT_OF_MEMORY; dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf, stop.maxeval, -1, stop.start, stop.maxtime, 0.0, 0.0, pow(stop.xtol_rel, (double) n), -1.0, stop.force_stop, stop.minf_max, 0.0, NULL, algorithm == NLOPT_GN_ORIG_DIRECT ? DIRECT_ORIGINAL : DIRECT_GABLONSKY); free(opt->work); opt->work = NULL; switch (dret) { case DIRECT_INVALID_BOUNDS: RETURN_ERR(NLOPT_INVALID_ARGS, opt, "invalid bounds for DIRECT"); case DIRECT_MAXFEVAL_TOOBIG: RETURN_ERR(NLOPT_INVALID_ARGS, opt, "maxeval too big for DIRECT"); case DIRECT_INVALID_ARGS: return NLOPT_INVALID_ARGS; case DIRECT_INIT_FAILED: RETURN_ERR(NLOPT_FAILURE, opt, "init failed for DIRECT"); case DIRECT_SAMPLEPOINTS_FAILED: RETURN_ERR(NLOPT_FAILURE, opt, "sample-points failed for DIRECT"); case DIRECT_SAMPLE_FAILED: RETURN_ERR(NLOPT_FAILURE, opt, "sample failed for DIRECT"); case DIRECT_MAXFEVAL_EXCEEDED: case DIRECT_MAXITER_EXCEEDED: return NLOPT_MAXEVAL_REACHED; case DIRECT_MAXTIME_EXCEEDED: return NLOPT_MAXTIME_REACHED; case DIRECT_GLOBAL_FOUND: return NLOPT_MINF_MAX_REACHED; case DIRECT_VOLTOL: case DIRECT_SIGMATOL: return NLOPT_XTOL_REACHED; case DIRECT_OUT_OF_MEMORY: return NLOPT_OUT_OF_MEMORY; case DIRECT_FORCED_STOP: return NLOPT_FORCED_STOP; } break; } case NLOPT_GN_AGS: #ifdef NLOPT_CXX11 if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return ags_minimize(ni, f, f_data, opt->m, opt->fc, x, minf, lb, ub, &stop); break; #else return NLOPT_INVALID_ARGS; #endif case NLOPT_GD_STOGO: case NLOPT_GD_STOGO_RAND: #ifdef NLOPT_CXX if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop, algorithm == NLOPT_GD_STOGO ? 0 : (int) POP(2 * n))) return NLOPT_FAILURE; break; #else return NLOPT_INVALID_ARGS; #endif #if 0 /* lacking a free/open-source license, we no longer use Rowan's code, and instead use by "sbplx" re-implementation */ case NLOPT_LN_SUBPLEX: { int iret, freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } iret = nlopt_subplex(f_bound, minf, x, n, opt, &stop, opt->dx); if (freedx) { free(opt->dx); opt->dx = NULL; } switch (iret) { case -2: return NLOPT_INVALID_ARGS; case -20: return NLOPT_FORCED_STOP; case -10: return NLOPT_MAXTIME_REACHED; case -1: return NLOPT_MAXEVAL_REACHED; case 0: return NLOPT_XTOL_REACHED; case 1: return NLOPT_SUCCESS; case 2: return NLOPT_MINF_MAX_REACHED; case 20: return NLOPT_FTOL_REACHED; case -200: return NLOPT_OUT_OF_MEMORY; default: return NLOPT_FAILURE; /* unknown return code */ } break; } #endif case NLOPT_LN_PRAXIS: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; return praxis_(0.0, DBL_EPSILON, step, ni, x, f_bound, opt, &stop, minf); } case NLOPT_LD_LBFGS: return luksan_plis(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage); case NLOPT_LD_VAR1: case NLOPT_LD_VAR2: return luksan_plip(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, algorithm == NLOPT_LD_VAR1 ? 1 : 2); case NLOPT_LD_TNEWTON: case NLOPT_LD_TNEWTON_RESTART: case NLOPT_LD_TNEWTON_PRECOND: case NLOPT_LD_TNEWTON_PRECOND_RESTART: return luksan_pnet(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, 1 + (algorithm - NLOPT_LD_TNEWTON) % 2, 1 + (algorithm - NLOPT_LD_TNEWTON) / 2); case NLOPT_GN_CRS2_LM: if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, (int) POP(0), 0); case NLOPT_G_MLSL: case NLOPT_G_MLSL_LDS: case NLOPT_GN_MLSL: case NLOPT_GD_MLSL: case NLOPT_GN_MLSL_LDS: case NLOPT_GD_MLSL_LDS: { nlopt_opt local_opt = opt->local_opt; nlopt_result ret; if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); if (!local_opt && (algorithm == NLOPT_G_MLSL || algorithm == NLOPT_G_MLSL_LDS)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "local optimizer must be specified for G_MLSL"); if (!local_opt) { /* default */ nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) ? nlopt_local_search_alg_nonderiv : nlopt_local_search_alg_deriv; /* don't call MLSL recursively! */ if (local_alg >= NLOPT_GN_MLSL && local_alg <= NLOPT_GD_MLSL_LDS) local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) ? NLOPT_LN_COBYLA : NLOPT_LD_MMA; local_opt = nlopt_create(local_alg, n); if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt, "failed to create local_opt"); nlopt_set_ftol_rel(local_opt, opt->ftol_rel); nlopt_set_ftol_abs(local_opt, opt->ftol_abs); nlopt_set_xtol_rel(local_opt, opt->xtol_rel); nlopt_set_xtol_abs(local_opt, opt->xtol_abs); nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); } if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); for (i = 0; i < n && stop.xtol_abs[i] > 0; ++i); if (local_opt->ftol_rel <= 0 && local_opt->ftol_abs <= 0 && local_opt->xtol_rel <= 0 && i < n) { /* it is not sensible to call MLSL without *some* nonzero tolerance for the local search */ nlopt_set_ftol_rel(local_opt, 1e-15); nlopt_set_xtol_rel(local_opt, 1e-7); } opt->force_stop_child = local_opt; ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop, local_opt, (int) POP(0), algorithm >= NLOPT_GN_MLSL_LDS && algorithm != NLOPT_G_MLSL); opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } case NLOPT_LD_MMA: case NLOPT_LD_CCSAQ: { nlopt_opt dual_opt; nlopt_result ret; #define LO(param, def) (opt->local_opt ? opt->local_opt->param : (def)) dual_opt = nlopt_create(LO(algorithm, nlopt_local_search_alg_deriv), nlopt_count_constraints(opt->m, opt->fc)); if (!dual_opt) RETURN_ERR(NLOPT_FAILURE, opt, "failed creating dual optimizer"); nlopt_set_ftol_rel(dual_opt, LO(ftol_rel, 1e-14)); nlopt_set_ftol_abs(dual_opt, LO(ftol_abs, 0.0)); nlopt_set_maxeval(dual_opt, LO(maxeval, 100000)); #undef LO if (algorithm == NLOPT_LD_MMA) ret = mma_minimize(n, f, f_data, opt->m, opt->fc, lb, ub, x, minf, &stop, dual_opt); else ret = ccsa_quadratic_minimize(n, f, f_data, opt->m, opt->fc, opt->pre, lb, ub, x, minf, &stop, dual_opt); nlopt_destroy(dual_opt); return ret; } case NLOPT_LN_COBYLA: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); } ret = cobyla_minimize(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop, opt->dx); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_LN_NEWUOA: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); return newuoa(ni, 2 * n + 1, x, 0, 0, step, &stop, minf, f_noderiv, opt); } case NLOPT_LN_NEWUOA_BOUND: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); return newuoa(ni, 2 * n + 1, x, lb, ub, step, &stop, minf, f_noderiv, opt); } case NLOPT_LN_BOBYQA: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); } ret = bobyqa(ni, 2 * n + 1, x, lb, ub, opt->dx, &stop, minf, opt->f, opt->f_data); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_LN_NELDERMEAD: case NLOPT_LN_SBPLX: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); } if (algorithm == NLOPT_LN_NELDERMEAD) ret = nldrmd_minimize(ni, f, f_data, lb, ub, x, minf, opt->dx, &stop); else ret = sbplx_minimize(ni, f, f_data, lb, ub, x, minf, opt->dx, &stop); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_AUGLAG: case NLOPT_AUGLAG_EQ: case NLOPT_LN_AUGLAG: case NLOPT_LN_AUGLAG_EQ: case NLOPT_LD_AUGLAG: case NLOPT_LD_AUGLAG_EQ: { nlopt_opt local_opt = opt->local_opt; nlopt_result ret; if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ) && !local_opt) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "local optimizer must be specified for AUGLAG"); if (!local_opt) { /* default */ local_opt = nlopt_create(algorithm == NLOPT_LN_AUGLAG || algorithm == NLOPT_LN_AUGLAG_EQ ? nlopt_local_search_alg_nonderiv : nlopt_local_search_alg_deriv, n); if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt, "failed to create local_opt"); nlopt_set_ftol_rel(local_opt, opt->ftol_rel); nlopt_set_ftol_abs(local_opt, opt->ftol_abs); nlopt_set_xtol_rel(local_opt, opt->xtol_rel); nlopt_set_xtol_abs(local_opt, opt->xtol_abs); nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); } if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); opt->force_stop_child = local_opt; ret = auglag_minimize(ni, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop, local_opt, algorithm == NLOPT_AUGLAG_EQ || algorithm == NLOPT_LN_AUGLAG_EQ || algorithm == NLOPT_LD_AUGLAG_EQ); opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } case NLOPT_GN_ISRES: if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return isres_minimize(ni, f, f_data, (int) (opt->m), opt->fc, (int) (opt->p), opt->h, lb, ub, x, minf, &stop, (int) POP(0)); case NLOPT_GN_ESCH: if (!finite_domain(n, lb, ub)) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); return chevolutionarystrategy(n, f, f_data, lb, ub, x, minf, &stop, (unsigned) POP(0), (unsigned) (POP(0) * 1.5)); case NLOPT_LD_SLSQP: return nlopt_slsqp(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop); default: return NLOPT_INVALID_ARGS; } return NLOPT_SUCCESS; /* never reached */ } /*********************************************************************/ typedef struct { nlopt_func f; nlopt_precond pre; void *f_data; } f_max_data; /* wrapper for maximizing: just flip the sign of f and grad */ static double f_max(unsigned n, const double *x, double *grad, void *data) { f_max_data *d = (f_max_data *) data; double val = d->f(n, x, grad, d->f_data); if (grad) { unsigned i; for (i = 0; i < n; ++i) grad[i] = -grad[i]; } return -val; } static void pre_max(unsigned n, const double *x, const double *v, double *vpre, void *data) { f_max_data *d = (f_max_data *) data; unsigned i; d->pre(n, x, v, vpre, d->f_data); for (i = 0; i < n; ++i) vpre[i] = -vpre[i]; } nlopt_result NLOPT_STDCALL nlopt_optimize(nlopt_opt opt, double *x, double *opt_f) { nlopt_func f; void *f_data; nlopt_precond pre; f_max_data fmd; int maximize; nlopt_result ret; nlopt_unset_errmsg(opt); if (!opt || !opt_f || !opt->f) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL args to nlopt_optimize"); f = opt->f; f_data = opt->f_data; pre = opt->pre; /* for maximizing, just minimize the f_max wrapper, which flips the sign of everything */ if ((maximize = opt->maximize)) { fmd.f = f; fmd.f_data = f_data; fmd.pre = pre; opt->f = f_max; opt->f_data = &fmd; if (opt->pre) opt->pre = pre_max; opt->stopval = -opt->stopval; opt->maximize = 0; } { /* possibly eliminate lb == ub dimensions for some algorithms */ nlopt_opt elim_opt = opt; if (elimdim_wrapcheck(opt)) { elim_opt = elimdim_create(opt); if (!elim_opt) { nlopt_set_errmsg(opt, "failure allocating elim_opt"); ret = NLOPT_OUT_OF_MEMORY; goto done; } elimdim_shrink(opt->n, x, opt->lb, opt->ub); } ret = nlopt_optimize_(elim_opt, x, opt_f); if (elim_opt != opt) { elimdim_destroy(elim_opt); elimdim_expand(opt->n, x, opt->lb, opt->ub); } } done: if (maximize) { /* restore original signs */ opt->maximize = maximize; opt->stopval = -opt->stopval; opt->f = f; opt->f_data = f_data; opt->pre = pre; *opt_f = -*opt_f; } return ret; } /*********************************************************************/ nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, int maxeval, double maxtime) { int save_maxeval; double save_maxtime; nlopt_result ret; nlopt_unset_errmsg(opt); if (!opt) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL opt arg"); save_maxeval = nlopt_get_maxeval(opt); save_maxtime = nlopt_get_maxtime(opt); /* override opt limits if maxeval and/or maxtime are more stringent */ if (save_maxeval <= 0 || (maxeval > 0 && maxeval < save_maxeval)) nlopt_set_maxeval(opt, maxeval); if (save_maxtime <= 0 || (maxtime > 0 && maxtime < save_maxtime)) nlopt_set_maxtime(opt, maxtime); ret = nlopt_optimize(opt, x, minf); nlopt_set_maxeval(opt, save_maxeval); nlopt_set_maxtime(opt, save_maxtime); return ret; } /*********************************************************************/ nlopt-2.6.1/src/api/options.c000066400000000000000000000657661345435414600161100ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include #include #include "nlopt-internal.h" #define ERR(err, opt, msg) (nlopt_set_errmsg(opt, msg) ? err : err) /*************************************************************************/ void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt) { if (opt) { unsigned i; if (opt->munge_on_destroy) { nlopt_munge munge = opt->munge_on_destroy; munge(opt->f_data); for (i = 0; i < opt->m; ++i) munge(opt->fc[i].f_data); for (i = 0; i < opt->p; ++i) munge(opt->h[i].f_data); } for (i = 0; i < opt->m; ++i) free(opt->fc[i].tol); for (i = 0; i < opt->p; ++i) free(opt->h[i].tol); free(opt->lb); free(opt->ub); free(opt->xtol_abs); free(opt->fc); free(opt->h); nlopt_destroy(opt->local_opt); free(opt->dx); free(opt->work); free(opt->errmsg); free(opt); } } nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n) { nlopt_opt opt; if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS) return NULL; opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); if (opt) { opt->algorithm = algorithm; opt->n = n; opt->f = NULL; opt->f_data = NULL; opt->pre = NULL; opt->maximize = 0; opt->munge_on_destroy = opt->munge_on_copy = NULL; opt->lb = opt->ub = NULL; opt->m = opt->m_alloc = 0; opt->fc = NULL; opt->p = opt->p_alloc = 0; opt->h = NULL; opt->stopval = -HUGE_VAL; opt->ftol_rel = opt->ftol_abs = 0; opt->xtol_rel = 0; opt->xtol_abs = NULL; opt->maxeval = 0; opt->numevals = 0; opt->maxtime = 0; opt->force_stop = 0; opt->force_stop_child = NULL; opt->local_opt = NULL; opt->stochastic_population = 0; opt->vector_storage = 0; opt->dx = NULL; opt->work = NULL; opt->errmsg = NULL; if (n > 0) { opt->lb = (double *) calloc(n, sizeof(double)); if (!opt->lb) goto oom; opt->ub = (double *) calloc(n, sizeof(double)); if (!opt->ub) goto oom; opt->xtol_abs = (double *) calloc(n, sizeof(double)); if (!opt->xtol_abs) goto oom; nlopt_set_lower_bounds1(opt, -HUGE_VAL); nlopt_set_upper_bounds1(opt, +HUGE_VAL); nlopt_set_xtol_abs1(opt, 0.0); } } return opt; oom: nlopt_destroy(opt); return NULL; } nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt) { nlopt_opt nopt = NULL; unsigned i; if (opt) { nlopt_munge munge; nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); *nopt = *opt; nopt->lb = nopt->ub = nopt->xtol_abs = NULL; nopt->fc = nopt->h = NULL; nopt->m_alloc = nopt->p_alloc = 0; nopt->local_opt = NULL; nopt->dx = NULL; nopt->work = NULL; nopt->errmsg = NULL; nopt->force_stop_child = NULL; munge = nopt->munge_on_copy; if (munge && nopt->f_data) if (!(nopt->f_data = munge(nopt->f_data))) goto oom; if (opt->n > 0) { nopt->lb = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->lb) goto oom; nopt->ub = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->ub) goto oom; nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->xtol_abs) goto oom; memcpy(nopt->lb, opt->lb, sizeof(double) * (opt->n)); memcpy(nopt->ub, opt->ub, sizeof(double) * (opt->n)); memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n)); } if (opt->m) { nopt->m_alloc = opt->m; nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) * (opt->m)); if (!nopt->fc) goto oom; memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m)); for (i = 0; i < opt->m; ++i) nopt->fc[i].tol = NULL; if (munge) for (i = 0; i < opt->m; ++i) if (nopt->fc[i].f_data && !(nopt->fc[i].f_data = munge(nopt->fc[i].f_data))) goto oom; for (i = 0; i < opt->m; ++i) if (opt->fc[i].tol) { nopt->fc[i].tol = (double *) malloc(sizeof(double) * nopt->fc[i].m); if (!nopt->fc[i].tol) goto oom; memcpy(nopt->fc[i].tol, opt->fc[i].tol, sizeof(double) * nopt->fc[i].m); } } if (opt->p) { nopt->p_alloc = opt->p; nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) * (opt->p)); if (!nopt->h) goto oom; memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p)); for (i = 0; i < opt->p; ++i) nopt->h[i].tol = NULL; if (munge) for (i = 0; i < opt->p; ++i) if (nopt->h[i].f_data && !(nopt->h[i].f_data = munge(nopt->h[i].f_data))) goto oom; for (i = 0; i < opt->p; ++i) if (opt->h[i].tol) { nopt->h[i].tol = (double *) malloc(sizeof(double) * nopt->h[i].m); if (!nopt->h[i].tol) goto oom; memcpy(nopt->h[i].tol, opt->h[i].tol, sizeof(double) * nopt->h[i].m); } } if (opt->local_opt) { nopt->local_opt = nlopt_copy(opt->local_opt); if (!nopt->local_opt) goto oom; } if (opt->dx) { nopt->dx = (double *) malloc(sizeof(double) * (opt->n)); if (!nopt->dx) goto oom; memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n)); } } return nopt; oom: nopt->munge_on_destroy = NULL; /* better to leak mem than crash */ nlopt_destroy(nopt); return NULL; } /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data) { if (opt) { nlopt_unset_errmsg(opt); if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data); opt->f = f; opt->f_data = f_data; opt->pre = pre; opt->maximize = 0; if (nlopt_isinf(opt->stopval) && opt->stopval > 0) opt->stopval = -HUGE_VAL; /* switch default from max to min */ return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) { return nlopt_set_precond_min_objective(opt, f, NULL, f_data); } nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data) { if (opt) { nlopt_unset_errmsg(opt); if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data); opt->f = f; opt->f_data = f_data; opt->pre = pre; opt->maximize = 1; if (nlopt_isinf(opt->stopval) && opt->stopval < 0) opt->stopval = +HUGE_VAL; /* switch default from min to max */ return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data) { return nlopt_set_precond_max_objective(opt, f, NULL, f_data); } /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb) { nlopt_unset_errmsg(opt); if (opt && (opt->n == 0 || lb)) { unsigned int i; if (opt->n > 0) memcpy(opt->lb, lb, sizeof(double) * (opt->n)); for (i = 0; i < opt->n; ++i) if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->lb[i] = opt->ub[i]; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb) { nlopt_unset_errmsg(opt); if (opt) { unsigned i; for (i = 0; i < opt->n; ++i) { opt->lb[i] = lb; if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->lb[i] = opt->ub[i]; } return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_lower_bound(nlopt_opt opt, int i, double lb) { nlopt_unset_errmsg(opt); if (opt) { if (i < 0 || i >= (int) opt->n) return ERR(NLOPT_INVALID_ARGS, opt, "invalid bound index"); opt->lb[i] = lb; if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->lb[i] = opt->ub[i]; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb) { nlopt_unset_errmsg(opt); if (opt && (opt->n == 0 || lb)) { memcpy(lb, opt->lb, sizeof(double) * (opt->n)); return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub) { nlopt_unset_errmsg(opt); if (opt && (opt->n == 0 || ub)) { unsigned int i; if (opt->n > 0) memcpy(opt->ub, ub, sizeof(double) * (opt->n)); for (i = 0; i < opt->n; ++i) if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->ub[i] = opt->lb[i]; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub) { nlopt_unset_errmsg(opt); if (opt) { unsigned i; for (i = 0; i < opt->n; ++i) { opt->ub[i] = ub; if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->ub[i] = opt->lb[i]; } return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_upper_bound(nlopt_opt opt, int i, double ub) { nlopt_unset_errmsg(opt); if (opt) { if (i < 0 || i >= (int) opt->n) return ERR(NLOPT_INVALID_ARGS, opt, "invalid bound index"); opt->ub[i] = ub; if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) opt->ub[i] = opt->lb[i]; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub) { nlopt_unset_errmsg(opt); if (opt && (opt->n == 0 || ub)) { memcpy(ub, opt->ub, sizeof(double) * (opt->n)); return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } /*************************************************************************/ #define AUGLAG_ALG(a) ((a) == NLOPT_AUGLAG || \ (a) == NLOPT_AUGLAG_EQ || \ (a) == NLOPT_LN_AUGLAG || \ (a) == NLOPT_LN_AUGLAG_EQ || \ (a) == NLOPT_LD_AUGLAG || \ (a) == NLOPT_LD_AUGLAG_EQ) nlopt_result NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt) { unsigned i; nlopt_unset_errmsg(opt); if (!opt) return NLOPT_INVALID_ARGS; if (opt->munge_on_destroy) { nlopt_munge munge = opt->munge_on_destroy; for (i = 0; i < opt->m; ++i) munge(opt->fc[i].f_data); } for (i = 0; i < opt->m; ++i) free(opt->fc[i].tol); free(opt->fc); opt->fc = NULL; opt->m = opt->m_alloc = 0; return NLOPT_SUCCESS; } static nlopt_result add_constraint(nlopt_opt opt, unsigned *m, unsigned *m_alloc, nlopt_constraint ** c, unsigned fm, nlopt_func fc, nlopt_mfunc mfc, nlopt_precond pre, void *fc_data, const double *tol) { double *tolcopy; unsigned i; if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc)) return NLOPT_INVALID_ARGS; if (tol) for (i = 0; i < fm; ++i) if (tol[i] < 0) return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance"); tolcopy = (double *) malloc(sizeof(double) * fm); if (fm && !tolcopy) return NLOPT_OUT_OF_MEMORY; if (tol) memcpy(tolcopy, tol, sizeof(double) * fm); else for (i = 0; i < fm; ++i) tolcopy[i] = 0; *m += 1; if (*m > *m_alloc) { /* allocate by repeated doubling so that we end up with O(log m) mallocs rather than O(m). */ *m_alloc = 2 * (*m); *c = (nlopt_constraint *) realloc(*c, sizeof(nlopt_constraint) * (*m_alloc)); if (!*c) { *m_alloc = *m = 0; free(tolcopy); return NLOPT_OUT_OF_MEMORY; } } (*c)[*m - 1].m = fm; (*c)[*m - 1].f = fc; (*c)[*m - 1].pre = pre; (*c)[*m - 1].mf = mfc; (*c)[*m - 1].f_data = fc_data; (*c)[*m - 1].tol = tolcopy; return NLOPT_SUCCESS; } static int inequality_ok(nlopt_algorithm algorithm) { /* nonlinear constraints are only supported with some algorithms */ return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_LN_COBYLA || AUGLAG_ALG(algorithm) || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_GN_ORIG_DIRECT || algorithm == NLOPT_GN_ORIG_DIRECT_L || algorithm == NLOPT_GN_AGS); } nlopt_result NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol) { nlopt_result ret; nlopt_unset_errmsg(opt); if (!m) { /* empty constraints are always ok */ if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return NLOPT_SUCCESS; } if (!opt) ret = NLOPT_INVALID_ARGS; else if (!inequality_ok(opt->algorithm)) ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, m, NULL, fc, NULL, fc_data, tol); if (ret < 0 && opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return ret; } nlopt_result NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol) { nlopt_result ret; nlopt_unset_errmsg(opt); if (!opt) ret = NLOPT_INVALID_ARGS; else if (!inequality_ok(opt->algorithm)) ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, 1, fc, NULL, pre, fc_data, &tol); if (ret < 0 && opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return ret; } nlopt_result NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol) { return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data, tol); } nlopt_result NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt) { unsigned i; nlopt_unset_errmsg(opt); if (!opt) return NLOPT_INVALID_ARGS; if (opt->munge_on_destroy) { nlopt_munge munge = opt->munge_on_destroy; for (i = 0; i < opt->p; ++i) munge(opt->h[i].f_data); } for (i = 0; i < opt->p; ++i) free(opt->h[i].tol); free(opt->h); opt->h = NULL; opt->p = opt->p_alloc = 0; return NLOPT_SUCCESS; } static int equality_ok(nlopt_algorithm algorithm) { /* equality constraints (h(x) = 0) only via some algorithms */ return (AUGLAG_ALG(algorithm) || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_LN_COBYLA); } nlopt_result NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol) { nlopt_result ret; nlopt_unset_errmsg(opt); if (!m) { /* empty constraints are always ok */ if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return NLOPT_SUCCESS; } if (!opt) ret = NLOPT_INVALID_ARGS; else if (!equality_ok(opt->algorithm)) ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n) ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, m, NULL, fc, NULL, fc_data, tol); if (ret < 0 && opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return ret; } nlopt_result NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol) { nlopt_result ret; nlopt_unset_errmsg(opt); if (!opt) ret = NLOPT_INVALID_ARGS; else if (!equality_ok(opt->algorithm)) ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n) ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, 1, fc, NULL, pre, fc_data, &tol); if (ret < 0 && opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); return ret; } nlopt_result NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol) { return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol); } /*************************************************************************/ #define SET(param, T, arg) \ nlopt_result NLOPT_STDCALL nlopt_set_##param(nlopt_opt opt, T arg) \ { \ if (opt) { \ nlopt_unset_errmsg(opt); \ opt->arg = arg; \ return NLOPT_SUCCESS; \ } \ return NLOPT_INVALID_ARGS; \ } #define GET(param, T, arg) T NLOPT_STDCALL \ nlopt_get_##param(const nlopt_opt opt) { \ return opt->arg; \ } #define GETSET(param, T, arg) GET(param, T, arg) SET(param, T, arg) GETSET(stopval, double, stopval) GETSET(ftol_rel, double, ftol_rel) GETSET(ftol_abs, double, ftol_abs) GETSET(xtol_rel, double, xtol_rel) nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs) { if (opt) { nlopt_unset_errmsg(opt); memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double)); return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs) { if (opt) { unsigned i; nlopt_unset_errmsg(opt); for (i = 0; i < opt->n; ++i) opt->xtol_abs[i] = xtol_abs; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } nlopt_result NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs) { memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double)); return NLOPT_SUCCESS; } GETSET(maxeval, int, maxeval) GET(numevals, int, numevals) GETSET(maxtime, double, maxtime) /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop) { if (opt) { nlopt_unset_errmsg(opt); opt->force_stop = force_stop; if (opt->force_stop_child) return nlopt_set_force_stop(opt->force_stop_child, force_stop); return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } GET(force_stop, int, force_stop) nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt) { return nlopt_set_force_stop(opt, 1); } /*************************************************************************/ GET(algorithm, nlopt_algorithm, algorithm) GET(dimension, unsigned, n) /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt) { if (opt) { nlopt_unset_errmsg(opt); if (local_opt && local_opt->n != opt->n) return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer"); nlopt_destroy(opt->local_opt); opt->local_opt = nlopt_copy(local_opt); if (local_opt) { if (!opt->local_opt) return NLOPT_OUT_OF_MEMORY; nlopt_set_lower_bounds(opt->local_opt, opt->lb); nlopt_set_upper_bounds(opt->local_opt, opt->ub); nlopt_remove_inequality_constraints(opt->local_opt); nlopt_remove_equality_constraints(opt->local_opt); nlopt_set_min_objective(opt->local_opt, NULL, NULL); nlopt_set_munge(opt->local_opt, NULL, NULL); opt->local_opt->force_stop = 0; } return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; } /*************************************************************************/ GETSET(population, unsigned, stochastic_population) GETSET(vector_storage, unsigned, vector_storage) /*************************************************************************/ nlopt_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx) { unsigned i; if (!opt) return NLOPT_INVALID_ARGS; nlopt_unset_errmsg(opt); if (dx == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); if (!opt->dx && opt->n > 0) { opt->dx = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->dx) return NLOPT_OUT_OF_MEMORY; } for (i = 0; i < opt->n; ++i) opt->dx[i] = dx; return NLOPT_SUCCESS; } nlopt_result NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx) { unsigned i; if (!opt) return NLOPT_INVALID_ARGS; nlopt_unset_errmsg(opt); if (!dx) { free(opt->dx); opt->dx = NULL; return NLOPT_SUCCESS; } for (i = 0; i < opt->n; ++i) if (dx[i] == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) return NLOPT_OUT_OF_MEMORY; memcpy(opt->dx, dx, sizeof(double) * (opt->n)); return NLOPT_SUCCESS; } nlopt_result NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx) { if (!opt) return NLOPT_INVALID_ARGS; nlopt_unset_errmsg(opt); if (!opt->n) return NLOPT_SUCCESS; if (!opt->dx) { nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */ nlopt_result ret = nlopt_set_default_initial_step(o, x); if (ret != NLOPT_SUCCESS) return ret; memcpy(dx, o->dx, sizeof(double) * (opt->n)); free(o->dx); o->dx = NULL; /* don't save, since x-dependent */ } else memcpy(dx, opt->dx, sizeof(double) * (opt->n)); return NLOPT_SUCCESS; } nlopt_result NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x) { const double *lb, *ub; unsigned i; nlopt_unset_errmsg(opt); if (!opt || !x) return NLOPT_INVALID_ARGS; lb = opt->lb; ub = opt->ub; if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) return NLOPT_OUT_OF_MEMORY; /* crude heuristics for initial step size of nonderivative algorithms */ for (i = 0; i < opt->n; ++i) { double step = HUGE_VAL; if (!nlopt_isinf(ub[i]) && !nlopt_isinf(lb[i]) && (ub[i] - lb[i]) * 0.25 < step && ub[i] > lb[i]) step = (ub[i] - lb[i]) * 0.25; if (!nlopt_isinf(ub[i]) && ub[i] - x[i] < step && ub[i] > x[i]) step = (ub[i] - x[i]) * 0.75; if (!nlopt_isinf(lb[i]) && x[i] - lb[i] < step && x[i] > lb[i]) step = (x[i] - lb[i]) * 0.75; if (nlopt_isinf(step)) { if (!nlopt_isinf(ub[i]) && fabs(ub[i] - x[i]) < fabs(step)) step = (ub[i] - x[i]) * 1.1; if (!nlopt_isinf(lb[i]) && fabs(x[i] - lb[i]) < fabs(step)) step = (x[i] - lb[i]) * 1.1; } if (nlopt_isinf(step) || nlopt_istiny(step)) { step = x[i]; } if (nlopt_isinf(step) || step == 0.0) step = 1; opt->dx[i] = step; } return NLOPT_SUCCESS; } /*************************************************************************/ void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt, nlopt_munge munge_on_destroy, nlopt_munge munge_on_copy) { if (opt) { opt->munge_on_destroy = munge_on_destroy; opt->munge_on_copy = munge_on_copy; } } void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt, nlopt_munge2 munge, void *data) { if (opt && munge) { unsigned i; opt->f_data = munge(opt->f_data, data); for (i = 0; i < opt->m; ++i) opt->fc[i].f_data = munge(opt->fc[i].f_data, data); for (i = 0; i < opt->p; ++i) opt->h[i].f_data = munge(opt->h[i].f_data, data); } } /*************************************************************************/ const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...) { va_list ap; va_start(ap, format); opt->errmsg = nlopt_vsprintf(opt->errmsg, format, ap); va_end(ap); return opt->errmsg; } void nlopt_unset_errmsg(nlopt_opt opt) { if (opt) { free(opt->errmsg); opt->errmsg = NULL; } } const char *nlopt_get_errmsg(nlopt_opt opt) { return opt->errmsg; } /*************************************************************************/ nlopt-2.6.1/src/octave/000077500000000000000000000000001345435414600147355ustar00rootroot00000000000000nlopt-2.6.1/src/octave/CMakeLists.txt000066400000000000000000000054451345435414600175050ustar00rootroot00000000000000set (MFILES NLOPT_GN_DIRECT.m NLOPT_GN_DIRECT_L.m NLOPT_GN_DIRECT_L_RAND.m NLOPT_GN_DIRECT_NOSCAL.m NLOPT_GN_DIRECT_L_NOSCAL.m NLOPT_GN_DIRECT_L_RAND_NOSCAL.m NLOPT_GN_ORIG_DIRECT.m NLOPT_GN_ORIG_DIRECT_L.m NLOPT_GD_STOGO.m NLOPT_GD_STOGO_RAND.m NLOPT_LD_LBFGS_NOCEDAL.m NLOPT_LD_LBFGS.m NLOPT_LN_PRAXIS.m NLOPT_LD_VAR1.m NLOPT_LD_VAR2.m NLOPT_LD_TNEWTON.m NLOPT_LD_TNEWTON_RESTART.m NLOPT_LD_TNEWTON_PRECOND.m NLOPT_LD_TNEWTON_PRECOND_RESTART.m NLOPT_GN_CRS2_LM.m NLOPT_GN_MLSL.m NLOPT_GD_MLSL.m NLOPT_GN_MLSL_LDS.m NLOPT_GD_MLSL_LDS.m NLOPT_LD_MMA.m NLOPT_LN_COBYLA.m NLOPT_LN_NEWUOA.m NLOPT_LN_NEWUOA_BOUND.m NLOPT_LN_NELDERMEAD.m NLOPT_LN_SBPLX.m NLOPT_LN_AUGLAG.m NLOPT_LD_AUGLAG.m NLOPT_LN_AUGLAG_EQ.m NLOPT_LD_AUGLAG_EQ.m NLOPT_LN_BOBYQA.m NLOPT_GN_ISRES.m NLOPT_AUGLAG.m NLOPT_AUGLAG_EQ.m NLOPT_G_MLSL.m NLOPT_G_MLSL_LDS.m NLOPT_LD_SLSQP.m NLOPT_LD_CCSAQ.m NLOPT_GN_ESCH.m) set (M_DATA ${MFILES} nlopt_minimize.m nlopt_minimize_constrained.m) if (Matlab_FOUND AND Matlab_MX_LIBRARY) cmake_minimum_required (VERSION 3.3) # for the matlab_add_mex macro matlab_add_mex (NAME nlopt_optimize-mex SRC nlopt_optimize-mex.c OUTPUT_NAME nlopt_optimize LINK_TO ${nlopt_lib}) if (NOT DEFINED INSTALL_MEX_DIR) set (INSTALL_MEX_DIR ${INSTALL_LIB_DIR}/matlab) endif () install (TARGETS nlopt_optimize-mex DESTINATION ${INSTALL_MEX_DIR}) if (NOT DEFINED INSTALL_M_DIR) set (INSTALL_M_DIR ${INSTALL_MEX_DIR}) endif () install (FILES ${M_DATA} DESTINATION ${INSTALL_M_DIR}) endif () if (OCTAVE_FOUND) file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/nlopt_optimize_usage.h "#define NLOPT_OPTIMIZE_USAGE \\\n") file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/nlopt_optimize.m INPUT_LINES) foreach (INPUT_LINE ${INPUT_LINES}) string (REGEX REPLACE "^% " "" INPUT_LINE ${INPUT_LINE}) string (REGEX REPLACE "^%" "" INPUT_LINE ${INPUT_LINE}) foreach (repl_expr "tolerance" "help NLOPT_LN_SBPLX" "population") string (REGEX REPLACE "\"${repl_expr}\"" "${repl_expr}" INPUT_LINE "${INPUT_LINE}") endforeach () file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt_optimize_usage.h "\"${INPUT_LINE}\\n\" \\\n") endforeach () file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt_optimize_usage.h "\n") include_directories (${OCTAVE_INCLUDE_DIRS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) octave_add_oct (nlopt_optimize SOURCES nlopt_optimize-oct.cc ${CMAKE_CURRENT_BINARY_DIR}/nlopt_optimize_usage.h LINK_LIBRARIES ${nlopt_lib}) if (NOT DEFINED INSTALL_OCT_DIR) file (RELATIVE_PATH INSTALL_OCT_DIR ${OCTAVE_ROOT_DIR} ${OCTAVE_OCT_SITE_DIR}) endif () install (TARGETS nlopt_optimize DESTINATION ${INSTALL_OCT_DIR}) if (NOT DEFINED INSTALL_M_DIR) file (RELATIVE_PATH INSTALL_M_DIR ${OCTAVE_ROOT_DIR} ${OCTAVE_M_SITE_DIR}) endif () install (FILES ${M_DATA} DESTINATION ${INSTALL_M_DIR}) endif () nlopt-2.6.1/src/octave/NLOPT_AUGLAG.m000066400000000000000000000002271345435414600170300ustar00rootroot00000000000000% NLOPT_AUGLAG: Augmented Lagrangian method (needs sub-algorithm) % % See nlopt_minimize for more information. function val = NLOPT_AUGLAG val = 36; nlopt-2.6.1/src/octave/NLOPT_AUGLAG_EQ.m000066400000000000000000000002661345435414600174200ustar00rootroot00000000000000% NLOPT_AUGLAG_EQ: Augmented Lagrangian method for equality constraints (needs sub-algorithm) % % See nlopt_minimize for more information. function val = NLOPT_AUGLAG_EQ val = 37; nlopt-2.6.1/src/octave/NLOPT_GD_MLSL.m000066400000000000000000000002461345435414600172120ustar00rootroot00000000000000% NLOPT_GD_MLSL: Multi-level single-linkage (MLSL), random (global, derivative) % % See nlopt_minimize for more information. function val = NLOPT_GD_MLSL val = 21; nlopt-2.6.1/src/octave/NLOPT_GD_MLSL_LDS.m000066400000000000000000000002641345435414600177140ustar00rootroot00000000000000% NLOPT_GD_MLSL_LDS: Multi-level single-linkage (MLSL), quasi-random (global, derivative) % % See nlopt_minimize for more information. function val = NLOPT_GD_MLSL_LDS val = 23; nlopt-2.6.1/src/octave/NLOPT_GD_STOGO.m000066400000000000000000000002111345435414600173260ustar00rootroot00000000000000% NLOPT_GD_STOGO: StoGO (global, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_GD_STOGO val = 8; nlopt-2.6.1/src/octave/NLOPT_GD_STOGO_RAND.m000066400000000000000000000002521345435414600201370ustar00rootroot00000000000000% NLOPT_GD_STOGO_RAND: StoGO with randomized search (global, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_GD_STOGO_RAND val = 9; nlopt-2.6.1/src/octave/NLOPT_GN_CRS2_LM.m000066400000000000000000000002711345435414600175540ustar00rootroot00000000000000% NLOPT_GN_CRS2_LM: Controlled random search (CRS2) with local mutation (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_CRS2_LM val = 19; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT.m000066400000000000000000000002111345435414600174170ustar00rootroot00000000000000% NLOPT_GN_DIRECT: DIRECT (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT val = 0; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT_L.m000066400000000000000000000002171345435414600177000ustar00rootroot00000000000000% NLOPT_GN_DIRECT_L: DIRECT-L (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT_L val = 1; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT_L_NOSCAL.m000066400000000000000000000002461345435414600207410ustar00rootroot00000000000000% NLOPT_GN_DIRECT_L_NOSCAL: Unscaled DIRECT-L (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT_L_NOSCAL val = 4; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT_L_RAND.m000066400000000000000000000002441345435414600205040ustar00rootroot00000000000000% NLOPT_GN_DIRECT_L_RAND: Randomized DIRECT-L (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT_L_RAND val = 2; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT_L_RAND_NOSCAL.m000066400000000000000000000002731345435414600215450ustar00rootroot00000000000000% NLOPT_GN_DIRECT_L_RAND_NOSCAL: Unscaled Randomized DIRECT-L (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT_L_RAND_NOSCAL val = 5; nlopt-2.6.1/src/octave/NLOPT_GN_DIRECT_NOSCAL.m000066400000000000000000000002401345435414600204600ustar00rootroot00000000000000% NLOPT_GN_DIRECT_NOSCAL: Unscaled DIRECT (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_DIRECT_NOSCAL val = 3; nlopt-2.6.1/src/octave/NLOPT_GN_ESCH.m000066400000000000000000000002021345435414600171670ustar00rootroot00000000000000% NLOPT_GN_ESCH: ESCH evolutionary strategy % % See nlopt_minimize for more information. function val = NLOPT_GN_ESCH val = 42; nlopt-2.6.1/src/octave/NLOPT_GN_ISRES.m000066400000000000000000000002551345435414600173420ustar00rootroot00000000000000% NLOPT_GN_ISRES: ISRES evolutionary constrained optimization (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_ISRES val = 35; nlopt-2.6.1/src/octave/NLOPT_GN_MLSL.m000066400000000000000000000002511345435414600172200ustar00rootroot00000000000000% NLOPT_GN_MLSL: Multi-level single-linkage (MLSL), random (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_MLSL val = 20; nlopt-2.6.1/src/octave/NLOPT_GN_MLSL_LDS.m000066400000000000000000000002671345435414600177310ustar00rootroot00000000000000% NLOPT_GN_MLSL_LDS: Multi-level single-linkage (MLSL), quasi-random (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_MLSL_LDS val = 22; nlopt-2.6.1/src/octave/NLOPT_GN_ORIG_DIRECT.m000066400000000000000000000002441345435414600202450ustar00rootroot00000000000000% NLOPT_GN_ORIG_DIRECT: Original DIRECT version (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_ORIG_DIRECT val = 6; nlopt-2.6.1/src/octave/NLOPT_GN_ORIG_DIRECT_L.m000066400000000000000000000002521345435414600205170ustar00rootroot00000000000000% NLOPT_GN_ORIG_DIRECT_L: Original DIRECT-L version (global, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_GN_ORIG_DIRECT_L val = 7; nlopt-2.6.1/src/octave/NLOPT_G_MLSL.m000066400000000000000000000002551345435414600171060ustar00rootroot00000000000000% NLOPT_G_MLSL: Multi-level single-linkage (MLSL), random (global, needs sub-algorithm) % % See nlopt_minimize for more information. function val = NLOPT_G_MLSL val = 38; nlopt-2.6.1/src/octave/NLOPT_G_MLSL_LDS.m000066400000000000000000000002731345435414600176100ustar00rootroot00000000000000% NLOPT_G_MLSL_LDS: Multi-level single-linkage (MLSL), quasi-random (global, needs sub-algorithm) % % See nlopt_minimize for more information. function val = NLOPT_G_MLSL_LDS val = 39; nlopt-2.6.1/src/octave/NLOPT_LD_AUGLAG.m000066400000000000000000000002331345435414600174040ustar00rootroot00000000000000% NLOPT_LD_AUGLAG: Augmented Lagrangian method (local, derivative) % % See nlopt_minimize for more information. function val = NLOPT_LD_AUGLAG val = 31; nlopt-2.6.1/src/octave/NLOPT_LD_AUGLAG_EQ.m000066400000000000000000000002721345435414600177740ustar00rootroot00000000000000% NLOPT_LD_AUGLAG_EQ: Augmented Lagrangian method for equality constraints (local, derivative) % % See nlopt_minimize for more information. function val = NLOPT_LD_AUGLAG_EQ val = 33; nlopt-2.6.1/src/octave/NLOPT_LD_CCSAQ.m000066400000000000000000000003261345435414600173010ustar00rootroot00000000000000% NLOPT_LD_CCSAQ: CCSA (Conservative Convex Separable Approximations) with simple quadratic approximations (local, derivative) % % See nlopt_minimize for more information. function val = NLOPT_LD_CCSAQ val = 41; nlopt-2.6.1/src/octave/NLOPT_LD_LBFGS.m000066400000000000000000000002401345435414600172770ustar00rootroot00000000000000% NLOPT_LD_LBFGS: Limited-memory BFGS (L-BFGS) (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_LBFGS val = 11; nlopt-2.6.1/src/octave/NLOPT_LD_LBFGS_NOCEDAL.m000066400000000000000000000002701345435414600204270ustar00rootroot00000000000000% NLOPT_LD_LBFGS_NOCEDAL: original NON-FREE L-BFGS code by Nocedal et al. (NOT COMPILED) % % See nlopt_minimize for more information. function val = NLOPT_LD_LBFGS_NOCEDAL val = 10; nlopt-2.6.1/src/octave/NLOPT_LD_MMA.m000066400000000000000000000002331345435414600170560ustar00rootroot00000000000000% NLOPT_LD_MMA: Method of Moving Asymptotes (MMA) (local, derivative) % % See nlopt_minimize for more information. function val = NLOPT_LD_MMA val = 24; nlopt-2.6.1/src/octave/NLOPT_LD_SLSQP.m000066400000000000000000000002441345435414600173500ustar00rootroot00000000000000% NLOPT_LD_SLSQP: Sequential Quadratic Programming (SQP) (local, derivative) % % See nlopt_minimize for more information. function val = NLOPT_LD_SLSQP val = 40; nlopt-2.6.1/src/octave/NLOPT_LD_TNEWTON.m000066400000000000000000000002301345435414600175770ustar00rootroot00000000000000% NLOPT_LD_TNEWTON: Truncated Newton (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_TNEWTON val = 15; nlopt-2.6.1/src/octave/NLOPT_LD_TNEWTON_PRECOND.m000066400000000000000000000002671345435414600207630ustar00rootroot00000000000000% NLOPT_LD_TNEWTON_PRECOND: Preconditioned truncated Newton (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_TNEWTON_PRECOND val = 17; nlopt-2.6.1/src/octave/NLOPT_LD_TNEWTON_PRECOND_RESTART.m000066400000000000000000000003271345435414600221640ustar00rootroot00000000000000% NLOPT_LD_TNEWTON_PRECOND_RESTART: Preconditioned truncated Newton with restarting (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_TNEWTON_PRECOND_RESTART val = 18; nlopt-2.6.1/src/octave/NLOPT_LD_TNEWTON_RESTART.m000066400000000000000000000002701345435414600210070ustar00rootroot00000000000000% NLOPT_LD_TNEWTON_RESTART: Truncated Newton with restarting (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_TNEWTON_RESTART val = 16; nlopt-2.6.1/src/octave/NLOPT_LD_VAR1.m000066400000000000000000000002501345435414600171540ustar00rootroot00000000000000% NLOPT_LD_VAR1: Limited-memory variable-metric, rank 1 (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_VAR1 val = 13; nlopt-2.6.1/src/octave/NLOPT_LD_VAR2.m000066400000000000000000000002501345435414600171550ustar00rootroot00000000000000% NLOPT_LD_VAR2: Limited-memory variable-metric, rank 2 (local, derivative-based) % % See nlopt_minimize for more information. function val = NLOPT_LD_VAR2 val = 14; nlopt-2.6.1/src/octave/NLOPT_LN_AUGLAG.m000066400000000000000000000002361345435414600174210ustar00rootroot00000000000000% NLOPT_LN_AUGLAG: Augmented Lagrangian method (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_AUGLAG val = 30; nlopt-2.6.1/src/octave/NLOPT_LN_AUGLAG_EQ.m000066400000000000000000000002751345435414600200110ustar00rootroot00000000000000% NLOPT_LN_AUGLAG_EQ: Augmented Lagrangian method for equality constraints (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_AUGLAG_EQ val = 32; nlopt-2.6.1/src/octave/NLOPT_LN_BOBYQA.m000066400000000000000000000002751345435414600174410ustar00rootroot00000000000000% NLOPT_LN_BOBYQA: BOBYQA bound-constrained optimization via quadratic models (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_BOBYQA val = 34; nlopt-2.6.1/src/octave/NLOPT_LN_COBYLA.m000066400000000000000000000002751345435414600174350ustar00rootroot00000000000000% NLOPT_LN_COBYLA: COBYLA (Constrained Optimization BY Linear Approximations) (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_COBYLA val = 25; nlopt-2.6.1/src/octave/NLOPT_LN_NELDERMEAD.m000066400000000000000000000002501345435414600200550ustar00rootroot00000000000000% NLOPT_LN_NELDERMEAD: Nelder-Mead simplex algorithm (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_NELDERMEAD val = 28; nlopt-2.6.1/src/octave/NLOPT_LN_NEWUOA.m000066400000000000000000000002711345435414600174560ustar00rootroot00000000000000% NLOPT_LN_NEWUOA: NEWUOA unconstrained optimization via quadratic models (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_NEWUOA val = 26; nlopt-2.6.1/src/octave/NLOPT_LN_NEWUOA_BOUND.m000066400000000000000000000003171345435414600204060ustar00rootroot00000000000000% NLOPT_LN_NEWUOA_BOUND: Bound-constrained optimization via NEWUOA-based quadratic models (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_NEWUOA_BOUND val = 27; nlopt-2.6.1/src/octave/NLOPT_LN_PRAXIS.m000066400000000000000000000002311345435414600174620ustar00rootroot00000000000000% NLOPT_LN_PRAXIS: Principal-axis, praxis (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_PRAXIS val = 12; nlopt-2.6.1/src/octave/NLOPT_LN_SBPLX.m000066400000000000000000000003041345435414600173450ustar00rootroot00000000000000% NLOPT_LN_SBPLX: Sbplx variant of Nelder-Mead (re-implementation of Rowan's Subplex) (local, no-derivative) % % See nlopt_minimize for more information. function val = NLOPT_LN_SBPLX val = 29; nlopt-2.6.1/src/octave/dummy.c000066400000000000000000000001121345435414600162260ustar00rootroot00000000000000#include int main(void) { printf("Hello world.\n"); return 0; } nlopt-2.6.1/src/octave/mkconstants.sh000077500000000000000000000013311345435414600176360ustar00rootroot00000000000000#!/bin/sh names=`egrep 'NLOPT_[LG][ND]|NLOPT_AUGLAG|NLOPT_G_MLSL' ../api/nlopt.h |sed 's/ //g' |tr = , |cut -d, -f1` i=0 gcc -I../util -I.. -E ../api/general.c | perl -pe 's/^ *\n//' > foo.c desc_start=`grep -n nlopt_algorithm_names foo.c |cut -d: -f1 |head -1` for n in $names; do if test -r $n.m; then perl -pi -e "s/val = [0-9]+;/val = $i;/" $n.m else descline=`expr $i + $desc_start + 1` desc=`tail -n +$descline foo.c |head -1 |cut -d\" -f2` cat > $n.m < 0 indicates verbose output % Minimization stops when any one of these conditions is met; any % condition that is omitted from stop will be ignored. WARNING: % not all algorithms interpret the stopping criteria in exactly the % same way, and in any case ftol/xtol specify only a crude estimate % for the accuracy of the minimum function value/x. % % The algorithm should be one of the following constants (name and % interpretation are the same as for the C function). Names with % _G*_ are global optimization, and names with _L*_ are local % optimization. Names with _*N_ are derivative-free, while names % with _*D_ are gradient-based algorithms. Algorithms: % % NLOPT_GD_MLSL_LDS, NLOPT_GD_MLSL, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, % NLOPT_GN_CRS2_LM, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_NOSCAL, % NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_DIRECT, % NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_ISRES, NLOPT_GN_MLSL_LDS, NLOPT_GN_MLSL, % NLOPT_GN_ORIG_DIRECT_L, NLOPT_GN_ORIG_DIRECT, NLOPT_LD_AUGLAG_EQ, % NLOPT_LD_AUGLAG, NLOPT_LD_LBFGS, NLOPT_LD_LBFGS_NOCEDAL, NLOPT_LD_MMA, % NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_PRECOND, % NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_LD_TNEWTON_RESTART, % NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LN_AUGLAG_EQ, NLOPT_LN_AUGLAG, % NLOPT_LN_BOBYQA, NLOPT_LN_COBYLA, NLOPT_LN_NELDERMEAD, % NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NEWUOA, NLOPT_LN_PRAXIS, NLOPT_LN_SBPLX % % For more information on individual algorithms, see their individual % help pages (e.g. "help NLOPT_LN_SBPLX"). function [xopt, fmin, retcode] = nlopt_minimize(algorithm, f, f_data, lb, ub, xinit, stop) [xopt, fmin, retcode] = nlopt_minimize_constrained(algorithm, f, f_data, {}, {}, lb, ub, xinit, stop); nlopt-2.6.1/src/octave/nlopt_minimize_constrained.m000066400000000000000000000120661345435414600225460ustar00rootroot00000000000000% Usage: [xopt, fmin, retcode] = nlopt_minimize_constrained % (algorithm, f, f_data, % fc, fc_data, lb, ub, % xinit, stop) % % Minimizes a nonlinear multivariable function f(x, f_data{:}), subject % to nonlinear constraints described by fc and fc_data (see below), where % x is a row vector, returning the optimal x found (xopt) along with % the minimum function value (fmin = f(xopt)) and a return code (retcode). % A variety of local and global optimization algorithms can be used, % as specified by the algorithm parameter described below. lb and ub % are row vectors giving the upper and lower bounds on x, xinit is % a row vector giving the initial guess for x, and stop is a struct % containing termination conditions (see below). % % This function is a front-end for the external routine % nlopt_minimize_constrained in the free NLopt nonlinear-optimization % library, which is a wrapper around a number of free/open-source % optimization subroutines. More details can be found on the NLopt % web page (ab-initio.mit.edu/nlopt) and also under % 'man nlopt_minimize_constrained' on Unix. % % f should be a handle (@) to a function of the form: % % [val, gradient] = f(x, ...) % % where x is a row vector, val is the function value f(x), and gradient % is a row vector giving the gradient of the function with respect to x. % The gradient is only used for gradient-based optimization algorithms; % some of the algorithms (below) are derivative-free and only require % f to return val (its value). f can take additional arguments (...) % which are passed via the argument f_data: f_data is a cell array % of the additional arguments to pass to f. (Recall that cell arrays % are specified by curly brackets { ... }. For example, pass f_data={} % for functions that require no additional arguments.) % % A few of the algorithms (below) support nonlinear constraints, % in particular NLOPT_LD_MMA and NLOPT_LN_COBYLA. These (if any) % are specified by fc and fc_data. fc is a cell array of % function handles, and fc_data is a cell array of cell arrays of the % corresponding arguments. Both must have the same length m, the % number of nonlinear constraints. That is, fc{i} is a handle % to a function of the form: % % [val, gradient] = fc(x, ...) % % (where the gradient is only used for gradient-based algorithms), % and the ... arguments are given by fc_data{i}{:}. % % If you have no nonlinear constraints, i.e. fc = fc_data = {}, then % it is equivalent to calling the the nlopt_minimize() function, % which omits the fc and fc_data arguments. % % stop describes the termination criteria, and is a struct with a % number of optional fields: % stop.ftol_rel = fractional tolerance on function value % stop.ftol_abs = absolute tolerance on function value % stop.xtol_rel = fractional tolerance on x % stop.xtol_abs = row vector of absolute tolerances on x components % stop.fmin_max = stop when f < fmin_max is found % stop.maxeval = maximum number of function evaluations % stop.maxtime = maximum run time in seconds % stop.verbose = > 0 indicates verbose output % Minimization stops when any one of these conditions is met; any % condition that is omitted from stop will be ignored. WARNING: % not all algorithms interpret the stopping criteria in exactly the % same way, and in any case ftol/xtol specify only a crude estimate % for the accuracy of the minimum function value/x. % % The algorithm should be one of the following constants (name and % interpretation are the same as for the C function). Names with % _G*_ are global optimization, and names with _L*_ are local % optimization. Names with _*N_ are derivative-free, while names % with _*D_ are gradient-based algorithms. Algorithms: % % NLOPT_GD_MLSL_LDS, NLOPT_GD_MLSL, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, % NLOPT_GN_CRS2_LM, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_NOSCAL, % NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_DIRECT, % NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_ISRES, NLOPT_GN_MLSL_LDS, NLOPT_GN_MLSL, % NLOPT_GN_ORIG_DIRECT_L, NLOPT_GN_ORIG_DIRECT, NLOPT_LD_AUGLAG_EQ, % NLOPT_LD_AUGLAG, NLOPT_LD_LBFGS, NLOPT_LD_LBFGS_NOCEDAL, NLOPT_LD_MMA, % NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_PRECOND, % NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_LD_TNEWTON_RESTART, % NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LN_AUGLAG_EQ, NLOPT_LN_AUGLAG, % NLOPT_LN_BOBYQA, NLOPT_LN_COBYLA, NLOPT_LN_NELDERMEAD, % NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NEWUOA, NLOPT_LN_PRAXIS, NLOPT_LN_SBPLX % % For more information on individual algorithms, see their individual % help pages (e.g. "help NLOPT_LN_SBPLX"). function [xopt, fmin, retcode] = nlopt_minimize_constrained(algorithm, f, f_data, fc, fc_data, lb, ub, xinit, stop) opt = stop; if (isfield(stop, 'minf_max')) opt.stopval = stop.minf_max; end opt.algorithm = algorithm; opt.min_objective = @(x) f(x, f_data{:}); opt.lower_bounds = lb; opt.upper_bounds = ub; for i = 1:length(fc) opt.fc{i} = @(x) fc{i}(x, fc_data{i}{:}); end [xopt, fmin, retcode] = nlopt_optimize(opt, xinit); nlopt-2.6.1/src/octave/nlopt_optimize-mex.c000066400000000000000000000302151345435414600207450ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* Matlab MEX interface to NLopt, and in particular to nlopt_optimize */ #include #include #include #include #include #include "nlopt.h" #define CHECK0(cond, msg) if (!(cond)) mexErrMsgTxt(msg); static double struct_val_default(const mxArray *s, const char *name, double dflt) { mxArray *val = mxGetField(s, 0, name); if (val) { CHECK0(mxIsNumeric(val) && !mxIsComplex(val) && mxGetM(val) * mxGetN(val) == 1, "opt fields, other than xtol_abs, must be real scalars"); return mxGetScalar(val); } return dflt; } static double *struct_arrval(const mxArray *s, const char *name, unsigned n, double *dflt) { mxArray *val = mxGetField(s, 0, name); if (val) { CHECK0(mxIsNumeric(val) && !mxIsComplex(val) && mxGetM(val) * mxGetN(val) == n, "opt vector field is not of length n"); return mxGetPr(val); } return dflt; } static mxArray *struct_funcval(const mxArray *s, const char *name) { mxArray *val = mxGetField(s, 0, name); if (val) { CHECK0(mxIsChar(val) || mxIsFunctionHandle(val), "opt function field is not a function handle/name"); return val; } return NULL; } static double *fill(double *arr, unsigned n, double val) { unsigned i; for (i = 0; i < n; ++i) arr[i] = val; return arr; } #define FLEN 128 /* max length of user function name */ #define MAXRHS 3 /* max nrhs for user function */ typedef struct user_function_data_s { char f[FLEN]; mxArray *plhs[2]; mxArray *prhs[MAXRHS]; int xrhs, nrhs; int verbose, neval; struct user_function_data_s *dpre; nlopt_opt opt; } user_function_data; static double user_function(unsigned n, const double *x, double *gradient, /* NULL if not needed */ void *d_) { user_function_data *d = (user_function_data *) d_; double f; d->plhs[0] = d->plhs[1] = NULL; memcpy(mxGetPr(d->prhs[d->xrhs]), x, n * sizeof(double)); CHECK0(0 == mexCallMATLAB(gradient ? 2 : 1, d->plhs, d->nrhs, d->prhs, d->f), "error calling user function"); CHECK0(mxIsNumeric(d->plhs[0]) && !mxIsComplex(d->plhs[0]) && mxGetM(d->plhs[0]) * mxGetN(d->plhs[0]) == 1, "user function must return real scalar"); f = mxGetScalar(d->plhs[0]); mxDestroyArray(d->plhs[0]); if (gradient) { CHECK0(mxIsDouble(d->plhs[1]) && !mxIsComplex(d->plhs[1]) && (mxGetM(d->plhs[1]) == 1 || mxGetN(d->plhs[1]) == 1) && mxGetM(d->plhs[1]) * mxGetN(d->plhs[1]) == n, "gradient vector from user function is the wrong size"); memcpy(gradient, mxGetPr(d->plhs[1]), n * sizeof(double)); mxDestroyArray(d->plhs[1]); } d->neval++; if (d->verbose) mexPrintf("nlopt_optimize eval #%d: %g\n", d->neval, f); if (mxIsNaN(f)) nlopt_force_stop(d->opt); return f; } static void user_pre(unsigned n, const double *x, const double *v, double *vpre, void *d_) { user_function_data *d = ((user_function_data *) d_)->dpre; d->plhs[0] = d->plhs[1] = NULL; memcpy(mxGetPr(d->prhs[d->xrhs]), x, n * sizeof(double)); memcpy(mxGetPr(d->prhs[d->xrhs + 1]), v, n * sizeof(double)); CHECK0(0 == mexCallMATLAB(1, d->plhs, d->nrhs, d->prhs, d->f), "error calling user function"); CHECK0(mxIsDouble(d->plhs[0]) && !mxIsComplex(d->plhs[0]) && (mxGetM(d->plhs[0]) == 1 || mxGetN(d->plhs[0]) == 1) && mxGetM(d->plhs[0]) * mxGetN(d->plhs[0]) == n, "vpre vector from user function is the wrong size"); memcpy(vpre, mxGetPr(d->plhs[0]), n * sizeof(double)); mxDestroyArray(d->plhs[0]); d->neval++; if (d->verbose) mexPrintf("nlopt_optimize precond eval #%d\n", d->neval); } #define CHECK1(cond, msg) if (!(cond)) { mxFree(tmp); nlopt_destroy(opt); nlopt_destroy(local_opt); mexWarnMsgTxt(msg); return NULL; }; nlopt_opt make_opt(const mxArray *opts, unsigned n) { nlopt_opt opt = NULL, local_opt = NULL; nlopt_algorithm algorithm; double *tmp = NULL; unsigned i; algorithm = (nlopt_algorithm) struct_val_default(opts, "algorithm", NLOPT_NUM_ALGORITHMS); CHECK1(((int)algorithm) >= 0 && algorithm < NLOPT_NUM_ALGORITHMS, "invalid opt.algorithm"); tmp = (double *) mxCalloc(n, sizeof(double)); opt = nlopt_create(algorithm, n); CHECK1(opt, "nlopt: out of memory"); nlopt_set_lower_bounds(opt, struct_arrval(opts, "lower_bounds", n, fill(tmp, n, -HUGE_VAL))); nlopt_set_upper_bounds(opt, struct_arrval(opts, "upper_bounds", n, fill(tmp, n, +HUGE_VAL))); nlopt_set_stopval(opt, struct_val_default(opts, "stopval", -HUGE_VAL)); nlopt_set_ftol_rel(opt, struct_val_default(opts, "ftol_rel", 0.0)); nlopt_set_ftol_abs(opt, struct_val_default(opts, "ftol_abs", 0.0)); nlopt_set_xtol_rel(opt, struct_val_default(opts, "xtol_rel", 0.0)); nlopt_set_xtol_abs(opt, struct_arrval(opts, "xtol_abs", n, fill(tmp, n, 0.0))); nlopt_set_maxeval(opt, struct_val_default(opts, "maxeval", 0.0) < 0 ? 0 : struct_val_default(opts, "maxeval", 0.0)); nlopt_set_maxtime(opt, struct_val_default(opts, "maxtime", 0.0)); nlopt_set_population(opt, struct_val_default(opts, "population", 0)); nlopt_set_vector_storage(opt, struct_val_default(opts, "vector_storage", 0)); if (struct_arrval(opts, "initial_step", n, NULL)) nlopt_set_initial_step(opt, struct_arrval(opts, "initial_step", n, NULL)); if (mxGetField(opts, 0, "local_optimizer")) { const mxArray *local_opts = mxGetField(opts, 0, "local_optimizer"); CHECK1(mxIsStruct(local_opts), "opt.local_optimizer must be a structure"); CHECK1(local_opt = make_opt(local_opts, n), "error initializing local optimizer"); nlopt_set_local_optimizer(opt, local_opt); nlopt_destroy(local_opt); local_opt = NULL; } mxFree(tmp); return opt; } #define CHECK(cond, msg) if (!(cond)) { mxFree(dh); mxFree(dfc); nlopt_destroy(opt); mexErrMsgTxt(msg); } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { unsigned n; double *x, *x0, opt_f; nlopt_result ret; mxArray *x_mx, *mx; user_function_data d, dpre, *dfc = NULL, *dh = NULL; nlopt_opt opt = NULL; CHECK(nrhs == 2 && nlhs <= 3, "wrong number of arguments"); /* options = prhs[0] */ CHECK(mxIsStruct(prhs[0]), "opt must be a struct"); /* x0 = prhs[1] */ CHECK(mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1]) && (mxGetM(prhs[1]) == 1 || mxGetN(prhs[1]) == 1), "x must be real row or column vector"); n = mxGetM(prhs[1]) * mxGetN(prhs[1]), x0 = mxGetPr(prhs[1]); CHECK(opt = make_opt(prhs[0], n), "error initializing nlopt options"); d.neval = 0; d.verbose = (int) struct_val_default(prhs[0], "verbose", 0); d.opt = opt; /* function f = prhs[1] */ mx = struct_funcval(prhs[0], "min_objective"); if (!mx) mx = struct_funcval(prhs[0], "max_objective"); CHECK(mx, "either opt.min_objective or opt.max_objective must exist"); if (mxIsChar(mx)) { CHECK(mxGetString(mx, d.f, FLEN) == 0, "error reading function name string (too long?)"); d.nrhs = 1; d.xrhs = 0; } else { d.prhs[0] = mx; strcpy(d.f, "feval"); d.nrhs = 2; d.xrhs = 1; } d.prhs[d.xrhs] = mxCreateDoubleMatrix(1, n, mxREAL); if ((mx = struct_funcval(prhs[0], "pre"))) { CHECK(mxIsChar(mx) || mxIsFunctionHandle(mx), "pre must contain function handles or function names"); if (mxIsChar(mx)) { CHECK(mxGetString(mx, dpre.f, FLEN) == 0, "error reading function name string (too long?)"); dpre.nrhs = 2; dpre.xrhs = 0; } else { dpre.prhs[0] = mx; strcpy(dpre.f, "feval"); dpre.nrhs = 3; dpre.xrhs = 1; } dpre.verbose = d.verbose > 2; dpre.opt = opt; dpre.neval = 0; dpre.prhs[dpre.xrhs] = d.prhs[d.xrhs]; dpre.prhs[d.xrhs+1] = mxCreateDoubleMatrix(1, n, mxREAL); d.dpre = &dpre; if (struct_funcval(prhs[0], "min_objective")) nlopt_set_precond_min_objective(opt, user_function,user_pre,&d); else nlopt_set_precond_max_objective(opt, user_function,user_pre,&d); } else { dpre.nrhs = 0; if (struct_funcval(prhs[0], "min_objective")) nlopt_set_min_objective(opt, user_function, &d); else nlopt_set_max_objective(opt, user_function, &d); } if ((mx = mxGetField(prhs[0], 0, "fc"))) { int j, m; double *fc_tol; CHECK(mxIsCell(mx), "fc must be a Cell array"); m = mxGetM(mx) * mxGetN(mx);; dfc = (user_function_data *) mxCalloc(m, sizeof(user_function_data)); fc_tol = struct_arrval(prhs[0], "fc_tol", m, NULL); for (j = 0; j < m; ++j) { mxArray *fc = mxGetCell(mx, j); CHECK(mxIsChar(fc) || mxIsFunctionHandle(fc), "fc must contain function handles or function names"); if (mxIsChar(fc)) { CHECK(mxGetString(fc, dfc[j].f, FLEN) == 0, "error reading function name string (too long?)"); dfc[j].nrhs = 1; dfc[j].xrhs = 0; } else { dfc[j].prhs[0] = fc; strcpy(dfc[j].f, "feval"); dfc[j].nrhs = 2; dfc[j].xrhs = 1; } dfc[j].verbose = d.verbose > 1; dfc[j].opt = opt; dfc[j].neval = 0; dfc[j].prhs[dfc[j].xrhs] = d.prhs[d.xrhs]; CHECK(nlopt_add_inequality_constraint(opt, user_function, dfc + j, fc_tol ? fc_tol[j] : 0) > 0, "nlopt error adding inequality constraint"); } } if ((mx = mxGetField(prhs[0], 0, "h"))) { int j, m; double *h_tol; CHECK(mxIsCell(mx), "h must be a Cell array"); m = mxGetM(mx) * mxGetN(mx);; dh = (user_function_data *) mxCalloc(m, sizeof(user_function_data)); h_tol = struct_arrval(prhs[0], "h_tol", m, NULL); for (j = 0; j < m; ++j) { mxArray *h = mxGetCell(mx, j); CHECK(mxIsChar(h) || mxIsFunctionHandle(h), "h must contain function handles or function names"); if (mxIsChar(h)) { CHECK(mxGetString(h, dh[j].f, FLEN) == 0, "error reading function name string (too long?)"); dh[j].nrhs = 1; dh[j].xrhs = 0; } else { dh[j].prhs[0] = h; strcpy(dh[j].f, "feval"); dh[j].nrhs = 2; dh[j].xrhs = 1; } dh[j].verbose = d.verbose > 1; dh[j].opt = opt; dh[j].neval = 0; dh[j].prhs[dh[j].xrhs] = d.prhs[d.xrhs]; CHECK(nlopt_add_equality_constraint(opt, user_function, dh + j, h_tol ? h_tol[j] : 0) > 0, "nlopt error adding equality constraint"); } } x_mx = mxCreateDoubleMatrix(mxGetM(prhs[1]), mxGetN(prhs[1]), mxREAL); x = mxGetPr(x_mx); memcpy(x, x0, sizeof(double) * n); ret = nlopt_optimize(opt, x, &opt_f); mxFree(dh); mxFree(dfc); mxDestroyArray(d.prhs[d.xrhs]); if (dpre.nrhs > 0) mxDestroyArray(dpre.prhs[d.xrhs+1]); nlopt_destroy(opt); plhs[0] = x_mx; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[1])) = opt_f; } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[2])) = (int) ret; } } nlopt-2.6.1/src/octave/nlopt_optimize-oct.cc000066400000000000000000000256571345435414600211220ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include #include #include "nlopt.h" #include "nlopt_optimize_usage.h" #include #if OCTAVE_MAJOR_VERSION < 3 || (OCTAVE_MAJOR_VERSION == 3 && OCTAVE_MINOR_VERSION < 8) # define octave_map Octave_map #endif #if OCTAVE_MAJOR_VERSION < 4 || (OCTAVE_MAJOR_VERSION == 4 && OCTAVE_MINOR_VERSION < 2) # define err_user_supplied_eval gripe_user_supplied_eval # define err_user_returned_invalid gripe_user_returned_invalid # define numel length #endif #if OCTAVE_MAJOR_VERSION < 4 || (OCTAVE_MAJOR_VERSION == 4 && OCTAVE_MINOR_VERSION < 4) # define iscell is_cell # define isstruct is_map #endif static int struct_val_default(octave_map &m, const std::string& k, int dflt) { if (m.contains(k)) { if (m.contents(k).numel() == 1 && (m.contents(k))(0).is_real_scalar()) return (m.contents(k))(0).int_value(); } return dflt; } static double struct_val_default(octave_map &m, const std::string& k, double dflt) { if (m.contains(k)) { if (m.contents(k).numel() == 1 && (m.contents(k))(0).is_real_scalar()) return (m.contents(k))(0).double_value(); } return dflt; } static Matrix struct_val_default(octave_map &m, const std::string& k, Matrix &dflt) { if (m.contains(k)) { if ((m.contents(k)).numel() == 1) { if ((m.contents(k))(0).is_real_scalar()) return Matrix(1, dflt.numel(), (m.contents(k))(0).double_value()); else if ((m.contents(k))(0).is_real_matrix()) return (m.contents(k))(0).matrix_value(); } } return dflt; } typedef struct { octave_function *f; int neval, verbose; nlopt_opt opt; } user_function_data; static double user_function(unsigned n, const double *x, double *gradient, /* NULL if not needed */ void *data_) { user_function_data *data = (user_function_data *) data_; octave_value_list args(1, 0); Matrix xm(1,n); for (unsigned i = 0; i < n; ++i) xm(i) = x[i]; args(0) = xm; octave_value_list res #if OCTAVE_MAJOR_VERSION > 4 || (OCTAVE_MAJOR_VERSION == 4 && OCTAVE_MINOR_VERSION > 2) = octave::feval(data->f, args, gradient ? 2 : 1); #else = data->f->do_multi_index_op(gradient ? 2 : 1, args); #endif if (res.length() < (gradient ? 2 : 1)) err_user_supplied_eval("nlopt_optimize"); else if (!res(0).is_real_scalar() || (gradient && !res(1).is_real_matrix() && !(n == 1 && res(1).is_real_scalar()))) err_user_returned_invalid("nlopt_optimize"); else { if (gradient) { if (n == 1 && res(1).is_real_scalar()) gradient[0] = res(1).double_value(); else { Matrix grad = res(1).matrix_value(); for (unsigned i = 0; i < n; ++i) gradient[i] = grad(i); } } data->neval++; if (data->verbose) printf("nlopt_optimize eval #%d: %g\n", data->neval, res(0).double_value()); double f = res(0).double_value(); if (f != f /* isnan(f) */) nlopt_force_stop(data->opt); return f; } return 0; } static double user_function1(unsigned n, const double *x, double *gradient, /* NULL if not needed */ void *data_) { octave_function *f = (octave_function *) data_; octave_value_list args(1, 0); Matrix xm(1,n); for (unsigned i = 0; i < n; ++i) xm(i) = x[i]; args(0) = xm; octave_value_list res #if OCTAVE_MAJOR_VERSION > 4 || (OCTAVE_MAJOR_VERSION == 4 && OCTAVE_MINOR_VERSION > 2) = octave::feval(f, args, gradient ? 2 : 1); #else = f->do_multi_index_op(gradient ? 2 : 1, args); #endif if (res.length() < (gradient ? 2 : 1)) err_user_supplied_eval("nlopt_optimize"); else if (!res(0).is_real_scalar() || (gradient && !res(1).is_real_matrix() && !(n == 1 && res(1).is_real_scalar()))) err_user_returned_invalid("nlopt_optimize"); else { if (gradient) { if (n == 1 && res(1).is_real_scalar()) gradient[0] = res(1).double_value(); else { Matrix grad = res(1).matrix_value(); for (unsigned i = 0; i < n; ++i) gradient[i] = grad(i); } } return res(0).double_value(); } return 0; } #define CHECK1(cond, msg) if (!(cond)) { fprintf(stderr, msg "\n\n"); nlopt_destroy(opt); nlopt_destroy(local_opt); return NULL; } nlopt_opt make_opt(octave_map &opts, int n) { nlopt_opt opt = NULL, local_opt = NULL; nlopt_algorithm algorithm = nlopt_algorithm(struct_val_default(opts, "algorithm", NLOPT_NUM_ALGORITHMS)); CHECK1(((int)algorithm) >= 0 && algorithm < NLOPT_NUM_ALGORITHMS, "invalid opt.algorithm"); opt = nlopt_create(algorithm, n); CHECK1(opt, "nlopt: out of memory"); Matrix m_inf(1, n, -HUGE_VAL); Matrix lb = struct_val_default(opts, "lower_bounds", m_inf); CHECK1(n == lb.numel(), "wrong length of opt.lower_bounds"); CHECK1(nlopt_set_lower_bounds(opt, lb.data()) > 0, "nlopt: out of memory"); Matrix p_inf(1, n, +HUGE_VAL); Matrix ub = struct_val_default(opts, "upper_bounds", p_inf); CHECK1(n == ub.numel(), "wrong length of opt.upper_bounds"); CHECK1(nlopt_set_upper_bounds(opt, ub.data()) > 0, "nlopt: out of memory"); nlopt_set_stopval(opt, struct_val_default(opts, "stopval", -HUGE_VAL)); nlopt_set_ftol_rel(opt, struct_val_default(opts, "ftol_rel", 0.0)); nlopt_set_ftol_abs(opt, struct_val_default(opts, "ftol_abs", 0.0)); nlopt_set_xtol_rel(opt, struct_val_default(opts, "xtol_rel", 0.0)); { Matrix zeros(1, n, 0.0); Matrix xtol_abs = struct_val_default(opts, "xtol_abs", zeros); CHECK1(n == xtol_abs.numel(), "stop.xtol_abs must have same length as x"); CHECK1(nlopt_set_xtol_abs(opt, xtol_abs.data())>0, "nlopt: out of memory"); } nlopt_set_maxeval(opt, struct_val_default(opts, "maxeval", 0) < 0 ? 0 : struct_val_default(opts, "maxeval", 0)); nlopt_set_maxtime(opt, struct_val_default(opts, "maxtime", 0.0)); nlopt_set_population(opt, struct_val_default(opts, "population", 0)); nlopt_set_vector_storage(opt, struct_val_default(opts, "vector_storage", 0)); if (opts.contains("initial_step")) { Matrix zeros(1, n, 0.0); Matrix initial_step = struct_val_default(opts, "initial_step", zeros); CHECK1(n == initial_step.numel(), "stop.initial_step must have same length as x"); CHECK1(nlopt_set_initial_step(opt, initial_step.data()) > 0, "nlopt: out of memory"); } if (opts.contains("local_optimizer")) { CHECK1(opts.contents("local_optimizer").numel() == 1 && (opts.contents("local_optimizer"))(0).isstruct(), "opt.local_optimizer must be a structure"); octave_map local_opts = (opts.contents("local_optimizer"))(0).map_value(); CHECK1((local_opt = make_opt(local_opts, n)), "error initializing local optimizer"); nlopt_set_local_optimizer(opt, local_opt); nlopt_destroy(local_opt); local_opt = NULL; } return opt; } #define CHECK(cond, msg) if (!(cond)) { fprintf(stderr, msg "\n\n"); nlopt_destroy(opt); return retval; } DEFUN_DLD(nlopt_optimize, args, nargout, NLOPT_OPTIMIZE_USAGE) { octave_value_list retval; nlopt_opt opt = NULL; CHECK(args.length() == 2 && nargout <= 3, "wrong number of args"); CHECK(args(0).isstruct(), "opt must be structure") octave_map opts = args(0).map_value(); CHECK(args(1).is_real_matrix() || args(1).is_real_scalar(), "x must be real vector"); Matrix x = args(1).is_real_scalar() ? Matrix(1, 1, args(1).double_value()) : args(1).matrix_value(); int n = x.numel(); CHECK((opt = make_opt(opts, n)), "error initializing nlopt options"); user_function_data d; d.neval = 0; d.verbose = struct_val_default(opts, "verbose", 0); d.opt = opt; if (opts.contains("min_objective")) { CHECK(opts.contents("min_objective").numel() == 1 && (opts.contents("min_objective"))(0).is_function_handle(), "opt.min_objective must be a function"); d.f = (opts.contents("min_objective"))(0).function_value(); nlopt_set_min_objective(opt, user_function, &d); } else if (opts.contains("max_objective")) { CHECK(opts.contents("max_objective").numel() == 1 && (opts.contents("max_objective"))(0).is_function_handle(), "opt.max_objective must be a function"); d.f = (opts.contents("max_objective"))(0).function_value(); nlopt_set_max_objective(opt, user_function, &d); } else { CHECK(0,"either opt.min_objective or opt.max_objective must exist"); } if (opts.contains("fc") && opts.contents("fc").numel() == 1) { CHECK((opts.contents("fc"))(0).iscell(), "opt.fc must be cell array"); Cell fc = (opts.contents("fc"))(0).cell_value(); Matrix zeros(1, fc.numel(), 0.0); Matrix fc_tol = struct_val_default(opts, "fc_tol", zeros); CHECK(fc_tol.numel() == fc.numel(), "opt.fc must have same length as opt.fc_tol"); for (int i = 0; i < fc.numel(); ++i) { CHECK(fc(i).is_function() || fc(i).is_function_handle(), "opt.fc must be a cell array of function handles"); CHECK(nlopt_add_inequality_constraint(opt, user_function1, fc(i).function_value(), fc_tol(i)) > 0, "nlopt error adding inequality constraint"); } } if (opts.contains("h") && opts.contents("h").numel() == 1) { CHECK((opts.contents("h"))(0).iscell(), "opt.h must be cell array"); Cell h = (opts.contents("h"))(0).cell_value(); Matrix zeros(1, h.numel(), 0.0); Matrix h_tol = struct_val_default(opts, "h_tol", zeros); CHECK(h_tol.numel() == h.numel(), "opt.h must have same length as opt.h_tol"); for (int i = 0; i < h.numel(); ++i) { CHECK(h(i).is_function() || h(i).is_function_handle(), "opt.h must be a cell array of function handles"); CHECK(nlopt_add_equality_constraint(opt, user_function1, h(i).function_value(), h_tol(i)) > 0, "nlopt error adding equality constraint"); } } double opt_f; nlopt_result ret = nlopt_optimize(opt, x.fortran_vec(), &opt_f); retval(0) = x; if (nargout > 1) retval(1) = opt_f; if (nargout > 2) retval(2) = int(ret); nlopt_destroy(opt); return retval; } nlopt-2.6.1/src/octave/nlopt_optimize.m000066400000000000000000000212641345435414600201740ustar00rootroot00000000000000% Usage: [xopt, fopt, retcode] = nlopt_optimize(opt, xinit) % % Optimizes (minimizes or maximizes) a nonlinear function under % nonlinear constraints from the starting guess xinit, where the % objective, constraints, stopping criteria, and other options are % specified in the structure opt described below. A variety of local % and global optimization algorithms can be used, as specified by the % opt.algorithm parameter described below. Returns the optimum % function value fopt, the location xopt of the optimum, and a % return code retcode described below (> 0 on success). % % The dimension (n) of the problem, i.e. the number of design variables, % is specified implicitly via the length of xinit. % % This function is a front-end for the external routine nlopt_optimize % in the free NLopt nonlinear-optimization library, which is a wrapper % around a number of free/open-source optimization subroutines. More % details can be found on the NLopt web page (ab-initio.mit.edu/nlopt) % and also under 'man nlopt_minimize' on Unix. % % OBJECTIVE FUNCTION: % % The objective function f is specified via opt.min_objective or % opt.max_objective for minimization or maximization, respectively. % opt.min/max_objective should be a handle (@) to a function of the form: % % [val, gradient] = f(x) % % where x is a row vector, val is the function value f(x), and gradient % is a row vector giving the gradient of the function with respect to x. % The gradient is only used for gradient-based optimization algorithms; % some of the algorithms (below) are derivative-free and only require % f to return val (its value). % % BOUND CONSTRAINTS: % % Lower and/or upper bounds for the design variables x are specified % via opt.lower_bounds and/or opt.upper_bounds, respectively: these % are vectors (of the same length as xinit, above) giving the bounds % in each component. An unbounded component may be specified by a % lower/upper bound of -inf/+inf, respectively. If opt.lower_bounds % and/or opt.upper_bounds are not specified, the default bounds are % -inf/+inf (i.e. unbounded), respectively. % % NONLINEAR CONSTRAINTS: % % Several of the algorithms in NLopt (MMA, COBYLA, and ORIG_DIRECT) also % support arbitrary nonlinear inequality constraints, and some also allow % nonlinear equality constraints (ISRES and AUGLAG). For these % algorithms, you can specify as many nonlinear constraints as you wish. % (The default is no nonlinear constraints.) % % Inequality constraints of the form fc{i}(x) <= 0 are specified via opt.fc, % which is a cell array of function handles (@) of the same form as % the objective function above (i.e., returning the value and optionally % the gradient of the constraint function fc{i}, where the gradient is % only needed for gradient-based algorithms). % % Equality constraints of the form h{i}(x) = 0 are specified via opt.h, % which is a cell array of function handles (@) of the same form as % the objective function above (i.e., returning the value and optionally % the gradient of the constraint function h{i}, where the gradient is % only needed for gradient-based algorithms). % % For both inequality and equality constraints, you can supply a % "tolerance" for each constraint: this tolerance is used for convergence % tests only, and a point x is considered feasible for purposes of % convergence if the constraint is violated by the given tolerance. % The tolerances are specified via opt.fc_tol and opt.h_tol, respectively, % which must be vectors of the same length as opt.fc and opt.h, so % that opt.fc_tol(i) is the tolerance for opt.fc{i} and opt.h_tol(i) % is the tolerance for opt.h{i}. These tolerances default to zero; a % small nonzero tolerance is recommended, however, especially for h_tol. % % ALGORITHMS % % The optimization algorithm must be specified via opt.algorithm. % % The algorithm should be one of the following constants (name and % interpretation are the same as for the C language interface). Names % with _G*_ are global optimization, and names with _L*_ are local % optimization. Names with _*N_ are derivative-free, while names % with _*D_ are gradient-based algorithms. Algorithms: % % NLOPT_GD_MLSL_LDS, NLOPT_GD_MLSL, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, % NLOPT_GN_CRS2_LM, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_NOSCAL, % NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_DIRECT, % NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_ISRES, NLOPT_GN_MLSL_LDS, NLOPT_GN_MLSL, % NLOPT_GN_ORIG_DIRECT_L, NLOPT_GN_ORIG_DIRECT, NLOPT_LD_AUGLAG_EQ, % NLOPT_LD_AUGLAG, NLOPT_LD_LBFGS, NLOPT_LD_LBFGS_NOCEDAL, NLOPT_LD_MMA, % NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_PRECOND, % NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_LD_TNEWTON_RESTART, % NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LN_AUGLAG_EQ, NLOPT_LN_AUGLAG, % NLOPT_LN_BOBYQA, NLOPT_LN_COBYLA, NLOPT_LN_NELDERMEAD, % NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NEWUOA, NLOPT_LN_PRAXIS, NLOPT_LN_SBPLX % % For more information on individual algorithms, see their individual % help pages (e.g. "help NLOPT_LN_SBPLX"). % % STOPPING CRITERIA: % % Multiple stopping criteria can be specified by setting one or more of % the following fields of opt. The optimization halts whenever any % one of the given criteria is satisfied. % % opt.stopval: Stop when an objective value of at least stopval is found. % That is, stop minimizing when a value <= stopval is found, or stop % maximizing when a value >= stopval is found. % % opt.ftol_rel: Relative tolerance on function value, to stop when % an optimization step (or an estimate of the optimum) changes % the function value by less than opt.ftol_rel multiplied by % the absolute value of the function. % % opt.ftol_abs: Absolute tolerance on function value, to stop when % an optimization step (or an estimate of the optimum) changes % the function value by less than opt.ftol_abs. % % opt.xtol_rel: Relative tolerance on function value, to stop when % an optimization step (or an estimate of the optimum) changes % every component of x by less than opt.xtol_rel multiplied by % the absolute value of that component of x. % % opt.xtol_abs: Absolute tolerance on function value, to stop when % an optimization step (or an estimate of the optimum) changes % every component of x by less than that component of opt.xtol_abs % -- should be a vector of same length as x. % % opt.maxeval: Maximum number of function evaluations. % % opt.maxtime: Maximum runtime (in seconds) for the optimization. % % RETURN CODE: % % The retcode result is positive upon successful completion, and % negative for an error. The specific values are: % % generic success code: +1 % stopval reached: +2 % ftol reached: +3 % xtol reached: +4 % maxeval reached: +5 % maxtime reached: +6 % generic failure code: -1 % invalid arguments: -2 % out of memory: -3 % roundoff-limited: -4 % % LOCAL OPTIMIZER: % % Some of the algorithms, especially MLSL and AUGLAG, use a different % optimization algorithm as a subroutine, typically for local optimization. % By default, they use MMA or COBYLA for gradient-based or derivative-free % searching, respectively. However, you can change this by specifying % opt.local_optimizer: this is a structure with the same types of fields as opt % (stopping criteria, algorithm, etcetera). The objective function % and nonlinear constraint parameters of opt.local_optimizer are ignored. % % INITIAL STEP SIZE: % % For derivative-free local-optimization algorithms, the optimizer must % somehow decide on some initial step size to perturb x by when it begins % the optimization. This step size should be big enough that the value % of the objective changes significantly, but not too big if you want to % find the local optimum nearest to x. By default, NLopt chooses this % initial step size heuristically from the bounds, tolerances, and other % information, but this may not always be the best choice. % % You can modify the initial step by setting opt.initial_step, which % is a vector of the same length as x containing the (nonzero) initial % step size for each component of x. % % STOCHASTIC POPULATION: % % Several of the stochastic search algorithms (e.g., CRS, MLSL, and % ISRES) start by generating some initial "population" of random points % x. By default, this initial population size is chosen heuristically in % some algorithm-specific way, but the initial population can by changed % by setting opt.population to the desired initial population size. % % VERBOSE OUTPUT: % % If opt.verbose is set to a nonzero value, then nlopt_optimize % will print out verbose output; for example, it will print the % value of the objective function after each evaluation. % % MORE INFORMATION: % % For more documentation, such as a detailed description of all the % algorithms, see the NLopt home page: http://ab-initio.mit.edu/nlopt nlopt-2.6.1/src/swig/000077500000000000000000000000001345435414600144255ustar00rootroot00000000000000nlopt-2.6.1/src/swig/CMakeLists.txt000066400000000000000000000063111345435414600171660ustar00rootroot00000000000000 if (POLICY CMP0078) cmake_policy(SET CMP0078 NEW) endif () include (UseSWIG) include (TargetLinkLibrariesWithDynamicLookup) if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/nlopt-enum-renames.i) file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/nlopt-enum-renames.i "// AUTOMATICALLY GENERATED -- DO NOT EDIT\n") file (STRINGS ${PROJECT_SOURCE_DIR}/src/api/nlopt.h NLOPT_H_LINES REGEX " NLOPT_[A-Z0-9_]+") foreach (NLOPT_H_LINE ${NLOPT_H_LINES}) string (REGEX REPLACE ".*NLOPT_([A-Z0-9_]+).*" "%rename(NLOPT_\\1) nlopt::\\1;\n" ENUM_LINE ${NLOPT_H_LINE}) file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/nlopt-enum-renames.i "${ENUM_LINE}") endforeach () endif () include_directories (${NLOPT_PRIVATE_INCLUDE_DIRS}) set_source_files_properties (nlopt.i PROPERTIES CPLUSPLUS ON) if (NUMPY_FOUND AND PYTHONLIBS_FOUND) set (SWIG_MODULE_nlopt_python_EXTRA_DEPS nlopt-python.i numpy.i) # swig_add_module is deprecated if (CMAKE_VERSION VERSION_LESS 3.8) swig_add_module (nlopt_python python nlopt.i) else () swig_add_library (nlopt_python LANGUAGE python SOURCES nlopt.i) endif () # UseSWIG generates now standard target names if (CMAKE_VERSION VERSION_LESS 3.13) set (nlopt_python ${SWIG_MODULE_nlopt_python_REAL_NAME}) else () set (nlopt_python "nlopt_python") endif () target_include_directories (${nlopt_python} PUBLIC ${PYTHON_INCLUDE_DIRS}) target_include_directories (${nlopt_python} PUBLIC ${NUMPY_INCLUDE_DIRS}) swig_link_libraries (nlopt_python ${nlopt_lib}) target_link_libraries_with_dynamic_lookup (${nlopt_python} ${PYTHON_LIBRARIES}) set_target_properties (${nlopt_python} PROPERTIES OUTPUT_NAME nlopt) if (CMAKE_VERSION VERSION_LESS 3.13) set_target_properties (${nlopt_python} PROPERTIES PREFIX "_") endif () install (FILES ${CMAKE_CURRENT_BINARY_DIR}/nlopt.py DESTINATION ${INSTALL_PYTHON_DIR}) install (TARGETS ${nlopt_python} LIBRARY DESTINATION ${INSTALL_PYTHON_DIR}) endif () # guile bindings with gcc only ok with swig >= 2.0.10 if (GUILE_FOUND AND (SWIG_VERSION VERSION_GREATER 2.0.9)) set_source_files_properties (nlopt.i PROPERTIES SWIG_FLAGS "-scmstub") set (SWIG_MODULE_nlopt_guile_EXTRA_DEPS nlopt-guile.i) # swig_add_module is deprecated if (CMAKE_VERSION VERSION_LESS 3.8) swig_add_module (nlopt_guile guile nlopt.i) else () swig_add_library (nlopt_guile LANGUAGE guile SOURCES nlopt.i) endif () # UseSWIG generates now standard target names if (CMAKE_VERSION VERSION_LESS 3.13) set (nlopt_guile ${SWIG_MODULE_nlopt_guile_REAL_NAME}) else () set (nlopt_guile "nlopt_guile") endif () target_include_directories (${nlopt_guile} PUBLIC ${GUILE_INCLUDE_DIRS}) swig_link_libraries (nlopt_guile ${nlopt_lib}) target_link_libraries_with_dynamic_lookup (${nlopt_guile} ${GUILE_LIBRARIES}) file (RELATIVE_PATH _REL_GUILE_SITE_PATH ${GUILE_ROOT_DIR} ${GUILE_SITE_DIR}) set (GUILE_SITE_PATH ${_REL_GUILE_SITE_PATH}) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/nlopt.scm DESTINATION ${GUILE_SITE_PATH}) file (RELATIVE_PATH _REL_GUILE_EXTENSION_PATH ${GUILE_ROOT_DIR} ${GUILE_EXTENSION_DIR}) set (GUILE_EXTENSION_PATH ${_REL_GUILE_EXTENSION_PATH}) install (TARGETS ${nlopt_guile} LIBRARY DESTINATION ${GUILE_EXTENSION_PATH}) endif () nlopt-2.6.1/src/swig/nlopt-exceptions.i000066400000000000000000000112231345435414600201110ustar00rootroot00000000000000// since exception specifications in C++ are evil, we instead provide // %catches specifications here so that SWIG can generate language-specific // exceptions (at least for exceptions explicitly thrown by NLopt) // // manually doing this stuff is annoying %catches(std::bad_alloc) nlopt::opt::opt(); %catches(std::bad_alloc) nlopt::opt::opt(algorithm a, unsigned n); %catches(std::bad_alloc) nlopt::opt::opt(const opt& f); %catches(std::bad_alloc) nlopt::opt::operator=(opt const& f); %catches(nlopt::roundoff_limited,nlopt::forced_stop,std::runtime_error,std::bad_alloc,std::invalid_argument) nlopt::opt::optimize(std::vector &x, double &opt_f); %catches(nlopt::roundoff_limited,nlopt::forced_stop,std::runtime_error,std::bad_alloc,std::invalid_argument) nlopt::opt::optimize(const std::vector &x0); %catches(std::runtime_error) nlopt::opt::get_algorithm(); %catches(std::runtime_error) nlopt::opt::get_algorithm_name(); %catches(std::runtime_error) nlopt::opt::get_dimension(); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_min_objective(func f, void *f_data); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_min_objective(vfunc vf, void *f_data); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_max_objective(func f, void *f_data); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_max_objective(vfunc vf, void *f_data); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_min_objective(func f, void *f_data, nlopt_munge md, nlopt_munge mc); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_max_objective(func f, void *f_data, nlopt_munge md, nlopt_munge mc); %catches(std::invalid_argument) nlopt::opt::remove_inequality_constraints(); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_constraint(func f, void *f_data, double tol=0); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_constraint(vfunc vf, void *f_data, double tol=0); %catches(std::invalid_argument) nlopt::opt::remove_equality_constraints(); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_constraint(func f, void *f_data, double tol=0); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_constraint(vfunc vf, void *f_data, double tol=0); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_mconstraint(mfunc mf, void *f_data, const std::vector &tol); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_mconstraint(mfunc mf, void *f_data, const std::vector &tol); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_constraint(func f, void *f_data, nlopt_munge md, nlopt_munge mc, double tol=0); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_constraint(func f, void *f_data, nlopt_munge md, nlopt_munge mc, double tol=0); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_mconstraint(mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc, const std::vector &tol); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_mconstraint(mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc, const std::vector &tol); #define SET_EXCEPT(name, T) %catches(std::invalid_argument) nlopt::opt::set_##name(T val); #define GET_EXCEPT(name) %catches(std::invalid_argument) nlopt::opt::get_##name(); #define SETVEC_EXCEPT(name) %catches(std::invalid_argument) nlopt::opt::set_##name(const std::vector &v); #define GETVEC_EXCEPT(name) %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::get_##name(std::vector &v); #define GETSET_EXCEPT(name, T) GET_EXCEPT(name) SET_EXCEPT(name, T) #define GETSETVEC_EXCEPT(name) GET_EXCEPT(name) SET_EXCEPT(name, double) GETVEC_EXCEPT(name) SETVEC_EXCEPT(name) GETSETVEC_EXCEPT(lower_bounds) GETSETVEC_EXCEPT(upper_bounds) GETSET_EXCEPT(stopval, double) GETSET_EXCEPT(ftol_rel, double) GETSET_EXCEPT(ftol_abs, double) GETSET_EXCEPT(xtol_rel, double) GETSETVEC_EXCEPT(xtol_abs) GETSET_EXCEPT(maxeval, int) GETSET_EXCEPT(maxtime, double) GETSET_EXCEPT(force_stop, int) %catches(std::invalid_argument) nlopt::opt::force_stop(); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_local_optimizer(const opt &lo); GETSET_EXCEPT(population, unsigned) GETSET_EXCEPT(vector_storage, unsigned) GETSETVEC_EXCEPT(initial_step) %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_default_initial_step(const std::vector &x); %catches(std::invalid_argument) nlopt::opt::get_initial_step(const std::vector &x, std::vector &dx); %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::get_initial_step_(const std::vector &x); nlopt-2.6.1/src/swig/nlopt-guile.i000066400000000000000000000050711345435414600170410ustar00rootroot00000000000000// -*- C++ -*- %{ // work around obsolete stuff used by swig guile #if SCM_MAJOR_VERSION >= 2 # define gh_symbol2scm scm_from_latin1_symbol # undef scm_listify # define scm_listify scm_list_n #else # define gh_symbol2scm scm_str2symbol #endif %} %typemap(throws) std::runtime_error %{ scm_throw(gh_symbol2scm("runtime-error"), scm_list_1(scm_from_locale_string(($1).what()))); %} %typemap(throws) std::bad_alloc %{ scm_throw(gh_symbol2scm("bad-alloc"), scm_list_1(scm_from_locale_string(($1).what()))); %} %typemap(throws) std::invalid_argument %{ scm_throw(gh_symbol2scm("invalid-argument"), scm_list_1(scm_from_locale_string(($1).what()))); %} %typemap(throws) nlopt::forced_stop %{ scm_throw(gh_symbol2scm("forced-stop"), SCM_EOL); %} %typemap(throws) nlopt::roundoff_limited %{ scm_throw(gh_symbol2scm("roundoff-limited"), SCM_EOL); %} %{ // because our f_data pointer to the Scheme function is stored on the // heap, rather than the stack, it may be missed by the Guile garbage // collection and be accidentally freed. Hence, use NLopts munge // feature to prevent this, by incrementing Guile's reference count. static void *free_guilefunc(void *p) { scm_gc_unprotect_object((SCM) p); return p; } static void *dup_guilefunc(void *p) { scm_gc_protect_object((SCM) p); return p; } // func wrapper around Guile function val = f(x, grad) static double func_guile(unsigned n, const double *x, double *grad, void *f) { SCM xscm = scm_c_make_vector(n, SCM_UNSPECIFIED); for (unsigned i = 0; i < n; ++i) SCM_SIMPLE_VECTOR_SET(xscm, i, scm_from_double(x[i])); SCM grad_scm = grad ? scm_c_make_vector(n, SCM_UNSPECIFIED) : SCM_BOOL_F; SCM ret = scm_call_2((SCM) f, xscm, grad_scm); if (!scm_is_real(ret)) throw std::invalid_argument("invalid result passed to nlopt"); if (grad) { for (unsigned i = 0; i < n; ++i) { if (!scm_is_real(ret)) throw std::invalid_argument("invalid gradient passed to nlopt"); grad[i] = scm_to_double(SCM_SIMPLE_VECTOR_REF(grad_scm, i)); } } return scm_to_double(ret); } %} %typemap(in)(nlopt::func f, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = func_guile; $2 = dup_guilefunc((void*) $input); // input = SCM pointer to Scheme function $3 = free_guilefunc; $4 = dup_guilefunc; } %typecheck(SWIG_TYPECHECK_POINTER)(nlopt::func f, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = scm_is_true(scm_procedure_p($input)); } // export constants as variables, rather than as functions returning the value %feature("constasvar", "1"); %scheme %{ (load-extension "nlopt_guile" "SWIG_init") %} nlopt-2.6.1/src/swig/nlopt-python.i000066400000000000000000000144231345435414600172560ustar00rootroot00000000000000// -*- C++ -*- ////////////////////////////////////////////////////////////////////////////// // Converting NLopt/C++ exceptions to Python exceptions %{ #define ExceptionSubclass(EXCNAME, EXCDOC) \ static PyTypeObject MyExc_ ## EXCNAME = { \ PyVarObject_HEAD_INIT(NULL, 0) \ "nlopt." # EXCNAME, \ sizeof(PyBaseExceptionObject), \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ Py_TPFLAGS_DEFAULT, \ PyDoc_STR(EXCDOC) \ }; \ static void init_ ## EXCNAME(PyObject *m) { \ MyExc_ ## EXCNAME .tp_base = (PyTypeObject *) PyExc_Exception; \ PyType_Ready(&MyExc_ ## EXCNAME); \ Py_INCREF(&MyExc_ ## EXCNAME); \ PyModule_AddObject(m, # EXCNAME, (PyObject *) &MyExc_ ## EXCNAME); \ } ExceptionSubclass(ForcedStop, "Python version of nlopt::forced_stop exception.") ExceptionSubclass(RoundoffLimited, "Python version of nlopt::roundoff_limited exception.") %} %init %{ init_ForcedStop(m); init_RoundoffLimited(m); %} %pythoncode %{ ForcedStop = _nlopt.ForcedStop RoundoffLimited = _nlopt.RoundoffLimited __version__ = str(_nlopt.version_major())+'.'+str(_nlopt.version_minor())+'.'+str(_nlopt.version_bugfix()) %} %typemap(throws) std::bad_alloc %{ PyErr_SetString(PyExc_MemoryError, ($1).what()); SWIG_fail; %} %typemap(throws) nlopt::forced_stop %{ if (!PyErr_Occurred()) PyErr_SetString((PyObject*)&MyExc_ForcedStop, "NLopt forced stop"); SWIG_fail; %} %typemap(throws) nlopt::roundoff_limited %{ PyErr_SetString((PyObject*)&MyExc_RoundoffLimited, "NLopt roundoff-limited"); SWIG_fail; %} ////////////////////////////////////////////////////////////////////////////// %{ #define SWIG_FILE_WITH_INIT %} %include "numpy.i" %init %{ import_array(); %} %numpy_typemaps(double, NPY_DOUBLE, unsigned) ////////////////////////////////////////////////////////////////////////////// // numpy.i does not include maps for std::vector, so I add them here, // taking advantage of the conversion functions provided by numpy.i // Typemap for input arguments of type const std::vector & %typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Macros") const std::vector & { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") const std::vector & (PyArrayObject* array=NULL, int is_new_object=0, std::vector arrayv) { npy_intp size[1] = { -1 }; array = obj_to_array_allow_conversion($input, NPY_DOUBLE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; arrayv = std::vector(array_size(array,0)); $1 = &arrayv; { double *arr_data = (double *) array_data(array); int arr_i, arr_s = array_stride(array,0) / sizeof(double); int arr_sz = array_size(array,0); for (arr_i = 0; arr_i < arr_sz; ++arr_i) arrayv[arr_i] = arr_data[arr_i * arr_s]; } } %typemap(freearg) const std::vector & { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } // Typemap for return values of type std::vector %typemap(out, fragment="NumPy_Fragments") std::vector { npy_intp sz = $1.size(); $result = PyArray_SimpleNew(1, &sz, NPY_DOUBLE); std::memcpy(array_data($result), $1.empty() ? NULL : &$1[0], sizeof(double) * sz); } ////////////////////////////////////////////////////////////////////////////// // Wrapper for objective function callbacks %{ static void *free_pyfunc(void *p) { Py_DECREF((PyObject*) p); return p; } static void *dup_pyfunc(void *p) { Py_INCREF((PyObject*) p); return p; } #if NPY_API_VERSION < 0x00000007 # define NPY_ARRAY_C_CONTIGUOUS NPY_C_CONTIGUOUS # define NPY_ARRAY_ALIGNED NPY_ALIGNED #endif static double func_python(unsigned n, const double *x, double *grad, void *f) { npy_intp sz = npy_intp(n), sz0 = 0, stride1 = sizeof(double); PyObject *xpy = PyArray_New(&PyArray_Type, 1, &sz, NPY_DOUBLE, &stride1, const_cast(x), // not NPY_WRITEABLE 0, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED, NULL); PyObject *gradpy = grad ? PyArray_SimpleNewFromData(1, &sz, NPY_DOUBLE, grad) : PyArray_SimpleNew(1, &sz0, NPY_DOUBLE); PyObject *arglist = Py_BuildValue("OO", xpy, gradpy); PyObject *result = PyEval_CallObject((PyObject *) f, arglist); Py_DECREF(arglist); Py_DECREF(gradpy); Py_DECREF(xpy); double val = HUGE_VAL; if (PyErr_Occurred()) { Py_XDECREF(result); throw nlopt::forced_stop(); // just stop, don't call PyErr_Clear() } else if (result && PyFloat_Check(result)) { val = PyFloat_AsDouble(result); Py_DECREF(result); } else { Py_XDECREF(result); throw std::invalid_argument("invalid result passed to nlopt"); } return val; } static void mfunc_python(unsigned m, double *result, unsigned n, const double *x, double *grad, void *f) { npy_intp nsz = npy_intp(n), msz = npy_intp(m); npy_intp mnsz[2] = {msz, nsz}; npy_intp sz0 = 0, stride1 = sizeof(double); PyObject *xpy = PyArray_New(&PyArray_Type, 1, &nsz, NPY_DOUBLE, &stride1, const_cast(x), // not NPY_WRITEABLE 0, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED, NULL); PyObject *rpy = PyArray_SimpleNewFromData(1, &msz, NPY_DOUBLE, result); PyObject *gradpy = grad ? PyArray_SimpleNewFromData(2, mnsz, NPY_DOUBLE, grad) : PyArray_SimpleNew(1, &sz0, NPY_DOUBLE); PyObject *arglist = Py_BuildValue("OOO", rpy, xpy, gradpy); PyObject *res = PyEval_CallObject((PyObject *) f, arglist); Py_XDECREF(res); Py_DECREF(arglist); Py_DECREF(gradpy); Py_DECREF(rpy); Py_DECREF(xpy); if (PyErr_Occurred()) { throw nlopt::forced_stop(); // just stop, don't call PyErr_Clear() } } %} %typemap(in)(nlopt::func f, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = func_python; $2 = dup_pyfunc((void*) $input); $3 = free_pyfunc; $4 = dup_pyfunc; } %typecheck(SWIG_TYPECHECK_POINTER)(nlopt::func f, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = PyCallable_Check($input); } %typemap(in)(nlopt::mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = mfunc_python; $2 = dup_pyfunc((void*) $input); $3 = free_pyfunc; $4 = dup_pyfunc; } %typecheck(SWIG_TYPECHECK_POINTER)(nlopt::mfunc mf, void *f_data, nlopt_munge md, nlopt_munge mc) { $1 = PyCallable_Check($input); } nlopt-2.6.1/src/swig/nlopt.i000066400000000000000000000022641345435414600157370ustar00rootroot00000000000000// -*- C++ -*- %define DOCSTRING "NLopt is a multi-language library for nonlinear optimization (local or global, with or without derivatives, and supporting nonlinear constraints). Complete documentation, including a Python tutorial, can be found at the NLopt web page: http://ab-initio.mit.edu/nlopt" %enddef %module(docstring=DOCSTRING) nlopt %{ #include "nlopt.hpp" %} %include "std_vector.i" namespace std { %template(nlopt_doublevector) vector; }; // prepend "nlopt_" in Guile to substitute for namespace #if defined(SWIGGUILE) %rename(nlopt_opt) nlopt::opt; %rename(nlopt_roundoff_limited) nlopt::roundoff_limited; %rename(nlopt_forced_stop) nlopt::forced_stop; %rename(nlopt_srand) nlopt::srand; %rename(nlopt_srand_time) nlopt::srand_time; %rename(nlopt_version) nlopt::version; %rename(nlopt_version_major) nlopt::version_major; %rename(nlopt_version_minor) nlopt::version_minor; %rename(nlopt_version_bugfix) nlopt::version_bugfix; %rename(nlopt_algorithm_name) nlopt::algorithm_name; %include "nlopt-enum-renames.i" #endif %include "nlopt-exceptions.i" #ifdef SWIGGUILE %include "nlopt-guile.i" #endif #ifdef SWIGPYTHON %include "nlopt-python.i" #endif %include "nlopt.hpp" nlopt-2.6.1/src/swig/numpy.i000066400000000000000000003157731345435414600157670ustar00rootroot00000000000000/* -*- C -*- (not really, but good for syntax highlighting) */ #ifdef SWIGPYTHON %{ #ifndef SWIG_FILE_WITH_INIT #define NO_IMPORT_ARRAY #endif #include "stdio.h" #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include %} /**********************************************************************/ %fragment("NumPy_Backward_Compatibility", "header") { %#if NPY_API_VERSION < 0x00000007 %#define NPY_ARRAY_DEFAULT NPY_DEFAULT %#define NPY_ARRAY_FARRAY NPY_FARRAY %#define NPY_FORTRANORDER NPY_FORTRAN %#endif } /**********************************************************************/ /* The following code originally appeared in * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was * translated from C++ to C by John Hunter. Bill Spotz has modified * it to fix some minor bugs, upgrade from Numeric to numpy (all * versions), add some comments and functionality, and convert from * direct code insertion to SWIG fragments. */ %fragment("NumPy_Macros", "header") { /* Macros to extract array attributes. */ %#if NPY_API_VERSION < 0x00000007 %#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) %#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) %#define array_numdims(a) (((PyArrayObject*)a)->nd) %#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) %#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) %#define array_strides(a) (((PyArrayObject*)a)->strides) %#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) %#define array_data(a) (((PyArrayObject*)a)->data) %#define array_descr(a) (((PyArrayObject*)a)->descr) %#define array_flags(a) (((PyArrayObject*)a)->flags) %#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f %#else %#define is_array(a) ((a) && PyArray_Check(a)) %#define array_type(a) PyArray_TYPE((PyArrayObject*)a) %#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) %#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) %#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) %#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) %#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) %#define array_data(a) PyArray_DATA((PyArrayObject*)a) %#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) %#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) %#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) %#endif %#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) %#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) %#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) } /**********************************************************************/ %fragment("NumPy_Utilities", "header") { /* Given a PyObject, return a string describing its type. */ const char* pytype_string(PyObject* py_obj) { if (py_obj == NULL ) return "C NULL value"; if (py_obj == Py_None ) return "Python None" ; if (PyCallable_Check(py_obj)) return "callable" ; if (PyString_Check( py_obj)) return "string" ; if (PyInt_Check( py_obj)) return "int" ; if (PyFloat_Check( py_obj)) return "float" ; if (PyDict_Check( py_obj)) return "dict" ; if (PyList_Check( py_obj)) return "list" ; if (PyTuple_Check( py_obj)) return "tuple" ; %#if PY_MAJOR_VERSION < 3 if (PyFile_Check( py_obj)) return "file" ; if (PyModule_Check( py_obj)) return "module" ; if (PyInstance_Check(py_obj)) return "instance" ; %#endif return "unknown type"; } /* Given a NumPy typecode, return a string describing the type. */ const char* typecode_string(int typecode) { static const char* type_names[25] = {"bool", "byte", "unsigned byte", "short", "unsigned short", "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long", "float", "double", "long double", "complex float", "complex double", "complex long double", "object", "string", "unicode", "void", "ntypes", "notype", "char", "unknown"}; return typecode < 24 ? type_names[typecode] : type_names[24]; } /* Make sure input has correct numpy type. This now just calls PyArray_EquivTypenums(). */ int type_match(int actual_type, int desired_type) { return PyArray_EquivTypenums(actual_type, desired_type); } %#ifdef SWIGPY_USE_CAPSULE void free_cap(PyObject * cap) { void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); if (array != NULL) free(array); } %#endif } /**********************************************************************/ %fragment("NumPy_Object_to_Array", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros", fragment="NumPy_Utilities") { /* Given a PyObject pointer, cast it to a PyArrayObject pointer if * legal. If not, set the python error string appropriately and * return NULL. */ PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode) { PyArrayObject* ary = NULL; if (is_array(input) && (typecode == NPY_NOTYPE || PyArray_EquivTypenums(array_type(input), typecode))) { ary = (PyArrayObject*) input; } else if is_array(input) { const char* desired_type = typecode_string(typecode); const char* actual_type = typecode_string(array_type(input)); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. Array of type '%s' given", desired_type, actual_type); ary = NULL; } else { const char* desired_type = typecode_string(typecode); const char* actual_type = pytype_string(input); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. A '%s' was given", desired_type, actual_type); ary = NULL; } return ary; } /* Convert the given PyObject to a NumPy array with the given * typecode. On success, return a valid PyArrayObject* with the * correct type. On failure, the python error string will be set and * the routine returns NULL. */ PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, int* is_new_object) { PyArrayObject* ary = NULL; PyObject* py_obj; if (is_array(input) && (typecode == NPY_NOTYPE || PyArray_EquivTypenums(array_type(input),typecode))) { ary = (PyArrayObject*) input; *is_new_object = 0; } else { py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); /* If NULL, PyArray_FromObject will have set python error value.*/ ary = (PyArrayObject*) py_obj; *is_new_object = 1; } return ary; } /* Given a PyArrayObject, check to see if it is contiguous. If so, * return the input pointer and flag it as not a new object. If it is * not contiguous, create a new PyArrayObject using the original data, * flag it as a new object and return the pointer. */ PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, int min_dims, int max_dims) { PyArrayObject* result; if (array_is_contiguous(ary)) { result = ary; *is_new_object = 0; } else { result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, array_type(ary), min_dims, max_dims); *is_new_object = 1; } return result; } /* Given a PyArrayObject, check to see if it is Fortran-contiguous. * If so, return the input pointer, but do not flag it as not a new * object. If it is not Fortran-contiguous, create a new * PyArrayObject using the original data, flag it as a new object * and return the pointer. */ PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object) { PyArrayObject* result; if (array_is_fortran(ary)) { result = ary; *is_new_object = 0; } else { Py_INCREF(array_descr(ary)); result = (PyArrayObject*) PyArray_FromArray(ary, array_descr(ary), NPY_FORTRANORDER); *is_new_object = 1; } return result; } /* Convert a given PyObject to a contiguous PyArrayObject of the * specified type. If the input object is not a contiguous * PyArrayObject, a new one will be created and the new object flag * will be set. */ PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, int typecode, int* is_new_object) { int is_new1 = 0; int is_new2 = 0; PyArrayObject* ary2; PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, &is_new1); if (ary1) { ary2 = make_contiguous(ary1, &is_new2, 0, 0); if ( is_new1 && is_new2) { Py_DECREF(ary1); } ary1 = ary2; } *is_new_object = is_new1 || is_new2; return ary1; } /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the * specified type. If the input object is not a Fortran-ordered * PyArrayObject, a new one will be created and the new object flag * will be set. */ PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, int typecode, int* is_new_object) { int is_new1 = 0; int is_new2 = 0; PyArrayObject* ary2; PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, &is_new1); if (ary1) { ary2 = make_fortran(ary1, &is_new2); if (is_new1 && is_new2) { Py_DECREF(ary1); } ary1 = ary2; } *is_new_object = is_new1 || is_new2; return ary1; } } /* end fragment */ /**********************************************************************/ %fragment("NumPy_Array_Requirements", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros") { /* Test whether a python object is contiguous. If array is * contiguous, return 1. Otherwise, set the python error string and * return 0. */ int require_contiguous(PyArrayObject* ary) { int contiguous = 1; if (!array_is_contiguous(ary)) { PyErr_SetString(PyExc_TypeError, "Array must be contiguous. A non-contiguous array was given"); contiguous = 0; } return contiguous; } /* Require that a numpy array is not byte-swapped. If the array is * not byte-swapped, return 1. Otherwise, set the python error string * and return 0. */ int require_native(PyArrayObject* ary) { int native = 1; if (!array_is_native(ary)) { PyErr_SetString(PyExc_TypeError, "Array must have native byteorder. " "A byte-swapped array was given"); native = 0; } return native; } /* Require the given PyArrayObject to have a specified number of * dimensions. If the array has the specified number of dimensions, * return 1. Otherwise, set the python error string and return 0. */ int require_dimensions(PyArrayObject* ary, int exact_dimensions) { int success = 1; if (array_numdims(ary) != exact_dimensions) { PyErr_Format(PyExc_TypeError, "Array must have %d dimensions. Given array has %d dimensions", exact_dimensions, array_numdims(ary)); success = 0; } return success; } /* Require the given PyArrayObject to have one of a list of specified * number of dimensions. If the array has one of the specified number * of dimensions, return 1. Otherwise, set the python error string * and return 0. */ int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n) { int success = 0; int i; char dims_str[255] = ""; char s[255]; for (i = 0; i < n && !success; i++) { if (array_numdims(ary) == exact_dimensions[i]) { success = 1; } } if (!success) { for (i = 0; i < n-1; i++) { sprintf(s, "%d, ", exact_dimensions[i]); strcat(dims_str,s); } sprintf(s, " or %d", exact_dimensions[n-1]); strcat(dims_str,s); PyErr_Format(PyExc_TypeError, "Array must have %s dimensions. Given array has %d dimensions", dims_str, array_numdims(ary)); } return success; } /* Require the given PyArrayObject to have a specified shape. If the * array has the specified shape, return 1. Otherwise, set the python * error string and return 0. */ int require_size(PyArrayObject* ary, npy_intp* size, int n) { int i; int success = 1; int len; char desired_dims[255] = "["; char s[255]; char actual_dims[255] = "["; for(i=0; i < n;i++) { if (size[i] != -1 && size[i] != array_size(ary,i)) { success = 0; } } if (!success) { for (i = 0; i < n; i++) { if (size[i] == -1) { sprintf(s, "*,"); } else { sprintf(s, "%ld,", (long int)size[i]); } strcat(desired_dims,s); } len = strlen(desired_dims); desired_dims[len-1] = ']'; for (i = 0; i < n; i++) { sprintf(s, "%ld,", (long int)array_size(ary,i)); strcat(actual_dims,s); } len = strlen(actual_dims); actual_dims[len-1] = ']'; PyErr_Format(PyExc_TypeError, "Array must have shape of %s. Given array has shape of %s", desired_dims, actual_dims); } return success; } /* Require the given PyArrayObject to to be Fortran ordered. If the * the PyArrayObject is already Fortran ordered, do nothing. Else, * set the Fortran ordering flag and recompute the strides. */ int require_fortran(PyArrayObject* ary) { int success = 1; int nd = array_numdims(ary); int i; npy_intp * strides = array_strides(ary); if (array_is_fortran(ary)) return success; /* Set the Fortran ordered flag */ array_enableflags(ary,NPY_ARRAY_FARRAY); /* Recompute the strides */ strides[0] = strides[nd-1]; for (i=1; i < nd; ++i) strides[i] = strides[i-1] * array_size(ary,i-1); return success; } } /* Combine all NumPy fragments into one for convenience */ %fragment("NumPy_Fragments", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros", fragment="NumPy_Utilities", fragment="NumPy_Object_to_Array", fragment="NumPy_Array_Requirements") { } /* End John Hunter translation (with modifications by Bill Spotz) */ /* %numpy_typemaps() macro * * This macro defines a family of 74 typemaps that allow C arguments * of the form * * 1. (DATA_TYPE IN_ARRAY1[ANY]) * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) * * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) * * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) * * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) * * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) * * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) * * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) * * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) * * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) * * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) * * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) * * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) * * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) * * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) * * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) * * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) * * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) * * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) * * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) * * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) * * where "DATA_TYPE" is any type supported by the NumPy module, and * "DIM_TYPE" is any int-like type suitable for specifying dimensions. * The difference between "ARRAY" typemaps and "FARRAY" typemaps is * that the "FARRAY" typemaps expect Fortran ordering of * multidimensional arrays. In python, the dimensions will not need * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" * typemaps). The IN_ARRAYs can be a numpy array or any sequence that * can be converted to a numpy array of the specified type. The * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The * ARGOUT_ARRAYs will be returned as new numpy arrays of the * appropriate type. * * These typemaps can be applied to existing functions using the * %apply directive. For example: * * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; * double prod(double* series, int length); * * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) * {(int rows, int cols, double* matrix )}; * void floor(int rows, int cols, double* matrix, double f); * * %apply (double IN_ARRAY3[ANY][ANY][ANY]) * {(double tensor[2][2][2] )}; * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) * {(double low[2][2][2] )}; * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) * {(double upp[2][2][2] )}; * void luSplit(double tensor[2][2][2], * double low[2][2][2], * double upp[2][2][2] ); * * or directly with * * double prod(double* IN_ARRAY1, int DIM1); * * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); * * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], * double ARGOUT_ARRAY3[ANY][ANY][ANY], * double ARGOUT_ARRAY3[ANY][ANY][ANY]); */ %define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) /************************/ /* Input Array Typemaps */ /************************/ /* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY1[ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY1[ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { $1_dim0 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY1[ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); } %typemap(freearg) (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = {-1}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY2[ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY2[ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { $1_dim0, $1_dim1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY2[ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } %typemap(freearg) (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } %typemap(freearg) (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } %typemap(freearg) (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { /* for now, only concerned with lists */ $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) { npy_intp size[2] = { -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; int is_new_object; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); is_new_object_array = (int *)calloc($2,sizeof(int)); if (array == NULL || object_array == NULL || is_new_object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; is_new_object_array[i] = is_new_object; if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; } %typemap(freearg) (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { Py_ssize_t i; if (array$argnum!=NULL) free(array$argnum); /*freeing the individual arrays if needed */ if (object_array$argnum!=NULL) { if (is_new_object_array$argnum!=NULL) { for (i=0; i<$2; i++) { if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) { Py_DECREF(object_array$argnum[i]); } } free(is_new_object_array$argnum); } free(object_array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* IN_ARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } %typemap(freearg) (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* IN_FARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } %typemap(freearg) (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { /* for now, only concerned with lists */ $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) { npy_intp size[3] = { -1, -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; int is_new_object; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); is_new_object_array = (int *)calloc($2,sizeof(int)); if (array == NULL || object_array == NULL || is_new_object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; is_new_object_array[i] = is_new_object; if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; $5 = (DIM_TYPE) size[2]; } %typemap(freearg) (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { Py_ssize_t i; if (array$argnum!=NULL) free(array$argnum); /*freeing the individual arrays if needed */ if (object_array$argnum!=NULL) { if (is_new_object_array$argnum!=NULL) { for (i=0; i<$2; i++) { if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) { Py_DECREF(object_array$argnum[i]); } } free(is_new_object_array$argnum); } free(object_array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* IN_ARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1 , -1}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } %typemap(freearg) (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* IN_FARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1 , -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /***************************/ /* In-Place Array Typemaps */ /***************************/ /* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY1[ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY1[ANY]) (PyArrayObject* array=NULL) { npy_intp size[1] = { $1_dim0 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) (PyArrayObject* array=NULL, int i=1) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = 1; for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) (PyArrayObject* array=NULL, int i=0) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = 1; for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); $2 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[2] = { $1_dim0, $1_dim1 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) { npy_intp size[2] = { -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); if (array == NULL || object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; if ( !temp_array || !require_dimensions(temp_array, 2) || !require_contiguous(temp_array) || !require_native(temp_array) || !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) ) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; } %typemap(freearg) (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (array$argnum!=NULL) free(array$argnum); if (object_array$argnum!=NULL) free(object_array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_ARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_FARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) { npy_intp size[3] = { -1, -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); if (array == NULL || object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; if ( !temp_array || !require_dimensions(temp_array, 3) || !require_contiguous(temp_array) || !require_native(temp_array) || !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) ) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; $5 = (DIM_TYPE) size[2]; } %typemap(freearg) (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (array$argnum!=NULL) free(array$argnum); if (object_array$argnum!=NULL) free(object_array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* INPLACE_ARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_FARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } /*************************/ /* Argout Array Typemaps */ /*************************/ /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY1[ANY]) (PyObject* array = NULL) { npy_intp dims[1] = { $1_dim0 }; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY1[ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) */ %typemap(in,numinputs=1, fragment="NumPy_Fragments") (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) (PyObject* array = NULL) { npy_intp dims[1]; if (!PyInt_Check($input)) { const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); SWIG_fail; } $2 = (DIM_TYPE) PyInt_AsLong($input); dims[0] = (npy_intp) $2; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); } %typemap(argout) (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) */ %typemap(in,numinputs=1, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) (PyObject* array = NULL) { npy_intp dims[1]; if (!PyInt_Check($input)) { const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); SWIG_fail; } $1 = (DIM_TYPE) PyInt_AsLong($input); dims[0] = (npy_intp) $1; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $2 = (DATA_TYPE*) array_data(array); } %typemap(argout) (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[2] = { $1_dim0, $1_dim1 }; array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /*****************************/ /* Argoutview Array Typemaps */ /*****************************/ /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) { $1 = &data_temp; $2 = &dim_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) { npy_intp dims[1] = { *$2 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim_temp; $2 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) { npy_intp dims[1] = { *$1 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /*************************************/ /* Managed Argoutview Array Typemaps */ /*************************************/ /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) { $1 = &data_temp; $2 = &dim_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) { npy_intp dims[1] = { *$2 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim_temp; $2 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) { npy_intp dims[1] = { *$1 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } %enddef /* %numpy_typemaps() macro */ /* *************************************************************** */ /* Concrete instances of the %numpy_typemaps() macro: Each invocation * below applies all of the typemaps above to the specified data type. */ %numpy_typemaps(signed char , NPY_BYTE , int) %numpy_typemaps(unsigned char , NPY_UBYTE , int) %numpy_typemaps(short , NPY_SHORT , int) %numpy_typemaps(unsigned short , NPY_USHORT , int) %numpy_typemaps(int , NPY_INT , int) %numpy_typemaps(unsigned int , NPY_UINT , int) %numpy_typemaps(long , NPY_LONG , int) %numpy_typemaps(unsigned long , NPY_ULONG , int) %numpy_typemaps(long long , NPY_LONGLONG , int) %numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) %numpy_typemaps(float , NPY_FLOAT , int) %numpy_typemaps(double , NPY_DOUBLE , int) /* *************************************************************** * The follow macro expansion does not work, because C++ bool is 4 * bytes and NPY_BOOL is 1 byte * * %numpy_typemaps(bool, NPY_BOOL, int) */ /* *************************************************************** * On my Mac, I get the following warning for this macro expansion: * 'swig/python detected a memory leak of type 'long double *', no destructor found.' * * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) */ /* *************************************************************** * Swig complains about a syntax error for the following macro * expansions: * * %numpy_typemaps(complex float, NPY_CFLOAT , int) * * %numpy_typemaps(complex double, NPY_CDOUBLE, int) * * %numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int) */ #endif /* SWIGPYTHON */ nlopt-2.6.1/src/util/000077500000000000000000000000001345435414600144315ustar00rootroot00000000000000nlopt-2.6.1/src/util/mt19937ar.c000066400000000000000000000164621345435414600161660ustar00rootroot00000000000000/* A C-program for MT19937, with initialization improved 2002/1/26. Coded by Takuji Nishimura and Makoto Matsumoto. Before using, initialize the state by using nlopt_init_genrand(seed) or nlopt_init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Modified 2007 by Steven G. Johnson for use with NLopt (to avoid namespace pollution, use uint32_t instead of unsigned long, and add the urand function). Modified 2009 to add normal-distributed random numbers. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ #include "nlopt-util.h" #if defined(HAVE_STDINT_H) # include #endif #ifndef HAVE_UINT32_T # if SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long uint32_t; # elif SIZEOF_UNSIGNED_INT == 4 typedef unsigned int uint32_t; # else # error No 32-bit unsigned integer type # endif #endif /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ /* SGJ 2010: make RNG thread-safe by declaring the RNG state as thread-local storage, at least for GCC, MSVC, and Intel C++ */ static THREADLOCAL uint32_t mt[N]; /* the array for the state vector */ static THREADLOCAL int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ /* initializes mt[N] with a seed */ void nlopt_init_genrand(unsigned long s) { mt[0]= s & 0xffffffffUL; for (mti=1; mti> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt[mti] &= 0xffffffffUL; /* for >32 bit machines */ } } /* generates a random number on [0,0xffffffff]-interval */ static uint32_t nlopt_genrand_int32(void) { uint32_t y; static uint32_t mag01[2]={0x0UL, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (mti >= N) { /* generate N words at one time */ int kk; if (mti == N+1) /* if init_genrand() has not been called, */ nlopt_init_genrand(5489UL); /* a default initial seed is used */ for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } for (;kk> 1) ^ mag01[y & 0x1UL]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mti = 0; } y = mt[mti++]; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } #if 0 /* not used in NLopt */ /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ static void nlopt_init_by_array(uint32_t init_key[], int key_length) { int i, j, k; nlopt_init_genrand(19650218UL); i=1; j=0; k = (N>key_length ? N : key_length); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=key_length) j=0; } for (k=N-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } } mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ } /* generates a random number on [0,0x7fffffff]-interval */ static long nlopt_genrand_int31(void) { return (long)(nlopt_genrand_int32()>>1); } /* generates a random number on [0,1]-real-interval */ static double nlopt_genrand_real1(void) { return nlopt_genrand_int32()*(1.0/4294967295.0); /* divided by 2^32-1 */ } /* generates a random number on [0,1)-real-interval */ static double nlopt_genrand_real2(void) { return nlopt_genrand_int32()*(1.0/4294967296.0); /* divided by 2^32 */ } /* generates a random number on (0,1)-real-interval */ static double nlopt_genrand_real3(void) { return (((double)nlopt_genrand_int32()) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ } #endif /* generates a random number on [0,1) with 53-bit resolution*/ static double nlopt_genrand_res53(void) { uint32_t a=nlopt_genrand_int32()>>5, b=nlopt_genrand_int32()>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } /* These real versions are due to Isaku Wada, 2002/01/09 added */ /* generate uniform random number in [a,b) with 53-bit resolution, added by SGJ */ double nlopt_urand(double a, double b) { return(a + (b - a) * nlopt_genrand_res53()); } /* generate a uniform random number in [0,n), added by SGJ */ int nlopt_iurand(int n) { return(nlopt_genrand_int32() % n); } /* normal-distributed random numbers with the given mean and std. deviation, added by SGJ */ double nlopt_nrand(double mean, double stddev) { /* Box-Muller algorithm to generate Gaussian from uniform see Knuth vol II algorithm P, sec. 3.4.1 */ double v1, v2, s; do { v1 = nlopt_urand(-1, 1); v2 = nlopt_urand(-1, 1); s = v1*v1 + v2*v2; } while (s >= 1.0); if (s == 0) { return mean; } else { return mean + v1 * sqrt(-2 * log(s) / s) * stddev; } } nlopt-2.6.1/src/util/mt19937ar_test.c000066400000000000000000000011471345435414600172170ustar00rootroot00000000000000#include #include "nlopt-util.h" int main(void) { int i; /* uint32_t init[4]={0x123, 0x234, 0x345, 0x456}, length=4; nlopt_init_by_array(init, length); */ nlopt_init_genrand(5489UL); /* nlopt_genrand_int32 */ printf("1000 outputs of nlopt_iurand()\n"); for (i=0; i<1000; i++) { printf("%10d ", nlopt_iurand(0x7fff)); if (i%5==4) printf("\n"); } /* genrand_real2 */ printf("\n1000 outputs of nlopt_urand()\n"); for (i=0; i<1000; i++) { printf("%10.8f ", nlopt_urand(0,1)); if (i%5==4) printf("\n"); } return 0; } nlopt-2.6.1/src/util/nlopt-getopt.c000066400000000000000000000043151345435414600172340ustar00rootroot00000000000000#include #include #include "nlopt-getopt.h" int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ optopt, /* character checked for validity */ optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define BADARG (int)':' #define EMSG "" /* * getopt -- * Parse argc/argv argument vector. */ int getopt(int nargc, char *const nargv[], const char *ostr) { static char *place = EMSG; /* option letter processing */ const char *oli; /* option letter list index */ if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; return (-1); } if (place[1] && *++place == '-') { /* found "--" */ ++optind; place = EMSG; return (-1); } } /* option letter okay? */ if ((optopt = (int) *place++) == (int) ':' || !(oli = strchr(ostr, optopt))) { /* if the user didn't specify '-' as an option, assume it means -1. */ if (optopt == (int) '-') return (-1); if (!*place) ++optind; if (opterr && *ostr != ':') (void) printf("illegal option -- %c\n", optopt); return (BADCH); } if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; } else { /* need an argument */ if (*place) /* no white space */ optarg = place; else if (nargc <= ++optind) { /* no arg */ place = EMSG; if (*ostr == ':') return (BADARG); if (opterr) (void) printf("option requires an argument -- %c\n", optopt); return (BADCH); } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } return (optopt); /* dump back option letter */ } nlopt-2.6.1/src/util/nlopt-getopt.h000066400000000000000000000041161345435414600172400ustar00rootroot00000000000000/* * Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef NLOPT_GETOPT_H #define NLOPT_GETOPT_H #ifdef __cplusplus extern "C" { #endif extern int opterr, optind, optopt, optreset; extern char *optarg; extern int getopt(int nargc, char *const nargv[], const char *ostr); #ifdef __cplusplus } #endif #endif nlopt-2.6.1/src/util/nlopt-util.h000066400000000000000000000137511345435414600167200ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef NLOPT_UTIL_H #define NLOPT_UTIL_H #include #include #include #include "nlopt_config.h" #include "nlopt.h" /* workaround for Solaris + gcc 3.4.x bug (see configure.ac) */ #if defined(__GNUC__) && defined(REPLACEMENT_HUGE_VAL) # undef HUGE_VAL # define HUGE_VAL REPLACEMENT_HUGE_VAL #endif #ifndef HAVE_COPYSIGN /* not quite right for y == -0, but good enough for us */ # define copysign(x, y) ((y) < 0 ? -fabs(x) : fabs(x)) #elif __STDC_VERSION__ < 199901 && !defined(__cplusplus) extern double copysign(double x, double y); /* may not be declared in C89 */ #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ int nlopt_isinf(double x); int nlopt_isfinite(double x); int nlopt_istiny(double x); int nlopt_isnan(double x); /* re-entrant qsort, uses the BSD convention */ extern void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, int (*compar) (void *, const void *, const void *)); /* seconds timer */ extern double nlopt_seconds(void); extern unsigned long nlopt_time_seed(void); /* pseudorandom number generation by Mersenne twister algorithm */ extern void nlopt_init_genrand(unsigned long s); extern double nlopt_urand(double a, double b); extern int nlopt_iurand(int n); extern double nlopt_nrand(double mean, double stddev); /* Sobol' low-discrepancy-sequence generation */ typedef struct nlopt_soboldata_s *nlopt_sobol; extern nlopt_sobol nlopt_sobol_create(unsigned sdim); extern void nlopt_sobol_destroy(nlopt_sobol s); extern void nlopt_sobol_next01(nlopt_sobol s, double *x); extern void nlopt_sobol_next(nlopt_sobol s, double *x, const double *lb, const double *ub); extern void nlopt_sobol_skip(nlopt_sobol s, unsigned n, double *x); /* stopping criteria */ typedef struct { unsigned n; double minf_max; double ftol_rel; double ftol_abs; double xtol_rel; const double *xtol_abs; int *nevals_p, maxeval; double maxtime, start; int *force_stop; char **stop_msg; /* pointer to msg string to update */ } nlopt_stopping; extern int nlopt_stop_f(const nlopt_stopping * stop, double f, double oldf); extern int nlopt_stop_ftol(const nlopt_stopping * stop, double f, double oldf); extern int nlopt_stop_x(const nlopt_stopping * stop, const double *x, const double *oldx); extern int nlopt_stop_dx(const nlopt_stopping * stop, const double *x, const double *dx); extern int nlopt_stop_xs(const nlopt_stopping * stop, const double *xs, const double *oldxs, const double *scale_min, const double *scale_max); extern int nlopt_stop_evals(const nlopt_stopping * stop); extern int nlopt_stop_time_(double start, double maxtime); extern int nlopt_stop_time(const nlopt_stopping * stop); extern int nlopt_stop_evalstime(const nlopt_stopping * stop); extern int nlopt_stop_forced(const nlopt_stopping * stop); /* like vsprintf, but reallocs p to whatever size is needed */ extern char *nlopt_vsprintf(char *p, const char *format, va_list ap); extern void nlopt_stop_msg(const nlopt_stopping * s, const char *format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 2, 3))) #endif ; /* for local optimizations, temporarily setting eval/time limits */ extern nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, int maxevals, double maxtime); /* data structure for nonlinear inequality or equality constraint (f <= 0 or f = 0, respectively). tol (>= 0) is a tolerance that is used for stopping criteria -- the point is considered "feasible" for purposes of stopping if the constraint is violated by at most tol. */ typedef struct { unsigned m; /* dimensional of constraint: mf maps R^n -> R^m */ nlopt_func f; /* one-dimensional constraint, requires m == 1 */ nlopt_mfunc mf; nlopt_precond pre; /* preconditioner for f (NULL if none or if mf) */ void *f_data; double *tol; } nlopt_constraint; extern unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint * c); extern unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint * c); extern void nlopt_eval_constraint(double *result, double *grad, const nlopt_constraint * c, unsigned n, const double *x); /* rescale.c: */ double *nlopt_compute_rescaling(unsigned n, const double *dx); double *nlopt_new_rescaled(unsigned n, const double *s, const double *x); void nlopt_rescale(unsigned n, const double *s, const double *x, double *xs); void nlopt_unscale(unsigned n, const double *s, const double *x, double *xs); void nlopt_reorder_bounds(unsigned n, double *lb, double *ub); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/util/qsort_r.c000066400000000000000000000123531345435414600162720ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include "nlopt-util.h" #include #include typedef int cmp_t(void *, const void *, const void *); static char *med3(char *, char *, char *, cmp_t *, void *); #define MIN(a, b) ((a) < (b) ? a : b) /* * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". */ static void swapfunc(char *a, char *b, size_t es) { char t; do { t = *a; *a++ = *b; *b++ = t; } while (--es > 0); } #define vecswap(a, b, n) \ if ((n) > 0) swapfunc(a, b, n) #define CMP(t, x, y) (cmp((t), (x), (y))) static char * med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk) { return CMP(thunk, a, b) < 0 ? (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); } void qsort_r_fallback(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d1, d2; int cmp_result; int swap_cnt; loop: swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swapfunc(pl, pl - es, es); return; } pm = (char *)a + (n / 2) * es; if (n > 7) { pl = a; pn = (char *)a + (n - 1) * es; if (n > 40) { size_t d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); pm = med3(pm - d, pm, pm + d, cmp, thunk); pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); } pm = med3(pl, pm, pn, cmp, thunk); } swapfunc(a, pm, es); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { if (cmp_result == 0) { swap_cnt = 1; swapfunc(pa, pb, es); pa += es; } pb += es; } while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { if (cmp_result == 0) { swap_cnt = 1; swapfunc(pc, pd, es); pd -= es; } pc -= es; } if (pb > pc) break; swapfunc(pb, pc, es); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swapfunc(pl, pl - es, es); return; } pn = (char *)a + n * es; d1 = MIN(pa - (char *)a, pb - pa); vecswap(a, pb - d1, d1); d1 = MIN(pd - pc, (ptrdiff_t) (pn - pd - es)); vecswap(pb, pn - d1, d1); d1 = pb - pa; d2 = pd - pc; if (d1 <= d2) { /* Recurse on left partition, then iterate on right partition */ if (d1 > es) { qsort_r_fallback(a, d1 / es, es, thunk, cmp); } if (d2 > es) { /* Iterate rather than recurse to save stack space */ /* qsort(pn - d2, d2 / es, es, cmp); */ a = pn - d2; n = d2 / es; goto loop; } } else { /* Recurse on right partition, then iterate on left partition */ if (d2 > es) { qsort_r_fallback(pn - d2, d2 / es, es, thunk, cmp); } if (d1 > es) { /* Iterate rather than recurse to save stack space */ /* qsort(a, d1 / es, es, cmp); */ n = d1 / es; goto loop; } } } /* these are required for GNU api compatibility as nlopt uses the BSD arguments ordering */ typedef struct { cmp_t* compar; void *thunk; } qsort_wrapper; #if defined(HAVE_QSORT_R) && defined(__linux__) static int qsort_cmp_wrap(const void *a, const void *b, void *thunk) { qsort_wrapper *wrap = (qsort_wrapper *) thunk; return (*wrap->compar)(wrap->thunk, a, b); } #endif void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, cmp_t* compar) { #if defined(HAVE_QSORT_R) && (defined(__APPLE__) || defined(__FreeBSD__)) qsort_r(base_, nmemb, size, thunk, compar); #elif defined(HAVE_QSORT_R) && defined(__linux__) extern void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg); qsort_wrapper wrapper; wrapper.compar = compar; wrapper.thunk = thunk; qsort_r(base_, nmemb, size, qsort_cmp_wrap, &wrapper); /*#elif defined(_WIN32) qsort_s(base_, nmemb, size, compar, thunk);*/ #else qsort_r_fallback(base_, nmemb, size, thunk, compar); #endif } nlopt-2.6.1/src/util/redblack.c000066400000000000000000000274561345435414600163620ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ /* simple implementation of red-black trees optimized for use with DIRECT */ #include #include #include "redblack.h" /* it is convenient to use an explicit node for NULL nodes ... we need to be careful never to change this node indirectly via one of our pointers! */ rb_node nil = { &nil, &nil, &nil, 0, BLACK }; #define NIL (&nil) void rb_tree_init(rb_tree * t, rb_compare compare) { t->compare = compare; t->root = NIL; t->N = 0; } static void destroy(rb_node * n) { if (n != NIL) { destroy(n->l); destroy(n->r); free(n); } } void rb_tree_destroy(rb_tree * t) { destroy(t->root); t->root = NIL; } void rb_tree_destroy_with_keys(rb_tree * t) { rb_node *n = rb_tree_min(t); while (n) { free(n->k); n->k = NULL; n = rb_tree_succ(n); } rb_tree_destroy(t); } static void rotate_left(rb_node * p, rb_tree * t) { rb_node *n = p->r; /* must be non-NIL */ p->r = n->l; n->l = p; if (p->p != NIL) { if (p == p->p->l) p->p->l = n; else p->p->r = n; } else t->root = n; n->p = p->p; p->p = n; if (p->r != NIL) p->r->p = p; } static void rotate_right(rb_node * p, rb_tree * t) { rb_node *n = p->l; /* must be non-NIL */ p->l = n->r; n->r = p; if (p->p != NIL) { if (p == p->p->l) p->p->l = n; else p->p->r = n; } else t->root = n; n->p = p->p; p->p = n; if (p->l != NIL) p->l->p = p; } static void insert_node(rb_tree * t, rb_node * n) { rb_compare compare = t->compare; rb_key k = n->k; rb_node *p = t->root; n->c = RED; n->p = n->l = n->r = NIL; t->N++; if (p == NIL) { t->root = n; n->c = BLACK; return; } /* insert (RED) node into tree */ while (1) { if (compare(k, p->k) <= 0) { /* k <= p->k */ if (p->l != NIL) p = p->l; else { p->l = n; n->p = p; break; } } else { if (p->r != NIL) p = p->r; else { p->r = n; n->p = p; break; } } } fixtree: if (n->p->c == RED) { /* red cannot have red child */ rb_node *u = p == p->p->l ? p->p->r : p->p->l; if (u != NIL && u->c == RED) { p->c = u->c = BLACK; n = p->p; if ((p = n->p) != NIL) { n->c = RED; goto fixtree; } } else { if (n == p->r && p == p->p->l) { rotate_left(p, t); p = n; n = n->l; } else if (n == p->l && p == p->p->r) { rotate_right(p, t); p = n; n = n->r; } p->c = BLACK; p->p->c = RED; if (n == p->l && p == p->p->l) rotate_right(p->p, t); else if (n == p->r && p == p->p->r) rotate_left(p->p, t); } } } rb_node *rb_tree_insert(rb_tree * t, rb_key k) { rb_node *n = (rb_node *) malloc(sizeof(rb_node)); if (!n) return NULL; n->k = k; insert_node(t, n); return n; } static int check_node(rb_node * n, int *nblack, rb_tree * t) { int nbl, nbr; rb_compare compare = t->compare; if (n == NIL) { *nblack = 0; return 1; } if (n->r != NIL && n->r->p != n) return 0; if (n->r != NIL && compare(n->r->k, n->k) < 0) return 0; if (n->l != NIL && n->l->p != n) return 0; if (n->l != NIL && compare(n->l->k, n->k) > 0) return 0; if (n->c == RED) { if (n->r != NIL && n->r->c == RED) return 0; if (n->l != NIL && n->l->c == RED) return 0; } if (!(check_node(n->r, &nbl, t) && check_node(n->l, &nbr, t))) return 0; if (nbl != nbr) return 0; *nblack = nbl + (n->c == BLACK); return 1; } int rb_tree_check(rb_tree * t) { int nblack; if (nil.c != BLACK) return 0; if (nil.p != NIL || nil.r != NIL || nil.l != NIL) return 0; if (t->root == NIL) return 1; if (t->root->c != BLACK) return 0; return check_node(t->root, &nblack, t); } rb_node *rb_tree_find(rb_tree * t, rb_key k) { rb_compare compare = t->compare; rb_node *p = t->root; while (p != NIL) { int comp = compare(k, p->k); if (!comp) return p; p = comp <= 0 ? p->l : p->r; } return NULL; } /* find greatest point in subtree p that is <= k */ static rb_node *find_le(rb_node * p, rb_key k, rb_tree * t) { rb_compare compare = t->compare; while (p != NIL) { if (compare(p->k, k) <= 0) { /* p->k <= k */ rb_node *r = find_le(p->r, k, t); if (r) return r; else return p; } else /* p->k > k */ p = p->l; } return NULL; /* k < everything in subtree */ } /* find greatest point in t <= k */ rb_node *rb_tree_find_le(rb_tree * t, rb_key k) { return find_le(t->root, k, t); } /* find greatest point in subtree p that is < k */ static rb_node *find_lt(rb_node * p, rb_key k, rb_tree * t) { rb_compare compare = t->compare; while (p != NIL) { if (compare(p->k, k) < 0) { /* p->k < k */ rb_node *r = find_lt(p->r, k, t); if (r) return r; else return p; } else /* p->k >= k */ p = p->l; } return NULL; /* k <= everything in subtree */ } /* find greatest point in t < k */ rb_node *rb_tree_find_lt(rb_tree * t, rb_key k) { return find_lt(t->root, k, t); } /* find least point in subtree p that is > k */ static rb_node *find_gt(rb_node * p, rb_key k, rb_tree * t) { rb_compare compare = t->compare; while (p != NIL) { if (compare(p->k, k) > 0) { /* p->k > k */ rb_node *l = find_gt(p->l, k, t); if (l) return l; else return p; } else /* p->k <= k */ p = p->r; } return NULL; /* k >= everything in subtree */ } /* find least point in t > k */ rb_node *rb_tree_find_gt(rb_tree * t, rb_key k) { return find_gt(t->root, k, t); } rb_node *rb_tree_min(rb_tree * t) { rb_node *n = t->root; while (n != NIL && n->l != NIL) n = n->l; return (n == NIL ? NULL : n); } rb_node *rb_tree_max(rb_tree * t) { rb_node *n = t->root; while (n != NIL && n->r != NIL) n = n->r; return (n == NIL ? NULL : n); } rb_node *rb_tree_succ(rb_node * n) { if (!n) return NULL; if (n->r == NIL) { rb_node *prev; do { prev = n; n = n->p; } while (prev == n->r && n != NIL); return n == NIL ? NULL : n; } else { n = n->r; while (n->l != NIL) n = n->l; return n; } } rb_node *rb_tree_pred(rb_node * n) { if (!n) return NULL; if (n->l == NIL) { rb_node *prev; do { prev = n; n = n->p; } while (prev == n->l && n != NIL); return n == NIL ? NULL : n; } else { n = n->l; while (n->r != NIL) n = n->r; return n; } } rb_node *rb_tree_remove(rb_tree * t, rb_node * n) { rb_key k = n->k; rb_node *m, *mp; if (n->l != NIL && n->r != NIL) { rb_node *lmax = n->l; while (lmax->r != NIL) lmax = lmax->r; n->k = lmax->k; n = lmax; } m = n->l != NIL ? n->l : n->r; if (n->p != NIL) { if (n->p->r == n) n->p->r = m; else n->p->l = m; } else t->root = m; mp = n->p; if (m != NIL) m->p = mp; if (n->c == BLACK) { if (m->c == RED) m->c = BLACK; else { deleteblack: if (mp != NIL) { rb_node *s = m == mp->l ? mp->r : mp->l; if (s->c == RED) { mp->c = RED; s->c = BLACK; if (m == mp->l) rotate_left(mp, t); else rotate_right(mp, t); s = m == mp->l ? mp->r : mp->l; } if (mp->c == BLACK && s->c == BLACK && s->l->c == BLACK && s->r->c == BLACK) { if (s != NIL) s->c = RED; m = mp; mp = m->p; goto deleteblack; } else if (mp->c == RED && s->c == BLACK && s->l->c == BLACK && s->r->c == BLACK) { if (s != NIL) s->c = RED; mp->c = BLACK; } else { if (m == mp->l && s->c == BLACK && s->l->c == RED && s->r->c == BLACK) { s->c = RED; s->l->c = BLACK; rotate_right(s, t); s = m == mp->l ? mp->r : mp->l; } else if (m == mp->r && s->c == BLACK && s->r->c == RED && s->l->c == BLACK) { s->c = RED; s->r->c = BLACK; rotate_left(s, t); s = m == mp->l ? mp->r : mp->l; } s->c = mp->c; mp->c = BLACK; if (m == mp->l) { s->r->c = BLACK; rotate_left(mp, t); } else { s->l->c = BLACK; rotate_right(mp, t); } } } } } t->N--; n->k = k; /* n may have changed during remove */ return n; /* the node that was deleted may be different from initial n */ } rb_node *rb_tree_resort(rb_tree * t, rb_node * n) { n = rb_tree_remove(t, n); insert_node(t, n); return n; } /* shift all key pointers by kshift ... this is useful when the keys are pointers into another array, that has been resized with realloc */ static void shift_keys(rb_node * n, ptrdiff_t kshift) { /* assumes n != NIL */ n->k += kshift; if (n->l != NIL) shift_keys(n->l, kshift); if (n->r != NIL) shift_keys(n->r, kshift); } void rb_tree_shift_keys(rb_tree * t, ptrdiff_t kshift) { if (t->root != NIL) shift_keys(t->root, kshift); } nlopt-2.6.1/src/util/redblack.h000066400000000000000000000061221345435414600163520ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #ifndef REDBLACK_H #define REDBLACK_H #include /* for ptrdiff_t */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef double *rb_key; /* key type ... double* is convenient for us, but of course this could be cast to anything desired (although void* would look more generic) */ typedef enum { RED, BLACK } rb_color; typedef struct rb_node_s { struct rb_node_s *p, *r, *l; /* parent, right, left */ rb_key k; /* key (and data) */ rb_color c; } rb_node; typedef int (*rb_compare) (rb_key k1, rb_key k2); typedef struct { rb_compare compare; rb_node *root; int N; /* number of nodes */ } rb_tree; extern void rb_tree_init(rb_tree * t, rb_compare compare); extern void rb_tree_destroy(rb_tree * t); extern void rb_tree_destroy_with_keys(rb_tree * t); extern rb_node *rb_tree_insert(rb_tree * t, rb_key k); extern int rb_tree_check(rb_tree * t); extern rb_node *rb_tree_find(rb_tree * t, rb_key k); extern rb_node *rb_tree_find_le(rb_tree * t, rb_key k); extern rb_node *rb_tree_find_lt(rb_tree * t, rb_key k); extern rb_node *rb_tree_find_gt(rb_tree * t, rb_key k); extern rb_node *rb_tree_resort(rb_tree * t, rb_node * n); extern rb_node *rb_tree_min(rb_tree * t); extern rb_node *rb_tree_max(rb_tree * t); extern rb_node *rb_tree_succ(rb_node * n); extern rb_node *rb_tree_pred(rb_node * n); extern void rb_tree_shift_keys(rb_tree * t, ptrdiff_t kshift); /* To change a key, use rb_tree_find+resort. Removing a node currently wastes memory unless you change the allocation scheme in redblack.c */ extern rb_node *rb_tree_remove(rb_tree * t, rb_node * n); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/src/util/redblack_test.c000066400000000000000000000142761345435414600174150ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include "redblack.h" #include "nlopt_config.h" /* workaround for Solaris + gcc 3.4.x bug (see configure.ac) */ #if defined(__GNUC__) && defined(REPLACEMENT_HUGE_VAL) # undef HUGE_VAL # define HUGE_VAL REPLACEMENT_HUGE_VAL #endif static int comp(rb_key k1, rb_key k2) { if (*k1 < *k2) return -1; if (*k1 > *k2) return +1; return 0; } int main(int argc, char **argv) { int N, M; int *k; double kd; rb_tree t; rb_node *n; int i, j; if (argc < 2) { fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n"); return 1; } N = atoi(argv[1]); k = (int *) malloc(N * sizeof(int)); rb_tree_init(&t, comp); srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL))); for (i = 0; i < N; ++i) { double *newk = (double *) malloc(sizeof(double)); *newk = (k[i] = rand() % N); if (!rb_tree_insert(&t, newk)) { fprintf(stderr, "error in rb_tree_insert\n"); return 1; } if (!rb_tree_check(&t)) { fprintf(stderr, "rb_tree_check_failed after insert!\n"); return 1; } } if (t.N != N) { fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); return 1; } for (i = 0; i < N; ++i) { kd = k[i]; if (!rb_tree_find(&t, &kd)) { fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); return 1; } } n = rb_tree_min(&t); for (i = 0; i < N; ++i) { if (!n) { fprintf(stderr, "not enough successors %d\n!", i); return 1; } printf("%d: %g\n", i, n->k[0]); n = rb_tree_succ(n); } if (n) { fprintf(stderr, "too many successors!\n"); return 1; } n = rb_tree_max(&t); for (i = 0; i < N; ++i) { if (!n) { fprintf(stderr, "not enough predecessors %d\n!", i); return 1; } printf("%d: %g\n", i, n->k[0]); n = rb_tree_pred(n); } if (n) { fprintf(stderr, "too many predecessors!\n"); return 1; } for (M = N; M > 0; --M) { int knew = rand() % N; /* random new key */ j = rand() % M; /* random original key to replace */ for (i = 0; i < N; ++i) if (k[i] >= 0) if (j-- == 0) break; if (i >= N) abort(); kd = k[i]; if (!(n = rb_tree_find(&t, &kd))) { fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); return 1; } n->k[0] = knew; if (!rb_tree_resort(&t, n)) { fprintf(stderr, "error in rb_tree_resort\n"); return 1; } if (!rb_tree_check(&t)) { fprintf(stderr, "rb_tree_check_failed after change %d!\n", N - M + 1); return 1; } k[i] = -1 - knew; } if (t.N != N) { fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); return 1; } for (i = 0; i < N; ++i) k[i] = -1 - k[i]; /* undo negation above */ for (i = 0; i < N; ++i) { rb_node *le, *gt; double lek, gtk; kd = 0.01 * (rand() % (N * 150) - N * 25); le = rb_tree_find_le(&t, &kd); gt = rb_tree_find_gt(&t, &kd); n = rb_tree_min(&t); lek = le ? le->k[0] : -HUGE_VAL; gtk = gt ? gt->k[0] : +HUGE_VAL; printf("%g <= %g < %g\n", lek, kd, gtk); if (n->k[0] > kd) { if (le) { fprintf(stderr, "found invalid le %g for %g\n", lek, kd); return 1; } if (gt != n) { fprintf(stderr, "gt is not first node for k=%g\n", kd); return 1; } } else { rb_node *succ = n; do { n = succ; succ = rb_tree_succ(n); } while (succ && succ->k[0] <= kd); if (n != le) { fprintf(stderr, "rb_tree_find_le gave wrong result for k=%g\n", kd); return 1; } if (succ != gt) { fprintf(stderr, "rb_tree_find_gt gave wrong result for k=%g\n", kd); return 1; } } } for (M = N; M > 0; --M) { j = rand() % M; for (i = 0; i < N; ++i) if (k[i] >= 0) if (j-- == 0) break; if (i >= N) abort(); kd = k[i]; if (!(n = rb_tree_find(&t, &kd))) { fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); return 1; } n = rb_tree_remove(&t, n); free(n->k); free(n); if (!rb_tree_check(&t)) { fprintf(stderr, "rb_tree_check_failed after remove!\n"); return 1; } k[i] = -1 - k[i]; } if (t.N != 0) { fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N); return 1; } rb_tree_destroy(&t); free(k); printf("SUCCESS.\n"); return 0; } nlopt-2.6.1/src/util/rescale.c000066400000000000000000000061411345435414600162150ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include "nlopt-util.h" /* Return a new array of length n (> 0) that gives a rescaling factor for each dimension, or NULL if out of memory, with dx being the array of nonzero initial steps in each dimension. */ double *nlopt_compute_rescaling(unsigned n, const double *dx) { double *s = (double *) malloc(sizeof(double) * n); unsigned i; if (!s) return NULL; for (i = 0; i < n; ++i) s[i] = 1.0; /* default: no rescaling */ if (n == 1) return s; for (i = 1; i < n && dx[i] == dx[i - 1]; ++i); if (i < n) { /* unequal initial steps, rescale to make equal to dx[0] */ for (i = 1; i < n; ++i) s[i] = dx[i] / dx[0]; } return s; } void nlopt_rescale(unsigned n, const double *s, const double *x, double *xs) { unsigned i; if (!s) { for (i = 0; i < n; ++i) xs[i] = x[i]; } else { for (i = 0; i < n; ++i) xs[i] = x[i] / s[i]; } } void nlopt_unscale(unsigned n, const double *s, const double *x, double *xs) { unsigned i; if (!s) { for (i = 0; i < n; ++i) xs[i] = x[i]; } else { for (i = 0; i < n; ++i) xs[i] = x[i] * s[i]; } } /* return a new array of length n equal to the original array x divided by the scale factors s, or NULL on a memory error */ double *nlopt_new_rescaled(unsigned n, const double *s, const double *x) { double *xs = (double *) malloc(sizeof(double) * n); if (!xs) return NULL; nlopt_rescale(n, s, x, xs); return xs; } /* since rescaling can flip the signs of the x components and the bounds, we may have to re-order the bounds in order to ensure that they remain in the correct order */ void nlopt_reorder_bounds(unsigned n, double *lb, double *ub) { unsigned i; for (i = 0; i < n; ++i) if (lb[i] > ub[i]) { double t = lb[i]; lb[i] = ub[i]; ub[i] = t; } } nlopt-2.6.1/src/util/soboldata.h000066400000000000000000002141231345435414600165550ustar00rootroot00000000000000/* Copyright (c) 2007 Massachusetts Institute of Technology * * 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. */ #ifndef SOBOLSEQ_H #define SOBOLSEQ_H /* Data on the primitive binary polynomials (a) and the corresponding starting values m, for Sobol sequences in up to 1111 dimensions, taken from: P. Bratley and B. L. Fox, Algorithm 659, ACM Trans. Math. Soft. 14 (1), 88-100 (1988), as modified by: S. Joe and F. Y. Kuo, ACM Trans. Math. Soft 29 (1), 49-57 (2003). */ #define MAXDIM 1111 #define MAXDEG 12 /* successive primitive binary-coefficient polynomials p(z) = a_0 + a_1 z + a_2 z^2 + ... a_31 z^31, where a_i is the i-th bit of sobol_a[j] for the j-th polynomial. */ static const uint32_t sobol_a[MAXDIM - 1] = { 3, 7, 11, 13, 19, 25, 37, 59, 47, 61, 55, 41, 67, 97, 91, 109, 103, 115, 131, 193, 137, 145, 143, 241, 157, 185, 167, 229, 171, 213, 191, 253, 203, 211, 239, 247, 285, 369, 299, 301, 333, 351, 355, 357, 361, 391, 397, 425, 451, 463, 487, 501, 529, 539, 545, 557, 563, 601, 607, 617, 623, 631, 637, 647, 661, 675, 677, 687, 695, 701, 719, 721, 731, 757, 761, 787, 789, 799, 803, 817, 827, 847, 859, 865, 875, 877, 883, 895, 901, 911, 949, 953, 967, 971, 973, 981, 985, 995, 1001, 1019, 1033, 1051, 1063, 1069, 1125, 1135, 1153, 1163, 1221, 1239, 1255, 1267, 1279, 1293, 1305, 1315, 1329, 1341, 1347, 1367, 1387, 1413, 1423, 1431, 1441, 1479, 1509, 1527, 1531, 1555, 1557, 1573, 1591, 1603, 1615, 1627, 1657, 1663, 1673, 1717, 1729, 1747, 1759, 1789, 1815, 1821, 1825, 1849, 1863, 1869, 1877, 1881, 1891, 1917, 1933, 1939, 1969, 2011, 2035, 2041, 2053, 2071, 2091, 2093, 2119, 2147, 2149, 2161, 2171, 2189, 2197, 2207, 2217, 2225, 2255, 2257, 2273, 2279, 2283, 2293, 2317, 2323, 2341, 2345, 2363, 2365, 2373, 2377, 2385, 2395, 2419, 2421, 2431, 2435, 2447, 2475, 2477, 2489, 2503, 2521, 2533, 2551, 2561, 2567, 2579, 2581, 2601, 2633, 2657, 2669, 2681, 2687, 2693, 2705, 2717, 2727, 2731, 2739, 2741, 2773, 2783, 2793, 2799, 2801, 2811, 2819, 2825, 2833, 2867, 2879, 2881, 2891, 2905, 2911, 2917, 2927, 2941, 2951, 2955, 2963, 2965, 2991, 2999, 3005, 3017, 3035, 3037, 3047, 3053, 3083, 3085, 3097, 3103, 3159, 3169, 3179, 3187, 3205, 3209, 3223, 3227, 3229, 3251, 3263, 3271, 3277, 3283, 3285, 3299, 3305, 3319, 3331, 3343, 3357, 3367, 3373, 3393, 3399, 3413, 3417, 3427, 3439, 3441, 3475, 3487, 3497, 3515, 3517, 3529, 3543, 3547, 3553, 3559, 3573, 3589, 3613, 3617, 3623, 3627, 3635, 3641, 3655, 3659, 3669, 3679, 3697, 3707, 3709, 3713, 3731, 3743, 3747, 3771, 3791, 3805, 3827, 3833, 3851, 3865, 3889, 3895, 3933, 3947, 3949, 3957, 3971, 3985, 3991, 3995, 4007, 4013, 4021, 4045, 4051, 4069, 4073, 4179, 4201, 4219, 4221, 4249, 4305, 4331, 4359, 4383, 4387, 4411, 4431, 4439, 4449, 4459, 4485, 4531, 4569, 4575, 4621, 4663, 4669, 4711, 4723, 4735, 4793, 4801, 4811, 4879, 4893, 4897, 4921, 4927, 4941, 4977, 5017, 5027, 5033, 5127, 5169, 5175, 5199, 5213, 5223, 5237, 5287, 5293, 5331, 5391, 5405, 5453, 5523, 5573, 5591, 5597, 5611, 5641, 5703, 5717, 5721, 5797, 5821, 5909, 5913, 5955, 5957, 6005, 6025, 6061, 6067, 6079, 6081, 6231, 6237, 6289, 6295, 6329, 6383, 6427, 6453, 6465, 6501, 6523, 6539, 6577, 6589, 6601, 6607, 6631, 6683, 6699, 6707, 6761, 6795, 6865, 6881, 6901, 6923, 6931, 6943, 6999, 7057, 7079, 7103, 7105, 7123, 7173, 7185, 7191, 7207, 7245, 7303, 7327, 7333, 7355, 7365, 7369, 7375, 7411, 7431, 7459, 7491, 7505, 7515, 7541, 7557, 7561, 7701, 7705, 7727, 7749, 7761, 7783, 7795, 7823, 7907, 7953, 7963, 7975, 8049, 8089, 8123, 8125, 8137, 8219, 8231, 8245, 8275, 8293, 8303, 8331, 8333, 8351, 8357, 8367, 8379, 8381, 8387, 8393, 8417, 8435, 8461, 8469, 8489, 8495, 8507, 8515, 8551, 8555, 8569, 8585, 8599, 8605, 8639, 8641, 8647, 8653, 8671, 8675, 8689, 8699, 8729, 8741, 8759, 8765, 8771, 8795, 8797, 8825, 8831, 8841, 8855, 8859, 8883, 8895, 8909, 8943, 8951, 8955, 8965, 8999, 9003, 9031, 9045, 9049, 9071, 9073, 9085, 9095, 9101, 9109, 9123, 9129, 9137, 9143, 9147, 9185, 9197, 9209, 9227, 9235, 9247, 9253, 9257, 9277, 9297, 9303, 9313, 9325, 9343, 9347, 9371, 9373, 9397, 9407, 9409, 9415, 9419, 9443, 9481, 9495, 9501, 9505, 9517, 9529, 9555, 9557, 9571, 9585, 9591, 9607, 9611, 9621, 9625, 9631, 9647, 9661, 9669, 9679, 9687, 9707, 9731, 9733, 9745, 9773, 9791, 9803, 9811, 9817, 9833, 9847, 9851, 9863, 9875, 9881, 9905, 9911, 9917, 9923, 9963, 9973, 10003, 10025, 10043, 10063, 10071, 10077, 10091, 10099, 10105, 10115, 10129, 10145, 10169, 10183, 10187, 10207, 10223, 10225, 10247, 10265, 10271, 10275, 10289, 10299, 10301, 10309, 10343, 10357, 10373, 10411, 10413, 10431, 10445, 10453, 10463, 10467, 10473, 10491, 10505, 10511, 10513, 10523, 10539, 10549, 10559, 10561, 10571, 10581, 10615, 10621, 10625, 10643, 10655, 10671, 10679, 10685, 10691, 10711, 10739, 10741, 10755, 10767, 10781, 10785, 10803, 10805, 10829, 10857, 10863, 10865, 10875, 10877, 10917, 10921, 10929, 10949, 10967, 10971, 10987, 10995, 11009, 11029, 11043, 11045, 11055, 11063, 11075, 11081, 11117, 11135, 11141, 11159, 11163, 11181, 11187, 11225, 11237, 11261, 11279, 11297, 11307, 11309, 11327, 11329, 11341, 11377, 11403, 11405, 11413, 11427, 11439, 11453, 11461, 11473, 11479, 11489, 11495, 11499, 11533, 11545, 11561, 11567, 11575, 11579, 11589, 11611, 11623, 11637, 11657, 11663, 11687, 11691, 11701, 11747, 11761, 11773, 11783, 11795, 11797, 11817, 11849, 11855, 11867, 11869, 11873, 11883, 11919, 11921, 11927, 11933, 11947, 11955, 11961, 11999, 12027, 12029, 12037, 12041, 12049, 12055, 12095, 12097, 12107, 12109, 12121, 12127, 12133, 12137, 12181, 12197, 12207, 12209, 12239, 12253, 12263, 12269, 12277, 12287, 12295, 12309, 12313, 12335, 12361, 12367, 12391, 12409, 12415, 12433, 12449, 12469, 12479, 12481, 12499, 12505, 12517, 12527, 12549, 12559, 12597, 12615, 12621, 12639, 12643, 12657, 12667, 12707, 12713, 12727, 12741, 12745, 12763, 12769, 12779, 12781, 12787, 12799, 12809, 12815, 12829, 12839, 12857, 12875, 12883, 12889, 12901, 12929, 12947, 12953, 12959, 12969, 12983, 12987, 12995, 13015, 13019, 13031, 13063, 13077, 13103, 13137, 13149, 13173, 13207, 13211, 13227, 13241, 13249, 13255, 13269, 13283, 13285, 13303, 13307, 13321, 13339, 13351, 13377, 13389, 13407, 13417, 13431, 13435, 13447, 13459, 13465, 13477, 13501, 13513, 13531, 13543, 13561, 13581, 13599, 13605, 13617, 13623, 13637, 13647, 13661, 13677, 13683, 13695, 13725, 13729, 13753, 13773, 13781, 13785, 13795, 13801, 13807, 13825, 13835, 13855, 13861, 13871, 13883, 13897, 13905, 13915, 13939, 13941, 13969, 13979, 13981, 13997, 14027, 14035, 14037, 14051, 14063, 14085, 14095, 14107, 14113, 14125, 14137, 14145, 14151, 14163, 14193, 14199, 14219, 14229, 14233, 14243, 14277, 14287, 14289, 14295, 14301, 14305, 14323, 14339, 14341, 14359, 14365, 14375, 14387, 14411, 14425, 14441, 14449, 14499, 14513, 14523, 14537, 14543, 14561, 14579, 14585, 14593, 14599, 14603, 14611, 14641, 14671, 14695, 14701, 14723, 14725, 14743, 14753, 14759, 14765, 14795, 14797, 14803, 14831, 14839, 14845, 14855, 14889, 14895, 14909, 14929, 14941, 14945, 14951, 14963, 14965, 14985, 15033, 15039, 15053, 15059, 15061, 15071, 15077, 15081, 15099, 15121, 15147, 15149, 15157, 15167, 15187, 15193, 15203, 15205, 15215, 15217, 15223, 15243, 15257, 15269, 15273, 15287, 15291, 15313, 15335, 15347, 15359, 15373, 15379, 15381, 15391, 15395, 15397, 15419, 15439, 15453, 15469, 15491, 15503, 15517, 15527, 15531, 15545, 15559, 15593, 15611, 15613, 15619, 15639, 15643, 15649, 15661, 15667, 15669, 15681, 15693, 15717, 15721, 15741, 15745, 15765, 15793, 15799, 15811, 15825, 15835, 15847, 15851, 15865, 15877, 15881, 15887, 15899, 15915, 15935, 15937, 15955, 15973, 15977, 16011, 16035, 16061, 16069, 16087, 16093, 16097, 16121, 16141, 16153, 16159, 16165, 16183, 16189, 16195, 16197, 16201, 16209, 16215, 16225, 16259, 16265, 16273, 16299, 16309, 16355, 16375, 16381, }; /* starting direction #'s m[i] = sobol_minit[i][j] for i=0..d of the * degree-d primitive polynomial sobol_a[j]. */ static const uint32_t sobol_minit[MAXDEG + 1][MAXDIM - 1] = { /* [0][*] */ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* [1][*] */ {0, 1, 3, 1, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 1, 1, 3, 1, 3, 1, 3, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 1, 3, 1, 1, 3, 1, 1, 3, 3, 1, 3, 1, 3, 3, 3, 3, 1, 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 3, 3, 3, 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 1, 1, 3, 3, 1, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 3, 1, 3, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 3, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 1, 3, 1, 3, 3, 1, 1, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 3, 1, 3, 1, 1, 3, 3, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 3, 1, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 1, 3, 3, 3, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 3, 1, 3, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 1, 3, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 3, 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 1, 1, 3, 3, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 3, 3, 1, 3, 1, 1, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, 1, 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 3, 3, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 1, 3, 3, 3, 1, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 1, 1, 3, 1, 3, 3, 3, 3, 3, 1}, /* [2][*] */ {0, 0, 7, 5, 1, 3, 3, 7, 5, 5, 7, 7, 1, 3, 3, 7, 5, 1, 1, 5, 3, 7, 1, 7, 5, 1, 3, 7, 7, 1, 1, 1, 5, 7, 7, 5, 1, 3, 3, 7, 5, 5, 5, 3, 3, 3, 1, 1, 5, 1, 1, 5, 3, 3, 3, 3, 1, 3, 7, 5, 7, 3, 7, 1, 3, 3, 5, 1, 3, 5, 5, 7, 7, 7, 1, 1, 3, 3, 1, 1, 5, 1, 5, 7, 5, 1, 7, 5, 3, 3, 1, 5, 7, 1, 7, 5, 1, 7, 3, 1, 7, 1, 7, 3, 3, 5, 7, 3, 3, 5, 1, 3, 3, 1, 3, 5, 1, 3, 3, 3, 7, 1, 1, 7, 3, 1, 3, 7, 5, 5, 7, 5, 5, 3, 1, 3, 3, 3, 1, 3, 3, 7, 3, 3, 1, 7, 5, 1, 7, 7, 5, 7, 5, 1, 3, 1, 7, 3, 7, 3, 5, 7, 3, 1, 3, 3, 3, 1, 5, 7, 3, 3, 7, 7, 7, 5, 3, 1, 7, 1, 3, 7, 5, 3, 3, 3, 7, 1, 1, 3, 1, 5, 7, 1, 3, 5, 3, 5, 3, 3, 7, 5, 5, 3, 3, 1, 3, 7, 7, 7, 1, 5, 7, 1, 3, 1, 1, 7, 1, 3, 1, 7, 1, 5, 3, 5, 3, 1, 1, 5, 5, 3, 3, 5, 7, 1, 5, 3, 7, 7, 3, 5, 3, 3, 1, 7, 3, 1, 3, 5, 7, 1, 3, 7, 1, 5, 1, 3, 1, 5, 3, 1, 7, 1, 5, 5, 5, 3, 7, 1, 1, 7, 3, 1, 1, 7, 5, 7, 5, 7, 7, 3, 7, 1, 3, 7, 7, 3, 5, 1, 1, 7, 1, 5, 5, 5, 1, 5, 1, 7, 5, 5, 7, 1, 1, 7, 1, 7, 7, 1, 1, 3, 3, 3, 7, 7, 5, 3, 7, 3, 1, 3, 7, 5, 3, 3, 5, 7, 1, 1, 5, 5, 7, 7, 1, 1, 1, 1, 5, 5, 5, 7, 5, 7, 1, 1, 3, 5, 1, 3, 3, 7, 3, 7, 5, 3, 5, 3, 1, 7, 1, 7, 7, 1, 1, 7, 7, 7, 5, 5, 1, 1, 7, 5, 5, 7, 5, 1, 1, 5, 5, 5, 5, 5, 5, 1, 3, 1, 5, 7, 3, 3, 5, 7, 3, 7, 1, 7, 7, 1, 3, 5, 1, 5, 5, 3, 7, 3, 7, 7, 5, 7, 5, 7, 1, 1, 5, 3, 5, 1, 5, 3, 7, 1, 5, 7, 7, 3, 5, 1, 3, 5, 1, 5, 3, 3, 3, 7, 3, 5, 1, 3, 7, 7, 3, 7, 5, 3, 3, 1, 7, 5, 1, 1, 3, 7, 1, 7, 1, 7, 3, 7, 3, 5, 7, 3, 5, 3, 1, 1, 1, 5, 7, 7, 3, 3, 1, 1, 1, 5, 5, 7, 3, 1, 1, 3, 3, 7, 3, 3, 5, 1, 3, 7, 3, 3, 7, 3, 5, 7, 5, 7, 7, 3, 3, 5, 1, 3, 5, 3, 1, 3, 5, 1, 1, 3, 7, 7, 1, 5, 1, 3, 7, 3, 7, 3, 5, 1, 7, 1, 1, 3, 5, 3, 7, 1, 5, 5, 1, 1, 3, 1, 3, 3, 7, 1, 7, 3, 1, 7, 3, 1, 7, 3, 5, 3, 5, 7, 3, 3, 3, 5, 1, 7, 7, 1, 3, 1, 3, 7, 7, 1, 3, 7, 3, 1, 5, 3, 1, 1, 1, 5, 3, 3, 7, 1, 5, 3, 5, 1, 3, 1, 3, 1, 5, 7, 7, 1, 1, 5, 3, 1, 5, 1, 1, 7, 7, 3, 5, 5, 1, 7, 1, 5, 1, 1, 3, 1, 5, 7, 5, 7, 7, 1, 5, 1, 1, 3, 5, 1, 5, 5, 3, 1, 3, 1, 5, 5, 3, 3, 3, 3, 1, 1, 3, 1, 3, 5, 5, 7, 5, 5, 7, 5, 7, 1, 3, 7, 7, 3, 5, 5, 7, 5, 5, 3, 3, 3, 1, 7, 1, 5, 5, 5, 3, 3, 5, 1, 3, 1, 3, 3, 3, 7, 1, 7, 7, 3, 7, 1, 1, 5, 7, 1, 7, 1, 7, 7, 1, 3, 7, 5, 1, 3, 5, 5, 5, 1, 1, 7, 1, 7, 1, 7, 7, 3, 1, 1, 5, 1, 5, 1, 5, 3, 5, 5, 5, 5, 5, 3, 3, 7, 3, 3, 5, 5, 3, 7, 1, 5, 7, 5, 1, 5, 5, 3, 5, 5, 7, 5, 3, 5, 5, 5, 1, 5, 5, 5, 5, 1, 3, 5, 3, 1, 7, 5, 5, 7, 1, 5, 3, 3, 1, 5, 3, 7, 1, 7, 5, 1, 1, 3, 1, 1, 7, 1, 5, 5, 3, 7, 3, 7, 5, 3, 1, 1, 3, 1, 3, 5, 5, 7, 5, 3, 7, 7, 7, 3, 7, 3, 7, 1, 3, 1, 7, 7, 1, 7, 3, 7, 3, 7, 3, 7, 3, 5, 1, 1, 7, 3, 1, 5, 5, 7, 1, 5, 5, 5, 7, 1, 5, 5, 1, 5, 5, 3, 1, 3, 1, 7, 3, 1, 3, 5, 7, 7, 7, 1, 1, 7, 3, 1, 5, 5, 5, 1, 1, 1, 1, 1, 5, 3, 5, 1, 3, 5, 3, 1, 1, 1, 1, 3, 7, 3, 7, 5, 7, 1, 5, 5, 7, 5, 3, 3, 7, 5, 3, 1, 1, 3, 1, 3, 1, 1, 3, 7, 1, 7, 1, 1, 5, 1, 7, 5, 3, 7, 3, 5, 3, 1, 1, 5, 5, 1, 7, 7, 3, 7, 3, 7, 1, 5, 1, 5, 3, 7, 3, 5, 7, 7, 7, 3, 3, 1, 1, 5, 5, 3, 7, 1, 1, 1, 3, 5, 3, 1, 1, 3, 3, 7, 5, 1, 1, 3, 7, 1, 5, 7, 3, 7, 5, 5, 7, 3, 5, 3, 1, 5, 3, 1, 1, 7, 5, 1, 7, 3, 7, 5, 1, 7, 1, 7, 7, 1, 1, 7, 1, 5, 5, 1, 1, 7, 5, 7, 1, 5, 3, 5, 3, 3, 7, 1, 5, 1, 1, 5, 5, 3, 3, 7, 5, 5, 1, 1, 1, 3, 1, 5, 7, 7, 1, 7, 5, 7, 3, 7, 3, 1, 3, 7, 3, 1, 5, 5, 3, 5, 1, 3, 5, 5, 5, 1, 1, 7, 7, 1, 5, 5, 1, 3, 5, 1, 5, 3, 5, 3, 3, 7, 5, 7, 3, 7, 3, 1, 3, 7, 7, 3, 3, 1, 1, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 1, 3, 5, 7, 7, 1, 5, 7, 3, 7, 1, 1, 3, 5, 7, 5, 3, 3, 3}, /* [3][*] */ {0, 0, 0, 0, 1, 7, 9, 13, 11, 1, 3, 7, 9, 5, 13, 13, 11, 3, 15, 5, 3, 15, 7, 9, 13, 9, 1, 11, 7, 5, 15, 1, 15, 11, 5, 11, 1, 7, 9, 7, 7, 1, 15, 15, 15, 13, 3, 3, 15, 5, 9, 7, 13, 3, 7, 5, 11, 9, 1, 9, 1, 5, 7, 13, 9, 9, 1, 7, 3, 5, 1, 11, 11, 13, 7, 7, 9, 9, 1, 1, 3, 9, 15, 1, 5, 13, 1, 9, 9, 9, 9, 9, 13, 11, 3, 5, 11, 11, 13, 5, 3, 15, 1, 11, 11, 7, 13, 15, 11, 13, 9, 11, 15, 15, 13, 3, 15, 7, 9, 11, 13, 11, 9, 9, 5, 13, 9, 1, 13, 7, 7, 7, 7, 7, 5, 9, 7, 13, 11, 9, 11, 15, 3, 13, 11, 1, 11, 3, 3, 9, 11, 1, 7, 1, 15, 15, 3, 1, 9, 1, 7, 13, 11, 3, 13, 11, 7, 3, 3, 5, 13, 11, 5, 11, 1, 3, 9, 7, 15, 7, 5, 13, 7, 9, 13, 15, 13, 9, 7, 15, 7, 9, 5, 11, 11, 13, 13, 9, 3, 5, 13, 9, 11, 15, 11, 7, 1, 7, 13, 3, 13, 3, 13, 9, 15, 7, 13, 13, 3, 13, 15, 15, 11, 9, 13, 9, 15, 1, 1, 15, 11, 11, 7, 1, 11, 13, 9, 13, 3, 5, 11, 13, 9, 9, 13, 1, 11, 15, 13, 3, 13, 7, 15, 1, 15, 3, 3, 11, 7, 13, 7, 7, 9, 7, 5, 15, 9, 5, 5, 7, 15, 13, 15, 5, 15, 5, 3, 1, 11, 7, 1, 5, 7, 9, 3, 11, 1, 15, 1, 3, 15, 11, 13, 5, 13, 1, 7, 1, 15, 7, 5, 1, 1, 15, 13, 11, 11, 13, 5, 11, 7, 9, 7, 1, 5, 3, 9, 5, 5, 11, 5, 1, 7, 1, 11, 7, 9, 13, 15, 13, 3, 1, 11, 13, 15, 1, 1, 11, 9, 13, 3, 13, 11, 15, 13, 9, 9, 9, 5, 5, 5, 5, 1, 15, 5, 9, 11, 7, 15, 5, 3, 13, 5, 3, 11, 5, 1, 11, 13, 9, 11, 3, 7, 13, 15, 1, 7, 11, 1, 13, 1, 15, 1, 9, 7, 3, 9, 11, 1, 9, 13, 13, 3, 11, 7, 9, 1, 7, 15, 9, 1, 5, 13, 5, 11, 3, 9, 15, 11, 13, 5, 1, 7, 7, 5, 13, 7, 7, 9, 5, 11, 11, 1, 1, 15, 3, 13, 9, 13, 9, 9, 11, 5, 5, 13, 15, 3, 9, 15, 3, 11, 11, 15, 15, 3, 11, 15, 15, 3, 1, 3, 1, 3, 3, 1, 3, 13, 1, 11, 5, 15, 7, 15, 9, 1, 7, 1, 9, 11, 15, 1, 13, 9, 13, 11, 7, 3, 7, 3, 13, 7, 9, 7, 7, 3, 3, 9, 9, 7, 5, 11, 13, 13, 7, 7, 15, 9, 5, 5, 3, 3, 13, 3, 9, 3, 1, 11, 1, 3, 11, 15, 11, 11, 11, 9, 13, 7, 9, 15, 9, 11, 1, 3, 3, 9, 7, 15, 13, 13, 7, 15, 9, 13, 9, 15, 13, 15, 9, 13, 1, 11, 7, 11, 3, 13, 5, 1, 7, 15, 3, 13, 7, 13, 13, 11, 3, 5, 3, 13, 11, 9, 9, 3, 11, 11, 7, 9, 13, 11, 7, 15, 13, 7, 5, 3, 1, 5, 15, 15, 3, 11, 1, 7, 3, 15, 11, 5, 5, 3, 5, 5, 1, 15, 5, 1, 5, 3, 7, 5, 11, 3, 13, 9, 13, 15, 5, 3, 5, 9, 5, 3, 11, 1, 13, 9, 15, 3, 5, 11, 9, 1, 3, 15, 9, 9, 9, 11, 7, 5, 13, 1, 15, 3, 13, 9, 13, 5, 1, 5, 1, 13, 13, 7, 7, 1, 9, 5, 11, 9, 11, 13, 3, 15, 15, 13, 15, 7, 5, 7, 9, 7, 9, 9, 9, 11, 9, 3, 11, 15, 13, 13, 5, 9, 15, 1, 1, 9, 5, 13, 3, 13, 15, 3, 1, 3, 11, 13, 1, 15, 9, 9, 3, 1, 9, 1, 9, 1, 13, 11, 15, 7, 11, 15, 13, 15, 1, 9, 9, 7, 3, 5, 11, 7, 3, 9, 5, 15, 7, 5, 3, 13, 7, 1, 1, 9, 15, 15, 15, 11, 3, 5, 15, 13, 7, 15, 15, 11, 11, 9, 5, 15, 9, 7, 3, 13, 1, 1, 5, 1, 3, 1, 7, 1, 1, 5, 1, 11, 11, 9, 9, 5, 13, 7, 7, 7, 1, 1, 9, 9, 11, 11, 15, 7, 5, 5, 3, 11, 1, 3, 7, 13, 7, 7, 7, 3, 15, 15, 11, 9, 3, 9, 3, 15, 13, 5, 3, 3, 3, 5, 9, 15, 9, 9, 1, 5, 9, 9, 15, 5, 15, 7, 9, 1, 9, 9, 5, 11, 5, 15, 15, 11, 7, 7, 7, 1, 1, 11, 11, 13, 15, 3, 13, 5, 1, 7, 1, 11, 3, 13, 15, 3, 5, 3, 5, 7, 3, 9, 9, 5, 1, 7, 11, 9, 3, 5, 11, 13, 13, 13, 9, 15, 5, 7, 1, 15, 11, 9, 15, 15, 13, 13, 13, 1, 11, 9, 15, 9, 5, 15, 5, 7, 3, 11, 3, 15, 7, 13, 11, 7, 3, 7, 13, 5, 13, 15, 5, 13, 9, 1, 15, 11, 5, 5, 1, 11, 3, 3, 7, 1, 9, 7, 15, 9, 9, 3, 11, 15, 7, 1, 3, 1, 1, 1, 9, 1, 5, 15, 15, 7, 5, 5, 7, 9, 7, 15, 13, 13, 11, 1, 9, 11, 1, 13, 1, 7, 15, 15, 5, 5, 1, 11, 3, 9, 11, 9, 9, 9, 1, 9, 3, 5, 15, 1, 1, 9, 7, 3, 3, 1, 9, 9, 11, 9, 9, 13, 13, 3, 13, 11, 13, 5, 1, 5, 5, 9, 9, 3, 13, 13, 9, 15, 9, 11, 7, 11, 9, 13, 9, 1, 15, 9, 7, 7, 1, 7, 9, 9, 15, 1, 11, 1, 13, 13, 15, 9, 13, 7, 15, 3, 9, 3, 1, 13, 7, 5, 9, 3, 1, 7, 1, 1, 13, 3, 3, 11, 1, 7, 13, 15, 15, 5, 7, 13, 13, 15, 11, 13, 1, 13, 13, 3, 9, 15, 15, 11, 15, 9, 15, 1, 13, 15, 1, 1, 5, 11, 5, 1, 11, 11, 5, 3, 9, 1, 3, 5, 13, 9, 7, 7, 1, 9, 9, 15, 7, 5, 5, 15, 13, 9, 7, 13, 3, 13, 11, 13, 7, 9, 13, 13, 13, 15, 9, 5, 5, 3, 3, 3, 1, 3, 15}, /* [4][*] */ {0, 0, 0, 0, 0, 0, 9, 3, 27, 15, 29, 21, 23, 19, 11, 25, 7, 13, 17, 1, 25, 29, 3, 31, 11, 5, 23, 27, 19, 21, 5, 1, 17, 13, 7, 15, 9, 31, 25, 3, 5, 23, 7, 3, 17, 23, 3, 3, 21, 25, 25, 23, 11, 19, 3, 11, 31, 7, 9, 5, 17, 23, 17, 17, 25, 13, 11, 31, 27, 19, 17, 23, 7, 5, 11, 19, 19, 7, 13, 21, 21, 7, 9, 11, 1, 5, 21, 11, 13, 25, 9, 7, 7, 27, 15, 25, 15, 21, 17, 19, 19, 21, 5, 11, 3, 5, 29, 31, 29, 5, 5, 1, 31, 27, 11, 13, 1, 3, 7, 11, 7, 3, 23, 13, 31, 17, 1, 27, 11, 25, 1, 23, 29, 17, 25, 7, 25, 27, 17, 13, 17, 23, 5, 17, 5, 13, 11, 21, 5, 11, 5, 9, 31, 19, 17, 9, 9, 27, 21, 15, 15, 1, 1, 29, 5, 31, 11, 17, 23, 19, 21, 25, 15, 11, 5, 5, 1, 19, 19, 19, 7, 13, 21, 17, 17, 25, 23, 19, 23, 15, 13, 5, 19, 25, 9, 7, 3, 21, 17, 25, 1, 27, 25, 27, 25, 9, 13, 3, 17, 25, 23, 9, 25, 9, 13, 17, 17, 3, 15, 7, 7, 29, 3, 19, 29, 29, 19, 29, 13, 15, 25, 27, 1, 3, 9, 9, 13, 31, 29, 31, 5, 15, 29, 1, 19, 5, 9, 19, 5, 15, 3, 5, 7, 15, 17, 17, 23, 11, 9, 23, 19, 3, 17, 1, 27, 9, 9, 17, 13, 25, 29, 23, 29, 11, 31, 25, 21, 29, 19, 27, 31, 3, 5, 3, 3, 13, 21, 9, 29, 3, 17, 11, 11, 9, 21, 19, 7, 17, 31, 25, 1, 27, 5, 15, 27, 29, 29, 29, 25, 27, 25, 3, 21, 17, 25, 13, 15, 17, 13, 23, 9, 3, 11, 7, 9, 9, 7, 17, 7, 1, 27, 1, 9, 5, 31, 21, 25, 25, 21, 11, 1, 23, 19, 27, 15, 3, 5, 23, 9, 25, 7, 29, 11, 9, 13, 5, 11, 1, 3, 31, 27, 3, 17, 27, 11, 13, 15, 29, 15, 1, 15, 23, 25, 13, 21, 15, 3, 29, 29, 5, 25, 17, 11, 7, 15, 5, 21, 7, 31, 13, 11, 23, 5, 7, 23, 27, 21, 29, 15, 7, 27, 27, 19, 7, 15, 27, 27, 19, 19, 9, 15, 1, 3, 29, 29, 5, 27, 31, 9, 1, 7, 3, 19, 19, 29, 9, 3, 21, 31, 29, 25, 1, 3, 9, 27, 5, 27, 25, 21, 11, 29, 31, 27, 21, 29, 17, 9, 17, 13, 11, 25, 15, 21, 11, 19, 31, 3, 19, 5, 3, 3, 9, 13, 13, 3, 29, 7, 5, 9, 23, 13, 21, 23, 21, 31, 11, 7, 7, 3, 23, 1, 23, 5, 9, 17, 21, 1, 17, 29, 7, 5, 17, 13, 25, 17, 9, 19, 9, 5, 7, 21, 19, 13, 9, 7, 3, 9, 3, 15, 31, 29, 29, 25, 13, 9, 21, 9, 31, 7, 15, 5, 31, 7, 15, 27, 25, 19, 9, 9, 25, 25, 23, 1, 9, 7, 11, 15, 19, 15, 27, 17, 11, 11, 31, 13, 25, 25, 9, 7, 13, 29, 19, 5, 19, 31, 25, 13, 25, 15, 5, 9, 29, 31, 9, 29, 27, 25, 27, 11, 17, 5, 17, 3, 23, 15, 9, 9, 17, 17, 31, 11, 19, 25, 13, 23, 15, 25, 21, 31, 19, 3, 11, 25, 7, 15, 19, 7, 5, 3, 13, 13, 1, 23, 5, 25, 11, 25, 15, 13, 21, 11, 23, 29, 5, 17, 27, 9, 19, 15, 5, 29, 23, 19, 1, 27, 3, 23, 21, 19, 27, 11, 17, 13, 27, 11, 31, 23, 5, 9, 21, 31, 29, 11, 21, 17, 15, 7, 15, 7, 9, 21, 27, 25, 29, 11, 3, 21, 13, 23, 19, 27, 17, 29, 25, 17, 9, 1, 19, 23, 5, 23, 1, 17, 17, 13, 27, 23, 7, 7, 11, 13, 17, 13, 11, 21, 13, 23, 1, 27, 13, 9, 7, 1, 27, 29, 5, 13, 25, 21, 3, 31, 15, 13, 3, 19, 13, 1, 27, 15, 17, 1, 3, 13, 13, 13, 31, 29, 27, 7, 7, 21, 29, 15, 17, 17, 21, 19, 17, 3, 15, 5, 27, 27, 3, 31, 31, 7, 21, 3, 13, 11, 17, 27, 25, 1, 9, 7, 29, 27, 21, 23, 13, 25, 29, 15, 17, 29, 9, 15, 3, 21, 15, 17, 17, 31, 9, 9, 23, 19, 25, 3, 1, 11, 27, 29, 1, 31, 29, 25, 29, 1, 23, 29, 25, 13, 3, 31, 25, 5, 5, 11, 3, 21, 9, 23, 7, 11, 23, 11, 1, 1, 3, 23, 25, 23, 1, 23, 3, 27, 9, 27, 3, 23, 25, 19, 29, 29, 13, 27, 5, 9, 29, 29, 13, 17, 3, 23, 19, 7, 13, 3, 19, 23, 5, 29, 29, 13, 13, 5, 19, 5, 17, 9, 11, 11, 29, 27, 23, 19, 17, 25, 13, 1, 13, 3, 11, 1, 17, 29, 1, 13, 17, 9, 17, 21, 1, 11, 1, 1, 25, 5, 7, 29, 29, 19, 19, 1, 29, 13, 3, 1, 31, 15, 13, 3, 1, 11, 19, 5, 29, 13, 29, 23, 3, 1, 31, 13, 19, 17, 5, 5, 1, 29, 23, 3, 19, 25, 19, 27, 9, 27, 13, 15, 29, 23, 13, 25, 25, 17, 19, 17, 15, 27, 3, 25, 17, 27, 3, 27, 31, 23, 13, 31, 11, 15, 7, 21, 19, 27, 19, 21, 29, 7, 31, 13, 9, 9, 7, 21, 13, 11, 9, 11, 29, 19, 11, 19, 21, 5, 29, 13, 7, 19, 19, 27, 23, 31, 1, 27, 21, 7, 3, 7, 11, 23, 13, 29, 11, 31, 19, 1, 5, 5, 11, 5, 3, 27, 5, 7, 11, 31, 1, 27, 31, 31, 23, 5, 21, 27, 9, 25, 3, 15, 19, 1, 19, 9, 5, 25, 21, 15, 25, 29, 15, 21, 11, 19, 15, 3, 7, 13, 11, 25, 17, 1, 5, 31, 13, 29, 23, 9, 5, 29, 7, 17, 27, 7, 17, 31, 9, 31, 9, 9, 7, 21, 3, 3, 3, 9, 11, 21, 11, 31, 9, 25, 5, 1, 31, 13, 29, 9, 29, 1, 11, 19, 7, 27, 13, 31, 7, 31, 7, 25, 23, 21, 29, 11, 11, 13, 11, 27, 1, 23, 31, 21, 23, 21, 19, 31, 5, 31, 25, 25, 19, 17, 11, 25, 7, 13, 1, 29, 17, 23, 15, 7, 29, 17, 13, 3, 17}, /* [5][*] */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 33, 7, 5, 11, 39, 63, 59, 17, 15, 23, 29, 3, 21, 13, 31, 25, 9, 49, 33, 19, 29, 11, 19, 27, 15, 25, 63, 55, 17, 63, 49, 19, 41, 59, 3, 57, 33, 49, 53, 57, 57, 39, 21, 7, 53, 9, 55, 15, 59, 19, 49, 31, 3, 39, 5, 5, 41, 9, 19, 9, 57, 25, 1, 15, 51, 11, 19, 61, 53, 29, 19, 11, 9, 21, 19, 43, 13, 13, 41, 25, 31, 9, 11, 19, 5, 53, 37, 7, 51, 45, 7, 7, 61, 23, 45, 7, 59, 41, 1, 29, 61, 37, 27, 47, 15, 31, 35, 31, 17, 51, 13, 25, 45, 5, 5, 33, 39, 5, 47, 29, 35, 47, 63, 45, 37, 47, 59, 21, 59, 33, 51, 9, 27, 13, 25, 43, 3, 17, 21, 59, 61, 27, 47, 57, 11, 17, 39, 1, 63, 21, 59, 17, 13, 31, 3, 31, 7, 9, 27, 37, 23, 31, 9, 45, 43, 31, 63, 21, 39, 51, 27, 7, 53, 11, 1, 59, 39, 23, 49, 23, 7, 55, 59, 3, 19, 35, 13, 9, 13, 15, 23, 9, 7, 43, 55, 3, 19, 9, 27, 33, 27, 49, 23, 47, 19, 7, 11, 55, 27, 35, 5, 5, 55, 35, 37, 9, 33, 29, 47, 25, 11, 47, 53, 61, 59, 3, 53, 47, 5, 19, 59, 5, 47, 23, 45, 53, 3, 49, 61, 47, 39, 29, 17, 57, 5, 17, 31, 23, 41, 39, 5, 27, 7, 29, 29, 33, 31, 41, 31, 29, 17, 29, 29, 9, 9, 31, 27, 53, 35, 5, 61, 1, 49, 13, 57, 29, 5, 21, 43, 25, 57, 49, 37, 27, 11, 61, 37, 49, 5, 63, 63, 3, 45, 37, 63, 21, 21, 19, 27, 59, 21, 45, 23, 13, 15, 3, 43, 63, 39, 19, 63, 31, 41, 41, 15, 43, 63, 53, 1, 63, 31, 7, 17, 11, 61, 31, 51, 37, 29, 59, 25, 63, 59, 47, 15, 27, 19, 29, 45, 35, 55, 39, 19, 43, 21, 19, 13, 17, 51, 37, 5, 33, 35, 49, 25, 45, 1, 63, 47, 9, 63, 15, 25, 25, 15, 41, 13, 3, 19, 51, 49, 37, 25, 49, 13, 53, 47, 23, 35, 29, 33, 21, 35, 23, 3, 43, 31, 63, 9, 1, 61, 43, 3, 11, 55, 11, 35, 1, 63, 35, 49, 19, 45, 9, 57, 51, 1, 47, 41, 9, 11, 37, 19, 55, 23, 55, 55, 13, 7, 47, 37, 11, 43, 17, 3, 25, 19, 55, 59, 37, 33, 43, 1, 5, 21, 5, 63, 49, 61, 21, 51, 15, 19, 43, 47, 17, 9, 53, 45, 11, 51, 25, 11, 25, 47, 47, 1, 43, 29, 17, 31, 15, 59, 27, 63, 11, 41, 51, 29, 7, 27, 63, 31, 43, 3, 29, 39, 3, 59, 59, 1, 53, 63, 23, 63, 47, 51, 23, 61, 39, 47, 21, 39, 15, 3, 9, 57, 61, 39, 37, 21, 51, 1, 23, 43, 27, 25, 11, 13, 21, 43, 7, 11, 33, 55, 1, 37, 35, 27, 61, 39, 5, 19, 61, 61, 57, 59, 21, 59, 61, 57, 25, 55, 27, 31, 41, 33, 63, 19, 57, 35, 13, 63, 35, 17, 11, 11, 49, 41, 55, 5, 45, 17, 35, 5, 31, 31, 37, 17, 45, 51, 1, 39, 49, 55, 19, 41, 13, 5, 51, 5, 49, 1, 21, 13, 17, 59, 51, 11, 3, 61, 1, 33, 37, 33, 61, 25, 27, 59, 7, 49, 13, 63, 3, 33, 3, 15, 9, 13, 35, 39, 11, 59, 59, 1, 57, 11, 5, 57, 13, 31, 13, 11, 55, 45, 9, 55, 55, 19, 25, 41, 23, 45, 29, 63, 59, 27, 39, 21, 37, 7, 61, 49, 35, 39, 9, 29, 7, 25, 23, 57, 5, 19, 15, 33, 49, 37, 25, 17, 45, 29, 15, 25, 3, 3, 49, 11, 39, 15, 19, 57, 39, 15, 11, 3, 57, 31, 55, 61, 19, 5, 41, 35, 59, 61, 39, 41, 53, 53, 63, 31, 9, 59, 13, 35, 55, 41, 49, 5, 41, 25, 27, 43, 5, 5, 43, 5, 5, 17, 5, 15, 27, 29, 17, 9, 3, 55, 31, 1, 45, 45, 13, 57, 17, 3, 61, 15, 49, 15, 47, 9, 37, 45, 9, 51, 61, 21, 33, 11, 21, 63, 63, 47, 57, 61, 49, 9, 59, 19, 29, 21, 23, 55, 23, 43, 41, 57, 9, 39, 27, 41, 35, 61, 29, 57, 63, 21, 31, 59, 35, 49, 3, 49, 47, 49, 33, 21, 19, 21, 35, 11, 17, 37, 23, 59, 13, 37, 35, 55, 57, 1, 29, 45, 11, 1, 15, 9, 33, 19, 53, 43, 39, 23, 7, 13, 13, 1, 19, 41, 55, 1, 13, 15, 59, 55, 15, 3, 57, 37, 31, 17, 1, 3, 21, 29, 25, 55, 9, 37, 33, 53, 41, 51, 19, 57, 13, 63, 43, 19, 7, 13, 37, 33, 19, 15, 63, 51, 11, 49, 23, 57, 47, 51, 15, 53, 41, 1, 15, 37, 61, 11, 35, 29, 33, 23, 55, 11, 59, 19, 61, 61, 45, 13, 49, 13, 63, 5, 61, 5, 31, 17, 61, 63, 13, 27, 57, 1, 21, 5, 11, 39, 57, 51, 53, 39, 25, 41, 39, 37, 23, 31, 25, 33, 17, 57, 29, 27, 23, 47, 41, 29, 19, 47, 41, 25, 5, 51, 43, 39, 29, 7, 31, 45, 51, 49, 55, 17, 43, 49, 45, 9, 29, 3, 5, 47, 9, 15, 19, 51, 45, 57, 63, 9, 21, 59, 3, 9, 13, 45, 23, 15, 31, 21, 15, 51, 35, 9, 11, 61, 23, 53, 29, 51, 45, 31, 29, 5, 35, 29, 53, 35, 17, 59, 55, 27, 51, 59, 27, 47, 15, 29, 37, 7, 49, 55, 5, 19, 45, 29, 19, 57, 33, 53, 45, 21, 9, 3, 35, 29, 43, 31, 39, 3, 45, 1, 41, 29, 5, 59, 41, 33, 35, 27, 19, 13, 25, 27, 43, 33, 35, 17, 17, 23, 7, 35, 15, 61, 61, 53, 5, 15, 23, 11, 13, 43, 55, 47, 25, 43, 15, 57, 45, 1, 49, 63, 57, 15, 31, 31, 7, 53, 27, 15, 47, 23, 7, 29, 53, 47, 9, 53, 3, 25, 55, 45, 63, 21, 17, 23, 31, 27, 27, 43, 63, 55, 63, 45, 51, 15, 27, 5, 37, 43, 11, 27, 5, 27, 59, 21, 7, 39, 27, 63, 35, 47, 55, 17, 17, 17, 3, 19, 21, 13, 49, 61, 39, 15}, /* [6][*] */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 33, 115, 41, 79, 17, 29, 119, 75, 73, 105, 7, 59, 65, 21, 3, 113, 61, 89, 45, 107, 21, 71, 79, 19, 71, 61, 41, 57, 121, 87, 119, 55, 85, 121, 119, 11, 23, 61, 11, 35, 33, 43, 107, 113, 101, 29, 87, 119, 97, 29, 17, 89, 5, 127, 89, 119, 117, 103, 105, 41, 83, 25, 41, 55, 69, 117, 49, 127, 29, 1, 99, 53, 83, 15, 31, 73, 115, 35, 21, 89, 5, 1, 91, 53, 35, 95, 83, 19, 85, 55, 51, 101, 33, 41, 55, 45, 95, 61, 27, 37, 89, 75, 57, 61, 15, 117, 15, 21, 27, 25, 27, 123, 39, 109, 93, 51, 21, 91, 109, 107, 45, 15, 93, 127, 3, 53, 81, 79, 107, 79, 87, 35, 109, 73, 35, 83, 107, 1, 51, 7, 59, 33, 115, 43, 111, 45, 121, 105, 125, 87, 101, 41, 95, 75, 1, 57, 117, 21, 27, 67, 29, 53, 117, 63, 1, 77, 89, 115, 49, 127, 15, 79, 81, 29, 65, 103, 33, 73, 79, 29, 21, 113, 31, 33, 107, 95, 111, 59, 99, 117, 63, 63, 99, 39, 9, 35, 63, 125, 99, 45, 93, 33, 93, 9, 105, 75, 51, 115, 11, 37, 17, 41, 21, 43, 73, 19, 93, 7, 95, 81, 93, 79, 81, 55, 9, 51, 63, 45, 89, 73, 19, 115, 39, 47, 81, 39, 5, 5, 45, 53, 65, 49, 17, 105, 13, 107, 5, 5, 19, 73, 59, 43, 83, 97, 115, 27, 1, 69, 103, 3, 99, 103, 63, 67, 25, 121, 97, 77, 13, 83, 103, 41, 11, 27, 81, 37, 33, 125, 71, 41, 41, 59, 41, 87, 123, 43, 101, 63, 45, 39, 21, 97, 15, 97, 111, 21, 49, 13, 17, 79, 91, 65, 105, 75, 1, 45, 67, 83, 107, 125, 87, 15, 81, 95, 105, 65, 45, 59, 103, 23, 103, 99, 67, 99, 47, 117, 71, 89, 35, 53, 73, 9, 115, 49, 37, 1, 35, 9, 45, 81, 19, 127, 17, 17, 105, 89, 49, 101, 7, 37, 33, 11, 95, 95, 17, 111, 105, 41, 115, 5, 69, 101, 27, 27, 101, 103, 53, 9, 21, 43, 79, 91, 65, 117, 87, 125, 55, 45, 63, 85, 83, 97, 45, 83, 87, 113, 93, 95, 5, 17, 77, 77, 127, 123, 45, 81, 85, 121, 119, 27, 85, 41, 49, 15, 107, 21, 51, 119, 11, 87, 101, 115, 63, 63, 37, 121, 109, 7, 43, 69, 19, 77, 49, 71, 59, 35, 7, 13, 55, 101, 127, 103, 85, 109, 29, 61, 67, 21, 111, 67, 23, 57, 75, 71, 101, 123, 41, 107, 101, 107, 125, 27, 47, 119, 41, 19, 127, 33, 31, 109, 7, 91, 91, 39, 125, 105, 47, 125, 123, 91, 9, 103, 45, 23, 117, 9, 125, 73, 11, 37, 61, 79, 21, 5, 47, 117, 67, 53, 85, 33, 81, 121, 47, 61, 51, 127, 29, 65, 45, 41, 95, 57, 73, 33, 117, 61, 111, 59, 123, 65, 47, 105, 23, 29, 107, 37, 81, 67, 29, 115, 119, 75, 73, 99, 103, 7, 57, 45, 61, 95, 49, 101, 101, 35, 47, 119, 39, 67, 31, 103, 7, 61, 127, 87, 3, 35, 29, 73, 95, 103, 71, 75, 51, 87, 57, 97, 11, 105, 87, 41, 73, 109, 69, 35, 121, 39, 111, 1, 77, 39, 47, 53, 91, 3, 17, 51, 83, 39, 125, 85, 111, 21, 69, 85, 29, 55, 11, 117, 1, 47, 17, 65, 63, 47, 117, 17, 115, 51, 25, 33, 123, 123, 83, 51, 113, 95, 121, 51, 91, 109, 43, 55, 35, 55, 87, 33, 37, 5, 3, 45, 21, 105, 127, 35, 17, 35, 37, 97, 97, 21, 77, 123, 17, 89, 53, 105, 75, 25, 125, 13, 47, 21, 125, 23, 55, 63, 61, 5, 17, 93, 57, 121, 69, 73, 93, 121, 105, 75, 91, 67, 95, 75, 9, 69, 97, 99, 93, 11, 53, 19, 73, 5, 33, 79, 107, 65, 69, 79, 125, 25, 93, 55, 61, 17, 117, 69, 97, 87, 111, 37, 93, 59, 79, 95, 53, 115, 53, 85, 85, 65, 59, 23, 75, 21, 67, 27, 99, 79, 27, 3, 95, 27, 69, 19, 75, 47, 59, 41, 85, 77, 99, 55, 49, 93, 93, 119, 51, 125, 63, 13, 15, 45, 61, 19, 105, 115, 17, 83, 7, 7, 11, 61, 37, 63, 89, 95, 119, 113, 67, 123, 91, 33, 37, 99, 43, 11, 33, 65, 81, 79, 81, 107, 63, 63, 55, 89, 91, 25, 93, 101, 27, 55, 75, 121, 79, 43, 125, 73, 27, 109, 35, 21, 71, 113, 89, 59, 95, 41, 45, 113, 119, 113, 39, 59, 73, 15, 13, 59, 67, 121, 27, 7, 105, 15, 59, 59, 35, 91, 89, 23, 125, 97, 53, 41, 91, 111, 29, 31, 3, 103, 61, 71, 35, 7, 119, 29, 45, 49, 111, 41, 109, 59, 125, 13, 27, 19, 79, 9, 75, 83, 81, 33, 91, 109, 33, 29, 107, 111, 101, 107, 109, 65, 59, 43, 37, 1, 9, 15, 109, 37, 111, 113, 119, 79, 73, 65, 71, 93, 17, 101, 87, 97, 43, 23, 75, 109, 41, 49, 53, 31, 97, 105, 109, 119, 51, 9, 53, 113, 97, 73, 89, 79, 49, 61, 105, 13, 99, 53, 71, 7, 87, 21, 101, 5, 71, 31, 123, 121, 121, 73, 79, 115, 13, 39, 101, 19, 37, 51, 83, 97, 55, 81, 91, 127, 105, 89, 63, 47, 49, 75, 37, 77, 15, 49, 107, 23, 23, 35, 19, 69, 17, 59, 63, 73, 29, 125, 61, 65, 95, 101, 81, 57, 69, 83, 37, 11, 37, 95, 1, 73, 27, 29, 57, 7, 65, 83, 99, 69, 19, 103, 43, 95, 25, 19, 103, 41, 125, 97, 71, 105, 83, 83, 61, 39, 9, 45, 117, 63, 31, 5, 117, 67, 125, 41, 117, 43, 77, 97, 15, 29, 5, 59, 25, 63, 87, 39, 39, 77, 85, 37, 81, 73, 89, 29, 125, 109, 21, 23, 119, 105, 43, 93, 97, 15, 125, 29, 51, 69, 37, 45, 31, 75, 109, 119, 53, 5, 101, 125, 121, 35, 29, 7, 63, 17, 63, 13, 69, 15, 105, 51, 127, 105, 9, 57, 95, 59, 109, 35, 49, 23, 33, 107, 55, 33, 57, 79, 73, 69, 59, 107, 55, 11, 63, 95, 103, 23, 125, 91, 31, 91, 51, 65, 61, 75, 69, 107, 65, 101, 59, 35, 15}, /* [7][*] */ {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, 0, 0, 0, 0, 7, 23, 39, 217, 141, 27, 53, 181, 169, 35, 15, 207, 45, 247, 185, 117, 41, 81, 223, 151, 81, 189, 61, 95, 185, 23, 73, 113, 239, 85, 9, 201, 83, 53, 183, 203, 91, 149, 101, 13, 111, 239, 3, 205, 253, 247, 121, 189, 169, 179, 197, 175, 217, 249, 195, 95, 63, 19, 7, 5, 75, 217, 245, 111, 189, 165, 169, 141, 221, 249, 159, 253, 207, 249, 219, 23, 49, 127, 237, 5, 25, 177, 37, 103, 65, 167, 81, 87, 119, 45, 79, 143, 57, 79, 187, 143, 183, 75, 97, 211, 149, 175, 37, 135, 189, 225, 241, 63, 33, 43, 13, 73, 213, 57, 239, 183, 117, 21, 29, 115, 43, 205, 223, 15, 3, 159, 51, 101, 127, 99, 239, 171, 113, 171, 119, 189, 245, 201, 27, 185, 229, 105, 153, 189, 33, 35, 137, 77, 97, 17, 181, 55, 197, 201, 155, 37, 197, 137, 223, 25, 179, 91, 23, 235, 53, 253, 49, 181, 249, 53, 173, 97, 247, 67, 115, 103, 159, 239, 69, 173, 217, 95, 221, 247, 97, 91, 123, 223, 213, 129, 181, 87, 239, 85, 89, 249, 141, 39, 57, 249, 71, 101, 159, 33, 137, 189, 71, 253, 205, 171, 13, 249, 109, 131, 199, 189, 179, 31, 99, 113, 41, 173, 23, 189, 197, 3, 135, 9, 95, 195, 27, 183, 1, 123, 73, 53, 99, 197, 59, 27, 101, 55, 193, 31, 61, 119, 11, 7, 255, 233, 53, 157, 193, 97, 83, 65, 81, 239, 167, 69, 71, 109, 97, 137, 71, 193, 189, 115, 79, 205, 37, 227, 53, 33, 91, 229, 245, 105, 77, 229, 161, 103, 93, 13, 161, 229, 223, 69, 15, 25, 23, 233, 93, 25, 217, 247, 61, 75, 27, 9, 223, 213, 55, 197, 145, 89, 199, 41, 201, 5, 149, 35, 119, 183, 53, 11, 13, 3, 179, 229, 43, 55, 187, 233, 47, 133, 91, 47, 71, 93, 105, 145, 45, 255, 221, 115, 175, 19, 129, 5, 209, 197, 57, 177, 115, 187, 119, 77, 211, 111, 33, 113, 23, 87, 137, 41, 7, 83, 43, 121, 145, 5, 219, 27, 11, 111, 207, 55, 97, 63, 229, 53, 33, 149, 23, 187, 153, 91, 193, 183, 59, 211, 93, 139, 59, 179, 163, 209, 77, 39, 111, 79, 229, 85, 237, 199, 137, 147, 25, 73, 121, 129, 83, 87, 93, 205, 167, 53, 107, 229, 213, 95, 219, 109, 175, 13, 209, 97, 61, 147, 19, 13, 123, 73, 35, 141, 81, 19, 171, 255, 111, 107, 233, 113, 133, 89, 9, 231, 95, 69, 33, 1, 253, 219, 253, 247, 129, 11, 251, 221, 153, 35, 103, 239, 7, 27, 235, 181, 5, 207, 53, 149, 155, 225, 165, 137, 155, 201, 97, 245, 203, 47, 39, 35, 105, 239, 49, 15, 253, 7, 237, 213, 55, 87, 199, 27, 175, 49, 41, 229, 85, 3, 149, 179, 129, 185, 249, 197, 15, 97, 197, 139, 203, 63, 33, 251, 217, 199, 199, 99, 249, 33, 229, 177, 13, 209, 147, 97, 31, 125, 177, 137, 187, 11, 91, 223, 29, 169, 231, 59, 31, 163, 41, 57, 87, 247, 25, 127, 101, 207, 187, 73, 61, 105, 27, 91, 171, 243, 33, 3, 1, 21, 229, 93, 71, 61, 37, 183, 65, 211, 53, 11, 151, 165, 47, 5, 129, 79, 101, 147, 169, 181, 19, 95, 77, 139, 197, 219, 97, 239, 183, 143, 9, 13, 209, 23, 215, 53, 137, 203, 19, 151, 171, 133, 219, 231, 3, 15, 253, 225, 33, 111, 183, 213, 169, 119, 111, 15, 201, 123, 121, 225, 113, 113, 225, 161, 165, 1, 139, 55, 3, 93, 217, 193, 97, 29, 69, 231, 161, 93, 69, 143, 137, 9, 87, 183, 113, 183, 73, 215, 137, 89, 251, 163, 41, 227, 145, 57, 81, 57, 11, 135, 145, 161, 175, 159, 25, 55, 167, 157, 211, 97, 247, 249, 23, 129, 159, 71, 197, 127, 141, 219, 5, 233, 131, 217, 101, 131, 33, 157, 173, 69, 207, 239, 81, 205, 11, 41, 169, 65, 193, 77, 201, 173, 1, 221, 157, 1, 15, 113, 147, 137, 205, 225, 73, 45, 49, 149, 113, 253, 99, 17, 119, 105, 117, 129, 243, 75, 203, 53, 29, 247, 35, 247, 171, 31, 199, 213, 29, 251, 7, 251, 187, 91, 11, 149, 13, 205, 37, 249, 137, 139, 9, 7, 113, 183, 205, 187, 39, 3, 79, 155, 227, 89, 185, 51, 127, 63, 83, 41, 133, 183, 181, 127, 19, 255, 219, 59, 251, 3, 187, 57, 217, 115, 217, 229, 181, 185, 149, 83, 115, 11, 123, 19, 109, 165, 103, 123, 219, 129, 155, 207, 177, 9, 49, 181, 231, 33, 233, 67, 155, 41, 9, 95, 123, 65, 117, 249, 85, 169, 129, 241, 173, 251, 225, 147, 165, 69, 81, 239, 95, 23, 83, 227, 249, 143, 171, 193, 9, 21, 57, 73, 97, 57, 29, 239, 151, 159, 191, 47, 51, 1, 223, 251, 251, 151, 41, 119, 127, 131, 33, 209, 123, 53, 241, 25, 31, 183, 107, 25, 115, 39, 11, 213, 239, 219, 109, 185, 35, 133, 123, 185, 27, 55, 245, 61, 75, 205, 213, 169, 163, 63, 55, 49, 83, 195, 51, 31, 41, 15, 203, 41, 63, 127, 161, 5, 143, 7, 199, 251, 95, 75, 101, 15, 43, 237, 197, 117, 167, 155, 21, 83, 205, 255, 49, 101, 213, 237, 135, 135, 21, 73, 93, 115, 7, 85, 223, 237, 79, 89, 5, 57, 239, 67, 65, 201, 155, 71, 85, 195, 89, 181, 119, 135, 147, 237, 173, 41, 155, 67, 113, 111, 21, 183, 23, 103, 207, 253, 69, 219, 205, 195, 43, 197, 229, 139, 177, 129, 69, 97, 201, 163, 189, 11, 99, 91, 253, 239, 91, 145, 19, 179, 231, 121, 7, 225, 237, 125, 191, 119, 59, 175, 237, 131, 79, 43, 45, 205, 199, 251, 153, 207, 37, 179, 113, 255, 107, 217, 61, 7, 181, 247, 31, 13, 113, 145, 107, 233, 233, 43, 79, 23, 169, 137, 129, 183, 53, 91, 55, 103, 223, 87, 177, 157, 79, 213, 139, 183, 231, 205, 143, 129, 243, 205, 93, 59, 15, 89, 9, 11, 47, 133, 227, 75, 9, 91, 19, 171, 163, 79, 7, 103, 5, 119, 155, 75, 11, 71, 95, 17, 13, 243, 207, 187}, /* [8][*] */ {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 307, 495, 417, 57, 151, 19, 119, 375, 451, 55, 449, 501, 53, 185, 317, 17, 21, 487, 13, 347, 393, 15, 391, 307, 189, 381, 71, 163, 99, 467, 167, 433, 337, 257, 179, 47, 385, 23, 117, 369, 425, 207, 433, 301, 147, 333, 85, 221, 423, 49, 3, 43, 229, 227, 201, 383, 281, 229, 207, 21, 343, 251, 397, 173, 507, 421, 443, 399, 53, 345, 77, 385, 317, 155, 187, 269, 501, 19, 169, 235, 415, 61, 247, 183, 5, 257, 401, 451, 95, 455, 49, 489, 75, 459, 377, 87, 463, 155, 233, 115, 429, 211, 419, 143, 487, 195, 209, 461, 193, 157, 193, 363, 181, 271, 445, 381, 231, 135, 327, 403, 171, 197, 181, 343, 113, 313, 393, 311, 415, 267, 247, 425, 233, 289, 55, 39, 247, 327, 141, 5, 189, 183, 27, 337, 341, 327, 87, 429, 357, 265, 251, 437, 201, 29, 339, 257, 377, 17, 53, 327, 47, 375, 393, 369, 403, 125, 429, 257, 157, 217, 85, 267, 117, 337, 447, 219, 501, 41, 41, 193, 509, 131, 207, 505, 421, 149, 111, 177, 167, 223, 291, 91, 29, 305, 151, 177, 337, 183, 361, 435, 307, 507, 77, 181, 507, 315, 145, 423, 71, 103, 493, 271, 469, 339, 237, 437, 483, 31, 219, 61, 131, 391, 233, 219, 69, 57, 459, 225, 421, 7, 461, 111, 451, 277, 185, 193, 125, 251, 199, 73, 71, 7, 409, 417, 149, 193, 53, 437, 29, 467, 229, 31, 35, 75, 105, 503, 75, 317, 401, 367, 131, 365, 441, 433, 93, 377, 405, 465, 259, 283, 443, 143, 445, 3, 461, 329, 309, 77, 323, 155, 347, 45, 381, 315, 463, 207, 321, 157, 109, 479, 313, 345, 167, 439, 307, 235, 473, 79, 101, 245, 19, 381, 251, 35, 25, 107, 187, 115, 113, 321, 115, 445, 61, 77, 293, 405, 13, 53, 17, 171, 299, 41, 79, 3, 485, 331, 13, 257, 59, 201, 497, 81, 451, 199, 171, 81, 253, 365, 75, 451, 149, 483, 81, 453, 469, 485, 305, 163, 401, 15, 91, 3, 129, 35, 239, 355, 211, 387, 101, 299, 67, 375, 405, 357, 267, 363, 79, 83, 437, 457, 39, 97, 473, 289, 179, 57, 23, 49, 79, 71, 341, 287, 95, 229, 271, 475, 49, 241, 261, 495, 353, 381, 13, 291, 37, 251, 105, 399, 81, 89, 265, 507, 205, 145, 331, 129, 119, 503, 249, 1, 289, 463, 163, 443, 63, 123, 361, 261, 49, 429, 137, 355, 175, 507, 59, 277, 391, 25, 185, 381, 197, 39, 5, 429, 119, 247, 177, 329, 465, 421, 271, 467, 151, 45, 429, 137, 471, 11, 17, 409, 347, 199, 463, 177, 11, 51, 361, 95, 497, 163, 351, 127, 395, 511, 327, 353, 49, 105, 151, 321, 331, 329, 509, 107, 109, 303, 467, 287, 161, 45, 385, 289, 363, 331, 265, 407, 37, 433, 315, 343, 63, 51, 185, 71, 27, 267, 503, 239, 293, 245, 281, 297, 75, 461, 371, 129, 189, 189, 339, 287, 111, 111, 379, 93, 27, 185, 347, 337, 247, 507, 161, 231, 43, 499, 73, 327, 263, 331, 249, 493, 37, 25, 115, 3, 167, 197, 127, 357, 497, 103, 125, 191, 165, 55, 101, 95, 79, 351, 341, 43, 125, 135, 173, 289, 373, 133, 421, 241, 281, 213, 177, 363, 151, 227, 145, 363, 239, 431, 81, 397, 241, 67, 291, 255, 405, 421, 399, 75, 399, 105, 329, 41, 425, 7, 283, 375, 475, 427, 277, 209, 411, 3, 137, 195, 289, 509, 121, 55, 147, 275, 251, 19, 129, 285, 415, 487, 491, 193, 219, 403, 23, 97, 65, 285, 75, 21, 373, 261, 339, 239, 495, 415, 333, 107, 435, 297, 213, 149, 463, 199, 323, 45, 19, 301, 121, 499, 187, 229, 63, 425, 99, 281, 35, 125, 349, 87, 101, 59, 195, 511, 355, 73, 263, 243, 101, 165, 141, 11, 389, 219, 187, 449, 447, 393, 477, 305, 221, 51, 355, 209, 499, 479, 265, 377, 145, 411, 173, 11, 433, 483, 135, 385, 341, 89, 209, 391, 33, 395, 319, 451, 119, 341, 227, 375, 61, 331, 493, 411, 293, 47, 203, 375, 167, 395, 155, 5, 237, 361, 489, 127, 21, 345, 101, 371, 233, 431, 109, 119, 277, 125, 263, 73, 135, 123, 83, 123, 405, 69, 75, 287, 401, 23, 283, 393, 41, 379, 431, 11, 475, 505, 19, 365, 265, 271, 499, 489, 443, 165, 91, 83, 291, 319, 199, 107, 245, 389, 143, 137, 89, 125, 281, 381, 215, 131, 299, 249, 375, 455, 43, 73, 281, 217, 297, 229, 431, 357, 81, 357, 171, 451, 481, 13, 387, 491, 489, 439, 385, 487, 177, 393, 33, 71, 375, 443, 129, 407, 395, 127, 65, 333, 309, 119, 197, 435, 497, 373, 71, 379, 509, 387, 159, 265, 477, 463, 449, 47, 353, 249, 335, 505, 89, 141, 55, 235, 187, 87, 363, 93, 363, 101, 67, 215, 321, 331, 305, 261, 411, 491, 479, 65, 307, 469, 415, 131, 315, 487, 83, 455, 19, 113, 163, 503, 99, 499, 251, 239, 81, 167, 391, 255, 317, 363, 359, 395, 419, 307, 251, 267, 171, 461, 183, 465, 165, 163, 293, 477, 223, 403, 389, 97, 335, 357, 297, 19, 469, 501, 249, 85, 213, 311, 265, 379, 297, 283, 393, 449, 463, 289, 159, 289, 499, 407, 129, 137, 221, 43, 89, 403, 271, 75, 83, 445, 453, 389, 149, 143, 423, 499, 317, 445, 157, 137, 453, 163, 87, 23, 391, 119, 427, 323, 173, 89, 259, 377, 511, 249, 31, 363, 229, 353, 329, 493, 427, 57, 205, 389, 91, 83, 13, 219, 439, 45, 35, 371, 441, 17, 267, 501, 53, 25, 333, 17, 201, 475, 257, 417, 345, 381, 377, 55, 403, 77, 389, 347, 363, 211, 413, 419, 5, 167, 219, 201, 285, 425, 11, 77, 269, 489, 281, 403, 79, 425, 125, 81, 331, 437, 271, 397, 299, 475, 271, 249, 413, 233, 261, 495, 171, 69, 27, 409, 21, 421, 367, 81, 483, 255, 15, 219, 365, 497, 181, 75, 431, 99, 325, 407, 229, 281, 63, 83, 493, 5, 113, 15, 271, 37, 87, 451, 299, 83, 451, 311, 441, 47, 455, 47, 253, 13, 109, 369, 347, 11, 409, 275, 63, 441, 15}, /* [9][*] */ {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, 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, 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, 0, 0, 0, 0, 519, 307, 931, 1023, 517, 771, 151, 1023, 539, 725, 45, 927, 707, 29, 125, 371, 275, 279, 817, 389, 453, 989, 1015, 29, 169, 743, 99, 923, 981, 181, 693, 309, 227, 111, 219, 897, 377, 425, 609, 227, 19, 221, 143, 581, 147, 919, 127, 725, 793, 289, 411, 835, 921, 957, 443, 349, 813, 5, 105, 457, 393, 539, 101, 197, 697, 27, 343, 515, 69, 485, 383, 855, 693, 133, 87, 743, 747, 475, 87, 469, 763, 721, 345, 479, 965, 527, 121, 271, 353, 467, 177, 245, 627, 113, 357, 7, 691, 725, 355, 889, 635, 737, 429, 545, 925, 357, 873, 187, 351, 677, 999, 921, 477, 233, 765, 495, 81, 953, 479, 89, 173, 473, 131, 961, 411, 291, 967, 65, 511, 13, 805, 945, 369, 827, 295, 163, 835, 259, 207, 331, 29, 315, 999, 133, 967, 41, 117, 677, 471, 717, 881, 755, 351, 723, 259, 879, 455, 721, 289, 149, 199, 805, 987, 851, 423, 597, 129, 11, 733, 549, 153, 285, 451, 559, 377, 109, 357, 143, 693, 615, 677, 701, 475, 767, 85, 229, 509, 547, 151, 389, 711, 785, 657, 319, 509, 99, 1007, 775, 359, 697, 677, 85, 497, 105, 615, 891, 71, 449, 835, 609, 377, 693, 665, 627, 215, 911, 503, 729, 131, 19, 895, 199, 161, 239, 633, 1013, 537, 255, 23, 149, 679, 1021, 595, 199, 557, 659, 251, 829, 727, 439, 495, 647, 223, 949, 625, 87, 481, 85, 799, 917, 769, 949, 739, 115, 499, 945, 547, 225, 1015, 469, 737, 495, 353, 103, 17, 665, 639, 525, 75, 447, 185, 43, 729, 577, 863, 735, 317, 99, 17, 477, 893, 537, 519, 1017, 375, 297, 325, 999, 353, 343, 729, 135, 489, 859, 267, 141, 831, 141, 893, 249, 807, 53, 613, 131, 547, 977, 131, 999, 175, 31, 341, 739, 467, 675, 241, 645, 247, 391, 583, 183, 973, 433, 367, 131, 467, 571, 309, 385, 977, 111, 917, 935, 473, 345, 411, 313, 97, 149, 959, 841, 839, 669, 431, 51, 41, 301, 247, 1015, 377, 329, 945, 269, 67, 979, 581, 643, 823, 557, 91, 405, 117, 801, 509, 347, 893, 303, 227, 783, 555, 867, 99, 703, 111, 797, 873, 541, 919, 513, 343, 319, 517, 135, 871, 917, 285, 663, 301, 15, 763, 89, 323, 757, 317, 807, 309, 1013, 345, 499, 279, 711, 915, 411, 281, 193, 739, 365, 315, 375, 809, 469, 487, 621, 857, 975, 537, 939, 585, 129, 625, 447, 129, 1017, 133, 83, 3, 415, 661, 53, 115, 903, 49, 79, 55, 385, 261, 345, 297, 199, 385, 617, 25, 515, 275, 849, 401, 471, 377, 661, 535, 505, 939, 465, 225, 929, 219, 955, 659, 441, 117, 527, 427, 515, 287, 191, 33, 389, 197, 825, 63, 417, 949, 35, 571, 9, 131, 609, 439, 95, 19, 569, 893, 451, 397, 971, 801, 125, 471, 187, 257, 67, 949, 621, 453, 411, 621, 955, 309, 783, 893, 597, 377, 753, 145, 637, 941, 593, 317, 555, 375, 575, 175, 403, 571, 555, 109, 377, 931, 499, 649, 653, 329, 279, 271, 647, 721, 665, 429, 957, 803, 767, 425, 477, 995, 105, 495, 575, 687, 385, 227, 923, 563, 723, 481, 717, 111, 633, 113, 369, 955, 253, 321, 409, 909, 367, 33, 967, 453, 863, 449, 539, 781, 911, 113, 7, 219, 725, 1015, 971, 1021, 525, 785, 873, 191, 893, 297, 507, 215, 21, 153, 645, 913, 755, 371, 881, 113, 903, 225, 49, 587, 201, 927, 429, 599, 513, 97, 319, 331, 833, 325, 887, 139, 927, 399, 163, 307, 803, 169, 1019, 869, 537, 907, 479, 335, 697, 479, 353, 769, 787, 1023, 855, 493, 883, 521, 735, 297, 1011, 991, 879, 855, 591, 415, 917, 375, 453, 553, 189, 841, 339, 211, 601, 57, 765, 745, 621, 209, 875, 639, 7, 595, 971, 263, 1009, 201, 23, 77, 621, 33, 535, 963, 661, 523, 263, 917, 103, 623, 231, 47, 301, 549, 337, 675, 189, 357, 1005, 789, 189, 319, 721, 1005, 525, 675, 539, 191, 813, 917, 51, 167, 415, 579, 755, 605, 721, 837, 529, 31, 327, 799, 961, 279, 409, 847, 649, 241, 285, 545, 407, 161, 591, 73, 313, 811, 17, 663, 269, 261, 37, 783, 127, 917, 231, 577, 975, 793, 921, 343, 751, 139, 221, 79, 817, 393, 545, 11, 781, 71, 1, 699, 767, 917, 9, 107, 341, 587, 903, 965, 599, 507, 843, 739, 579, 397, 397, 325, 775, 565, 925, 75, 55, 979, 931, 93, 957, 857, 753, 965, 795, 67, 5, 87, 909, 97, 995, 271, 875, 671, 613, 33, 351, 69, 811, 669, 729, 401, 647, 241, 435, 447, 721, 271, 745, 53, 775, 99, 343, 451, 427, 593, 339, 845, 243, 345, 17, 573, 421, 517, 971, 499, 435, 769, 75, 203, 793, 985, 343, 955, 735, 523, 659, 703, 303, 421, 951, 405, 631, 825, 735, 433, 841, 485, 49, 749, 107, 669, 211, 497, 143, 99, 57, 277, 969, 107, 397, 563, 551, 447, 381, 187, 57, 405, 731, 769, 923, 955, 915, 737, 595, 341, 253, 823, 197, 321, 315, 181, 885, 497, 159, 571, 981, 899, 785, 947, 217, 217, 135, 753, 623, 565, 717, 903, 581, 955, 621, 361, 869, 87, 943, 907, 853, 353, 335, 197, 771, 433, 743, 195, 91, 1023, 63, 301, 647, 205, 485, 927, 1003, 987, 359, 577, 147, 141, 1017, 701, 273, 89, 589, 487, 859, 343, 91, 847, 341, 173, 287, 1003, 289, 639, 983, 685, 697, 35, 701, 645, 911, 501, 705, 873, 763, 745, 657, 559, 699, 315, 347, 429, 197, 165, 955, 859, 167, 303, 833, 531, 473, 635, 641, 195, 589, 821, 205, 3, 635, 371, 891, 249, 123, 77, 623, 993, 401, 525, 427, 71, 655, 951, 357, 851, 899, 535, 493, 323, 1003, 343, 515, 859, 1017, 5, 423, 315, 1011, 703, 41, 777, 163, 95, 831, 79, 975, 235, 633, 723, 297, 589, 317, 679, 981, 195, 399, 1003, 121, 501, 155}, /* [10][*] */ {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, 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, 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, 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, 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, 7, 2011, 1001, 49, 825, 415, 1441, 383, 1581, 623, 1621, 1319, 1387, 619, 839, 217, 75, 1955, 505, 281, 1629, 1379, 53, 1111, 1399, 301, 209, 49, 155, 1647, 631, 129, 1569, 335, 67, 1955, 1611, 2021, 1305, 121, 37, 877, 835, 1457, 669, 1405, 935, 1735, 665, 551, 789, 1543, 1267, 1027, 1, 1911, 163, 1929, 67, 1975, 1681, 1413, 191, 1711, 1307, 401, 725, 1229, 1403, 1609, 2035, 917, 921, 1789, 41, 2003, 187, 67, 1635, 717, 1449, 277, 1903, 1179, 363, 1211, 1231, 647, 1261, 1029, 1485, 1309, 1149, 317, 1335, 171, 243, 271, 1055, 1601, 1129, 1653, 205, 1463, 1681, 1621, 197, 951, 573, 1697, 1265, 1321, 1805, 1235, 1853, 1307, 945, 1197, 1411, 833, 273, 1517, 1747, 1095, 1345, 869, 57, 1383, 221, 1713, 335, 1751, 1141, 839, 523, 1861, 1105, 389, 1177, 1877, 805, 93, 1591, 423, 1835, 99, 1781, 1515, 1909, 1011, 303, 385, 1635, 357, 973, 1781, 1707, 1363, 1053, 649, 1469, 623, 1429, 1241, 1151, 1055, 503, 921, 3, 349, 1149, 293, 45, 303, 877, 1565, 1583, 1001, 663, 1535, 395, 1141, 1481, 1797, 643, 1507, 465, 2027, 1695, 367, 937, 719, 545, 1991, 83, 819, 239, 1791, 1461, 1647, 1501, 1161, 1629, 139, 1595, 1921, 1267, 1415, 509, 347, 777, 1083, 363, 269, 1015, 1809, 1105, 1429, 1471, 2019, 381, 2025, 1223, 827, 1733, 887, 1321, 803, 1951, 1297, 1995, 833, 1107, 1135, 1181, 1251, 983, 1389, 1565, 273, 137, 71, 735, 1005, 933, 67, 1471, 551, 457, 1667, 1729, 919, 285, 1629, 1815, 653, 1919, 1039, 531, 393, 1411, 359, 221, 699, 1485, 471, 1357, 1715, 595, 1677, 153, 1903, 1281, 215, 781, 543, 293, 1807, 965, 1695, 443, 1985, 321, 879, 1227, 1915, 839, 1945, 1993, 1165, 51, 557, 723, 1491, 817, 1237, 947, 1215, 1911, 1225, 1965, 1889, 1503, 1177, 73, 1767, 303, 177, 1897, 1401, 321, 921, 217, 1779, 327, 1889, 333, 615, 1665, 1825, 1639, 237, 1205, 361, 129, 1655, 983, 1089, 1171, 401, 677, 643, 749, 303, 1407, 1873, 1579, 1491, 1393, 1247, 789, 763, 49, 5, 1607, 1891, 735, 1557, 1909, 1765, 1777, 1127, 813, 695, 97, 731, 1503, 1751, 333, 769, 865, 693, 377, 1919, 957, 1359, 1627, 1039, 1783, 1065, 1665, 1917, 1947, 991, 1997, 841, 459, 221, 327, 1595, 1881, 1269, 1007, 129, 1413, 475, 1105, 791, 1983, 1359, 503, 691, 659, 691, 343, 1375, 1919, 263, 1373, 603, 1383, 297, 781, 145, 285, 767, 1739, 1715, 715, 317, 1333, 85, 831, 1615, 81, 1667, 1467, 1457, 1453, 1825, 109, 387, 1207, 2039, 213, 1351, 1329, 1173, 57, 1769, 951, 183, 23, 451, 1155, 1551, 2037, 811, 635, 1671, 1451, 863, 1499, 1673, 363, 1029, 1077, 1525, 277, 1023, 655, 665, 1869, 1255, 965, 277, 1601, 329, 1603, 1901, 395, 65, 1307, 2029, 21, 1321, 543, 1569, 1185, 1905, 1701, 413, 2041, 1697, 725, 1417, 1847, 411, 211, 915, 1891, 17, 1877, 1699, 687, 1089, 1973, 1809, 851, 1495, 1257, 63, 1323, 1307, 609, 881, 1543, 177, 617, 1505, 1747, 1537, 925, 183, 77, 1723, 1877, 1703, 397, 459, 521, 257, 1177, 389, 1947, 1553, 1583, 1831, 261, 485, 289, 1281, 1543, 1591, 1123, 573, 821, 1065, 1933, 1373, 2005, 905, 207, 173, 1573, 1597, 573, 1883, 1795, 1499, 1743, 553, 335, 333, 1645, 791, 871, 1157, 969, 557, 141, 223, 1129, 1685, 423, 1069, 391, 99, 95, 1847, 531, 1859, 1833, 1833, 341, 237, 1997, 1799, 409, 431, 1917, 363, 335, 1039, 1085, 1657, 1975, 1527, 1111, 659, 389, 899, 595, 1439, 1861, 1979, 1569, 1087, 1009, 165, 1895, 1481, 1583, 29, 1193, 1673, 1075, 301, 1081, 1377, 1747, 1497, 1103, 1789, 887, 739, 1577, 313, 1367, 1299, 1801, 1131, 1837, 73, 1865, 1065, 843, 635, 55, 1655, 913, 1037, 223, 1871, 1161, 461, 479, 511, 1721, 1107, 389, 151, 35, 375, 1099, 937, 1185, 1701, 769, 639, 1633, 1609, 379, 1613, 2031, 685, 289, 975, 671, 1599, 1447, 871, 647, 99, 139, 1427, 959, 89, 117, 841, 891, 1959, 223, 1697, 1145, 499, 1435, 1809, 1413, 1445, 1675, 171, 1073, 1349, 1545, 2039, 1027, 1563, 859, 215, 1673, 1919, 1633, 779, 411, 1845, 1477, 1489, 447, 1545, 351, 1989, 495, 183, 1639, 1385, 1805, 1097, 1249, 1431, 1571, 591, 697, 1509, 709, 31, 1563, 165, 513, 1425, 1299, 1081, 145, 1841, 1211, 941, 609, 845, 1169, 1865, 1593, 347, 293, 1277, 157, 211, 93, 1679, 1799, 527, 41, 473, 563, 187, 1525, 575, 1579, 857, 703, 1211, 647, 709, 981, 285, 697, 163, 981, 153, 1515, 47, 1553, 599, 225, 1147, 381, 135, 821, 1965, 609, 1033, 983, 503, 1117, 327, 453, 2005, 1257, 343, 1649, 1199, 599, 1877, 569, 695, 1587, 1475, 187, 973, 233, 511, 51, 1083, 665, 1321, 531, 1875, 1939, 859, 1507, 1979, 1203, 1965, 737, 921, 1565, 1943, 819, 223, 365, 167, 1705, 413, 1577, 745, 1573, 655, 1633, 1003, 91, 1123, 477, 1741, 1663, 35, 715, 37, 1513, 815, 941, 1379, 263, 1831, 1735, 1111, 1449, 353, 1941, 1655, 1349, 877, 285, 1723, 125, 1753, 985, 723, 175, 439, 791, 1051, 1261, 717, 1555, 1757, 1777, 577, 1583, 1957, 873, 331, 1163, 313, 1, 1963, 963, 1905, 821, 1677, 185, 709, 545, 1723, 215, 1885, 1249, 583, 1803, 839, 885, 485, 413, 1767, 425, 129, 1035, 329, 1263, 1881, 1779, 1565, 359, 367, 453, 707, 1419, 831, 1889, 887, 1871, 1869, 747, 223, 1547, 1799, 433, 1441, 553, 2021, 1303, 1505, 1735, 1619, 1065, 1161, 2047, 347, 867, 881, 1447, 329, 781, 1065, 219, 589, 645, 1257, 1833, 749, 1841, 1733, 1179, 1191, 1025, 1639, 1955, 1423, 1685, 1711, 493, 549, 783, 1653, 397, 895, 233, 759, 1505, 677, 1449, 1573, 1297, 1821, 1691, 791, 289, 1187, 867, 1535, 575, 183}, /* [11][*] */ {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3915, 97, 3047, 937, 2897, 953, 127, 1201, 3819, 193, 2053, 3061, 3759, 1553, 2007, 2493, 603, 3343, 3751, 1059, 783, 1789, 1589, 283, 1093, 3919, 2747, 277, 2605, 2169, 2905, 721, 4069, 233, 261, 1137, 3993, 3619, 2881, 1275, 3865, 1299, 3757, 1193, 733, 993, 1153, 2945, 3163, 3179, 437, 271, 3493, 3971, 1005, 2615, 2253, 1131, 585, 2775, 2171, 2383, 2937, 2447, 1745, 663, 1515, 3767, 2709, 1767, 3185, 3017, 2815, 1829, 87, 3341, 793, 2627, 2169, 1875, 3745, 367, 3783, 783, 827, 3253, 2639, 2955, 3539, 1579, 2109, 379, 2939, 3019, 1999, 2253, 2911, 3733, 481, 1767, 1055, 4019, 4085, 105, 1829, 2097, 2379, 1567, 2713, 737, 3423, 3941, 2659, 3961, 1755, 3613, 1937, 1559, 2287, 2743, 67, 2859, 325, 2601, 1149, 3259, 2403, 3947, 2011, 175, 3389, 3915, 1315, 2447, 141, 359, 3609, 3933, 729, 2051, 1755, 2149, 2107, 1741, 1051, 3681, 471, 1055, 845, 257, 1559, 1061, 2803, 2219, 1315, 1369, 3211, 4027, 105, 11, 1077, 2857, 337, 3553, 3503, 3917, 2665, 3823, 3403, 3711, 2085, 1103, 1641, 701, 4095, 2883, 1435, 653, 2363, 1597, 767, 869, 1825, 1117, 1297, 501, 505, 149, 873, 2673, 551, 1499, 2793, 3277, 2143, 3663, 533, 3991, 575, 1877, 1009, 3929, 473, 3009, 2595, 3249, 675, 3593, 2453, 1567, 973, 595, 1335, 1715, 589, 85, 2265, 3069, 461, 1659, 2627, 1307, 1731, 1501, 1699, 3545, 3803, 2157, 453, 2813, 2047, 2999, 3841, 2361, 1079, 573, 69, 1363, 1597, 3427, 2899, 2771, 1327, 1117, 1523, 3521, 2393, 2537, 1979, 3179, 683, 2453, 453, 1227, 779, 671, 3483, 2135, 3139, 3381, 3945, 57, 1541, 3405, 3381, 2371, 2879, 1985, 987, 3017, 3031, 3839, 1401, 3749, 2977, 681, 1175, 1519, 3355, 907, 117, 771, 3741, 3337, 1743, 1227, 3335, 2755, 1909, 3603, 2397, 653, 87, 2025, 2617, 3257, 287, 3051, 3809, 897, 2215, 63, 2043, 1757, 3671, 297, 3131, 1305, 293, 3865, 3173, 3397, 2269, 3673, 717, 3041, 3341, 3595, 3819, 2871, 3973, 1129, 513, 871, 1485, 3977, 2473, 1171, 1143, 3063, 3547, 2183, 3993, 133, 2529, 2699, 233, 2355, 231, 3241, 611, 1309, 3829, 1839, 1495, 301, 1169, 1613, 2673, 243, 3601, 3669, 2813, 2671, 2679, 3463, 2477, 1795, 617, 2317, 1855, 1057, 1703, 1761, 2515, 801, 1205, 1311, 473, 3963, 697, 1221, 251, 381, 3887, 1761, 3093, 3721, 2079, 4085, 379, 3601, 3845, 433, 1781, 29, 1897, 1599, 2163, 75, 3475, 3957, 1641, 3911, 2959, 2833, 1279, 1099, 403, 799, 2183, 2699, 1711, 2037, 727, 289, 1785, 1575, 3633, 2367, 1261, 3953, 1735, 171, 1959, 2867, 859, 2951, 3211, 15, 1279, 1323, 599, 1651, 3951, 1011, 315, 3513, 3351, 1725, 3793, 2399, 287, 4017, 3571, 1007, 541, 3115, 429, 1585, 1285, 755, 1211, 3047, 915, 3611, 2697, 2129, 3669, 81, 3939, 2437, 915, 779, 3567, 3701, 2479, 3807, 1893, 3927, 2619, 2543, 3633, 2007, 3857, 3837, 487, 1769, 3759, 3105, 2727, 3155, 2479, 1341, 1657, 2767, 2541, 577, 2105, 799, 17, 2871, 3637, 953, 65, 69, 2897, 3841, 3559, 4067, 2335, 3409, 1087, 425, 2813, 1705, 1701, 1237, 821, 1375, 3673, 2693, 3925, 1541, 1871, 2285, 847, 4035, 1101, 2029, 855, 2733, 2503, 121, 2855, 1069, 3463, 3505, 1539, 607, 1349, 575, 2301, 2321, 1101, 333, 291, 2171, 4085, 2173, 2541, 1195, 925, 4039, 1379, 699, 1979, 275, 953, 1755, 1643, 325, 101, 2263, 3329, 3673, 3413, 1977, 2727, 2313, 1419, 887, 609, 2475, 591, 2613, 2081, 3805, 3435, 2409, 111, 3557, 3607, 903, 231, 3059, 473, 2959, 2925, 3861, 2043, 3887, 351, 2865, 369, 1377, 2639, 1261, 3625, 3279, 2201, 2949, 3049, 449, 1297, 897, 1891, 411, 2773, 749, 2753, 1825, 853, 2775, 3547, 3923, 3923, 987, 3723, 2189, 3877, 3577, 297, 2763, 1845, 3083, 2951, 483, 2169, 3985, 245, 3655, 3441, 1023, 235, 835, 3693, 3585, 327, 1003, 543, 3059, 2637, 2923, 87, 3617, 1031, 1043, 903, 2913, 2177, 2641, 3279, 389, 2009, 525, 4085, 3299, 987, 2409, 813, 2683, 373, 2695, 3775, 2375, 1119, 2791, 223, 325, 587, 1379, 2877, 2867, 3793, 655, 831, 3425, 1663, 1681, 2657, 1865, 3943, 2977, 1979, 2271, 3247, 1267, 1747, 811, 159, 429, 2001, 1195, 3065, 553, 1499, 3529, 1081, 2877, 3077, 845, 1793, 2409, 3995, 2559, 4081, 1195, 2955, 1117, 1409, 785, 287, 1521, 1607, 85, 3055, 3123, 2533, 2329, 3477, 799, 3683, 3715, 337, 3139, 3311, 431, 3511, 2299, 365, 2941, 3067, 1331, 1081, 1097, 2853, 2299, 495, 1745, 749, 3819, 619, 1059, 3559, 183, 3743, 723, 949, 3501, 733, 2599, 3983, 3961, 911, 1899, 985, 2493, 1795, 653, 157, 433, 2361, 3093, 3119, 3679, 2367, 1701, 1445, 1321, 2397, 1241, 3305, 3985, 2349, 4067, 3805, 3073, 2837, 1567, 3783, 451, 2441, 1181, 487, 543, 1201, 3735, 2517, 733, 1535, 2175, 3613, 3019}, /* [12][*] */ {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 2319, 653, 1379, 1675, 1951, 7075, 2087, 7147, 1427, 893, 171, 2019, 7235, 5697, 3615, 1961, 7517, 6849, 2893, 1883, 2863, 2173, 4543, 73, 381, 3893, 6045, 1643, 7669, 1027, 1549, 3983, 1985, 6589, 7497, 2745, 2375, 7047, 1117, 1171, 1975, 5199, 3915, 3695, 8113, 4303, 3773, 7705, 6855, 1675, 2245, 2817, 1719, 569, 1021, 2077, 5945, 1833, 2631, 4851, 6371, 833, 7987, 331, 1899, 8093, 6719, 6903, 5903, 5657, 5007, 2689, 6637, 2675, 1645, 1819, 689, 6709, 7717, 6295, 7013, 7695, 3705, 7069, 2621, 3631, 6571, 6259, 7261, 3397, 7645, 1115, 4753, 2047, 7579, 2271, 5403, 4911, 7629, 4225, 1209, 6955, 6951, 1829, 5579, 5231, 1783, 4285, 7425, 599, 5785, 3275, 5643, 2263, 657, 6769, 6261, 1251, 3249, 4447, 4111, 3991, 1215, 131, 4397, 3487, 7585, 5565, 7199, 3573, 7105, 7409, 1671, 949, 3889, 5971, 3333, 225, 3647, 5403, 3409, 7459, 6879, 5789, 6567, 5581, 4919, 1927, 4407, 8085, 4691, 611, 3005, 591, 753, 589, 171, 5729, 5891, 1033, 3049, 6567, 5257, 8003, 1757, 4489, 4923, 6379, 5171, 1757, 689, 3081, 1389, 4113, 455, 2761, 847, 7575, 5829, 633, 6629, 1103, 7635, 803, 6175, 6587, 2711, 3879, 67, 1179, 4761, 7281, 1557, 3379, 2459, 4273, 4127, 7147, 35, 3549, 395, 3735, 5787, 4179, 5889, 5057, 7473, 4713, 2133, 2897, 1841, 2125, 1029, 1695, 6523, 1143, 5105, 7133, 3351, 2775, 3971, 4503, 7589, 5155, 4305, 1641, 4717, 2427, 5617, 1267, 399, 5831, 4305, 4241, 3395, 3045, 4899, 1713, 171, 411, 7099, 5473, 5209, 1195, 1077, 1309, 2953, 7343, 4887, 3229, 6759, 6721, 6775, 675, 4039, 2493, 7511, 3269, 4199, 6625, 7943, 2013, 4145, 667, 513, 2303, 4591, 7941, 2741, 987, 8061, 3161, 5951, 1431, 831, 5559, 7405, 1357, 4319, 4235, 5421, 2559, 4415, 2439, 823, 1725, 6219, 4903, 6699, 5451, 349, 7703, 2927, 7809, 6179, 1417, 5987, 3017, 4983, 3479, 4525, 4643, 4911, 227, 5475, 2287, 5581, 6817, 1937, 1421, 4415, 7977, 1789, 3907, 6815, 6789, 6003, 5609, 4507, 337, 7427, 7943, 3075, 6427, 1019, 7121, 4763, 81, 3587, 2929, 1795, 8067, 2415, 1265, 4025, 5599, 4771, 3025, 2313, 6129, 7611, 6881, 5253, 4413, 7869, 105, 3173, 1629, 2537, 1023, 4409, 7209, 4413, 7107, 7469, 33, 1955, 2881, 5167, 6451, 4211, 179, 5573, 7879, 3387, 7759, 5455, 7157, 1891, 5683, 5689, 6535, 3109, 6555, 6873, 1249, 4251, 6437, 49, 2745, 1201, 7327, 4179, 6783, 623, 2779, 5963, 2585, 6927, 5333, 4033, 285, 7467, 4443, 4917, 3, 4319, 5517, 3449, 813, 5499, 2515, 5771, 3357, 2073, 4395, 4925, 2643, 7215, 5817, 1199, 1597, 1619, 7535, 4833, 609, 4797, 8171, 6847, 793, 6757, 8165, 3371, 2431, 5235, 4739, 7703, 7223, 6525, 5891, 5605, 4433, 3533, 5267, 5125, 5037, 225, 6717, 1121, 5741, 2013, 4327, 4839, 569, 5227, 7677, 4315, 2391, 5551, 859, 3627, 6377, 3903, 4311, 6527, 7573, 4905, 7731, 1909, 1555, 3279, 1949, 1887, 6675, 5509, 2033, 5473, 3539, 5033, 5935, 6095, 4761, 1771, 1271, 1717, 4415, 5083, 6277, 3147, 7695, 2461, 4783, 4539, 5833, 5583, 651, 1419, 2605, 5511, 3913, 5795, 2333, 2329, 4431, 3725, 6069, 2699, 7055, 6879, 1017, 3121, 2547, 4603, 2385, 6915, 6103, 5669, 7833, 2001, 4287, 6619, 955, 2761, 5711, 6291, 3415, 3909, 2841, 5627, 4939, 7671, 6059, 6275, 6517, 1931, 4583, 7301, 1267, 7509, 1435, 2169, 6939, 3515, 2985, 2787, 2123, 1969, 3307, 353, 4359, 7059, 5273, 5873, 6657, 6765, 6229, 3179, 1583, 6237, 2155, 371, 273, 7491, 3309, 6805, 3015, 6831, 7819, 713, 4747, 3935, 4109, 1311, 709, 3089, 7059, 4247, 2989, 1509, 4919, 1841, 3045, 3821, 6929, 4655, 1333, 6429, 6649, 2131, 5265, 1051, 261, 8057, 3379, 2179, 1993, 5655, 3063, 6381, 3587, 7417, 1579, 1541, 2107, 5085, 2873, 6141, 955, 3537, 2157, 841, 1999, 1465, 5171, 5651, 1535, 7235, 4349, 1263, 1453, 1005, 6893, 2919, 1947, 1635, 3963, 397, 969, 4569, 655, 6737, 2995, 7235, 7713, 973, 4821, 2377, 1673, 1, 6541} }; #endif nlopt-2.6.1/src/util/sobolseq.c000066400000000000000000000203751345435414600164330ustar00rootroot00000000000000/* Copyright (c) 2007 Massachusetts Institute of Technology * * 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. */ /* Generation of Sobol sequences in up to 1111 dimensions, based on the algorithms described in: P. Bratley and B. L. Fox, Algorithm 659, ACM Trans. Math. Soft. 14 (1), 88-100 (1988), as modified by: S. Joe and F. Y. Kuo, ACM Trans. Math. Soft 29 (1), 49-57 (2003). Note that the code below was written without even looking at the Fortran code from the TOMS paper, which is only semi-free (being under the restrictive ACM copyright terms). Then I went to the Fortran code and took out the table of primitive polynomials and starting direction #'s ... since this is just a table of numbers generated by a deterministic algorithm, it is not copyrightable. (Obviously, the format of these tables then necessitated some slight modifications to the code.) For the test integral of Joe and Kuo (see the main() program below), I get exactly the same results for integrals up to 1111 dimensions compared to the table of published numbers (to the 5 published significant digits). This is not to say that the authors above should not be credited for their clear description of the algorithm (and their tabulation of the critical numbers). Please cite them. Just that I needed a free/open-source implementation. */ #include #include #include "nlopt-util.h" #if defined(HAVE_STDINT_H) # include #endif #ifndef HAVE_UINT32_T # if SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long uint32_t; # elif SIZEOF_UNSIGNED_INT == 4 typedef unsigned int uint32_t; # else # error No 32-bit unsigned integer type # endif #endif typedef struct nlopt_soboldata_s { unsigned sdim; /* dimension of sequence being generated */ uint32_t *mdata; /* array of length 32 * sdim */ uint32_t *m[32]; /* more convenient pointers to mdata, of direction #s */ uint32_t *x; /* previous x = x_n, array of length sdim */ unsigned *b; /* position of fixed point in x[i] is after bit b[i] */ uint32_t n; /* number of x's generated so far */ } soboldata; /* Return position (0, 1, ...) of rightmost (least-significant) zero bit in n. * * This code uses a 32-bit version of algorithm to find the rightmost * one bit in Knuth, _The Art of Computer Programming_, volume 4A * (draft fascicle), section 7.1.3, "Bitwise tricks and * techniques." * * Assumes n has a zero bit, i.e. n < 2^32 - 1. * */ static unsigned rightzero32(uint32_t n) { #if defined(__GNUC__) && \ ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ > 3) return __builtin_ctz(~n); /* gcc builtin for version >= 3.4 */ #else const uint32_t a = 0x05f66a47; /* magic number, found by brute force */ static const unsigned decode[32] = { 0, 1, 2, 26, 23, 3, 15, 27, 24, 21, 19, 4, 12, 16, 28, 6, 31, 25, 22, 14, 20, 18, 11, 5, 30, 13, 17, 10, 29, 9, 8, 7 }; n = ~n; /* change to rightmost-one problem */ n = a * (n & (-n)); /* store in n to make sure mult. is 32 bits */ return decode[n >> 27]; #endif } /* generate the next term x_{n+1} in the Sobol sequence, as an array x[sdim] of numbers in (0,1). Returns 1 on success, 0 on failure (if too many #'s generated) */ static int sobol_gen(soboldata * sd, double *x) { unsigned c, b, i, sdim; if (sd->n == 4294967295U) return 0; /* n == 2^32 - 1 ... we would need to switch to a 64-bit version to generate more terms. */ c = rightzero32(sd->n++); sdim = sd->sdim; for (i = 0; i < sdim; ++i) { b = sd->b[i]; if (b >= c) { sd->x[i] ^= sd->m[c][i] << (b - c); x[i] = ((double) (sd->x[i])) / (1U << (b + 1)); } else { sd->x[i] = (sd->x[i] << (c - b)) ^ sd->m[c][i]; sd->b[i] = c; x[i] = ((double) (sd->x[i])) / (1U << (c + 1)); } } return 1; } #include "soboldata.h" static int sobol_init(soboldata * sd, unsigned sdim) { unsigned i, j; if (!sdim || sdim > MAXDIM) return 0; sd->mdata = (uint32_t *) malloc(sizeof(uint32_t) * (sdim * 32)); if (!sd->mdata) return 0; for (j = 0; j < 32; ++j) { sd->m[j] = sd->mdata + j * sdim; sd->m[j][0] = 1; /* special-case Sobol sequence */ } for (i = 1; i < sdim; ++i) { uint32_t a = sobol_a[i - 1]; unsigned d = 0, k; while (a) { ++d; a >>= 1; } d--; /* d is now degree of poly */ /* set initial values of m from table */ for (j = 0; j < d; ++j) sd->m[j][i] = sobol_minit[j][i - 1]; /* fill in remaining values using recurrence */ for (j = d; j < 32; ++j) { a = sobol_a[i - 1]; sd->m[j][i] = sd->m[j - d][i]; for (k = 0; k < d; ++k) { sd->m[j][i] ^= ((a & 1) * sd->m[j - d + k][i]) << (d - k); a >>= 1; } } } sd->x = (uint32_t *) malloc(sizeof(uint32_t) * sdim); if (!sd->x) { free(sd->mdata); return 0; } sd->b = (unsigned *) malloc(sizeof(unsigned) * sdim); if (!sd->b) { free(sd->x); free(sd->mdata); return 0; } for (i = 0; i < sdim; ++i) { sd->x[i] = 0; sd->b[i] = 0; } sd->n = 0; sd->sdim = sdim; return 1; } static void sobol_destroy(soboldata * sd) { free(sd->mdata); free(sd->x); free(sd->b); } /************************************************************************/ /* NLopt API to Sobol sequence creation, which hides soboldata structure behind an opaque pointer */ nlopt_sobol nlopt_sobol_create(unsigned sdim) { nlopt_sobol s = (nlopt_sobol) malloc(sizeof(soboldata)); if (!s) return NULL; if (!sobol_init(s, sdim)) { free(s); return NULL; } return s; } extern void nlopt_sobol_destroy(nlopt_sobol s) { if (s) { sobol_destroy(s); free(s); } } /* next vector x[sdim] in Sobol sequence, with each x[i] in (0,1) */ void nlopt_sobol_next01(nlopt_sobol s, double *x) { if (!sobol_gen(s, x)) { /* fall back on pseudo random numbers in the unlikely event that we exceed 2^32-1 points */ unsigned i; for (i = 0; i < s->sdim; ++i) x[i] = nlopt_urand(0.0, 1.0); } } /* next vector in Sobol sequence, scaled to (lb[i], ub[i]) interval */ void nlopt_sobol_next(nlopt_sobol s, double *x, const double *lb, const double *ub) { unsigned i, sdim; nlopt_sobol_next01(s, x); for (sdim = s->sdim, i = 0; i < sdim; ++i) x[i] = lb[i] + (ub[i] - lb[i]) * x[i]; } /* if we know in advance how many points (n) we want to compute, then adopt the suggestion of the Joe and Kuo paper, which in turn is taken from Acworth et al (1998), of skipping a number of points equal to the largest power of 2 smaller than n */ void nlopt_sobol_skip(nlopt_sobol s, unsigned n, double *x) { if (s) { unsigned k = 1; while (k * 2 < n) k *= 2; while (k-- > 0) sobol_gen(s, x); } } nlopt-2.6.1/src/util/sobolseq_test.c000066400000000000000000000051711345435414600174670ustar00rootroot00000000000000/* Copyright (c) 2007 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include "nlopt-util.h" #define MAXDIM 1111 /* test integrand from Joe and Kuo paper ... integrates to 1 */ static double testfunc(unsigned n, const double *x) { double f = 1; unsigned j; for (j = 1; j <= n; ++j) { double cj = pow((double) j, 0.3333333333333333333); f *= (fabs(4 * x[j - 1] - 2) + cj) / (1 + cj); } return f; } int main(int argc, char **argv) { unsigned n, j, i, sdim; static double x[MAXDIM]; double testint_sobol = 0, testint_rand = 0; nlopt_sobol s; if (argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } nlopt_init_genrand(time(NULL)); sdim = atoi(argv[1]); s = nlopt_sobol_create(sdim); n = atoi(argv[2]); nlopt_sobol_skip(s, n, x); for (j = 1; j <= n; ++j) { nlopt_sobol_next01(s, x); testint_sobol += testfunc(sdim, x); if (j < 100) { printf("x[%u]: %g", j, x[0]); for (i = 1; i < sdim; ++i) printf(", %g", x[i]); printf("\n"); } for (i = 0; i < sdim; ++i) x[i] = nlopt_urand(0., 1.); testint_rand += testfunc(sdim, x); } nlopt_sobol_destroy(s); printf("Test integral = %g using Sobol, %g using pseudorandom.\n", testint_sobol / n, testint_rand / n); printf(" error = %g using Sobol, %g using pseudorandom.\n", testint_sobol / n - 1, testint_rand / n - 1); return 0; } nlopt-2.6.1/src/util/stop.c000066400000000000000000000136361345435414600155730ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include #include "nlopt-util.h" /* utility routines to implement the various stopping criteria */ static int relstop(double vold, double vnew, double reltol, double abstol) { if (nlopt_isinf(vold)) return 0; return (fabs(vnew - vold) < abstol || fabs(vnew - vold) < reltol * (fabs(vnew) + fabs(vold)) * 0.5 || (reltol > 0 && vnew == vold)); /* catch vnew == vold == 0 */ } int nlopt_stop_ftol(const nlopt_stopping * s, double f, double oldf) { return (relstop(oldf, f, s->ftol_rel, s->ftol_abs)); } int nlopt_stop_f(const nlopt_stopping * s, double f, double oldf) { return (f <= s->minf_max || nlopt_stop_ftol(s, f, oldf)); } int nlopt_stop_x(const nlopt_stopping * s, const double *x, const double *oldx) { unsigned i; for (i = 0; i < s->n; ++i) if (!relstop(oldx[i], x[i], s->xtol_rel, s->xtol_abs[i])) return 0; return 1; } int nlopt_stop_dx(const nlopt_stopping * s, const double *x, const double *dx) { unsigned i; for (i = 0; i < s->n; ++i) if (!relstop(x[i] - dx[i], x[i], s->xtol_rel, s->xtol_abs[i])) return 0; return 1; } static double sc(double x, double smin, double smax) { return smin + x * (smax - smin); } /* some of the algorithms rescale x to a unit hypercube, so we need to scale back before we can compare to the tolerances */ int nlopt_stop_xs(const nlopt_stopping * s, const double *xs, const double *oldxs, const double *scale_min, const double *scale_max) { unsigned i; for (i = 0; i < s->n; ++i) if (!relstop(sc(oldxs[i], scale_min[i], scale_max[i]), sc(xs[i], scale_min[i], scale_max[i]), s->xtol_rel, s->xtol_abs[i])) return 0; return 1; } int nlopt_stop_evals(const nlopt_stopping * s) { return (s->maxeval > 0 && *(s->nevals_p) >= s->maxeval); } int nlopt_stop_time_(double start, double maxtime) { return (maxtime > 0 && nlopt_seconds() - start >= maxtime); } int nlopt_stop_time(const nlopt_stopping * s) { return nlopt_stop_time_(s->start, s->maxtime); } int nlopt_stop_evalstime(const nlopt_stopping * stop) { return nlopt_stop_evals(stop) || nlopt_stop_time(stop); } int nlopt_stop_forced(const nlopt_stopping * stop) { return stop->force_stop && *(stop->force_stop); } unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint * c) { unsigned i, count = 0; for (i = 0; i < p; ++i) count += c[i].m; return count; } unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint * c) { unsigned i, max_dim = 0; for (i = 0; i < p; ++i) if (c[i].m > max_dim) max_dim = c[i].m; return max_dim; } void nlopt_eval_constraint(double *result, double *grad, const nlopt_constraint * c, unsigned n, const double *x) { if (c->f) result[0] = c->f(n, x, grad, c->f_data); else c->mf(c->m, result, n, x, grad, c->f_data); } char *nlopt_vsprintf(char *p, const char *format, va_list ap) { size_t len = strlen(format) + 128; int ret; p = (char *) realloc(p, len); if (!p) abort(); /* TODO: check HAVE_VSNPRINTF, and fallback to vsprintf otherwise */ while ((ret = vsnprintf(p, len, format, ap)) < 0 || (size_t) ret >= len) { /* C99 vsnprintf returns the required number of bytes (excluding \0) if the buffer is too small; older versions (e.g. MS) return -1 */ len = ret >= 0 ? (size_t) (ret + 1) : (len * 3) >> 1; p = (char *) realloc(p, len); if (!p) abort(); } return p; } void nlopt_stop_msg(const nlopt_stopping * s, const char *format, ...) { va_list ap; if (s->stop_msg) { va_start(ap, format); *(s->stop_msg) = nlopt_vsprintf(*(s->stop_msg), format, ap); va_end(ap); } } /*************************************************************************/ int nlopt_isinf(double x) { return (fabs(x) >= HUGE_VAL * 0.99) #if defined(HAVE_ISINF) || isinf(x) #else || (!nlopt_isnan(x) && nlopt_isnan(x - x)) #endif ; } int nlopt_isfinite(double x) { return (fabs(x) <= DBL_MAX) #if defined(HAVE_ISFINITE) || isfinite(x) #elif defined(_WIN32) || _finite(x) #endif ; } int nlopt_istiny(double x) { if (x == 0.0) return 1; else { #if defined(HAVE_FPCLASSIFY) return fpclassify(x) == FP_SUBNORMAL; #elif defined(_WIN32) int c = _fpclass(x); return c == _FPCLASS_ND || c == _FPCLASS_PD; #else return fabs(x) < 2.2250738585072014e-308; /* assume IEEE 754 double */ #endif } } int nlopt_isnan(double x) { #if defined(HAVE_ISNAN) return isnan(x); #elif defined(_WIN32) return _isnan(x); #else return (x != x); /* might fail with aggressive optimization */ #endif } nlopt-2.6.1/src/util/timer.c000066400000000000000000000060411345435414600157160ustar00rootroot00000000000000/* Copyright (c) 2007-2014 Massachusetts Institute of Technology * * 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. */ #include "nlopt-util.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #if defined(_WIN32) || defined(__WIN32__) # include #endif /* return time in seconds since some arbitrary point in the past */ double nlopt_seconds(void) { static THREADLOCAL int start_inited = 0; /* whether start time has been initialized */ #if defined(HAVE_GETTIMEOFDAY) static THREADLOCAL struct timeval start; struct timeval tv; if (!start_inited) { start_inited = 1; gettimeofday(&start, NULL); } gettimeofday(&tv, NULL); return (tv.tv_sec - start.tv_sec) + 1.e-6 * (tv.tv_usec - start.tv_usec); #elif defined(HAVE_TIME) return time(NULL); #elif defined(_WIN32) || defined(__WIN32__) static THREADLOCAL ULONGLONG start; FILETIME ft; if (!start_inited) { start_inited = 1; GetSystemTimeAsFileTime(&ft); start = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime; } GetSystemTimeAsFileTime(&ft); return 100e-9 * (((((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime) - start); #else /* use clock() as a fallback... this is somewhat annoying because clock() may wrap around with a fairly short period */ static THREADLOCAL clock_t start; if (!start_inited) { start_inited = 1; start = clock(); } return (clock() - start) * 1.0 / CLOCKS_PER_SEC; #endif } /* number based on time for use as random seed */ unsigned long nlopt_time_seed(void) { #if defined(HAVE_GETTIMEOFDAY) struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec ^ tv.tv_usec); #elif defined(HAVE_TIME) return time(NULL); #elif defined(_WIN32) || defined(__WIN32__) FILETIME ft; GetSystemTimeAsFileTime(&ft); return ft.dwHighDateTime ^ ft.dwLowDateTime; #else return clock(); #endif } nlopt-2.6.1/test/000077500000000000000000000000001345435414600136445ustar00rootroot00000000000000nlopt-2.6.1/test/CMakeLists.txt000066400000000000000000000054101345435414600164040ustar00rootroot00000000000000add_custom_target (tests) # have to add timer.c and mt19937ar.c as symbols are declared extern add_executable (testopt testfuncs.c testfuncs.h testopt.c ${PROJECT_SOURCE_DIR}/src/util/timer.c ${PROJECT_SOURCE_DIR}/src/util/mt19937ar.c ${PROJECT_SOURCE_DIR}/src/util/nlopt-getopt.c) target_link_libraries (testopt ${nlopt_lib}) if (NLOPT_CXX) set_target_properties(testopt PROPERTIES LINKER_LANGUAGE CXX) endif () target_include_directories (testopt PRIVATE ${NLOPT_PRIVATE_INCLUDE_DIRS}) add_dependencies (tests testopt) foreach (algo_index RANGE 29)# 43 foreach (obj_index RANGE 1)# 21 set (enable_ TRUE) # cxx stogo if (NOT NLOPT_CXX) if (algo_index STREQUAL 8 OR algo_index STREQUAL 9) set (enable_ FALSE) endif () endif () # cxx11 ags if (NOT NLOPT_CXX11 AND algo_index STREQUAL 43) set (enable_ FALSE) endif () # L-BFGS if (algo_index STREQUAL 10) set (enable_ FALSE) endif () # LN_NEWUOA_BOUND timeouts on msvc if (algo_index STREQUAL 27) set (enable_ FALSE) endif () if (enable_) add_test (NAME testopt_algo${algo_index}_obj${obj_index} COMMAND testopt -r 0 -a ${algo_index} -o ${obj_index}) if (CMAKE_HOST_SYSTEM_NAME MATCHES Windows) set_tests_properties (testopt_algo${algo_index}_obj${obj_index} PROPERTIES ENVIRONMENT "PATH=${PROJECT_BINARY_DIR}\\${CMAKE_BUILD_TYPE};$ENV{PATH}") # to load dll endif () endif () endforeach () endforeach () if (NUMPY_FOUND AND PYTHONLIBS_FOUND AND (SWIG_FOUND OR (EXISTS ${PROJECT_SOURCE_DIR}/src/swig/nlopt-python.cpp))) set (PYINSTALLCHECK_ENVIRONMENT "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/src/swig" "PYTHONPATH=${PROJECT_BINARY_DIR}/src/swig" ) add_test (NAME test_python COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/t_python.py) set_tests_properties (test_python PROPERTIES ENVIRONMENT "${PYINSTALLCHECK_ENVIRONMENT}") endif () if (OCTAVE_FOUND) add_test (NAME test_octave COMMAND ${OCTAVE_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/t_octave.m ${PROJECT_SOURCE_DIR}/src/octave ${PROJECT_BINARY_DIR}/src/octave) endif () if (GUILE_FOUND AND ((SWIG_FOUND AND SWIG_VERSION VERSION_GREATER 2.0.9) OR (EXISTS ${PROJECT_SOURCE_DIR}/src/swig/nlopt-guile.cpp))) set (GUILECHECK_ENVIRONMENT "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/src/swig" "GUILE_LOAD_PATH=${PROJECT_BINARY_DIR}/src/swig" ) add_test (NAME test_guile COMMAND ${GUILE_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/t_guile.scm) set_tests_properties (test_guile PROPERTIES ENVIRONMENT "${GUILECHECK_ENVIRONMENT}") endif () if (NLOPT_FORTRAN) add_executable (t_fortran t_fortran.f90) target_link_libraries (t_fortran ${nlopt_lib}) add_test (NAME test_fortran COMMAND t_fortran) endif () nlopt-2.6.1/test/box.c000066400000000000000000000125731345435414600146100ustar00rootroot00000000000000#include #include #include "nlopt.h" /****************************************************************************/ /* test function from M. J. Box, "A new method of constrained optimization and a comparison with other methods," Computer J. 8 (1), 42-52 (1965) */ int testfuncs_verbose = 1; int testfuncs_counter = 0; static double testfuncs_status(int n, const double *x, double f) { ++testfuncs_counter; if (testfuncs_verbose) { int i; printf("f_%d (%g", testfuncs_counter, x[0]); for (i = 1; i < n; ++i) printf(", %g", x[i]); printf(") = %g\n", f); } return f; } #define RETURN(f) return testfuncs_status(n, x, f); static const double k1 = -145421.402, k2 = 2931.1506, k3 = -40.427932, k4 = 5106.192, k5 = 15711.36, k6 = -161622.577, k7 = 4176.15328, k8 = 2.8260078, k9 = 9200.476, k10 = 13160.295, k11 = -21686.9194, k12 = 123.56928, k13 = -21.1188894, k14 = 706.834, k15 = 2898.573, k16 = 28298.388, k17 = 60.81096, k18 = 31.242116, k19 = 329.574, k20 = -2882.082, k21 = 74095.3845, k22 = -306.262544, k23 = 16.243649, k24 = -3094.252, k25 = -5566.2628, k26 = -26237, k27 = 99, k28 = -0.42, k29 = 1300, k30 = 2100, k31 = 925548.252, k32 = -61968.8432, k33 = 23.3088196, k34 = -27096.648, k35 = -50843.766; static double box(int n, const double *x, double *grad, void *data) { double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; double b, x6, y1, y2, y3, y4, u; const double a0 = 9, a1 = 15, a2 = 50, a3 = 9.583, a4 = 20, a5 = 15, a6 = 6, a7 = 0.75; b = x2 + 0.01 * x3; x6 = (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5) * x1; y1 = k6 + k7 * x2 + k8 * x3 + k9 * x4 + k10 * x5; y2 = k11 + k12 * x2 + k13 * x3 + k14 * x4 + k15 * x5; y3 = k16 + k17 * x2 + k18 * x3 + k19 * x4 + k20 * x5; y4 = k21 + k22 * x2 + k23 * x3 + k24 * x4 + k25 * x5; u = a2 * y1 + a3 * y2 + a4 * y3 + a5 * y4 + 7840 * a6 - 100000 * a0 - 50800 * b * a7 + k31 + k32 * x2 + k33 * x3 + k34 * x4 + k35 * x5; if (grad) { int i; grad[0] = u + a1 * (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5); grad[1] = x1 * (a2 * k7 + a3 * k12 + a4 * k17 + a5 * k22 - 50800 * a7 + k32) + a1 * (k2 * x1); grad[2] = x1 * (a2 * k8 + a3 * k13 + a4 * k18 + a5 * k23 - 50800 * a7 * 0.01) + a1 * x1 * k3; grad[3] = x1 * (a2 * k9 + a3 * k14 + a4 * k19 + a5 * k24) + a1 * x1 * k4; grad[4] = x1 * (a2 * k10 + a3 * k15 + a4 * k20 + a5 * k25) + a1 * x1 * k5; for (i = 0; i < 5; ++i) grad[i] = -grad[i]; } RETURN(-(u * x1 - 24345 + a1 * x6)); } static double box_constraint(int n, const double *x, double *grad, void *data) { int which_constraint = *((int *) data); double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; double x6, y1, y2, y3, x7, x8; int i; x6 = (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5) * x1; y1 = k6 + k7 * x2 + k8 * x3 + k9 * x4 + k10 * x5; y2 = k11 + k12 * x2 + k13 * x3 + k14 * x4 + k15 * x5; y3 = k16 + k17 * x2 + k18 * x3 + k19 * x4 + k20 * x5; x7 = (y1 + y2 + y3) * x1; x8 = (k26 + k27 * x2 + k28 * x3 + k29 * x4 + k30 * x5) * x1 + x6 + x7; if (grad) { grad[0] = grad[1] = grad[2] = grad[3] = grad[4] = 0; if (which_constraint != 2 && which_constraint != -2) { /* grad x6 */ grad[0] += (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5); grad[1] += x1 * k2; grad[2] += x1 * k3; grad[3] += x1 * k4; grad[4] += x1 * k5; } if (which_constraint != 1 && which_constraint != -1) { /* grad x7 */ grad[0] += (y1 + y2 + y3); grad[1] += x1 * (k7 + k12 + k17); grad[2] += x1 * (k8 + k13 + k18); grad[3] += x1 * (k9 + k14 + k19); grad[4] += x1 * (k10 + k15 + k20); } if (which_constraint == 3 || which_constraint == -3) { /* grad (x8 - x6 - x7) */ grad[0] += k26 + k27 * x2 + k28 * x3 + k29 * x4 + k30 * x5; grad[1] += x1 * k27; grad[2] += x1 * k28; grad[3] += x1 * k29; grad[4] += x1 * k30; } } if (which_constraint == -1) { if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; return -x6; } else if (which_constraint == 1) { return x6 - 294000; } else if (which_constraint == -2) { if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; return -x7; } else if (which_constraint == 2) { return x7 - 294000; } else if (which_constraint == -3) { if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; return -x8; } else if (which_constraint == 3) { return x8 - 277200; } return 0; } int main(void) { const double box_lb[5] = { 0, 1.2, 20, 9, 6.5 }; const double box_ub[5] = { HUGE_VAL, 2.4, 60, 9.3, 7.0 }; const double box_xmin[5] = { 4.53743, 2.4, 60, 9.3, 7.0 }; int cdata[6] = { -1, 1, -2, 2, -3, 3 }; double x[5] = { 2.52, 2, 37.5, 9.25, 6.8 }; double minf; nlopt_minimize_constrained(NLOPT_LN_COBYLA, 5, box, NULL, 6, box_constraint, cdata, sizeof(int), box_lb, box_ub, x, &minf, -HUGE_VAL, 1e-10, 0, 0, NULL, 0, 0); printf("found f(%g,%g,%g,%g,%g) = %0.8f after %d iters\n", x[0], x[1], x[2], x[3], x[4], minf, testfuncs_counter); return 0; } nlopt-2.6.1/test/lorentzfit.c000066400000000000000000000053471345435414600162210ustar00rootroot00000000000000#include #include #include #include typedef struct { int N; double *x, *y; /* length N; */ } lorentzdata; static double sqr(double x) { return x * x; } static int count = 0; static double lorentzerr(int n, const double *p, double *grad, void *data) { lorentzdata *d = (lorentzdata *) data; int N = d->N; const double *xs = d->x; const double *ys = d->y; double val = 0; int i, j; for (i = 0; i < N; ++i) { double x = xs[i], y = ys[i]; double lorsum = 0; for (j = 0; j < n; j += 3) { double A = p[j + 0]; double w = p[j + 1]; double G = p[j + 2]; double lor = A / (sqr(x - w) + G * G); lorsum += lor; } val += sqr(y - lorsum); if (grad) for (j = 0; j < n; j += 3) { double A = p[j + 0]; double w = p[j + 1]; double G = p[j + 2]; double deninv = 1.0 / (sqr(x - w) + G * G); grad[j + 0] += -2 * (y - lorsum) * deninv; grad[j + 1] += 4 * A * (w - x) * (y - lorsum) * sqr(deninv); grad[j + 2] += 4 * A * G * (y - lorsum) * sqr(deninv); } } ++count; // printf("%d: f(%g,%g,%g) = %g\n", count, p[0],p[1],p[2], val); return val; } extern double nlopt_urand(double a, double b); int main(void) { lorentzdata d; int i; double A = 1, w = 0, G = 1, noise = 0.01; double lb[3] = { -HUGE_VAL, -HUGE_VAL, 0 }; double ub[3] = { HUGE_VAL, HUGE_VAL, HUGE_VAL }; double p[3] = { 0, 1, 2 }, minf; nlopt_srand_time(); d.N = 200; d.x = (double *) malloc(sizeof(double) * d.N * 2); d.y = d.x + d.N; for (i = 0; i < d.N; ++i) { d.x[i] = nlopt_urand(-0.5, 0.5) * 8 * G + w; d.y[i] = 2 * noise * nlopt_urand(-0.5, 0.5) + A / (sqr(d.x[i] - w) + G * G); } nlopt_minimize(NLOPT_LN_NEWUOA_BOUND, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); count = 0; nlopt_minimize(NLOPT_LN_COBYLA, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); count = 0; nlopt_minimize(NLOPT_LN_NELDERMEAD, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); count = 0; nlopt_minimize(NLOPT_LN_SBPLX, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); return 0; } nlopt-2.6.1/test/t_fortran.f90000066400000000000000000000026161345435414600161670ustar00rootroot00000000000000program main external myfunc, myconstraint double precision lb(2) integer*8 opt double precision d1(2), d2(2) double precision x(2), minf integer ires include 'nlopt.f' opt=0 call nlo_create(opt, NLOPT_LD_MMA, 2) call nlo_get_lower_bounds(ires, opt, lb) lb(2) = 0.0 call nlo_set_lower_bounds(ires, opt, lb) call nlo_set_min_objective(ires, opt, myfunc, 0) d1(1) = 2. d1(2) = 0. call nlo_add_inequality_constraint(ires, opt, myconstraint, d1, 1.D-8) d2(1) = -1. d2(2) = 1. call nlo_add_inequality_constraint(ires, opt, myconstraint, d2, 1.D-8) call nlo_set_xtol_rel(ires, opt, 1.D-4) x(1) = 1.234 x(2) = 5.678 call nlo_optimize(ires, opt, x, minf) if (ires.lt.0) then write(*,*) 'nlopt failed!' stop 1 else write(*,*) 'found min at ', x(1), x(2) write(*,*) 'min val = ', minf endif call nlo_destroy(opt) end subroutine myfunc(val, n, x, grad, need_gradient, f_data) double precision val, x(n), grad(n) integer n, need_gradient if (need_gradient.ne.0) then grad(1) = 0.0 grad(2) = 0.5 / dsqrt(x(2)) endif val = dsqrt(x(2)) end subroutine myconstraint(val, n, x, grad, need_gradient, d) integer need_gradient double precision val, x(n), grad(n), d(2), a, b a = d(1) b = d(2) if (need_gradient.ne.0) then grad(1) = 3. * a * (a*x(1) + b)**2 grad(2) = -1.0 endif val = (a*x(1) + b)**3 - x(2) end nlopt-2.6.1/test/t_guile.scm000066400000000000000000000022641345435414600160040ustar00rootroot00000000000000(use-modules (nlopt)) (define (myfunc x grad) (if grad (begin (vector-set! grad 0 0.0) (vector-set! grad 1 (/ 0.5 (sqrt (vector-ref x 1)))))) (sqrt (vector-ref x 1))) (define (myconstraint x grad a b) (let ((x0 (vector-ref x 0)) (x1 (vector-ref x 1))) (if grad (begin (vector-set! grad 0 (* 3 a (expt (+ (* a x0) b) 2))) (vector-set! grad 1 -1.0))) (- (expt (+ (* a x0) b) 3) x1))) (define opt (new-nlopt-opt NLOPT-LD-MMA 2)) (nlopt-opt-set-lower-bounds opt (vector (- (inf)) 0)) (nlopt-opt-set-min-objective opt myfunc) (nlopt-opt-add-inequality-constraint opt (lambda (x grad) (myconstraint x grad 2 0)) 1e-8) (nlopt-opt-add-inequality-constraint opt (lambda (x grad) (myconstraint x grad -1 1)) 1e-8) (nlopt-opt-set-xtol-rel opt 1e-4) (define x (nlopt-opt-optimize opt (vector 1.234 5.678))) (define minf (nlopt-opt-last-optimum-value opt)) (define result (nlopt-opt-last-optimize-result opt)) (display "x=") (display x) (newline) (display "minf=") (display minf) (newline) nlopt-2.6.1/test/t_octave.m000066400000000000000000000013511345435414600156260ustar00rootroot00000000000000 arg_list = argv (); for i = 1:nargin loadpath = arg_list{i}; printf ('-- adding path: %s\n', loadpath); addpath (loadpath); endfor function [val, gradient] = myfunc(x) val = sqrt(x(2)); if (nargout > 1) gradient = [0, 0.5 / val]; end endfunction function [val, gradient] = myconstraint(x,a,b) val = (a*x(1) + b)^3 - x(2); if (nargout > 1) gradient = [3*a*(a*x(1) + b)^2, -1]; end endfunction opt.algorithm = NLOPT_LD_MMA % opt.algorithm = NLOPT_LN_COBYLA opt.lower_bounds = [-inf, 0] opt.min_objective = @myfunc opt.fc = { (@(x) myconstraint(x,2,0)), (@(x) myconstraint(x,-1,1)) } opt.fc_tol = [1e-8, 1e-8]; opt.xtol_rel = 1e-4 [xopt, fmin, retcode] = nlopt_optimize(opt, [1.234 5.678]) nlopt-2.6.1/test/t_python.py000066400000000000000000000015701345435414600160650ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import print_function import nlopt import numpy as np def myfunc(x, grad): if grad.size > 0: grad[0] = 0.0 grad[1] = 0.5 / np.sqrt(x[1]) return np.sqrt(x[1]) def myconstraint(x, grad, a, b): if grad.size > 0: grad[0] = 3 * a * (a*x[0] + b)**2 grad[1] = -1.0 return (a*x[0] + b)**3 - x[1] opt = nlopt.opt(nlopt.LD_MMA, 2) opt.set_lower_bounds([-float('inf'), 0]) opt.set_min_objective(myfunc) opt.add_inequality_constraint(lambda x, grad: myconstraint(x,grad, 2, 0), 1e-8) opt.add_inequality_constraint(lambda x, grad: myconstraint(x,grad, -1, 1), 1e-8) opt.set_xtol_rel(1e-4) x = opt.optimize([1.234, 5.678]) minf = opt.last_optimum_value() print('optimum at ', x[0], x[1]) print('minimum value = ', minf) print('result code = ', opt.last_optimize_result()) print('nevals = ', opt.get_numevals()) nlopt-2.6.1/test/testfuncs.c000066400000000000000000000436631345435414600160420ustar00rootroot00000000000000#include #include #include "testfuncs.h" #include "nlopt_config.h" #define UNUSED(x) (void) x static double sqr(double x) { return x * x; } int testfuncs_verbose = 0; int testfuncs_counter = 0; static double testfuncs_status(unsigned n, const double *x, double f) { ++testfuncs_counter; if (testfuncs_verbose) { unsigned i; printf("f_%d (%g", testfuncs_counter, x[0]); for (i = 1; i < n; ++i) printf(", %g", x[i]); printf(") = %g\n", f); } return f; } #define RETURN(f) return testfuncs_status(n, x, f); #define PI2 6.283185307179586 /* 2*pi */ #define PI3 9.424777960769379 /* 3*pi */ #define PI4 12.5663706143592 /* 4*pi */ /****************************************************************************/ static double rosenbrock_f(unsigned n, const double *x, double *grad, void *data) { double a = x[1] - x[0] * x[0], b = 1 - x[0]; UNUSED(data); if (grad) { grad[0] = -400 * a * x[0] - 2 * b; grad[1] = 200 * a; } RETURN(100 * sqr(a) + sqr(b)); } static const double rosenbrock_lb[2] = { -2, -2 }; static const double rosenbrock_ub[2] = { 2, 2 }; static const double rosenbrock_xmin[2] = { 1, 1 }; /****************************************************************************/ static double mccormic_f(unsigned n, const double *x, double *grad, void *data) { double a = x[0] + x[1], b = x[0] - x[1]; UNUSED(data); if (grad) { grad[0] = cos(a) + 2 * b - 1.5; grad[1] = cos(a) - 2 * b + 2.5; } RETURN(sin(a) + sqr(b) - 1.5 * x[0] + 2.5 * x[1] + 1); } static const double mccormic_lb[2] = { -1.5, -3 }; static const double mccormic_ub[2] = { 4, 4 }; static const double mccormic_xmin[2] = { -0.547197553, -1.54719756 }; /****************************************************************************/ static double boxbetts_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double f = 0; UNUSED(data); if (grad) grad[0] = grad[1] = grad[2] = 0; for (i = 1; i <= 10; ++i) { double e0 = exp(-0.1 * i * x[0]); double e1 = exp(-0.1 * i * x[1]); double e2 = exp(-0.1 * i) - exp(-1.0 * i); double g = e0 - e1 - e2 * x[2]; f += sqr(g); if (grad) { grad[0] += (2 * g) * (-0.1 * i * e0); grad[1] += (2 * g) * (0.1 * i * e1); grad[2] += -(2 * g) * e2; } } RETURN(f); } static const double boxbetts_lb[3] = { 0.9, 9, 0.9 }; static const double boxbetts_ub[3] = { 1.2, 11.2, 1.2 }; static const double boxbetts_xmin[3] = { 1, 10, 1 }; /****************************************************************************/ static double paviani_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double f = 0, prod = 1; UNUSED(data); if (grad) for (i = 0; i < 10; ++i) grad[i] = 0; for (i = 0; i < 10; ++i) { double ln1 = log(x[i] - 2); double ln2 = log(10 - x[i]); f += sqr(ln1) + sqr(ln2); if (grad) grad[i] += 2 * ln1 / (x[i] - 2) - 2 * ln2 / (10 - x[i]); prod *= x[i]; } f -= (prod = pow(prod, 0.2)); if (grad) for (i = 0; i < 10; ++i) grad[i] -= 0.2 * prod / x[i]; RETURN(f); } static const double paviani_lb[10] = { 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001 }; static const double paviani_ub[10] = { 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999 }; static const double paviani_xmin[10] = { 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583 }; /****************************************************************************/ static double grosenbrock_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double f = 0; UNUSED(data); if (grad) grad[0] = 0; for (i = 0; i < 29; ++i) { double a = x[i + 1] - x[i] * x[i], b = 1 - x[i]; if (grad) { grad[i] += -400 * a * x[i] - 2 * b; grad[i + 1] = 200 * a; } f += 100 * sqr(a) + sqr(b); } RETURN(f); } static const double grosenbrock_lb[30] = { -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30 }; static const double grosenbrock_ub[30] = { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }; static const double grosenbrock_xmin[30] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /****************************************************************************/ static double goldsteinprice_f(unsigned n, const double *x, double *grad, void *data) { double x0, x1, a1, a12, a2, b1, b12, b2; x0 = x[0]; x1 = x[1]; a1 = x0 + x1 + 1; a12 = sqr(a1); a2 = 19 - 14 * x0 + 3 * x0 * x0 - 14 * x1 + 6 * x0 * x1 + 3 * x1 * x1; b1 = 2 * x0 - 3 * x1; b12 = sqr(b1); b2 = 18 - 32 * x0 + 12 * x0 * x0 + 48 * x1 - 36 * x0 * x1 + 27 * x1 * x1; UNUSED(data); if (grad) { grad[0] = (1 + a12 * a2) * (2 * b1 * 2 * b2 + b12 * (-32 + 24 * x0 - 36 * x1)) + (2 * a1 * a2 + a12 * (-14 + 6 * x0 + 6 * x1)) * (30 + b12 * b2); grad[1] = (1 + a12 * a2) * (2 * b1 * (-3) * b2 + b12 * (48 - 36 * x0 + 54 * x1)) + (2 * a1 * a2 + a12 * (-14 + 6 * x0 + 6 * x1)) * (30 + b12 * b2); } RETURN((1 + a12 * a2) * (30 + b12 * b2)); } static const double goldsteinprice_lb[2] = { -2, -2 }; static const double goldsteinprice_ub[2] = { 2, 2 }; static const double goldsteinprice_xmin[2] = { 0, -1 }; /****************************************************************************/ static double shekel_f(unsigned n, const double *x, double *grad, void *data) { static const double A[10][4] = { {4, 4, 4, 4}, {1, 1, 1, 1}, {8, 8, 8, 8}, {6, 6, 6, 6}, {3, 7, 3, 7}, {2, 9, 2, 9}, {5, 5, 3, 3}, {8, 1, 8, 1}, {6, 2, 6, 2}, {7, 3.6, 7, 3.6} }; static const double c[10] = { .1, .2, .2, .4, .4, .6, .3, .7, .5, .5 }; unsigned i; double f = 0; unsigned m = *((unsigned *) data); if (grad) for (i = 0; i < n; ++i) grad[i] = 0; for (i = 0; i < m; ++i) { double fi = 1.0 / (c[i] + sqr(x[0] - A[i][0]) + sqr(x[1] - A[i][1]) + sqr(x[2] - A[i][2]) + sqr(x[3] - A[i][3])); f -= fi; if (grad) { grad[0] += (2 * fi * fi) * (x[0] - A[i][0]); grad[1] += (2 * fi * fi) * (x[1] - A[i][1]); grad[2] += (2 * fi * fi) * (x[2] - A[i][2]); grad[3] += (2 * fi * fi) * (x[3] - A[i][3]); } } RETURN(f); } static unsigned shekel_m[3] = { 5, 7, 10 }; static const double shekel_lb[4] = { 0, 0, 0, 0 }; static const double shekel_ub[4] = { 10, 10, 10, 10 }; static const double shekel0_xmin[4] = { 4.000037154, 4.000133276, 4.000037154, 4.000133276 }; static const double shekel1_xmin[4] = { 4.000572917, 4.000689366, 3.999489709, 3.999606158 }; static const double shekel2_xmin[4] = { 4.000746531, 4.000592935, 3.999663399, 3.999509801 }; /****************************************************************************/ static double levy_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double a = x[n - 1] - 1, b = 1 + sqr(sin(PI2 * x[n - 1])); double f = sqr(sin(PI3 * x[0])) + a * b; UNUSED(data); if (grad) { for (i = 0; i < n; ++i) grad[i] = 0; grad[0] = 2 * PI3 * sin(PI3 * x[0]) * cos(PI3 * x[0]); grad[n - 1] += b + a * 2 * PI2 * sin(PI2 * x[n - 1]) * cos(PI2 * x[n - 1]); } for (i = 0; i < n - 1; ++i) { a = x[i] - 1; b = 1 + sqr(sin(PI3 * x[i + 1])); f += sqr(a) * b; if (grad) { grad[i] += 2 * a * b; grad[i + 1] += 2 * PI3 * sqr(a) * sin(PI3 * x[i + 1]) * cos(PI3 * x[i + 1]); } } RETURN(f); } static const double levy_lb[7] = { -5, -5, -5, -5, -5, -5, -5 }; static const double levy_ub[7] = { 5, 5, 5, 5, 5, 5, 5 }; static const double levy_xmin[7] = { 1, 1, 1, 1, 1, 1, -4.75440246 }; static const double levy4_lb[4] = { -10, -10, -10, -10 }; static const double levy4_ub[4] = { 10, 10, 10, 10 }; static const double levy4_xmin[4] = { 1, 1, 1, -9.75235596 }; /****************************************************************************/ static double griewank_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double f = 1, p = 1; UNUSED(data); for (i = 0; i < n; ++i) { f += sqr(x[i]) * 0.00025; p *= cos(x[i] / sqrt(i + 1.)); if (grad) grad[i] = x[i] * 0.0005; } f -= p; if (grad) for (i = 0; i < n; ++i) grad[i] += p * tan(x[i] / sqrt(i + 1.)) / sqrt(i + 1.); RETURN(f); } static const double griewank_lb[10] = { -500, -500, -500, -500, -500, -500, -500, -500, -500, -500 }; static const double griewank_ub[10] = { 600, 600, 600, 600, 600, 600, 600, 600, 600, 600 }; static const double griewank_xmin[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /****************************************************************************/ static double sixhumpcamel_f(unsigned n, const double *x, double *grad, void *data) { UNUSED(data); if (grad) { grad[0] = 8 * x[0] - 2.1 * 4 * pow(x[0], 3.) + 2 * pow(x[0], 5.) + x[1]; grad[1] = x[0] - 8 * x[1] + 16 * pow(x[1], 3.); } RETURN(4 * sqr(x[0]) - 2.1 * pow(x[0], 4.) + pow(x[0], 6.) / 3. + x[0] * x[1] - 4 * sqr(x[1]) + 4 * pow(x[1], 4.)); } static const double sixhumpcamel_lb[2] = { -5, -5 }; static const double sixhumpcamel_ub[2] = { 5, 5 }; static const double sixhumpcamel_xmin[2] = { 0.08984201317, -0.7126564032 }; /****************************************************************************/ static double convexcosh_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double f = 1; UNUSED(data); for (i = 0; i < n; ++i) f *= cosh((x[i] - i) * (i + 1)); if (grad) for (i = 0; i < n; ++i) grad[i] = f * tanh((x[i] - i) * (i + 1)) * (i + 1); RETURN(f); } static const double convexcosh_lb[10] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const double convexcosh_ub[10] = { 2, 3, 6, 7, 8, 10, 11, 13, 14, 16 }; static const double convexcosh_xmin[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; /****************************************************************************/ static double branin_f(unsigned n, const double *x, double *grad, void *data) { double a = 1 - 2 * x[1] + 0.05 * sin(PI4 * x[1]) - x[0]; double b = x[1] - 0.5 * sin(PI2 * x[0]); UNUSED(data); if (grad) { grad[0] = -2 * a - cos(PI2 * x[0]) * PI2 * b; grad[1] = 2 * a * (0.05 * PI4 * cos(PI4 * x[1]) - 2) + 2 * b; } RETURN(sqr(a) + sqr(b)); } static const double branin_lb[2] = { -10, -10 }; static const double branin_ub[2] = { 10, 10 }; static const double branin_xmin[2] = { 1, 0 }; /****************************************************************************/ static double shubert_f(unsigned n, const double *x, double *grad, void *data) { unsigned i, j; double f = 0; UNUSED(data); for (j = 1; j <= 5; ++j) for (i = 0; i < n; ++i) f -= j * sin((j + 1) * x[i] + j); if (grad) { for (i = 0; i < n; ++i) { grad[i] = 0; for (j = 1; j <= 5; ++j) grad[i] -= j * (j + 1) * cos((j + 1) * x[i] + j); } } RETURN(f); } static const double shubert_lb[2] = { -10, -10 }; static const double shubert_ub[2] = { 10, 10 }; static const double shubert_xmin[2] = { -6.774576143, -6.774576143 }; /****************************************************************************/ static double hansen_f(unsigned n, const double *x, double *grad, void *data) { unsigned i; double a = 0, b = 0; UNUSED(data); for (i = 1; i <= 5; ++i) a += i * cos((i - 1) * x[0] + i); for (i = 1; i <= 5; ++i) b += i * cos((i + 1) * x[1] + i); if (grad) { grad[0] = 0; for (i = 1; i <= 5; ++i) grad[0] -= i * (i - 1) * sin((i - 1) * x[0] + i); grad[0] *= b; grad[1] = 0; for (i = 1; i <= 5; ++i) grad[1] -= i * (i + 1) * sin((i + 1) * x[1] + i); grad[1] *= a; } RETURN(a * b); } static const double hansen_lb[2] = { -10, -10 }; static const double hansen_ub[2] = { 10, 10 }; static const double hansen_xmin[2] = { -1.306707704, -1.425128429 }; /****************************************************************************/ static double osc1d_f(unsigned n, const double *x, double *grad, void *data) { double y = *x - 1.23456789; UNUSED(data); if (grad) grad[0] = y * 0.02 + sin(y - 2 * sin(3 * y)) * (1 - 6 * cos(3 * y)); RETURN(sqr(y * 0.1) - cos(y - 2 * sin(3 * y))); } static const double osc1d_lb[1] = { -5 }; static const double osc1d_ub[1] = { 5 }; static const double osc1d_xmin[1] = { 1.23456789 }; /****************************************************************************/ static double corner4d_f(unsigned n, const double *x, double *grad, void *data) { double u = x[0] + x[1] * x[2] * sin(2 * x[3]); double v = x[0] + 2 * sin(u); UNUSED(data); UNUSED(n); if (grad) { grad[0] = 2 * v * (1 + 2 * cos(u)); grad[1] = 2 * v * 2 * cos(u) * x[2] * sin(2 * x[3]) + 0.1; grad[2] = 2 * v * 2 * cos(u) * x[1] * sin(2 * x[3]) + 0.1; grad[3] = 2 * v * 2 * cos(u) * x[1] * x[2] * cos(2 * x[3]) * 2 + 0.1; } RETURN(1 + v * v + 0.1 * (x[1] + x[2] + x[3])); } static const double corner4d_lb[4] = { 0, 0, 0, 0 }; static const double corner4d_ub[4] = { 1, 1, 1, 1 }; static const double corner4d_xmin[4] = { 0, 0, 0, 0 }; /****************************************************************************/ static double side4d_f(unsigned n, const double *x, double *grad, void *data) { double x0, x1, x2, x3, d0, d1, d2, d3; const double w0 = 0.1, w1 = 0.2, w2 = 0.3, w3 = 0.4; UNUSED(data); UNUSED(n); x0 = +0.4977 * x[0] - 0.3153 * x[1] - 0.5066 * x[2] - 0.4391 * x[3]; x1 = -0.3153 * x[0] + 0.3248 * x[1] - 0.4382 * x[2] - 0.4096 * x[3]; x2 = -0.5066 * x[0] - 0.4382 * x[1] + 0.3807 * x[2] - 0.4543 * x[3]; x3 = -0.4391 * x[0] - 0.4096 * x[1] - 0.4543 * x[2] + 0.5667 * x[3]; d0 = -1. / (x0 * x0 + w0 * w0); d1 = -1. / (x1 * x1 + w1 * w1); d2 = -1. / (x2 * x2 + w2 * w2); d3 = -1. / (x3 * x3 + w3 * w3); if (grad) { grad[0] = 2 * (x0 * d0 * d0 * +0.4977 + x1 * d1 * d1 * -0.3153 + x2 * d2 * d2 * -0.5066 + x3 * d3 * d3 * -0.4391); grad[1] = 2 * (x0 * d0 * d0 * -0.3153 + x1 * d1 * d1 * +0.3248 + x2 * d2 * d2 * -0.4382 + x3 * d3 * d3 * -0.4096); grad[2] = 2 * (x0 * d0 * d0 * -0.5066 + x1 * d1 * d1 * -0.4382 + x2 * d2 * d2 * +0.3807 + x3 * d3 * d3 * -0.4543); grad[3] = 2 * (x0 * d0 * d0 * -0.4391 + x1 * d1 * d1 * -0.4096 + x2 * d2 * d2 * -0.4543 + x3 * d3 * d3 * +0.5667); } RETURN(d0 + d1 + d2 + d3); } static const double side4d_lb[4] = { 0.1, -1, -1, -1 }; static const double side4d_ub[4] = { 1, 1, 1, 1 }; static const double side4d_xmin[4] = { 0.1, 0.102971169, 0.0760520641, -0.0497098571 }; /****************************************************************************/ /****************************************************************************/ const testfunc testfuncs[NTESTFUNCS] = { {rosenbrock_f, NULL, 1, 2, rosenbrock_lb, rosenbrock_ub, rosenbrock_xmin, 0.0, "Rosenbrock function"}, {mccormic_f, NULL, 1, 2, mccormic_lb, mccormic_ub, mccormic_xmin, -1.91322295, "McCormic function"}, {boxbetts_f, NULL, 1, 3, boxbetts_lb, boxbetts_ub, boxbetts_xmin, 0.0, "Box and Betts exponential quadratic sum"}, {paviani_f, NULL, 1, 10, paviani_lb, paviani_ub, paviani_xmin, -45.7784697, "Paviani function"}, {grosenbrock_f, NULL, 1, 30, grosenbrock_lb, grosenbrock_ub, grosenbrock_xmin, 0.0, "Generalized Rosenbrock function"}, {goldsteinprice_f, NULL, 1, 2, goldsteinprice_lb, goldsteinprice_ub, goldsteinprice_xmin, 3.0, "Goldstein and Price function"}, {shekel_f, shekel_m + 0, 1, 4, shekel_lb, shekel_ub, shekel0_xmin, -10.15319968, "Shekel m=5 function"}, {shekel_f, shekel_m + 1, 1, 4, shekel_lb, shekel_ub, shekel1_xmin, -10.40294057, "Shekel m=7 function"}, {shekel_f, shekel_m + 2, 1, 4, shekel_lb, shekel_ub, shekel2_xmin, -10.53640982, "Shekel m=10 function"}, {levy_f, NULL, 1, 4, levy4_lb, levy4_ub, levy4_xmin, -21.50235596, "Levy n=4 function"}, {levy_f, NULL, 1, 5, levy_lb, levy_ub, levy_xmin + 2, -11.50440302, "Levy n=5 function"}, {levy_f, NULL, 1, 6, levy_lb, levy_ub, levy_xmin + 1, -11.50440302, "Levy n=6 function"}, {levy_f, NULL, 1, 7, levy_lb, levy_ub, levy_xmin, -11.50440302, "Levy n=7 function"}, {griewank_f, NULL, 1, 10, griewank_lb, griewank_ub, griewank_xmin, 0.0, "Griewank function"}, {sixhumpcamel_f, NULL, 1, 2, sixhumpcamel_lb, sixhumpcamel_ub, sixhumpcamel_xmin, -1.031628453, "Six-hump camel back function"}, {convexcosh_f, NULL, 1, 10, convexcosh_lb, convexcosh_ub, convexcosh_xmin, 1.0, "Convex product of cosh functions"}, {branin_f, NULL, 1, 2, branin_lb, branin_ub, branin_xmin, -.0, "Branin function"}, {shubert_f, NULL, 1, 2, shubert_lb, shubert_ub, shubert_xmin, -24.06249888, "Shubert function"}, {hansen_f, NULL, 1, 2, hansen_lb, hansen_ub, hansen_xmin, -176.5417931367, "Hansen function"}, {osc1d_f, NULL, 1, 1, osc1d_lb, osc1d_ub, osc1d_xmin, -1.0, "1d oscillating function with a single minimum"}, {corner4d_f, NULL, 1, 4, corner4d_lb, corner4d_ub, corner4d_xmin, 1.0, "4d function with minimum at corner"}, {side4d_f, NULL, 1, 4, side4d_lb, side4d_ub, side4d_xmin, -141.285020472, "4d function with minimum at side"} }; nlopt-2.6.1/test/testfuncs.h000066400000000000000000000011521345435414600160320ustar00rootroot00000000000000#ifndef TESTFUNCS_H #define TESTFUNCS_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include "nlopt.h" typedef struct { nlopt_func f; void *f_data; int has_gradient; int n; const double *lb, *ub, *xmin; double minf; const char *name; } testfunc; #define NTESTFUNCS 22 extern const testfunc testfuncs[NTESTFUNCS]; extern int testfuncs_verbose; extern int testfuncs_counter; #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif nlopt-2.6.1/test/testopt.c000066400000000000000000000332251345435414600155170ustar00rootroot00000000000000/* Copyright (c) 2007-2011 Massachusetts Institute of Technology * * 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. */ #include #include #include #include #include "nlopt_config.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_GETOPT_H # include #else # include "nlopt-getopt.h" #endif #define USE_FEENABLEEXCEPT 0 #if USE_FEENABLEEXCEPT # include extern "C" int feenableexcept(int EXCEPTS); #endif #include "nlopt.h" #include "nlopt-util.h" #include "testfuncs.h" static nlopt_algorithm algorithm = NLOPT_GN_DIRECT_L; static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0, xtol_abs = 0, minf_max_delta; static int maxeval = 1000, iterations = 1, center_start = 0; static double maxtime = 0.0; static double xinit_tol = -1; static int force_constraints = 0; static int fix_bounds[100] = { 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, 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, 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, 0, 0, 0, 0 }; static void listalgs(FILE * f) { int i; fprintf(f, "Available algorithms:\n"); for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i) fprintf(f, " %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i)); } static void listfuncs(FILE * f) { int i; fprintf(f, "Available objective functions:\n"); for (i = 0; i < NTESTFUNCS; ++i) fprintf(f, " %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n); } typedef struct { const double *lb, *ub; nlopt_func f; void *f_data; } bounds_wrap_data; static double bounds_wrap_func(unsigned n, const double *x, double *grad, void *d_) { bounds_wrap_data *d = (bounds_wrap_data *) d_; unsigned i; double b = 0; for (i = 0; i < n; ++i) { if (x[i] < d->lb[i]) { b = d->lb[i]; break; } else if (x[i] > d->ub[i]) { b = d->ub[i]; break; } } if (i < n) fprintf(stderr, "WARNING: bounds violated by x[%u] = %g = %g + %g\n", i, x[i], b, x[i] - b); return d->f(n, x, grad, d->f_data); } static int test_function(int ifunc) { nlopt_opt opt; testfunc func; int i, iter; double *x, minf, minf_max, f0, *xtabs, *lb, *ub; nlopt_result ret; double start = nlopt_seconds(); int total_count = 0, max_count = 0, min_count = 1 << 30; double total_err = 0, max_err = 0; bounds_wrap_data bw; if (ifunc < 0 || ifunc >= NTESTFUNCS) { fprintf(stderr, "testopt: invalid function %d\n", ifunc); listfuncs(stderr); return 0; } func = testfuncs[ifunc]; x = (double *) malloc(sizeof(double) * func.n * 5); if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; } lb = x + func.n * 3; ub = lb + func.n; xtabs = x + func.n * 2; bw.lb = lb; bw.ub = ub; bw.f = func.f; bw.f_data = func.f_data; for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs; minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL); printf("-----------------------------------------------------------\n"); printf("Optimizing %s (%d dims) using %s algorithm\n", func.name, func.n, nlopt_algorithm_name(algorithm)); printf("lower bounds at lb = ["); for (i = 0; i < func.n; ++i) printf(" %g", func.lb[i]); printf("]\n"); printf("upper bounds at ub = ["); for (i = 0; i < func.n; ++i) printf(" %g", func.ub[i]); printf("]\n"); memcpy(lb, func.lb, func.n * sizeof(double)); memcpy(ub, func.ub, func.n * sizeof(double)); for (i = 0; i < func.n; ++i) if (fix_bounds[i]) { printf("fixing bounds for dim[%d] to xmin[%d]=%g\n", i, i, func.xmin[i]); lb[i] = ub[i] = func.xmin[i]; } if (force_constraints) { for (i = 0; i < func.n; ++i) { if (nlopt_iurand(2) == 0) ub[i] = nlopt_urand(lb[i], func.xmin[i]); else lb[i] = nlopt_urand(func.xmin[i], ub[i]); } printf("adjusted lower bounds at lb = ["); for (i = 0; i < func.n; ++i) printf(" %g", lb[i]); printf("]\n"); printf("adjusted upper bounds at ub = ["); for (i = 0; i < func.n; ++i) printf(" %g", ub[i]); printf("]\n"); } if (fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf) > 1e-8) { fprintf(stderr, "BUG: function does not achieve given lower bound!\n"); fprintf(stderr, "f(%g", func.xmin[0]); for (i = 1; i < func.n; ++i) fprintf(stderr, ", %g", func.xmin[i]); fprintf(stderr, ") = %0.16g instead of %0.16g, |diff| = %g\n", func.f(func.n, func.xmin, 0, func.f_data), func.minf, fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf)); free(x); return 0; } for (iter = 0; iter < iterations; ++iter) { double val; testfuncs_counter = 0; printf("Starting guess x = ["); for (i = 0; i < func.n; ++i) { if (center_start) x[i] = (ub[i] + lb[i]) * 0.5; else if (xinit_tol < 0) { /* random starting point near center of box */ double dx = (ub[i] - lb[i]) * 0.25; double xm = 0.5 * (ub[i] + lb[i]); x[i] = nlopt_urand(xm - dx, xm + dx); } else { x[i] = nlopt_urand(-xinit_tol, xinit_tol) + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i]; if (x[i] > ub[i]) x[i] = ub[i]; else if (x[i] < lb[i]) x[i] = lb[i]; } printf(" %g", x[i]); } printf("]\n"); f0 = func.f(func.n, x, x + func.n, func.f_data); printf("Starting function value = %g\n", f0); if (iter == 0 && testfuncs_verbose && func.has_gradient) { printf("checking gradient:\n"); for (i = 0; i < func.n; ++i) { double f; x[i] *= 1 + 1e-6; f = func.f(func.n, x, NULL, func.f_data); x[i] /= 1 + 1e-6; printf(" grad[%d] = %g vs. numerical derivative %g\n", i, x[i + func.n], (f - f0) / (x[i] * 1e-6)); } } testfuncs_counter = 0; opt = nlopt_create(algorithm, func.n); nlopt_set_min_objective(opt, bounds_wrap_func, &bw); nlopt_set_lower_bounds(opt, lb); nlopt_set_upper_bounds(opt, ub); nlopt_set_stopval(opt, minf_max); nlopt_set_ftol_rel(opt, ftol_rel); nlopt_set_ftol_abs(opt, ftol_abs); nlopt_set_xtol_rel(opt, xtol_rel); nlopt_set_xtol_abs(opt, xtabs); nlopt_set_maxeval(opt, maxeval); nlopt_set_maxtime(opt, maxtime); ret = nlopt_optimize(opt, x, &minf); printf("finished after %g seconds.\n", nlopt_seconds() - start); printf("return code %d from nlopt_minimize\n", ret); if (ret < 0 && ret != NLOPT_ROUNDOFF_LIMITED && ret != NLOPT_FORCED_STOP) { fprintf(stderr, "testopt: error in nlopt_minimize\n"); free(x); return 0; } printf("Found minimum f = %g after %d evaluations (numevals = %d).\n", minf, testfuncs_counter, nlopt_get_numevals(opt)); nlopt_destroy(opt); total_count += testfuncs_counter; if (testfuncs_counter > max_count) max_count = testfuncs_counter; if (testfuncs_counter < min_count) min_count = testfuncs_counter; printf("Minimum at x = ["); for (i = 0; i < func.n; ++i) printf(" %g", x[i]); printf("]\n"); if (func.minf == 0) printf("|f - minf| = %g\n", fabs(minf - func.minf)); else printf("|f - minf| = %g, |f - minf| / |minf| = %e\n", fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf)); total_err += fabs(minf - func.minf); if (fabs(minf - func.minf) > max_err) max_err = fabs(minf - func.minf); printf("vs. global minimum f = %g at x = [", func.minf); for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]); printf("]\n"); val = func.f(func.n, x, NULL, func.f_data); if (fabs(val - minf) > 1e-12) { fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n", minf - val, minf, val); free(x); return 0; } } if (iterations > 1) printf("average #evaluations = %g (%d-%d)\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, min_count, max_count, total_err / iterations, max_err); free(x); return 1; } static void usage(FILE * f) { fprintf(f, "Usage: testopt [OPTIONS]\n" "Options:\n" " -h : print this help\n" " -L : list available algorithms and objective functions\n" " -v : verbose mode\n" " -a : use optimization algorithm \n" " -o : use objective function \n" " -0 : starting guess within + (1+) * optimum\n" " -b : eliminate given dims by equating bounds\n"); fprintf(f, " -c : starting guess at center of cell\n" " -C : put optimum outside of bound constraints\n" " -e : use at most evals (default: %d, 0 to disable)\n" " -t : use at most seconds (default: disabled)\n" " -x : relative tolerance on x (default: disabled)\n" " -X : absolute tolerance on x (default: disabled)\n", maxeval); fprintf(f, " -f : relative tolerance on f (default: disabled)\n" " -F : absolute tolerance on f (default: disabled)\n" " -m : stop when minf+ is reached (default: disabled)\n" " -i : iterate optimization times (default: 1)\n" " -r : use random seed for starting guesses\n"); } int main(int argc, char **argv) { int c; nlopt_srand_time(); testfuncs_verbose = 0; minf_max_delta = -HUGE_VAL; if (argc <= 1) usage(stdout); #if USE_FEENABLEEXCEPT feenableexcept(FE_INVALID); #endif while ((c = getopt(argc, argv, "hLvCc0:r:a:o:i:e:t:x:X:f:F:m:b:")) != -1) switch (c) { case 'h': usage(stdout); return EXIT_SUCCESS; case 'L': listalgs(stdout); listfuncs(stdout); return EXIT_SUCCESS; case 'v': testfuncs_verbose = 1; break; case 'C': force_constraints = 1; break; case 'r': nlopt_srand((unsigned long) atoi(optarg)); break; case 'a': c = atoi(optarg); if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) { fprintf(stderr, "testopt: invalid algorithm %d\n", c); listalgs(stderr); return EXIT_FAILURE; } algorithm = (nlopt_algorithm) c; break; case 'o': if (!test_function(atoi(optarg))) return EXIT_FAILURE; break; case 'e': maxeval = atoi(optarg); break; case 'i': iterations = atoi(optarg); break; case 't': maxtime = atof(optarg); break; case 'x': xtol_rel = atof(optarg); break; case 'X': xtol_abs = atof(optarg); break; case 'f': ftol_rel = atof(optarg); break; case 'F': ftol_abs = atof(optarg); break; case 'm': minf_max_delta = atof(optarg); break; case 'c': center_start = 1; break; case '0': center_start = 0; xinit_tol = atof(optarg); break; case 'b':{ const char *s = optarg; while (s && *s) { int b = atoi(s); if (b < 0 || b >= 100) { fprintf(stderr, "invalid -b argument"); return EXIT_FAILURE; } fix_bounds[b] = 1; s = strchr(s, ','); if (s) ++s; } break; } default: fprintf(stderr, "harminv: invalid argument -%c\n", c); usage(stderr); return EXIT_FAILURE; } return EXIT_SUCCESS; }

ȼ02g<Ap5YLq AO>UcNcڮ>s(ޞml;olɤCsn`&5o3?Ƞ=PaSS?XrjHq#~d)ix'@Yq @!5a8 w |g >BrC{Z볖 ӻ=% fB1n@8pzy{l(vO׫:p Jo }A 66VjIHU/-l9C30$%@!C}>Vi@;% M9Sx/8+Oz4D:a 8ʀ1O܏ _:^.BolR`FyV܏ j;Hu9"UwD h!Jy@SZ[" ŴC97%mDgN3nlfmw}nJ< F/{[=(\87BlBg{;sѧȉKֳWϟ!뭫N ^4) I [>'n{~@zob7r$yә_BjcBQcV\tf$0ʬE+fd3Qִׁ Lx~./ۦ%KA@ F<\tS8ªߊu.æƘ`9 YV6OypjeS]5|t8 m7LXTF:epꋧԻen@ #L<O,zh$yxJ'Cuw#?Ƅ6=QhB->V (#ZgB_\;N hy[4_6iDg-\'Csr@ȃ0%R gBnIr'/]fOg_J90䞃`MB ' ї jތ /@9V1Uȸ~?qhgrzC!/ε6.HhBD&9苉u57@7?ZJ@ %>NjgbJ_~p M0Nẽe&`ka5H@up ~'N'mErG_GIY83ǔgv ?: ;K# @DЕo$_/ۑ;32NBĞѠm&<@;v6 Rϡ.|\!LKJ/$ =PVH$9<@!5N`[k"b `稼Elp:qi6 pR5}Ҿ?Q?VI ӊ@!Yi69MF,+mwP{Mxwtu%pêF90>I]^hB*SUe")wr8M<աPUqx1TVkW]r`\Z1" Rq|L1j}znK_O~y@!l؀)oO0EK_@adB7d#Ag|_.VƜf~ݐ"_+vT5V]sZgÉoz^b )֫xC~}hr3߶ݒRӸּF!^(u&p tpil+0w׎WxKTe xq7 .Œ]9BӋ)s9&j+DUGs!%$! )1 Jf@re#jwǯ)ѣ)|6-xƍlMn3ޔSfcz]:A¸h(߶Ŕs.c\ୁ) ,`[|ŹD@;: mJ< /z܏KKڒ7Q kK@B=PѦڸ3)X]-wt#h 467< zM]ِ:ߡKgjxVBꝑݾU/LS#D@[L":wI`5۴q~ާu-]$@cBoˆ\It6wg5 qM ,xs$&G{sӭtg37h57W ] 6+ D,t`>e3(ULt ƗwM\ս7OPALn&87ݰCwl)9 0;iJ)K(r'b泍sDy.u_S]G ̯NCA D?h9UdTtzgdf- @w,kR:F)/˶GbvKO \M 'vGfFԀ91:cs;GN햔9L2Q8pm1?\3l—c Xqzq}@‘x = #u~5eBq IV8ϻz~9/Jә1q'nO)tq6/x_AԲ&`2B902Z(⫃RZ.BӬP'П!90yR -_r='Oa 0]F*$+@gီ%)m#Sݲؙ>U8M@FM6$p.[&;.?9 g KR.+oc԰ݼ,Ѓ>q [D9Y +҇ܕ@G?7<~Tg(3Shm (Tkyvirm}WX|OtiBKQv) E^Dp)&yG ,.jKqf.4pQ>r/.]pJg5~wgiپ)k6h#;UQ$DAamw%_-.Mk>90:`w^:(:b qBP1@V)=˳z=IF(F9ڠ)G6S:8/8TmmqmۚцzKwR .D6)|hV zx#d< {7Rms?|+O:σ2IJ> ۿlTNq/GêS4y"z[N5"c4]yD qmw5˥ +*$jHM8Y`jHh;?^Fϸ|˼IJ)0:dy]@j'2)yg(vw! % _V <1l?bonb.95;Τxaj7'KFLy<q9B@ =a8B9y~K θďc8&1BXի˚0J9 PA4д?k4]rm@6Sx&p{G}[kxX]+> L|#D/VB\`QGFCwuxq$Hsy 5To,Oxs`|kVi{2BWf&=.=eG2Qm/ 7A^?v5Z/zyK2\|}F^)jPpi~eFw;%Bà 2'~<Vyԁ=Ejķm@%7\XJ k7`w@:Ȧxy[ʋUP@!{^k*3>6m)0>2! sM\tYDڠӼA!Tn-}}Py@!ŋf`( P>2;u,W(ai=|#\^N;g!j3/6@!OZcRUhA6Zsr5DQadg.N^ ~,m)0|0&j @!Nq[8m@\\G<{_Gщ (L},g1z¸:a(m{:|N(aѭeد[O% AH ]_|B*vg>ac (mR`x`"Nb/PH=m\aSam) 6H)0[~>[0K@ԫ4wfLEzܙ^?#DsO!f %aZYc_~M'@Y!o{]g'T}r`|'4uھ>u|,tqȵv'^#*{m@!Ї^%QI08⃼Kp  /{PH PAZ5Fh{xIyg=}7Di,:G *c+lIS(DR)0<D$\iҖ ^}If5-Ni>d!K9'dL|A7iGt\o0sXM@kGS+L.}P3iPnb_S$kFAQT2{jomD2\|H^ hpiښԔPL^qѹ/KH8܉qnˁ/S>k慨ݢݲߏ Ѻ˱IBLSteQW@G f2A t(!flH ͓׆Ƶ\ !h{ˆ:z༎ +xv5Dk\LYf'J9=qQؕ,篥( TL$'S=u*RN53 ;oB =aP!m҈8WwXZ]wXB{@۽~米L38Zo@!iՋ{'ih{0I!`m]QVa@. }=*8Muo{aFߋV5.p^ k@smO).MJ m9M9{@#'B9Tb<>]qu1B`:\<`?@YӒ`=߇R Q<ՌVeRՋ#W\0(? ˥,90>UqOH|2n\2Qm@ABdwx}<.l|0>(#9G * y#ejFQ74ߜb!͔xyj{VW6: QDq sbT";.ۜx@K{c1z!4X'^@YVsxxiS&ƧQg՛'zqBjzz_QuUoh{,0Rzj[ByW[\+V.Qq7=QS 64yW\ ׺jjc\q06DD_'I#kɦWQ^=}P@G :WЈW *0wy7@!U}ʹӱD` Ρ8W/Xx<S(ŧSПeX'֭9\٧bnτ- "Oe-c)a:IVL@X>H+~(~l/xs%|E B%.UQ@#v1qlP8ֽ>Zc y|tc8Jiyŗ(y^M?0?1JaQ6Z 'NMPjk2,1 =Y$$R#ܨBƢg92.M Jzm%f+(PC.*@ccDtEK؈ 89(Gowq-lS5^/P1L ;J.e~u`i\##S>T|a,g ^K4۸5:&AEud%qM@R^\K" _p5HD;Nj"^\w&M4-[=V#@G qmmxn8xr38pIS(4+@$T 󦇾` mq TUdg;V)P@$j_uU@eH:}+u"ZpԳǷLd:`Roqn''ϊ!AJa'%I]ZLk"Tepm#E{,zSZl0-?bH`ʍ닯PH\uݼ;: @G {2ƚwO&/z,DDJ"upe =+L ~[,DgU\Lq?4pщhge]pJ;\ܮ8 ?\Ӹn}!\#&yѫ\8n C0i%W(oj#R0$I!XwEYYd|޿JE(1=q͉DJ&S}d^B>ɀDž'!L1mw<qi|T˼Apᙃexψ{pJ_biA5wP6xBIpmDkr :sqѪ#2WV  /RJyctZz_8R98m4 0ushFhmW|qgT>mDz]lEK Dݘ>Da]PMPi/*Eڎs Fk^g/֙}#EԙֹYCaLh{a81yfh BpQJλWw%Imp4Ձ.?.c .)0<&i%W(>lkyp8ONB٬+pR΃F5;f@G Ԃb!xrU&ϊy~gPswF8r1Fn1I'Pr-m3Ú{`Ң닯:PH:F[m@Okm‡$87\er =[IDg<ޏ"hLh^?h~B*ajꏄ4')6C%o^ S ^9=1}ʺ^񱖠ڏ *cIAy~%i Ծ=_q8!GR[ZN)cK1˥+qBjn a'@Y>ꯣ*ചp&m'g0=}L&Neyɩ}JN(@5)vdml2\xxė(9pZu~squhys/u*$JA;[-Rs( ꑦhC E:.<.N鮹@RpTs|`|Vmyº}@zZ%^@EmogC(vK^}XAopri_ki#kih3gl`s;-}~=7(i4 EY7y;i'X_fW68腡GO!tm@0%6*tua3;tgݟ=Pn~_lWA᥮Vl7ϹL%=P햔hAx&igm=ZVt,@5[5Lq5G΀}}{ 0ԯjH2(vˀ?Wt^y@#=J6/lhI\n]P?tvP$߆$ERt%o)ﶛ(oRtnQZռ?s=PmqAoEtywfϝQڊpqyYߌm:u8tN(=l[@{r :!13Σ|e/Yw[s| 2%S!"<9N4"HÖu_o/=?##W6zvP"Q/,,qo)JA7l0)$m2( pƽ2'Eq&g|n<E0a4+`b{8s.6}A Q'a2)0 c3m_P(Il}`m'v\?SX}IqOH|ŏ~5,d0 ir Dth¾^A EjbF)0Rc@ڮ>(xzuT~MQOI?x20ͥfLjVi+2'wQ6y6;ѵIq-xRi;bk %סj)Q̤{e*64)P΍& Tv+ KÖd߇7Z[S)`49B*r7Mzj2R +h*s¿T<#8)0t9MgChvjAlJ- mhw-Hͺ750!h{¸c@)ӯ]q(\#c !<"3%6{y΅&m1Ѿ[X\FSʃ rbfu(mM`|S2{(M9mc~d;[@[cJ1mڈX /oźvhl 90, i9 9 znm {sneiVP k3RDʀRk(;{gj< P kLqܮ;^v~w9)]O4M 8NiJ5.5(†7hJ Ӕ#08bd,2Z#Ik9*M @{ lθpҋt[;'>ADž @ٵ/zpJ#smczsס EPmFAlEtt|e‧9%~?n3"Ka{ xZ` G Ӱm4Sl%eN#Gҿ*ü8WAHiyVC];]04q e]_<#@!Ozǵ @[) 83.Tq5'lg봭VcN8@Bj2˺Р*g~ȑh)=Lǐ&臍O.p0Ie VZCUZS'ŅEIۗ ʕ/V ."uu3u7tpB:Ri2Gtgh{ ajAh s)5NWOGi(vO_hAgmDty~@S6ݒiDШKe~-~U(sW>N~r\kq~F/K9pm1A~t@+lY|eнq,k]6mޣj`S=J}[JSSJ[ `xm`R`X xxBr2i i3&e-j>~ȱhU)4f(an)$a>,,6K9ն'R8nw8+7J$PUbyb=szS,X9.S|ڎ>!Rw@SG7] R*̼N%ˋ!p0sn)Qk]%LsD!n1p㝤o!_6Ce{\T nƣhp)Pz2zllރ2%w lQhzj78͙*U J`nm2\TP ,{.uCsNeUYvžlPMa5)$)?9 xJ-eӮx~#(vKQ@odFĹӮF]~In7q\ APJ,nߣi-t׌b \ތ% >> =PH } uL ^dJLs\\r`;-RϷ5.0] ^iz0V;RSA= N Jk8ӶHSR6) z8˔6eDWmToF>7/:.n>6s>sN8Fܴ1 E V@5Es{ v(q(vϙ6~;Š#!:jF㎕ƪFd0[L @fee}>4`Xq{Iqq]x=}xyj{c3. ˆL?[(r$>J0Bn\DgєIqlG]| Wlz "i9-vҢ%nLRǂ^ՆpHS r?:)"tn9B*1]e\ՂIr8M4u2:z{m߲A"i7hݮ>"3!G%P:bʛS`V;۞x ^fVLq` D5Lq-xNŵ}}@ytn2gEgXlR\Lظ8Rk1{F>jF(ÅT; l{ BN뜎j?~aLq').61}U k.ۄtVBHy1hOlX8R_F!rܗ ݳ_L1hQlXHKj}x@ۯr*ݦ-^n<>S@{Njs 6c8;Sj^zqm1<ƃNI) q?Ǥx@/0)*~9&n46_Dgi.u ̚>.N#8NK~{k4i% =a论i  0R o{Il+;r$E¸X,~kόQJOO)>`xL|c`8@]W9u(q]3PG}eW%}Nz>TsCtDE"ҏyn:~ XHA| T5#d ,@{  6SDg\Mo[YӀ )BLvJh:p) 2rԞjn\sQljo' hqm8Nz)n8)px)spWA|?!(Fpg۰tzR 76 }J)+8\ǫV&sC{bBSJĹx"B}¶LXBMI`Q"NȦiÄR2% P873LWv Ce{⬤76}OjPIqa-@x j=o]u>*TAIa! R\g%ѳ~mꨡ@=YCAq a1w|97ńXWB6cR*?((vKR4ٔ~Aߡp; P !;ޱ&5*;sS .~^L}쫍O KN XPH]اƢ6<9! )E r`RDS(Nke}u"kmIdolR\H"G'M(v4V놘?;gÒC90s⺢ zaVEt]j(ڂ*1qv<-5{ImeR^#+Ί'<ʼJz8{5>)ͮg]*P|.f茳TK%KDL8uSާX)-_#kE>h}ڽAT]QsPS!ʙ: ,$QMO< `Bù~c'Ņ3ڦr] o=Pܑzr(Evhqi p=W/OtOg3Jv_:Gf87Tedb8L1++<3&M If0KtpiӨWm~@{js 6-3J5x܊t3(q y>xN8s.cG d uç6eD_ t,bx]}xz2˱x@=r Us e]<.՜IJ1V=}ڎ>}&ZE?ヂ,mw4us\o#qogowM 3hsڧc׬bm ͜P igDS?&nU[%zRuy ]L9s|zK3$K&F%ljdh@xfAYj;:r WSc4}Q)#4QY$x pؠd}0'eS=v5URTLmG()Q^߯W$ Sh@l(5yyw-'kᜤ~+o_7ԭlP [4)vB]'&}ofOJ=P>&. E.:.Ur\݂L8!uιՀnkc؜q~=?dzy(UGb#CY(zOhgr;$/vY^L\ A.Iw0M)u#LJka]1m2\Lz4ā KReOz~ܓޤ2*`2$$1%`r|֭"S8tmkxZsҾ8Sل}ozS:Sbd&mO|q)킞ilԬ` ` 2rNe:i=φG؆'a`'Rmw*!Svqo9.P$BfĈeO{ۼ%v g3mYިAq!q*ː]O| @!վF<Ӷrs`Wl|2\D&*K]Gt8Ni:gw%Q 1(A;gSF3LQKx|1ҦT :˒N6KFֺ2LF(F%MMg\4m]̛}i1ϦR y8dIΒ'IjgruQUt9"SV8N->O6uXD}f%i<}zY2/PI2nK$CжL]Qf%;Ӳ[wo(1شUbH+>o8Ƨ~TwcRHO=N|>V&M4~{TحSQ ݦ'){b4tZj2A @LbrZ6/Lvc3ǘy>Jsȁ]kʤC %'> jItHmkT 0$͗*ez`'ۤ BB*qJL'lR )>OG(޷K-r`#( veBM%ZWñc_(@ _P% 66oi_j <~ON{HF6eR`HF6ň>s= :I%-T68|5_) g۟že_O4lQ y6i (ifXQT d'v~FᰙKahl8-ZaE62\D3"H~lÄS9OΦZ͎dvqm5*J!hl($MPKw˪ )ЦO 8 c tM"ј&Ɔ(k:PfyXom0d^myekU#/$iY 3.q '.60Y/Ծ˳ﴯx|QzԱ>?:mR`L~u򱶧1R$6#z#2@|br0U#VOZ4Zrh}\cqV#ڼZm3h=*&`6Pϥ%ySD%Kr\mYe-l]q*3~bKO hO5PAgDtƙ4)To6 $Oh~QAgcDt3>ǪV/oP Sg!wyxˏS=WLWz3_I3~(&gw@ 23uX/~nG-z=|-jE 2[w8P{ /YZ%5 ׶}gӜCۏȜm9%"0hU%3Μ  7ČDV ܑi2! s5io4OnEyhmޣcM%ir+Z*-e-%ushͦ"MለLA$NUUy#|>}f&ra(atnÏAӏ~مL"kR|*s2 sh[:  Uk2B*~1@!.;fZmm7nu 0bk3p} bEjDRsm=1"F5S 4HE.~Q@!O"V}yU\P,^8F`p6YqSY Pb ݄k0NRyuLQ_AaS.ܗ G`p&b*eeCe|\ # 88Coll1na&V.\ZNs"u[Ajn ݄I;ɽ]_t澌 ȆQ^7'їVĪ7/͏S Wn8UGRo"+{tP.=:ޥ,uwɬ/}S4JqJezBEǥ}x5*`.u(X2'l-yYpb.TV'k};X8C[Ɂb. i] x[\಍ bK Ŗ18߈ʸQ<%46JkK?jM.q0'I$7m)ҥR DrxU#2n PmG}\z@Mp#C)mT7Mz8q}?Ćo'&x ld iTu"93[SM0(L8Эo/v:99RN"뮼"nBNdw0D\Id:xY2ڪ>i >@!Noy9oφ''.8.\ bWǍ=þ'C D_T)Gi xt}sO&nXC8qG(:>@{O3/Ka/5V ޠRq"0ڷ$pbO80-ȡ&:.e;XRnwf^g GR`?K>>F3oPe`-88y6 }Tec0S]9p&? ^1R`I]:>@SxНe9PN,Or :9h+n>ލH :*H*a*:pU]so뵕[s8 T `1U;b ;56lG(E:? 9?4 9THigy-oNEI[eg4oTF ݹ9 uQ92K>]itҔP&9RqcĚ)mgYO< yL9oU Lc]z)*0LLF*јK][TI#elUמƮ4 qy>QV K]X%ʩ*Ite=v*CI( $cQRZ#(Q4r덪SӯucC==>w)cOtmjۺ>0(ew'FC__5YM9F=fѣnďU*W ݩQP]}knG6ۏ?mM(t~kz}Ʊ؇;n9"͏lj/7>{y/v_CBhsW?(Vi5y@Ԛ֙N*Z~ݴŊt ph F904QS&Uś w6eކ2W4T@T{gЏvmiPQ'Ņ-R:mU8!86JV`IXM }s2\Mj'hԆ.ݺc~y@Yr\WZ̳Įf_K't(+E:*?a]QTgE+g ZL^q}ǥ6t&q>[qNgYc!ɨ9)OnD}Go2fu[2T:_a(ו#ڇ򣽘fFx;3Nһbø7lԗ#zr=[k1 ˞ZNڃ*Eϣ鸪ױ9u ebr#@]k~jԪ4Mjٯ%/qkI3!z?xYUiاj=m#˞ZQѩ5llkΩllr&}W\tw0~QSZ\ӮhY)H/V׼]{YNםOAq_t~;\'h +|%hr AtM }2zv<Ŕ 4tӤ+)h_v WӎSP?ki:ikZve c63mQ0eO[ȃ oMH/T/w=fꊕJA_W^5O֩^_3sԯVgՊ~hJب;^ %W׎jݳFVTLK8q.}8M?7_M1:V4ESVJ!͵ƗT)GᗺIo ;kտ~>s5~uLkc/ u(m9%^U[_auλp ="җ$ۍK6YV9֙mP 2oj|g봟Lָ߯ gzGYt0-*Rus ɈU>Ï?2zj | T*K5/VX[]9ҜUb dׯ*%SU.AWsV9t/gŜW&]Un/ʡU^YXlϱp5wXwP׫oקyI,ne hЍ}ּs驇:rd_'C/dfIIeH[J$e.nPmX?]XV1{>r>PRK,-TojnOO>֬+D\~֗6}c>Iq{\=lLX5PXFI~peDԪQjgS}QV' @-Uߝn.^nAV*?( =ajk`Jyjc`5C({3t^)Z?uq҄_}o{d0{@5sGՈܮzu< >jltu ٶmd{@|O (kZڇȗ=P1Ϻ+zPv>g(Pv?.}rvDՇ<9_kJbӥ3ꃙ3}';a+Ԟ(6\աj⚱zyO;t>'{=mK &聒2jӸkTm5Q8)NjX}I>)0tA37"PH] ǥtpPUm@ﶅrBj[h02n UY Bz7" PH3.dDspe6_9|R_pXYW :DEYtu=U8SS=*tA":(a,Tb`Me@ٽe~5)Q7][}g){ p?:9JmG~5v[ L VУjk❖ t:n_kt>SqB3j=T;S}ָL'[IS Q/{(=e6I?ja=G qf8|b=P*7'0"ꢆ|&I?K[uG&q(PvD_'H*1qލ~U霓02\a枴'ֺ-Rmt3 vx&pqc+sMEPqeX q#@{7:S1.nhFYAOwLM溣j 6wmUvRok]d۱<~&pqc-MUvNkahmv펽.{o6 @G 4ڪ>59NA6и/ƈwWn\>).Ua5(=*~vSHAhO CeYC [m8b _%1jЕ0n\Hઢqߛ{Qjg(8:[𔦬ic+?ƇPàSD>Nn IҶKpa $i+NwQƨVv2(Pve`GV^F\e.u M 4Ja|'Y3t} I[pNb}̺wAΨ ) eAN;R N^k281im}`\ ?Ь8F>$šz&z~F})qy1⋲'1d르&ϨٱA@u3U#.nq<,^#*XK5R`F{u}zd/zHv1(z[SYxQp4p'|yTA|piXoa9?ج @!zN9: @8 |qXp3ύiMVj֛`U)E ( =aqJ p@!Usۿ땮z5'U(Es[ ƥn짍E3w|[ {n[}l8ed!8È8{/:%UBR &rl h̥d? ݅~3:(|i ?mٖ9#p:LM%HA/rVL(pX™Iۏj`')/?qe+zCF4J}] &(eQ4J!0_z'fghmF871Ptj;Ocq 9Lrfz&TU#ssG.P60 3"g5(]%EC݂8UW /&Y""m$6i2@0f,D]a`yz~p0q%BhҬ1j8̰ud+?L?0Rݢ`XӢ3 (PF  @Le5J}I6TJ IW+&z8!n$. av3ٚ'1 &~@!ՆQ}zkAF)0xru)@ mbRU}t'b@b!8kBDUlֲTZtc%~0!p Wj'kuye?XKP,^K0AF~|"ŷe@zɮ跃bV(Y=z$ECb@#XK H1eR`H)[¸% ;]=  l f5M26mΗE߱bzN(J8aMKO j;jJ/K0{UR`H_ _u}@!\-VmI 6J)0$19Dۚ>Xzjr, 5\:nYmGNm^VLeKV[ej?t2z[s V'P~zKw &?F90&" V+QRl`geÉ/Y~R4"IyUAmpZnm9K[9,0VWpJ;rM!fn0f׼q9(ZdjRmi:i^͜~\'zJ\M(+Z%;4 8!*n(!_=;&OYm*_4p1Ňf=C&骻-zdo[uP,^u{BZuqV u븊}8$.+Jw`0 A"\]q*|nCFuDZ8s(%@!7}^?csyA;(ٝGj0Z[p-kԃҩP w\5<@!unE[U[}oyZ q2XDN9'f'?Zoh-Clc\H I(⾑FfstKFJ!X#h$GظhpB3kCx!J;ut]UPc}wK `rI!WzX ;B'ּEbV8EsL,S|ݧB3 Z~ήzF[k08>'?otIJǕI$@;B;xGkJ:i[Ag:  N p{  ([z3fpe3C[/uc #(#E_Դv3:z=  $({G\3:Eɐy[%/S/{tg'ʧ1 3Tp x#WڜBcbi&P4κcU&$N]>"i(4l8p?4 _Ȗar,|&,`~}/{qzWQYUO0*+ (8ϿOU?(1vUB;m"( 4DM6g}3z諾.!yVtSմt)_O8Ow>N8SHO&UJ;]É/9#Sg~]Ak1y^gGoQ#?8[=YS>mzd ݓ56]gǬM.؊y6l xuɛSqxN zy"N|Qm?\v™x$ +sY(PzZߚr%`.y}gM J2rL8>K06e׋?YLe1Rmdt|l+@A%ۂ|-pC3mԆӚPgo;-w!M 0xF6d EGu6v sBYӤ86[(m?!1vnI-6Ɨ=IJz)b6}R` \>2QRU7cC!0D l}ĸf"f}QN'u@@YLY`J@n@r/~]7K;}Ac$ vWWv;=@ybX q`}y=Ï٩圣=(NMs' d3L,E 3׮O}?7L_B''H4|PJ'$I'.p'ǬR`Cs5TlPseހX8ʈqԘ'@=uz@LZI@YHY?BCj!i!CG>)i04#~&XÌxrl@كTMCұC%4a)? e1wVݞ<3e&(38mrKų=ʦg.|uX0W,wob.֧i3S[7ۼj4}PBI@b~с[F<jdLY.uWhWM(ej 4`šJ)3!t#T53.ݴ3$d n˩K:#[a IFПaϠ2_vK9U#.5hO2O<`zX).=HaWPH3~Jn(_~H@vKmyW~8Z hCo'w92@L]Wb 9T6S` >нN:PHU;ʬ꯾x$-#1p第nvɲ(Pvޓz{@;@`πcWr`̤c3_BDâWZ AmWŹa);"h5ϥi7w RBc/GP,&M_fs9z\{c[7 %` (,}A%TA2m#*;&v{w{8&peo}H<p&O :,t*^JntQ8eh8Ew4{#"pIlބy,q8bgkJ:0[Y*:/Kȳ1R`E U}@,{zbX:{qOW( u=|[WA/׽0No:Tٓ۲= ͝ ^T ҥ4y3̛B,wFR3'oSůKAx@#)30DeSgZ?!> k %Rh'cLGo sQ}+g=N8=SZ]OW&|RXVԟ3*fՓ^:+e7w">a=|s#ĴC{ȧy>cbyE(PvK7ͱ.HFg6"|q[| $Hzv[kL*?`=PHUSNVWu;$yNbNsaBH'܅7c} lz@Y?Bf#0~vi\h1hEzcaA38>U9 ̶zz8ۊ:<><N8Lכt߰ Zs9{p8!m^_ D5ޚ$ÅYCt"'@=N8atEa~kg"/d+T5N[\8ԣ=1<ޕ/0ch+eciaqylɔmju89dS>'Jߧl[ K,^lRG `CjX6ԣR+]jEt%F1g$@.z(YZUbb~ܧ-@%|c x{x|I]~* (]B Q Q܁w+'=N8=] (Ȓ!3GdzAכ<1I{@=U6j(_}}ShPAMrD #[P!`jKO 87,snet6(?ﭟ^!a󰆤3'q-&'>z^ ;(ReHu3 qz]U 6 Y~Đ,T/eߓ]}=@T8{R5ۚc8"*<[N](v?N| #euumv^$ebhZ2jL}4@Zg~.B:L{_`(P̭Uf&rF<ӝjRbÙ22mTZliemH GHՈnWr֮%nkEW?z:88$S'ũyɦY fBj{J%'dzT㺭שi^G)0G3^:Me#PHUEP9:qAP(Rݥ>ng'uG ,)1Dp\qxj5Q7\ȯ0W$}e7䵭B8&M:1K}s ^ld(]E n 9^W/yu[cDA{4ǎ@!5mie͏ov{^/La(,eBQ]uKCou}|'PvKqlu@ou@|i?V64")11}R YENRՄn/B ?W{ߎ@wʸѻ _sGj]}bBOd͒}S.-5M'fY,"l.i_LyeOO}nJFXf_A' "6輮Õ2( 2ďОY/)Ә?JM(mГ#вY Uqf2>Y׷! > P6ݿ̬Skw5dM|#.Y[{w7qhOʊRN8~z)۲8Gcv`#=h\mh#Cd ?[*IB=A-%?gzMi d'j*_oi!3(|f(:-]I[yY{k f2 j} 4ɓg"kkB$ૢ RR7{*ep7 >)0iY~ x1IWV nQ#qYH|[/ 6~6؝0E1[rs$Q|K ۽pcwlG@YL3P.J<w4)N: &uݬ?! lkF hB݊· /z#Gy^=,6T ⹶k:t Zd(KԌvU6{5G1zh:VQvu&͚=Jڂ;˘3_idG1 SHuU!έ7d=Qԏ Y0 uܓk?0Ne`tj J*>qBz(u,[p܂ =aܯ5sy*~teq'O &8j>Hpx:{Kx [>M` Q3٭R(o>V,7w0ExP?P\K8>U?O6j1X/?ؖc'6I{@#  %piNaXm+>8S(ƥ)x@eafWO܎3m>x6{άI1vw9aQO2Q(\ȋ= J K1{9L'eX-+?ݒ(4Kufy3b S(P1amsKfTibĠ w.jӎFNMq<ihF+ިai U̽8 2p \~SY,:yi]Nn%Z 16i0eEu#pik+&j^qi/ =aDtAw g'1&({pwO4QtVʱe TJEgz،G KTo$pSw2)0T>ωu}@!ϒ $Wn:b/zM%T8c2 dqbӂxWynjֵä'=N|QL6S not]'薾}m"± oH\:&u;[ϧ|[JnzRamD,%J!٬Ѻ#=N|;[_٢ nmœ|Ё~ZwބtΛz n|ӛb+/q:bR,x*Hhm_Tܶ|@(PvKFCk#2.)uV:W6mz̄k Ļ2U酾2?Wtd,G,obp5D鞡TS̙l L'\&´ABzzrD" e@Nlbi+O.(^^`)vv `j$~DBm#%}^ M`L n/95)'N'sq阥Iᩙ 呦\]|B*m16Oˁ\e@, RLfsAm[_(nQ w]FUg4(vfoYg2xA UYOO ,:$:- uvUv]NzH{zS\lG[d\mtpBjLzF3y'FLcH? @G ^ y$_aY0}]t$T]Nn+?U>E@!ϺGv}ĸ 3A;i0hRN,qR晚}>]*l1R`K%\i'(M|[AgxvFp38^Vjr8vPwEvַDz[Eh02ZODPtkY0_qKVP ԫ/?ɵne \Ipu Eg)7q/&[,rl})^8"Lpe@zni].R6nw8Ewzn(1a*l@[z{UVpd4Z7V3乫g(Y~P$ =aܯJвu܀OG ck)k̗ݓ֯y2U؟y%s9'{\o#8xHiyZkvb9xP̚8Ӝ:vEog~;Co< "zg2:"eP~3^+:o0W7{YehĉܦNF۲G ,!(D'OK$AA>⛜o+a{F]`j78?`B/ Lֳ1t἞ E% 鹛(ѫ JCv}Y$/{;=|I% 2PU <~tIB1yk*~+¤zzP&e@Yt݌tZ\dqe7E'9"让M =4^@O0m8TSv7ӯ}aG&R "fgMl)H({ˆ|]P,•'}&HrͳFyU'UE}Rm(mTL/Ez& nqNٴ`iOC:p*AJ+uYFӲ%Qs<pb%K:ߗR_14_{Hjt7%PRµϟݟ򧯿???~(Zc^yuⓦˢ( |m80{iL _rz1eS>()qI' )zlq #hBkMNe,}}@G uǰ/#{0o1lz8 6-)EtXuܢd"Z"~{PYSi.Swr9?J:,QWm+S'YOHjpY?_@Io[ܢI}N__Z7H|/ i:?SHu zma]5!!% j?"3G}PF=>M/f@VN/ [pJgk E8B-/fk_0Wo%zҁ+' 7E@Z .m#7W|HF?#egC نyn{sٌ =a1IX32瑙v_$+Oےgk t$:/ n~YkH}Nߔ8L +^Xj@!Us<^q6}p[@Yy"C =a(IC0LC7.6 #H0Ϭ qmhAf0W>8V7wc> ~EgV"m#9񠲗S =a&)>s.͜Zdm>S|*i;&(Pv˙/!0ಭ(XhF4Xʽ㽨|G&_d]˭NK\ḻlO.2; 5Έ; ` Q()QƘ"kÆ}M߶dy?#+Hj IaR30YVYBä#sQ=qK܍9(5g1r6یSg\M(;9ոi:/O|ґuvɵwuk@![iA[$$ R)Z"(vF/+Vg_ɉY9zzy8 pڣk( M} ).liOMT^#eֶU7$1 &)0Ncl{) 'XB|?)?=Pȶ2%z'xЀpz@# q'J3R`K @!Ue\MJ*v)&eo+J'6@٥ZwYF|?e&uѣm w1'膌TE װ# 0l ̗=aF;(c/P\\, X1Cqdeδ'm8ҴA'8ߖe#eU鉈l$0WƘ%z%uk۲ʢ~ywp&erpX]OS>&&(\]|B*¹FTRϱmbVce6T@bl&018vu7TpB&t,u(9<_f'ÅEڪ45I_BRM">L(e3۸9 eo)k^Yn~,qa:Wfw-RS%ZM 8?⬥Dj*['O-|<Dž, p>5qIe!IVpePkkJ0E7|(K\}b fQR5uGSRSc(.y^`h-W00HXA۠!V)e]0T'GYP잲~Fw"8 5W{ChJMߕ_d T^Vl[cOS )c¢՘tH}F[{2XBI ޶Ћ#>=H),Wlr%ߖ=a_ڟ'\_fⲬu'H ַOE_tK-rVyUXm[;+arӘ^. `UUY@W`_vGSn JAڬd_&@YL^=dqШXkr*Mu1ۙď =Pn8^& ѷIqaH8r">[ftt.n\*Vs@m@#pCu$]H^B)DZbp)P<#dѥ%To6{|$K3XJsHS6Ja.~#l=Il6)(rh"Wqb9Hz[@Y]z(dwBG- 5W >RC:/r`LzajkeyjLŏe!S{BU?:]pN 8۶&0tvRxѸtBXk" ݌tU$;jsˬss^_DaB0˫4 099tkl{:b*<'I|Q0yl``ZT"ڀqqɑ >HxW^9wL፯rLxCxЦ< o _@\-L{m9:$UVçjs\)3DK8f8fV. T]oKy.|S\R#'OGז랜hW WN'TI`a'"H2؜ο+rpv0ѱnn g:X=&[༜6&DžtfjŗS/41'[ȔG>).NAp[̰ K}7kL/[(ЎOBXUQN lgr18 *;!$*%89VʵQe*c'|&?ohOfl=M&Q[ci;=|M;oQqc\oՠQ7c..u;8bwJ<,R`֣j1T#(PvG77:4g\oS)xFzޛ3N1=v#>#B*޴Yr7:&T( bГ*ۗA;rq8[z8sO?Vř7dv0#xxΓIQ0\JUE'/ pR٣vSUlj/"W9& zQ(IGW@*qLIg {oәѠ ιmzU2܃<2T,<9ǧ !*n;Ԃesj?Pyy*JS{Ioʸí=?+mmm@wA 1'EEDpa j$u\88hLr (vB0@FP/{899óVȂ琢:+9 Jsۏ(W^Ͽ_8T]oA%솨m#E mmBTősP"ӔwbOvk7Y7VU{\:0 ޓJ)(yNJ,&I_u1x9GZ(akmJ'(eg(c0l9MZ-ek =-G N!?q oLYYM_p(ޱ~eSghBY#?fRMUy R  -HlWfPX.^O ԋ;@[% RB K-۹C 0qLAYS 7[^s5!¸_|_(-EOP|Gz9O~"q)xg=gu`qn׽n<^ }#N|ѽx 膪QգM%oNtC8y7p.-f b|G(Ps~B1Zuq^9nǘZbf{R`84:jyC82COs/3Oi 'P+ *x}?Гd qdA Ak}ClO8ey= `e8[B!3 6@T3ͬO I錇)b QNU}xz ng'KyNpjaqeo/8>˫50~?ätmb({¸_}HOvL?z_M){ck@t(⮑t.QzjQ ɑfA im i\L=Wa8 c..Cx7O[$Z/ +">&2}IS)-Jڂ[&&si f$&}ӆ!?Inbۀ7sf:7lcJ-xj )qstՐl~g(Ҏl߬FZ(d@'N\E4q8!NW w=ʏq ūq\>gD]\Yng % YS) e0_PHܤ;AW[îkH |ߺhpi.اEUH=`@NjjT֍鵅r`H(혚jWo(ͰieS a7'Ur<MR'-p-/}z plڧC fH x>B* :եZ>e7L0+tSxʧU)-XPv~J7Z 5quReocMhߓ<;gf :׍YjE 9T{&  _OJW' WX3(J9Ix P} g( 烵KV12:}ZЅ'Pp"Xk0¹9Ya]H40R 7CIr y.hS} 5UjJWτPHnV=y/0Mj>t&(rǏewM<(DzDo.~@!-[+>>Rb0|Q o wyB =KV[ ט{gC:60+wWz{V67U7a^(vrmC@%&0h[lqwғ51GwQk\ Qk\Vm_.f{0m@ά+ݶV(޸Pq6É/w)-R^g v Q( I0߮:j>Xxz:=6up%~xZbVlj`1pB+ 5=^;ٞnd1eb:)N"ꢌVhé|CjvVZzl8ѽ#:nZ ;.Z TI^$-W3*$T,X .%6 Ȣ:k#6 lG.n0ۖ^f:\g>%ACa,[/U_dOpGR,`DR!^ЙzvwAFunɋco -.Cl} V(AFan腞Sbf۹˵vජ6˂̍U:OAѳ>tztdtжQpuaS fBBqXn&-3ۥd9ٴANxM 𖿸}ƲsжYsC08d"+qIV uQoh7۪Dc!qN6mْi b([0J vA[ *i@L12tz$7oE=,{{"aN6m!i¼rLSZ1a5qq*ox>*QZY$D":Җ)u:Qу$b^tB(,ΨR[:KJ.gtV.`T 80/A)hAKg@xu.8'Utu19aJtؘ:ņrڶv^.<+-x$1~}F砭L֥O_0[0zѦy7Э|43l?5MܽяV]_OޜvU_ø>;(^@ŏ_\7!?}w\xwP^gh+Rv !<gpj~iĬ- y"2u NM7I0@idjWK;QqA־~BœlP;ah ijh/=FnmjH WE` %Z:E {)! ,nM)g$s=8gZ-CT蠭\Yt^*0"mp4W7lkt.p~$lG_^6UsжB)1 o7z[z%Ru :-OA-dtc7E骉9O/3z뼹jiZ,ț%A-JVc mcЋJa6- S,/i +_hl:gDٴ)*4gڝCQ%A6EM޻3`Ѕx lv]_Z F\z;9ti8gS:wzkN[u֠+]`:SET%~js1mnמet" W.UI3Ws6ѡF:/=VB&,Gŕ믂#?J3kN{Vf(,PGDMzW/|hy# @a+`oy9:p!1Q:h/=Т 2э 9$PmĄuOAͺtE@_gq. tж͹NShF()dw Qf8gT[a] G|&. sirwxT9&/:4AljF(+ B$33jҭf&c[sV[5 /.}7Lղwa9 t+V  Ψu`4T@{;KSV* \J3i 8A[)4 ^-0SKP,1˕`uT\1jTLHS1: i>>f=tж{R1hA%0+lpq弹nAp4$ h*?3}`8A6y#7Dp~.qN6ْ A DٜO\ IYtL;'+J`*̬pΦ5)4$ FO~C l\H),m~;h(SBX,R’LCȲ3 :o32aM#3MY N_B "U-J3,;3*.w La*C0$X$K{hAv@gZn/Y 4ҁEZXY5y^Qm=/?M7mMm;a^60iɞ~3=E^W=U?Ȑ\+!\Y=glZ~G%Z9hhS*mLe2,R ;NWmA22*̅`I|:#K3&fwd qט\%Avr]HG,lppSCr-XXCjE%KVw=g@B$H ZZsYgV tf!7d|K+Km'aɀ YNu؀綋[:hI) -ƼO29ٴ/hA]ȴL[=Mea m;0I$1h9.6"eSNӯl1' b^YԢdӀsFոX&es|)m;.qެ lqpڶPbD*W#AiaO.LKm1̮ ,fjZj:Da gog9v9h>bt >n"6wj<37x8mp7ώ.Ŵ">:=*Gfx栎+Q'd:L*!B<&9#AF qV@f_K}9ꀴ+gpxs6vzYKm8ru<3R^Ļi QQNkagT F$s00gTlTF&qڶ-n3[ JC<,IqA)Wt8f4Ki#(%}l*).huy^. ϓ@gTdV*; 8'jS-SUM#;8YIiW4+dVBݬ茺jjk^ls8mŹ楜uU9/a?e;|z}5tOg=Ͼ ݼ9ӺS_<Э95܅ o/#鲮ʗuGΡ0­Q5amxr8wGy:@䊈:]w$]ht>tMk!47!7>\Q7Z'Bke\ ={/w7ϡ{}CN-A"8.@w9i5 CUĸL]:8wc}UJyŒtY\$Sݧ)ôh/_\63]U;]޼?|7/|l]d}jB?.V^i]ҍwG/u"g65N7qx XGQ//qd +|sͪZd GhyA6_~)?s/0cj:gz\hTq5}\ #4 1"_ĢATڍ'a%MퟴvC*a7Bu|afozZck1$s0ODBt岜rwx'ZsxI3o>CХ V1Hϟe:)i2-?WЋoL|wI[(u s_rg8=o1m`ʉ <~I?<}?qe.fH7WюdǗt'Mr;sw^ 1i%q9D凃go),EwM_~r%d&O6(Aߤͅ=GM[^O?*r fe]a#,1rI?r\PM):&d3šְ8_@v(ۓDz_87/|5dQTKNua@~IʫdNL[a)[/#KBL}JUf6 5ЬkeAFFA>,[\%[+|Auloa_ 85JW_-_˒|u'I}-'U:o+0\lA<շ%]E l}齗[%zS e7aIDkLN 3|qe{\UUX1%y\(q·Jc*%Pd0ѓ-UJR\ C3}Ս%w iԺGEO }IzTDIvv Ou J-٪Dc:okҫ.ˌf4O#S^%]:'EtS'cSeӧFL_nerir+)?> FY 4|߼<+z싗}65iicy^)}B`L,Oh¡+.M-P7fS񇸇֎N'Iߤ9VTM%1H_<Ŋ ֝:qwBRY3l)Zfb.fCs!IQtDɒ tNͦe Bݣ:˺>-Tǰ`tJS2^D,Ei^3s[Ѹ ye8EW\ JQ]Ժ'܉" G2ѧ?i 뾐x9 )]ܼ%tq|aqRdN9y}:|~}x{hц\gL], mendstream endobj 688 0 obj 67245 endobj 696 0 obj <> stream x$Mn%M1˖MK%bln6ɞ/["Gr8"2q5V(?pr_ݭ߯_?t_[O?G_|?KmQ? WwmZm_??~__SA1Aoudn oU~M_=[[Ͱh6_KM!aMcןˣ[vevug*YLͥa|[Vտo}2E2x"TjmaMSC6Rm4y5uNыu_nF:ok_l?irb{j/#,oږ^eU^`zwkԊmqmn]tTVMT呇ncjE/muui0hZ[e^Zt]cZj_^^ݭ[ n­>7k4eZ6Zjmt:؟gNj߇Y! *:}~Q e%qo6ed/XcLd+XVu֡c^]2xM+{i:fa(ϷO:ڨmt~rVn"y2ӫ2fPҫ\Z%^{UmYZ=J3/56Y ȞڪZU϶5uC:dO=s9/p]>,A2'75kVO4%|(=cBi 3O%XAj# >V#㢣.!h=! ]YN,TSQ}924/#8a,6He_vWz,E,.Gi]Xbۢͯ%˩uXf(-T}v*(Swl.#jRJ1zgqv̥_{̵ /YIcüHjT)9ID#t_O7IJȶg,j~QY#*P"^tG**FS`|1' Pf_,RPMX('19=PCttH1r 7oŵ3̀rˠÚcAOTLSl5F(n9SP@vqBZyUƲH6|'^t|DUkPǔp ꘈ&ƲlNJj% 7f9Amßp >3,Q2ʁ{:v7Pȡ3IîAD"jOn& Ȯ6SYܺv)֎苛̷[)KAd>71 QDtEiW71~ՐD3L 90';):[RXԡ4;x:(Vd^TR##+#y:]6Y)8p(=eQy>8n({i/*F)i4Q( (D t׬ttOm4wr2dfZ.}z7]׀u*m7-0,Ir`s 9ny3]G,g roYMifGd<`R\mȼr~SٴcRQDnjoy~V/Kd ȮVRnV[+jx bϡ;b6+rЂx ǫr @!떆emݸ8/^uinK*Y*p& ݵ?(PUK<]*yjڽyIqRAIn]}nxHA1%YO< Ȯbɼ [)J=ŜK1VwJ:*(#ri?{urĺlzY#ٟ:xӀꃀ-۹rg٦axtS)4/>}N*I Jam+t0[=u.b$nq]oUPG3fy8EXD:v$pG[r""gÖ( <l @!Ɓ\ǒFq dq F;stl×m8E"y99AsR ]yٕ}2LQ=i˕.N[cm &=mH)0L$qr> ]F]yj+Ƶu^r`2\mViCʁB< 1ذ=x~/v|XLYⒾxȮ+>F!On$$6;4nCլ\0[iU-u~ ) &LR'GǟXĄuau? 'Å)VX=NAë2ZX#yxQmp_䪙|uN .kQʖOڝXPĴ"Pu+_he*$l8).Lx%(䨏ܻzQCϺ2}<H- Lqa> ]W|@!T}\359@EEKB5o!, )NLQ_PӨowEӲ( >Uy/S2LM匠1׳]Z$w02G[e.k3 *2lqCte>.f5J-Ί )Kx|$(7f>brşj-ĥ,ImX=~0Ä?UzC} %ZQ*Q[ێ J9*ر1J/ʁqF1ǫB1Ҩ*ohf7؈R\Y)s?D (P/W{%<%//\]r riY۩Z/2@oh,6LqY- [$4(P}.1W a (S}EKeiIq;3V 9vm1ͶIrs|0{2`n`np$ք.wϷJ}X̊@n2YEY 9p#ws}=veJc`~|;B4eXXlEp@Ԩgj:}Xdqˤ1F9?Dg]uldW)u ϭ1nk;FvrHm`paJ;*۞uhuyn. @U]i6Rl< ;i?}bDj=!ɣ/_k)8rusry럂~2}2dː ͰwzɼHqpws[B>hmG';'8xU6Bcs(gWOh`_άLN*sO9c 9\Bjx|Æ3Cy&g( pzr f0sT{!rmKP`c* ;@aG:~,z:%H&01QkX[,o` '^e9d~V󈞂UQH&݊9w>i !l ̑avτȝ0Ks, Bgim3~K5dqĴ˭3L3y;=P;%E凄Ӹvo"3ҝ.2}9O-g|Va,Pq.d4 ϬF=e\V}4ui7LWKE&9dժy ^t;WR2[uܞzI0XL.$Y繺J6xm73ʸV,aoe<:O0V2M 9[&^.i gsՌ/rO?a8tJk-@MsEΆ' mn2~n;;w9aBeoJc;ІCOj7{n6m0=q Be?E臧wB4>H?( H?,R:˼xC/[U'| 3mzïHFCzRlD)N@2qI!Z)~ǀUT# uWHr(%\y(䰽]\kXJ $i]&iMrBYIYN/}SO:Q pISMrn/a۠ؠ6!)0d`yj0y#" '{r:Ϲ~Ms`z 86?.dzB[CV7)xpL3mJFt(YH%Mj8Xf1943c(9.&.Y6tkaפr$C.yyμ,Flr(qerNN@&|g@!C5O90FWW ySj`-5N'0Ӕ;f؟7]Ȍċ|{}`@bw;4r`S9(ۧ؉AO,9N@vtŔE?׹csBX}bLq1){Ŋ&FrLCZG"mGm8kz#a۵miY}Zfa6-)P@sk61l>PGkNՈf(fUB\% W=vBq=ԙ%5@΢o=Nȁ)j ꍫ#z:=MMg'}GLHꈈc%7iڢ0.-'^t,3yUVT[?lQ' ȤFx|mN%ha/{~d4`ѵcf,hzQ"Ok]ט< z3Fk!Jl?)hʸV,ioe!l]9]H,gl2Xa=tK ]4jҫg]o9f? NEa/z`_+՚?( #ht 7Jwt6!.f"DFgJ }ձ|~8xA'g B&e{R;IT9'AOY׏O#IX]0i#8'ϸ?USa!9y>4(:wl).cm'l~MǶFo?t^ƌABs `R㺔zaTh:am^R,YH`VW}kRF$]nE!Q@qkDseڞx5wY E( Vh,3v14}L( VhlV(itDBz!0\kn6D9}'& J_Ov3kD*?,R=9=&z*?[ [3xVv+auMim )Ƅhd!k 9P'KoʑRd& F=e3{ׯ~Hj6x]U" ^&+<^RDЫkŲz'uRs*%Co m[bz`r*#X*{rmMHvhÄZPqj9?c /볝B2848w>;^ .k_zcS(rN7NqŝF׬)9 QDy(QN*E|J{ @;)%0R)vf#@#Ey-zxL1; 'TҝոD h&QOM|&}Kv?=NQ!SSKswƘ=R VЄLvAwБMO r)>o!˚N pe<5oyOPqGT zy~$8 UK/v0쎪EoNee!Z|QOy-U ~+G} Y(*+7o^6 ޢBw`,Y\pz6ҸԖSNSbz%ݕY-bC&7Pl9<%@)l>&7Ԋٴ1xq ?,2F:udWw IK*}^{aPo嫧9NXeU&(U^B} Jv / [F9cn\L2k^q: NX|yʣ9%=kgW &=[1g f˦'Q3sjpU_PJU-8QO??W}_57?~?e9?͗Ȧ/Th,_Ӂ(~h*Uĭ߿?]Mgy$PٲtcVZUL0Ğn/6|QO)ke]<(-!my+r#Myb f5p|>eWn3gXj#JBZG^T6cyHcf 9;6i}%|@0 ,kvbLB5aݩ.S3~>h2\X3>]n%86Arʊ!H^E<< ij֍"BWf7EqXCTX%9)}>~-&KSyr?t0=է~;oYcP[Wp"<`H ==}S$; M)Z}$@ z,&Vh0SSQ/3˹N$KNr ؎sҾ(;r1}B\1PG0 g@b!B5biy,  ;%y,Y+l\{|`2)}v;+v&o&B=?Rj9u9;R#( }J=A|+]*1Akr 2 `!dI1+B}R 9q Q^S6k?1Q]+W-٬3m[),Z8M(٪/=3L> *yCr;{\W[1N̝ biр_J=Z]gIv( ;#v)LlÃtӣ۷凅 !=0oҰ (EP|`#zV+T&߁5)pBZ&fS}qx\ Ɗ7&6#"˄cjJ5%M9x%wIW<]F_}n`@]Bj{RXi8מÑZ!),dFh4,$3=]ӪvG8l<);!W\jV芇-Qþ1 ܕ\`wV(,8W% _lƮB=uPKe\+Tw{T"[̄Jَ_(* *h.VgI¥{k9 vCPגV?Ce@Y@~HfHIJ'!pU$vIC7=)V y hֆQOP"Eh΀ߘ2d@1]2?* ~{ED6Aqllj\ ιqRnO .c>6CDO+`[ +=GǙmuܕ 7ʌ궚ռc( +z[F=>Yf-V>ayӯ(?*E?QqatQdG|8Q|쎺rF-zh!11iw xp517,R/d/ BF;μK!OVp&d1ɴl fOMs@a;Zꛊ³݀xxnȢ=u9_ ;ppݬ%03DK,vt%X H ( 2_L3fIa1)T;<@!nl0ipQQ+`pn֮l@x_0Ԥ|: JvaCen.c~2( 2oy`)Su-=2`֮hWLZM۠ñ T3˙e?7kC3!*9Un\}ތ7xY-)J%$Ѵ i_̟mcḤ5KPƵbKVv[r ORw~yCN]m9ˆuvipB=-uMzxQۚ0gQR?,0mGQ̀]PD+nmJ($gi;}×:vOP@ӻL+px6'vyFh8(=]gt\G2)Ia1COPQ;u%%F0`!wt!G<7\?;[Cn3"HD8~i[׶z}] MM {o6YL 7N|&%X[nSêaZty2Bqѷ |Yꡛz3a SXXq6di3܈ilQM)+Z1װ.d޾]x>J86Q@o{9םܚ/!Yn ȮXz3g'3,exVt6k&Բ눧(C%|!΍>klhX{W!Z4:e_' .gv<3_}S  fz6 }z}tZ.`/x2>yyԢ{rhm@)0,?>XV9_8!z4Osa Hۜdo wn)[P 띑#EEB5e5ɐ{![ԓN5g Α Y:vdCjEJ{ܖ:캾GH0^qqa2ȥ6?`Nqzv_)π"EnQ^ 둑@NQ& /F_t(s> g[(_r[|ie돏]rZ%2co*+'vCĢ;-Μ{n{@!׹wաwKi5td?|k^S[}yu(x htB)0.c'(}, NUA|ㄜEo|&9eR.h,QKL?(ax#0/eQ1 6+)[b&U+B"\QM QgBo⤵F5KjH1cY_KGҽQYpŽ~-7?rQnxp"-`bY#+( ʸVhmN(pE~wܡr6 Vno)qnn2ߖ)̤@ŔxJW_<`ػgx 9npHȴK8ur?QAẀMJ +Fz/B5VRpEyGi|{ɠH-JqakxO{Bsv^׊G[=PW ڹ':fU,GePU]U VOҊPϸӴpշϓZBU6?)>j|P`MBDwqyIQ9 ﻢ} 9~Q1V3[y#% }:[#B=Vt7ԩ]_ê#P@it\?^vmJGt8zQ *+sW͑rT Df D:( ȮK=>xٸ'#(ڣ*w# VG]o5Sxu? ÓD.l/?ۃOkF'g‹w%ϪyoJk U$ lngEn/uZP.Z0 !8O]FGՕ-<*@D$E]Aㆍ2eǛzsހCZ !Uyfp .ک`vƈQ6ds['w֥Q9ˍ Yr'MTd ? {7Mcq"|R8^@Q|^tv4ɵ#P@vU[SE2Ki-+jaI#P@vM??`бYCtyɌ/}muAq#P@vu o~ΦNLw'/zuYg}ʓIPXE=>mޏ%M  |DܘHyjYKO:`0@e8vMJ-R1HsE<5qyFU^JWd&nG N@vq m |Lg !]V4Pډ(&щ(rNV)} 駭 P@vYi8ъZٚ~Xz}g:Nh(P}ӸAF[Ej]W]gkPu͡*DQyu-GJ8ilR`tA!v[e* 9TW'*vn:;vK@6+.9UJD L1c0EZx} R [#J=j/feIy,S@]๋Se"/'edOK_la`EWʼn?F9J4^,GۨR`t!rYEN(BEQ2ќLLjZdWz [(J=ן~fPa\F7xe\+]F[0˄~*\$&:Űqty>ӕ_~hRXc U[^vy@n/{; lH)PpdlHg}dz( N:N9y}Ps8{j- BX[ c' oAx`tG vS`|S$ AvjB5+ K1?qEeX14Bq?Cm\7JeHҪ+/&(g(]zxsV@Cھ>(ym3։tvv$$H;*Bԥʼn:bT4~'V`0ƞ+Z7Z"(CM<*sDžWpΟg>uq;-VvG]yq}8q­$~IOj]$q&@.ZW*t(P=;+ARQeV1r!ahQ8uQ0F9W&WN;Y-_jv(ex$`b3DtE;@M@1yʔ 2(x;}e76_@v/shXa厐*u?xW=YV5p͔zx(Z/3EXGrE/A)]q?Eh#"W^޼QVwPwmg;SbzA 8wc` {kіRϸUl{)'ċbWA4*M7Еv{%2kΐozxh9x ozm'x ٪ϕ*UTq+tH9+ ]v{^wxl0NH'WJW? w'^tTם5w6A.TcJ 7μԖ>(y(o1tyu;E;)sa1i r΁oe6XR㵪x{fߠ@7?\_|Bl]L_;.0xh9v@!n-l\r.ax06-).;-?7읩P\R9ͮMR lX~pjvb[;rч.RP@vҧ֭@}ܻs`\ Gs~fgL=pqػz'ڕ[v@!NPOtz5'!,8|aB9ᮟ6W!ɆF^%"e.Nȁ2j"LKr d@ sirTԑՄ7ܹlX(&@=P/'0)Ib:<}鏆ΏQ(ZapK ;T{lD*GwCP@Ғ/Pȁ{Ϲ-!\iod9v@! yWH,3ܑMKyI&@=PƵ`1<*Հ`9ۀ2\x} tPhen- YT~5xb ^zZi1'ܨ.W­mR„S_(H9'Jf[:A~[z_>H=( o8 94$!yĭ[6ܲz /P}/D/)式8=N8?Vmf}r w&^tGMDl[{gCن%\ {kр -\Bur>(u)(RZZ$s}E2 9pQ])xp‡ gD*aQU3_iQ ЇWCt3w 1(0k`_[w ᜤȅ* a /x᭸yNMxKoӒk5Һ늯PqCt+od˃pJe\+tJδ{~7b H&Mvbs`xq؋Vv1Y@Eqoi=j[ft%Q'^tTэ|t@!W[;\sZ&Z=mot 'EKXrgZۖ<~[K( ʸVP?z?wśm@)098մ+Or4ͻ%7'5INᝈSN'@ǿ(^bMעam%ɴן>߿珿L1mcKɌ~_/?o~QqeuK tco(e_%ɴ ÑƝ:^^nebfg%7ƳL}( ʘgP1 h P@)']A''bX Z2n xgQ b0 9TO=.tlZR`x% 7|)+rrI=l/S3VdQL= p{ ၭk%mՏGѐ)N@vG]T#lRDҴ;I#0 Mt%&#2x=PŹS9GW42 ~JSp&ҷg~'Ja! ۮ)0 D7næ{]__~'Ez]\+oe@Wtk)(䂂յm.-MNjɪljUT#IlL|zq:> Wh 0+x$57j.r]81J.M^k{q'ܨ:MsjCFP ф ֦ZC3+hp8ޢooI4f5^n׶wlH)ۈDP}K<u빭}: 9P_\7ƒ"G GsIIBUW?Jv*8 `Gomsgkגj)3;]YGq.ӔW:K'8a4 Z w<$)Em%ҞG[gvh[Q*m걇ax)(qꑨʸV4oe1ƴ J=vtu rQ--[ɏGnoic30%i,g?kc;ddwԕ߉YwCqE@4r`RQTF)Ng=9eI":<7Ļ/`(龜 QH(Zc=:C 3GRL?(:@ f3T7@=Pq08،]R`X[ w6TOv< @aJzX=LYüK ёH}Ic]}IzU"J擣U>)ixx=P?!PZ{Tx~-nKwX&}9y(k"`d*6pY~zdD$vS`x])o뉯Pa;l)=_oZΨy|^R%a ʂ1~#@/9kWqü*y {kUڬQ)q(-_ajaz )&(%blMn.XrW ^yZg!^_%z.oPv# IX&Xǔ2UL`ZɊI^vtq0*8mz*8f;c/w {-uSU( kӗoӓR I!=V>WF/h>p'%[>W[_~ؚ*'a ر's$O*'@!OemI:r<:d!N42Er1r (&p&Τ '&0sJy҇lxzy=2SDy@%y<ϰg2bt|+i?EP@vEJa(9N;0^WX_\Z29d{kUv~yTw @fxeh=PE5*iPS ЕIYde@ת)8xk6*&C8[9@ .\L]ɇd FPF,<=7p<@ CHk ȮxҼUMuvn~zIAYʝy+w>RC,q^L+>)&fTIe)j .f]Xm@sZʰж8܂!gNϗdWS>pO zT:[˯o(ĻOOXtryьe}:'7۶p' Sr'=NA躺>J'`{Nq1u m']Qe9GixzI#@5GB_祾%=J@v4銷Ѓe?QӏcN+9Vo8T>]Qy+,\٧ԓU,"aoA&aO9ۗ:5-cpQaau>`u=Pȡ<%Ќ4g3Jw3]aoԦ$遰ʞBNx 5OC dWKުXN ؽ|LTLWƵbH{+`LFȕeS;#e%84ԏ Ȯҝ6z;ȟHLx"/zG"d]Mޖcq=iP$)Zd dϲNvj{5I8M*,|;# hPV|3p IŔ1=ǐB tdY͕yKf /o$!ʸdK."tuaꠌO,mlDz颱h(^xbRHHQZ=).&.8m8@ |8ueiP Ii)ԯ=b0ԭMº;G@>^vŦ歊 \zS2YĨ"go9rn4gkH2ȸD01CޞAc;mC|?'Nq9~{%' L1B-so⨏ d19ȴ&Np]egD b8d#Jae7RSr/٫ ?63Կ&).λl :v[Y;4ܤo<.E9x br;| e?9;XC`/x!ਞ75`Ġ 9𜉛zѹ^n1T ޑqqQ7IR\0 _o8r~g=NQ)ʟH,I}8l/>rh( V@=+ŠYdHd ?_>Ǒ Rθ=;v/ ;< ]i?p[|k/.D63Ħ"R6 (ga8sŦ\ .ơ6IDgMξ62HdxĒ}} b=J@vJլֲ=_LG+Ŵp|]/ M Y4PN;}Pء]7 FJ6rI Ղ&r8񢘴"!?hۅQp)I-L%#_+H^J~" 6:`bh$Np1Ze(HSL'RcixP#( $^ACv/*zlzNd.JPUF0E@YH8G\X[W(2paZ!of+ĨHI'o d3O_RW.AE?GD$γHr`Ӂsĭ"vnw~9".džμn`{3bڀ2\DGvyf'8>>-#$1UhO{`&0؆3wK Y.'D(PSBD݈{|lj]!6-E:}_g|8+6\Bw=yR`΂2,uųri O&{ٻb9 ,! eDC.r~rv6/z̈yQr;xxQ:Tc@+it8+-m'(F9e Ȧ$|η ? έd4ǀ9"mENm+IpE)ӗSȟ eSO!TsDrΌ^m.|ƻH;vD $%+"o[R#e63 {t-ں{:Y?,5TqkJ=N@.gwkg{,N}c~~: #(I(&B3\XrPI6Xni¦;4.|9xѻlM@Hw9h<3:$3UK'MR su氷OON`wI~=BE]DY[\FI88I^~uϑN@nr.FDWԺzGN)sGKA%!ݬOO2>1Ǵև %-]f\N*vVcf#lb~*rrBbQºq,F]D g3Cl\Q8ӭ$j,]pA`ʶ;Q D_AuQؔ/p͑Ϧ-wн_pSMʟǾ{9?).̩*"Wh;sni aѽ,aM m6C!R@,9}:ǖLG@ sc̚%I4"*y:D#4FMj!x,ϒ]lv#I/{?\DWƵSH}+S5̝m^D\Q4(J ,<);Ds5 9ԛWPG0ɽ2"Sj3%pteCVF[.S0Y@(?H-&-pIO)g/}AM~xW2:?HO6}@S=tPne0+#Fӭn>M8r9!`n{O7N0uXkBvTޛ>NQQ:jƇ8jvI_\:eq~*zb?^( xr 5a{NQ heΣ>=Pqa7@Ƈ( 61!1qvCПHgcVQkn1ǚ[[?E3O<GmZ<,%{|?$V 9PO=GoE1]u'F@kǸnDċ.S:G1޶b7M^׊#,+!J}[+jMp' Eҏm-ٜ_koP7 *JXqOxp#n*L{Unpgs~ċ.bЭ愋?U2@ٻ|7ieɭW%Ũ2S)^P% 6ğGDd:"qy>`8@x`gFŅ4Eђr Jn @ۃn|!2yAm>*~~s؊8$vF%m_a(~7Nxz-!/Glt6=8y!#Q6ą^s,E_-đ vR 'ø4RשnIY-p^u!< @,uHs 8!Rx/ ݷQ~),CP퓯*E3L5}B)7Ggzt!n m1m!~g&E)TlZ~Ηۮa6!L(!3' D本I۶''YxJLpåKMw#n:ýV6ׂrSx\_xh{_۬0Sk]rw>LAKL).rI+Kw#^::89xt*d4f([߽Q7D1Z0 ^AB 9Sg x@[p"s2s2mj}θ_1M}_tY}M.}pa%mG=RNh.v \7)0dH_(@;=΋=~ q>Y1T@Dx@ۓs ߶ =~҉\|'wWOjdЗj@G4'`:E >E0|0xDBC6;IDy9/ }ծZWL_8'K,G7 bsGw/%*~aIpcju݋bbVU@!{ ZOӻ-(\!!x%Qމδryܹoᴲ Z98W) ע E G-@-*(M:X_殜a=+[ Oң žtBXj'I{nfP߱}RZrP-? E\PpWL/pb6'mlӿ޷oþoZ-La9~Fqgï^y ~;AOKI+VĹzl/RRrzoK@"jٴ[Qu??[Ki/Onm]s$)by:rT ~:ժș3&ת[v,k6:SD=mz*]QFMr߻^Zq.-sKD㬷 qFFi^ĄR^*~\u\JѲKzYmG&Nst"Ѷn,702@9MoW58UScY}WKܥ(&U?u]Tm7K_Y}]ZJoը7޸3mo}ɾ.ȿIcqe}/s}-zykVjN0}p kul6V{׺Cb[/^6:> XA)+eU=w:YNIթtZjOkާSʆ,y(7*MvA/lQ:h4ҝF|;यrihOhyokeh!e^}[I@Eq 4_SlZFv=3l8j [=o,~|fqN! j'pg{ІS>Z6-Z9Qk=V߆UFZ[^Vs'o,G8RѢKRs!_s23<Yט,y.`)\5;dqq1_r-.rH:d/~ ł!7=6C5Umبm755W_6Es_nRqBZΫ^t+Ef W{90;沘Mtw"J7C@MjO.85o;*pHv_Uۻ.j~ /Veoݢ@#Z17bRsQs@}Hr5 M 0w,9h8o{X4?A)fe{F-.`:NYyc%1@[| LpTpWܴK)LA* 9T鋹@!fNtUIyڻ3. Dl0X$ߙ@[|Knr{bNpZ '%Ĝ.O3a ҧڞN{7淬m zco zcNWZo<],qNSV+960. ֚.<3CO5X满x@! IP{KX^o#ݛ?%p6ɫHnq:?S0ܚ1:KC @F0o{9ƷRq}lxr(Nv0wcVB Z}}W?7zVm8+1u)ŸnPfw ymOއ{_@޳"㔨SD,cvuuF8@Wy2mǻ_Gvʦ;8 -Y R7:<&fjP w=_ vR =T~re0/ @!eN}qћm"7.ljozv I\H,utn\:ջ""/fu[&Q h;8 ǻR3r>!PHӹ!hyšm>3@% #󯉱3I^Sw/?lGL8ܺ6UĀ94æa v8+>뇗|nyX n*k8JaLۂO K-KC4̃G~pi=iq,~t"ZN$\ĉ[vVm4DPtAPEbL ^='E:G:6R`Gsp=PHɝZ5nw_JB $"8w\Ŝ~Vevgq0m6 (9R6mYbhc) d/n[H?j,v1ZtT/@ҭ 85wہxGΧ)ΫN b wj}j{gdFJz@ۣ+*t.z|%F1?ơ$1i1@!_Q((jYzlL=b`7-}-y &~*t8M"7=^0#(azˍLboG^aQJ"Is:q|s$٥mW \V{Wsy-S%ʁq,t޿=PHQ-RyNI`q<)u%g"a}R8Cny[61)N h'ջoNd8!5)DPUxpL"Bq0:fzc`WQ =opl~qnu^9\ZF5+w=}y§}WMp=Pٹ9w1Y,$}{_k Ħ)pNGV?S[)ruNʓԵoG={NM|Ksn"b7ai[0b(NA.Uq:_) ύDh:A -Oĝ] IӛabUy!J!48tc!<쇵ާ0EmsQ2S>8DF#D )yp !- mG~&lXܞaX2]O5zL.e 7L8ӨcXn7e ;(LZɱٿײ# -~Gr,1? ʩe̽nǡkJԬ1b@d 'Ϻw=N8SGvXKdxWpm;wH(T-^hAi-ez wm;{)RA]gSD )N?/~Key.fZDto1x`ɜpC ?KV)q엓cGJkk%AMP K"b'"Zlli~g柏(bb`ldM4bfT~盀7=o8{똡am!H&Q Q()Ҥ.帝RǣbӜ"~Z3c=ʿ|-ZR/8F?1㏏/x}>~oQHsga| lOϨm 6:A% -JxLz{6[6lxmqxak޶ؗæپk B2o4"n#bRf*L3-a Ł_D8wbl݈ш S_u+Zi"y1iR`Lv/QR֖O4k1: 2OAV;dypBL*[<~B9hG! N\OwK}:#HybSc& TO# )uOMŵ~&@8=OAbF i+<57D }"U!T0(qK|x@c>If¬[藣 BW63b88d~KX䓉N k'' 4YN? VO^p!ZaWC/{+Y_5JB6ϳ ?o˭ Q:yן=7SL] 'A{\z=赛MgT@̸v (aEbpo/֮CD :-k9:S9J1Y>'1ڱ`1"d@M&Ī L׾&U^L G&ضۤ3mapUѩcMEtOL?϶P)0fRQ9qr;q )Q]y<U/OoM7AWq,͇'+zg״w~LzgsceC}{rs_]p\΃NEπh{#_9 t)|4F[zEaZlVO}VC 71$ nm#{uߗ?W2tNFc:&' SʥܪL EWgm^)>Kð_uɓbcC 'u@{_2^L"uZf)a)Ǎ>R/uIDrγ*R4 5֖P1 }2 [)b,4fhM=y]~zX._yG۠uԩ7A+!xvlsxyQǰT $ 7}G zG+< nӧм+Ddq[pm^87l͝/r ayl^wwCSX:kh,"Ϊ9׍,>&Q S")y )7z v>F@[19 ̒-]>cNެHZɟP-fI`oV'uޘפ Ω:MvNBUw0fFEڴڒ ڞHW.IN(`0 A8 , %R*@4aB藡CM<8'JVӓ/մ8pmOlb+<6+T;'5mv[).6@[{4ՖUHH ێ36% eQLϠXFՔeYo aS5~2/@#_&O@mkD)n,kE{N"R9Б S 'wשZ[rX?t樘mz"Hv/HnRKiR܃7 K :40'.=C@RCQ6Sb{N@[L446?Pؕ{׉R <@O,rעcQ3MqQH@\d s$LŹH*PBO],?!g :y5s$|ݏ[94]Bc7گ}6yR` tzJ+xZB qx\#g}m$pmOM?GeZw-C5U=Tt 3-Q/Mk:3"E;9S<'>o{b:N/-"0i8"mDer p`C@q]1oE "\?@Ў\qNCud7֔@[lsn3;ךyweF-F)0LG/o?uB=_tM ұn$pR{J U{9*Jw^Ka5 =kn_h!;ǽ/OhOWe~R4B!oێ3̯$m'c6,q.:*LU zƤJiڶ/WR<8,RA׹ Ag4+UqOc T 0̚RSWF]D=~_!hFrMAr&bvD 9Q]OLٷYڞLgA~MR:!|ǥ^諗/I^xǿ&(Š "㌲7$nE$u2G7oul _ǐDl8='b۱ b=PH/ԌSWx-Q`+c'8Q34l;4 )z 筸>g RLDe0 #bx.yKc_?57b'|a=PHt^? P=dMBl'Z!n!v8dβzk!(vC1cq42ݭt=Hnfү^Nf<8+z#P7qBݞ|NѦ's8:}XZqjN@N phm9'N]|&\3m`Q+ƩX4BfsS#*[XfW\΄^'qϥR(v!古y;l )Ź]Vt(zos, 9Bʝ8q.r( \u˟PJÍF+GݷmaWf{~~I"Y)S0imI1d*wEݾQ|V;f)0dcn'ڴc}@!rEσ/q9h{x&GaG ,鮗swp?Ƒ'̯КP3ANWe1G{@fs t%b0;\{16e$pqb;ң7;prF@J,wOu0dDG S3@@NP YulV:KEdh;R3m(>oO:sL@#,vs:6WĀB%h>hRb3+eh;+E?xy x_?>y)E#P-mszR@yJy_n v`_9I_Z%JER,=ڞy@9M1gޢ}Cmu)^=N5|JD=vYY?ke'FZq}c@WFȽ_޿0ɴII`Aj>2&DK6 Ԙ<B2\e#+pn$2pB=>Vo]. k֌1s8NPzL!zjVY (?Yi8AOo8.i ;,*>*iXց8aRH)C z5<]J{(T\ { y?Ծ`}L =*|qZr- =g{p: b,yʏ:+>~%#I4YFfnhVzͧt]Lg( AizǍfw&I9.dFr>fR0עsgȤ N-̤\z}5PiV-st@Ctت PHQۚ-°`bļ Q9$qQ ŷqVևM\L|cPGh;&3^틏vW0D84ϝ!!Cȗz^L<y TRX"|0Ʀˑۗ)Gog=FȐd?@;{wE;BVU5Gq/xwNNo"RTiO {N!OqqrlEӳv \GTyr\czۋO9 TJ^ۯ.qm4㋊n9"|;33^țBy2lb!@# &`Cy!Q>M5z\Zl+F9S v/8(Td*뮯|*@#,/sp[Bb@+ӹD*R%&z KnsD9idKS?k(8#e /նv9$m kCg)Upp*Sw`5La 1=PbYy}tB%UGj|gܯU{v`_D.8'E(v=(mab@mRF}_--㵝ɔ AgȻt"l8ĥEeg=Ê15r0v#JrZWmUz8 uQ%̷AgE_B_t[ G,yYq0h \2Og=N؉,QTIkp~n-S k@'soX_<{b"K_6ZTb (vqBg60=v|z=ͮ$|ÛC(5h[ܟPH]mۗ}Y7ӻomR`\{HL5UZS5uj?N!PY!^9fWYˆRC&$$˼5PUMQ 3Ў$i6 l 5AWd==fSٺ>^X 'ś&[Kn$>@!nIm H2oFP%d$iϲ9P"SɬM[G2 mGY}*a` ph7m9#1L v}qBi =eh{K_/Cߠ"X#,[I@+Jp,µr 0,b ̋GDKn 4a^@t~AiG 4ums͋.@t G`9"b rPͶwu&T Zx K+RvE=L,ؖ^Z^`$DP:#4טR-o ߷Agb^]Z7b: +5qTF2`/~J%"0>Y < [Lo;pr $̛#Ƣ|YέK3 >ٴmեg}g,ڎH1v&}V,e*Ov@3.,iM]\/$0MIEMbq_@`F R{(¦|tڕsvGmG1@Wm![-k<\=9.|_dU|>JNiɺh{Ix9ɭ+l@!,+Ceu(vSCʹB%m6C)0q 4SRfrS9R;ڄ%\VX[fMK 7)bۈr]=-kOwerIaKmdYK7r;r@ʱmR\V缥[LHۗQ6᱈/Tsj@SYB7%·1ʨmrkΩto?(F_ /[QAr@gh~xRg8d)N$|WiJaI`eKc @!WƗZ>_ԶQ qs.X|B Dܼ6E , qt9K %2ܖVArh;j[E8pĀjqd~}Ϙ(vq* ucPjJaaGCĠO PHamm\7g3z@I&7d b.[.bP6E)0,6 i@pc  )gފ~pD9qh(l9/׬ŕ߽ޏ"U2vΘ `p0vd)Ys&ۯW@ UΘrMp0v8)`Ǧ9⦨=W,Qf0C<3E[ "Po\ʎ6|XW=IR\X` ,<-|3[U[;m-HچG{|d H3zQ`ˁrL t!p>@@| BJ6^X^JC%8]6C)0<<ҎE m(neŋ)ͬxm޸kfjiv_PlNHS6L5!,SׯWwz@@_x@(Թ5L[S ٚ~sJb#UM-1.- ߙ@[W4!2'NJNw=^ڃT/TǓzyf)d_<]w+6sK$@8HsQX>_ 2'mGrvKzJKyf6t ksVȭz{wV]s`ǀz;$} a'6c}9@!Kx^SbЋM3P_=PHF;zuB(+ˮ&(k"aB e 3S7bǰҨW]C?|gT >7h| hL ?#Е\6q\bOZ4}ָsDh;ΘJv|QiB({? 1Sp6ѿHdlq?0y>=ym/R Jy-Z)N|_d4=P:$պrbX fY{ӵś+nMq5 .َER~߆}# ˰# Rrφ_wTKYu5.̫~o?֗-Qwo.7i]J4?iPQ\ݶ"B?O*m&e(zyEtn)t׍z`zrq綧LjOKL<\lsU)OL/qZ$=;:7( =h15yQRΑ%#f%IrmLz@ہG˪]N OyƦ&S#v/2(ip8J6(i|.cK Bzv}uvoKt[}ڇ7V(iYj{" B^д-wl!2R\\cFn9%E?'kR`hqKIg=MyEضƿ)ShCQY4/<(N+D|~{-}@# S*C9^6f ʍк{SK_vʠw/zur1e|gL cێ3&֮(aVV[?qT¥ b'uPf/2_'>j۲8@5@9W,Ox}@!NŪuz@[l0 D@oT;tXAIt-TwmGЙ;f~ 1TjBmT@nۋ˅ݿ!_Q8z1I17UN__0keRwoݯIBz\Jsz r!q B9"|.ecl/.mGYt1C&sҜ6 ;XqX5I㪑c )*+^q_1:@#L[ ?fʈ%*8zT6Y) =(&H& 7}=\u 30lmO0o;Ҫ_=O'xg{)u+If"SDt p&*uLq0;mE5ݵ=+Ѓl)LΤ닜 )xMoxrmR`\z>W R&K91b%{[0}Z#=F0dn'n(Ϗ*J\E ~N4UkY18BAUb,*Xa '.h>`td usԳ9criJq?qGzSRe.~D#cHTQ|ϸ83+ߎC&&reK D5KBhR36 BFܖP];EwI ﺮٹC:ˉo7O|PH圃m1vSTd=g&: [W%NW WߗW<,}.Ŵh D"HD}]q+R4 pMDP>/OLQh{8b]yO-Y/ =įozپG~V\Xrak|t  =u mbkraX궯Vm^p(CFn&%{ 茨@ [ ێ3^H"{&1Ts\ mG+lK3SN$*'Ld%W( q>)@#R{%YF<^κl?kz[t-ArC(vqBch tOYV*n]yOߝʀP: ˳g-b@N9K=V?u*:c]Z@[Qj SW48prfY~ ,{vCPcqAʖ m;θ_ԷJ˨. =T@g^z8rɓz 2g`K"O2*d=. & V~CþarDrqP:q(QݡM0,Tәn Q݅Pr8#B !DӰ%-4p~mdL3~jA6A/d/0r˙>gTOcS7%Em>ޘz-%Xmea\|. BZo oD^⯌*/ e€/#8u.jDAc%^qE +e$,U$~9Y["7%@8Y >6+;'H]tU̦Q /@[SUEm*J@tF:coߒ:(`lZ{RoN_gPT=tCщ@ 'vpwzZժ=O/}rE 0,6]t#@ )u4MzON_R\K,\S˾3,SoQu+ 3f,Lr/<[NMɛ$TiDos  Ag+k0W Dwqx]ār v626Mr,*xoo*qm )UO>ESݍT!KQ yv;Zih;.NDj_sUro|tj\u/{v[ϵxr(N&+åa~Tir27=U#tšdK4}7jL)Wk-P:CeXW0(Y8{MW@# rc9ğS"f(;~E'Q+ ge BӤXڭ^1S-UTEw^ū9P:X~q,% sXX`*x|v"LJ=퍓itQwCGBj|FQ͙@Rp:3I@)#)4V-ͥV-{LKM",G@ǃcwpY;ځ*%Rh՜bdɏd'?Å%K(ywf*0&b-v35eP)@B،=fb̶]5#]`:0 rrum/ j@BQiW_XAzZl!i8^p=1{_6,Gspq9Ijmc^rrK"K9 KɿX@!r^X![ aeHiQ3[_@I.ZYu^zxFx_@^ E 'uZdWeDSaы~_ VeD`E瞖;4EJ(7CҚ''>YM3#x`t]1=lь=(vt?rD5GHIC<9gc5I`=9cqmOhS9dZC5b~)bHw׉:jW[K.;ƵXǡq8B}Z&0\x1b%vT뾡ۄ$oe^қNu*x&D)Uz6[ d AgL^W۹bh;T*boMFՐSj6+aҤW6iM[7اJ>6m9.u}6 BNҹ+`\tT F=^+{pQ-Z8hmGЙ/Ztɭ`iWW$ƥS?WNG 'DZ_i(\~0. @z]xe*`\5fځxnckX>~*y@C9l%4r'\"mիVcDmG3 QH`\Uk[O)VcXb2_ L^3y%VRe23__q6h;ΈOPHl ˙ål_#:))ǺD.;^Lscۈ@JCp{TjmܲVk_6H;,/{;`k#mGЙ/(K8꯬wʏ8M}9,RWy f{)-*mp]eƕQX@R:[Z.7V@am VEB|~F sxsٓC%>|@9+ar{F~vЉP #κcod}ńpa> 'VYbΫ ak|ƅ { e?4a‰Pj- [k)bY&eC`^Y r?ڨbj|]ZB,#t.xtN>ig0 :/|^CBb@γ2 O'vl2+mGY|'Ee*Ӭ5.^BL :KyځjNOezM* mGЙ9"ƥZ4_f?ns'n$F R, 40cҞ ;V,ifaهZvw*Y@t扽f;fwA2 Y4l(0&?}gB6R Oh{"C ljGW> F=&1\ԩ,zA,ᮟH(Ltms'R֍SRpq(OP4KZ̴vh􉦹/2! foKqo02YL\2%0&I ܅fʥ(:.s>RRhNoq)OhR XQp~DGAM\c)H\)OHM6v6>hjU*'A "@!g1cq5>o{ߌ+)[q _, |gIN8o{J@01cqt{i)dU`sBsyEBEkX?8yy@[EYۖR^WzGwUyŮC]7;ʼno:8TC(DMOqk?k?U*-TK$ezoQXhmO1V@E1i2,H3, 'wO5g2v†$蘴wy-:UC8X9_Ņ90v}gLӎEB 1h߷n}ٟTWs_\%$ƽ`8:"O9̐MT QBbP0NV:w`rmR\Ljn=#,&GERY; _h(f5_wX0G~]Cf4(jPήo?nT4tUz& OeZW~ybG1ذY8(X_ s)' WS`Kǡ8;yﰕ"}=N-&}2_({Ӈ@Ƅ.+n_3e㗔}~JD"@#,3'is8!ѻ#0D<:eu>rC}/OrC(sC.:!^lz8]1Pt ~ir@12XȒ ڮy63[9=t w|2_ZL{ssO-Mvµ=ot9m8p<L-UEr5%gPrn "Gg,|_'~☔e+H& 4ˏEϔRE L;Xqi4C{Ze)`L "*H48ᤆBy~VK\>иO{q! }i i`@erڞ/pߝ;. C{p> P]g-}tNz.0mm[;W3\ < N0sTIZbNeD¤"4G{4>7$0piJ! dX%.]_o\`!̺X`HG1Qw>&юOMp$gE;h{v>jò{_20M*$~4+7sΡ~V\ݷmGЙ&sQYqs>V%nA(?T6fH~u!)8PUN˝n6Z%@̚^rs G%::)0LH@gW )<<g ޷AgnvC6i(j^g* QaFmx rlvUP4ogx X-E҅6T-H\<@!E8Қ@8 NmB5ClT;&n'v}74_-F^!X (8(RM]ްǜ"YS wrPJӈrxRh JF-㩶5#Rpxb֌8\:3%9vpqM!xm8)~Qr|@ ũ o%b9.\|W#zj]En8p')䟀$}yvf#~f+Վ+B)Z|&J o(7 gc[~ajlwc:Z{@۳xaUugcapquDʤ5#}A9pB|i[޺C@^Eqa { }o_1PzU * n(O~ep3~Vށ6 a<0wH]Ajzr朝"iOFqv^.(۳/֝wvMqPE)c v&t+JO/G;o}ōX3sHQѠ `ˇبV@̖Oi_UU}@'Fߟ_iznDJ1Du)c}){SULmyN-ђ<נL6ؽ-d`5yy0߮\S =o^[|aL Rbf67a'7'{)(WmwMzpOvk}Л&)!9=hR֋&L 16|{ColR`LqIv 8!6 gSh SZ:lYuijU_b Cy׭\a~Wu)CvL)P4հ@ۣzWVJČEjK`擊f(_ JK5ez^5vY=u-1()0y:Դ|-x/3D)w--ɔT1q{vsdL dl|TwlN7;c[#t >73{@z&'u)-n,ngmTԩpm$#+PhNLr#ԘDƄ-j ;gmnug t߽;T%Ɓ2pe ˖,[J\v??$AB?X\=/4 `-9};S ?(.^aýFI+go{Q =E?UA~^u/sI. =.]*!,`'ͯܔG!Q =G1EpvQG MU]eߥCn83 mWOvYpLMŒJrA}c>{Qnٝgv rT>q'ݏ8XQi@7 O7:z}E熟p腛@CPH%l^K֒b0 hW1;&d|c,z~J"׎~s ?pDJ!iAOaD̲OsS`<7u>۶]N_1]vEQB ŸRcB (!J'߬m}t[_nq]Rn9f60&j\]bBsV0ah xrY5y04AUZtCcN!3ZB2[*X4D =7^!i"LU[lEZ&Љ-K-_Ylg6 #mѳΥz\w&q/IT*xGdM\=bDak Ζ奕sF;!]n̙($r)K͡B@S8 #h&T8ܐ㑥֜.`qmᆏbNbfeˍ}[%\Qhaz&C]~3Ջpɟ2y'&C41_ux/QԶ$}bHvw8CC=AD̼nzof80h{ .14i|oC0>(tN CS~n2_(쥊;~ h{>oVkC: 88Y4"lm՚;m>XJ)|B~ ɸR۠T^A*ntXߢcVAtiyZ4{+31Έ |e6d^_zxir@6.i>X,PH#p8+GssC]묏K=k yIl0U =iJ^@G`RtG- \F KskroB2WZc)ڞ[)-Mͩ4cfƶ!߰<nEzJVneafMDE[Jp%-PH֪|Ɯ$Hl֬&T:ݭNc'#{&vSfxN!c) FCm,ZERa;K9S?RXڞڟ״^'_i(߯_cY!> Tᇱn#||!>.hqmcCU84hyVmY_U9p{}:…58tNn|B,ԠB\P\GV3/~0:OY ε{j⎝ñ ~f[Ρ =;F E ׉ c&o OjQsxH_|oyVGfwQzvwh?:k$}iK Q#14i{¤5Pٞ?gɩ9Ft"E;6o% #۹%'p-vʦ}X1ip,u~ĀOLRk!íPNk((`(Plڇ֜~4I1zUWt1GvdҿR_az' Q"p1z13ޏ PHCpunmEv]Oa=^S 1rQl[ƒ+O˥(¹>t5„8t(y2ԗHm;ZXJ)ލC ÙPs%dz" XBt>YגєO[~ta&yNϊ&OTBd>v' U>q$O˫>99_|!Q2N!;Eаw9|b]ئ8޴R.qz"y8rd< w83?5ZpkK/c} gPa&FnC݀g oafnN-?C /Rf{Dߩ,@N2odGNS^c#Ǣڼqւ[>Z'ar"K\+Bc+)VdqqȨ8!Pӿ},w8u7y8~s?s M?% -Sr4i~-i]rCr"ް?Vf-Oorߌ9tkR?8Gɍs>R{ P~?g%67ſ/? is_ces/?$̥4K9wˑx$I:Ojiruo{j!_ۿZ綟l*ϳMZK.ҾwI(1=e6MO!iBJ]_ݯ<1̯?$a:NOFP'_{}ƴ]˯啋OXU!Uʮi ݩDMǼ+SR)ӸSS(9m_%~m5!v9lhK}K~v~Y]{rbkV.{"6LϔLSKG&mMcCMؔOK@b=gO^Z2m_%qli/wj}-ɴJ}}޶}5u3}qT]_EZ6 5r>]_\Reږ9ϾiwϾ]:Xvж}s=.a|c>ޣ&c:v4n>:F'yiɞ[צWj9UMl SSϿ}Ҩd[KcJt4%7qV{h Uir-Jڐh"_y#( ה&lpӸVշ$B}B$_ܔߠLsk׌o)c4XJ ŏot֦u˛4ubͬCS>X*ц9 z&aMh>Q3'x\4Յ?$tQ^_1+ LYB1;Sӷ6?>ҙ64ѿȀtHչ 1 暇h?Khfs(U6΢4!ѷЈg?7BٮۣhTgsЛ:Vo&Di]$S,ѷ҈n}5|3mpAWܓѿlRȧISӴNwzy<7@IǴ|FkwtJ4o:{z;Q摋DuzoKek[0{u-FwvZKZRjSW:"|Q1URB?L7muո?J-CeM @mHz~T r\}b*G}w5lr =3:ܝJng8< `K(Ipa/^dG=>,H8QCyw*ю QGAN)NNltK7O8b!Fŝs&4rN) !1po[Xg}r@6~NFZuض5Һ/VH#9'$4u? CZ9P ɼuJ)6;ޝQYE8<$KIO_<-N8)9s'( h{c;,VUt?X:r_$':dq ζzK+QY'pV -5=+оsބ,NHFѶ$)t )ؙkepO,PH]#WZjA~/w1gvFjX "9Fkp87Xӑr}NKEJkPXn„`̷m/l@ ԾZsZ' -̢,PIVy26M#V m ~e,=/c uw\TT\D-$,<)뢟z$f+=x) ]Ng^ {zCOEg>48lτ4kt{=?Nv|+SΟp6kK  =mɩs 'Po'e;ѻj_)(wWwLNT`$v"˜'* 2;B.T -RwMӕcgLV86Oj}HX "15V'.*28JQh~J{i-Tq =E SD&5bk{q@Vs'cەoػ57뉝HL_qv9f_2'Y)pdOeo獹`K @?}@!wU8-tx*0Ov@UEc aY$Ŵ)Gh~\PEPd2; =IZVRCs [!@?B!=/b!(I5\ޞvmcFr)  4p{z_p-PH湝ܬY@Pw_Nvaml@-UcpLR==?,PIVhYi-%aZOpX0*}B uGVK.bܕzRY ZKIW׽g\1Nr**ό_ZPrP'5rb@Ϫgì)N^QX Zbp43A9=/K >uUhί#] h{rUp:q̪ gSc9Վ}WUI,PHxO2: Fm^մB@s+]Oe[aI s8=a-Ø.%۽)3˯ʼn:OmEm?ɝ9U_s p G&8A7魳힃(v9y.TOg{jCMegJ>Xɛ{',LX@τ0lqⲎ`JTF =mO2ZTiN|CfSPB@ۅ} aTLR1#&b眘B{@=i6~+@'ӑ;Ly1N/ 1hok~:lBRs ;dcCcҐcҐ@'uE]k:rCNpzBcw~:gp|OW}҉ਯQz"PO,wIəlGrCNg($N, YK>-g=O@9 "P(U A Q9NjQNjQŒr%9QbSǣ<ҩFTxHʊ;s>;wk-ۏޓSh|Cq A+qȊ;#e1SYVVԩ++3Vhv|W ߎ9mUYE8Mӕx= w0NZ/*q5. v:|"{0l%k=!pBsn{2_< $Va4\E/w'v9}N&F8v10y9.vF#5.s \6ɻ,c}lhz(熏堄#l_— &(3w(Խ$gHՊBPq(AEz=UB 7R7zci+bz揯+Φ4iS܅?Sh[ܚz|aM(z݊E`) V+Z h@"@աq׎SQE89Ҷ[[ h{buҨJÑN\ac)]t腾**iS^@㊲ VCϑޗE{c=cU"7bX {Rܵ? \x'\xTN 8'q) w9t6ʛ:GiJo<8A{>Uȝ9U_w諿(Dd]w6ܬqX-UeDF_#Ơ+`F7^.t +.T)[U@&}vYɣgI.3238$g.!^]^ ӑr9M[<0V&%q%wZF=Y;k2i mCjZŨz!W %eqqҰB`R@v-)wUۇ;( ]Ng!u6L;gfEHRN;14ل@SbHv#G W.w;'czH߇tKƴ> &(v95MGn_OtBC_6ٍHvs8 r]Q9@'s,[2цN@˽F@0bKA=b-_Ns ;4o6]ҖywM :'%ˠbY@%\2 \XrQ=D+kIVIL:V=gHHJ⨯+'b:ik0Vfgq.r.U߶;zud2I+[!P\񀛓N]ihZ\gYT*?B 0-PtWIgs9qvSZjd lVI[Qy1$:s< PɵpvQkZ7.*%6=-h} Z1sxZ7:,@E3feB2VQa뾤 1ԠOc[Bæ֏]ֱR؊mY՜7M(j?_s>~8|E@e{r9{f2bC,r]cm>ŬZ+[ܡ=}x}-y L8!AK^T h(Gf[{oLE8WC@F,K 2%u߷0Xߛ'M2+a*S!Pr:{PZÊ1,;r:󃥹u9tCe+ *~Oy;r'f)PsC{WNltjUMOUqqq j~[hG@vَ'./VRJ yٛdQ(2W(.S)DNy1H䴇6M_mp:BP"pts!ݪEڤ˺6IH sIQqIx乹Vf\E8? dNE 눝1U_o H;d±\f w ߎ̩}}a~LP9e=9>o~H.ij3$Yb-QgU|[M.CDj*'4&%r,p9-j~]Ii7"igbCy/"y'ziu4n#R"U[XU&lڞlXK>N:֟qk3'wľ N8{ixqUpS7xx̢|Y8ٗ!v:Ĕ'4r,pȂVR-m#w:t:pۓޤYO.QY}jWÖ !gRkK8?e9ѾϚkq4!rpB =av(Lxk!Y}oLE8-*L.A'ӡղ 5te LlOɡEQI }\ck;{bx,E0Fv9$T&>VrV4%GsŒd#&@OԏP*sRQNTB29N6\ qn+HC24$ %0b}2K/:"T6U Y+ vOon['N&~gV QhQL3'E,ּ+׿~^0"'&Tbk(hרh =E+@JC'YL"CgpԉQO?18!9OaP;EB,*ך+ǧc P;XSOX ;kZ溏^s&h{5*! c*vf찦*q =NĬ*OvW-Z;ΕAM=1~28]/yZ&;eCܸ3@'oRzy^-k1ü֖(0n.9Gs̝veICc_ vΜ$ת=ӡT qԗS崪m8, (3XY6zV Zܾ^Z),(3 {I:ƚ_2T|mVshw(hμs֬ݭ~X4jҸ mك^Y;zVy\ÈA+8JhH-BL5A+=)QWz\S+H^꩝5RuגIr"fv9JTp1'Μl@!'XײL5^,^YVh|])w:m@!ul|Ϊܛ?^LevJhi!A=|aD o6]NWԕ6@Wjrz8Ի'{U (e*QZpWXÖ~SgvHQ9(Q D$#ڹG(˹X)XF*IMBelgv9As 5gsثޜ/k ThP/ +PaQqn1b%v\C#P1jm1{P m+2AuOV}_ktэmgJo^^܋!H]3Wj*O\C܋'ZkPBk8װ@!NnLڞY?l ɺS5ɅrP  O8ȼWy]yps =8 r2uL+%m[E˓}de+UhP9A;mrz)йG&@#Bp_Ts_SRo{;la-osTL!N¾Y!VTP19J''概#%q-T9ً-]OZm|) ]Ng0fXqBW^07:PW܍NU㛆r۹%¹w8Or//N8{ Lp0W&R)WV0|7B@t5){-.v:5(<|<0Isu]T7.k@>$pGiAܮuoYCoO{32o7p^>tEw;gD7ɦc7]R8{۝a- 7o%va_.ލ:Z:gljp%MshGVjfBΞ 79‹Iq«( =duiYX#N޵SW4QV|ԟ |.Upn]-C|ђ>3&ZEhǴΟa'I#S8&m(2ġf.6 \Jy1m`d6:~WiDp:"PI@!fRz| cIFd?p"M&-!2i|SPx[\%.{Ic hnG M^jF!L(2RiR0!ٶ%^ QvBP2 NXKt'4q,pgȂSI/ wNG}oѮN]}PBp|́<-vNJ%q̦"SQq9hB0HCC'38Krά;(i-v(II* ]ؕgQK}-5Yu:TJNh'Y9 !d;,]Е4o`q'VMtxl[Z0G'Wy3ӝr>=|)¹Gx:Mw?mqBNkWq`<嶕gc1m&N͗n0\Q`pݓ-Ph!?V@t4'憬,qh wC@=NB;ʋ!|^qGuc4()S(v9 ncLWOŶ1Pr:b\ͤ8y3mt[s.Y[~ӱU`PÚ"UFk&%][팵+|+m?+1]l۟U/TyK!E 9hl@!DGtly+ҩw-z h{bv{'8'N!=qLqY)B 'mh\Qcv Ync-"`tV X"ضgs7xo} 'ys/y'ysy'ysyZ|4o h޳ŝ;Z@t ?7=%?Q |YyjDن?m( *g+Z^cF/FƇbQB?͠'{?G1~,Ph eNv]ow5Tzy[N>8hl@nBAUFez?C9 V (v9=lWh:n/w:PW*{57jGlGþGY y+-mۣ)TX=ϴB` V8Lp!XCC!LJ66Ht\@E%a<0 6{ET'ڮ OdžBf*[A.e{PK7W]lp:y4]״-L<֝kڱ?'&⶿'"|Ż0Y;inpQh1Ur"rde #p"8Rz߬k ik{G. [=!@,7_K).ѓ`.mc/[NAEk5^2W|+P3Nlt|i7-L8{$^5w'va_Y./dOtȵ Phޱ/JdE=1~Qp{Ѳ.VΛc֧\@52P8r+;FM _< un[=wၟqD{w˛H'sYrԅ涼q%-N¾ !DVu.pij'}8 ]Ng:BR'P^i6۽fjMEG^/q}? y'4pܷSډ PFC5PH'k1چ.LYp?n{"cUK]v*v_؂"ߪ&ә}їk(<!#!6>/MS})o8}PoT9Ԩ-(Dim~7V!jJr)uԾ wx%stz(-zRc 爄z|WG8CeslB"=18$YU1up0aVtꎷB!PHBpևر5燎o\ ǹWeSz9wr7|g@$I/Ԍ1WIZ;(Ps?@,*MJGpV"@]d}quu5Y^OMuzW'yhlO'cwh5&2C&Sa4jq06L:j2d )iuAԧ %8N*|H"> NyENI KtRB0Tnr 9_Nz kŽPSI@!Ywsk0b{]r.VE.3NXN9',2VMݓ⳩-NH|W[ڎ 5ЦR[R-gJ\cR~RmnTGDZIo p,piMu?F?9eivRt9]99"~&Ǥ8):=ϛqw`ed+OΕ^Ie9q=ar>%y?Wiu9zy4"@E*/ēn{#D79Qq=Q-8yz4\_c-eN+&'va_ N * Ϸ *s0W[#$j+\i5{ +,p% z/W=_z#<ŧih*ئaTqyˈˏzt3!Pr:#[}q|:; ݝr|B(dOw \\~5X3Iδ/d@錔To.,NHc$HA1<1|oӯs'<4LT/lG"@ۅ9j&&O$ _Axc;WB@ϩc:ӶzSOtb O \5h hCG˭+\@kl==E˹F2 s tY n.#/?/WBbpyQVAN*- ϸ .,P4(3c]bkݡBdݧmmZGߥPlÄ47¾obP6KQ£58wȳ(.d/N}s4g@i=1K8u+Mld@b"'r=]>_AnQn"Q c1?p,=9 CUqpڞ5ӜFM ؖ; 8|3%,|٧>'$玗6˹zEawZUh{ܶA_*LPDRRK 8{{U{aXjm *S!NpqF A(\L&%&bp/0?>| n7B@tW a( 8R[GnZ\2.ٺ`Fۯ f]rNDA^C/)¹6N2nM+sy쌜;:!KgE Q*ur/ԒFNG-95e67 @NZsQVd!hNVXc7pe) vqeڔSc)ƜgSs6Z|}m(v9=TxtN^3(<(# !T57Y͍W-oUp:RPB qªD$\U"d+kS}4~~S;@Ac!""žlE% ,DWI j jԼheiGӦ%Nr{HfA)[!Pr:{bPYS.Mwayd.B_qZw: [1jq( hp+ٽtgZw:}_+ΐG_aa"RX\"OXLQ'4-gZXᦛv{)(H=aŽW@Ȏ^T؊2e(aa'RX\'NXR Ktl@!EYNv:T!PH9Taq<ÊeuHYqu<5ǿkdqV5j=^D>VBW p]2t}'w:䔫}k/-!C:NruOT[;{ӓ;r*($.5Hk))`0#GYʳ@ " dtzCs^$hQh"b}lY4P\Gt)O`zAIAvx>Vry=+[Hn @錬8CcrEHG &b&''#'X/EPq‰ q÷m!d|)SNBJX/2F9PJAa*F'za:KljӮTQ"prv[! WTu,װwV;.y>_!8Mӕ_5Ƚ˪%xe) gq1侰& }QQö޵kʍn]>|Db@t5q;v6\85bC@c9xomC)ضWar;ttl@!I+3r=($^$_^(ڒя2~ C)N'LJ,NHև_mөb:ʱ/NnnUJ!mb ޕؕ[|s %wlew~)4j9e+ ]NgE&GZU 1&B@tmc΄dOMLXt34Tj^5/oډ (K!P͏*Yoqiv@]-ri}ʮ(U@O*+*j&\ '$X *S1ky@ DDY{Ԍ +W=QR NG-D;'tzCO5d{dʐ7hgkVG Yu0+skn78MOӷkX;q롫nuiU B?dz7 IL~ %Jz>G^BMZ=/aXsp5W\J{Y&X@Ù4(C Ʌ%p0uFﭭ'r*?S-}b߅G}Bg%.N_`qm. |*hyB=!W7. V J_E3и m+e]>ooo{28M>0[,PTz˯ "-By108=@Z#,x ?_&~6r:L@N}&;Ua 2B>rk{p\ñM'wIhθ_*T4T^(:':h,rqO8U*V;`ELS]E.1P5*+ gBVNuNVduRVGQ"eoz{B@t v-Cu=Vy˔t@τЪevzCv_C +ߌUIaqU=Mǿks5׽(g|r1l-P\,j㚒ԼԨ>Se +S!Pr:5P5A3#+_Oʊ_j5]Dw:C;֞R2m&jmО\Z/\@qy휰R<),R',祏pסp:bPB2u!U*N*1 gZX+W+SWMϙWW!}\p:RPB"}xBelve+cH+@wC_] . /M jȓ<05䑃v%[u@15le*Lq,Pr:C14UAԬr`cٗ&'f.3`k:WQ7zJfs6.PT.1i]lNʼnmä呦rLL,9@D L8%Z S}(S$D+8BU<,NHJ0ޏLN,fL8 FRG]nr~=>eTƥ7<`4ℛ5 P' 93(v#?'0u !0bJ,$'抜}Qe,5d( 7cpsAO ,N8ε`+kz}q] ե By@!Ⱦk'I]`h\յvmәr=ӡPHcG3mْs_oM h{r4)9z ABPk]VHy/pmkCOFe5f,E8tpQ1UpqM+Xjy =--R P:kK'9_XZ"^mә-EnŋVm.WᙐzCKבB.fŬ,!Anet4Y~?حg5! 8!g!詝@YV#"p=a:mV;^:XXUX 5~:NG9ʡLXXUD!e:RuDʪB .[a4-dZn1L.\[n+{h9.3o-6tf@̷\P:*鸾;zzf>|'zl: G*P h^khIX@/< ^ΐ1_;3?m{H0 f="T\nMGsoL̸w7lz TBNղ|CWqn}.u6uŸ7%ҏU~9 .5p)=Oub7B@tV'i 1F]8fq8y."oB2?RL4+a%b ~]ОdΞd_C1@Nן׷((/L!m 'aNKKdSf?!?uAA! w7{s-[5'0ޣl@?#*(ӓ"(cBc#6g?pp hM= 4"{}s>cqB92I  p :X9T#4u@c䶔YƛPTv}QFVOY'4`yj+D4ahM;HnrHxٮ!|cnr,닾+?1b@tp? hX;ũ[!Pr:{z0lF!A:9iՇhܫWW&B@tpS|-qv ZT2ZeRr!@6: :vic{C֍!Pr:/,&A2@&ܪ$e\#z[!Pr:~Eig$q_q6|& )@o"v=H_Sgў^-`Pa@qjz),z'y[ȝNG VZڊRw}{` ifp HIp JhJ/0.A͘=9~ƴ8!Y*N0)yi Wamәh9{~g&WSՒXB*ONrk𺕷mH'w:BМA%$(WqoC(Goܒ!u* s\\ xx]26\@?.A%."bB2Nw=[,XrClm,$zV;z3}លdt#ΝƬײyxO9xGnwHWy/7z)Z- )RΥ}RZ{.%!,܌6㞰l9X VT\3oG[EuNZ |sq,p'|G }8(DKO mA1cxX+o,Ws.1_ȹ 1iGN!փ]a:,ı mI4cB ~xyvqܲ1b vP~܏OUcNHλe)W.KDLZF"xLcODtN4\:;.+{~Ӣ^dįnq'=:C"'4&s,pBh66b.:Pz8~-V:2kNZ"URS\h/,BF=enIh%Q;ݖ2LI6]NW)$ކ'&y߃3&ǫtg+'ڊ2ℳ;FPXWOc8AqcA1W zr_\-@!yBYCsԊKO_.@橼q[@ۅ}=ՍvpTWx;,剸UqVmFRhQN I= ]NgC0;p[j"{xx1MpRrٵFY*_F) o~p\2c :r170ܦ+d_߮^x.)Z}@a4 RN^U⾎:*C}tO4 cƎs-&i4ti|1K[n 5!z1!Z@?!vnK:c4l8`£=/($硐IiBH' $N9ߜP9rvN4hK#ly pm%nW9\ ' udon󘓦r 1Wd+kL趤m=5ۉPmӓ;W)8¶|tWymڏT"@K)E[mE˒;r'4綧)2FI,Nlρe쒅lHt0 o"ն]NgUL㵹+Ct3JҊ};~/^Mhc5McwPi㋌bbQS,< |Sqf>guCcN e k!R7/'=@APi3(nYڤAtadޝA{Q9pGIkʹ )- =:tl4]MB#n(rBb͟o>c"(>As$Q rGaWe}RoP #(;HZMՖz:#oz:Iοy{C$ ]N_Ll{-ĂP԰i'dpb?p@uR]` a<]Sv$jc8IY@/=,9e*¹K8^~Oo;cmXBz`b.hC i1jec(L hiZG)#%ەO5%o/op:P"t{TՑ+r&kڎCz vɢX9!5$'krSkY+K!N8Yz:^48詝5U]s6k\)9] '`= O|Zj.` pch;OYhY'ʹ#˱ n)͟Xs'B™IO:'ߎsPͽZm4g;(OεgS 5ZОwflB 6.k9(NJ* ; /x08fw~.$U驝HM'G}Mʖ:[2GP\a)@˵퉕űRBzAJe g]zKVH' ]#_eաDy$0*Vh,HV"G}]Z#0M-Z.ԉt|8ن^kּ_hsYÒmj,Ctb ͮ~LI-ezS!8cb%Fպ>Jڞ*fSÇqݣlglk;XkH& ]Ng;RrNdV5h BB Y&gӘ-Hk k?r-㢕SQE8!w{.e3C 4{p FSN¾ _ZXZAUM-ꬳai7B@t5r~5{MP|ܖpkO g\tnhqm"n#!5A4(fSS4r=kުtN^ݶF@!ܑ;8ZX EC9 zޟ|$+e*>JԕKlrT w:(4$ҏL8֝ZBP/:+{v Y=)Ky w;ǔfN??(8nuC[PI9*l9pxB)Br,z휎wl@]Mۗ2A=ɝ9*rE>iNѪXRAd5Mz;z*(xi%k ,l A(S!PȪ|PKU(y5V`h-gr$\9fdbu+L岔/K2m K!Pr:s*DOACthbC_P){g e9{b%r^m.jZMWkqmև]ՖM~)kmYաTi®(- m[w:T6!e攲Ew XyhZ`nw{:ۦ((@{{?ՒBFO3E&0ֱ\y(@QcN-A-Pǻ2ZpBO8^ο'{karm'rb NVxqqν`yO/Z@t揵beF2>fc m~@Ծ[SD4ל,Nlӓ08}ݏ`HƊ@y ~Hį<(O :DzrCN Bdzz_d,P\潘 !,|:',D_hV eJ0gAek|q @t:_WZ{qX*lcS-4@bZL"8d䑲^dU״Qx5O{[!Pr:Ӎ>OW~~ -CK/i)޾2 h{2XI{|&dqmz%c0IXOֵIcAmx=NTH19JI%em ZCM>?ColMӒQ(!B+Vehw\dn${/=#葌lHf?A oXG59in/[bhB?!?X% Ԍeǃ^Z,09Fuu崣EuZef*W@>uhm% ]WQ!Tz+\/#K-~M# W!f,>hYQ Yp{d"XXd Wc4 tTOt.;&n~[ﶣ9⊞dF Mi]+.Yk +OL® v9e/q3 n쥖b\9NXa)Q_+^GXcϋ,xrmP+<8I|Ya"p|?W/ϗ {SplSzʤޘʞ!A!cNHL!cOHD%c$1gIN1cV>JֿWE0$ɕڔ(.^uJFPXИWؑs;JbL+) )O<_KVW驝5U_u Lp傑 hOtb \P盧'~msLU{19WrY`rC,iB@tV}QadޛœѮcJ[:G mYަ'E} ww:DzvG8!'jv֮$ݕUU Η}铄d[iUott@":40F`9^vסoxxnqPu*7ܒJ˄fpbƚ{Tüi]Ď^І[vdPNH/kl%/R:oܴr[B>C,'!֋]Y)Q5n8+RvXۼָiKepn@K)ߋKE=_3[㋶KXձoĵݞ#: Nwg^'Z"? [Qz8=qٴ\BUSW >(@E q8)慛˚镶p7'䖔Oʼne"1WƎi0h>{6g(:{&4{{O5qk\<ӂZU@h`g[8.OrX!DZ@hߋF+y-ix`ǡג?`d<`ǩD{_| ƎeK0^zcOVKE|&tg9Ne^poX{FZg@~ߠoԨg',`ٸ˫WND& IO < z!i%hb:b+Ub_vF砝{cʭY3fRwk"*k1.}&xe>>m ~_\VIqn5CGT'䎔όlj%"$Z|`z^vߦOCKt/d#t} bXEry!^a-k؜ۭ\eh(^3E9Pq:W͜T3SW5svbY)MQ@f+@iȮsƼSk.z=~ gyz4"Њ;OcCY6KJK>!%.cwv'e>-bijF_0S=8eV̡Ks1.L)I!^.e]X1j2e]>-4Mĵ݀+/JniXΊv6=iol~׀κ׶{jxcqI1CzO2y%nq p? f>nҌ.᠝[R\Y}m{>-ܮr~y"tN&T A%Po+9sM&cQ@x9S'w:OZ&Aŵ=ƿ]Ta66>ϛxw;T'k]j结Mȁx 0+ɣrMύe}k$saY7I%)Q&UU)k=).KSD!N8AM*27T#,5K*SvbilH\6$/gb8˯bSX⪘'hT]Sg k6L;[^W)Q KIr5mQ9=&w宱d`Ec'_,H!JH!aϥ2쩄8=/>!q_ &_eH;!'Љ@%Y%Y: %YcL6{s.ǚeVYNnh>k:5=sS58%w\5N&˚r5c;aKso"@qm7 }p)/LNJY`±ޖYJW"&LyD!N8v]SY4k6 6݀Ѭuy^z|ℓ!PLPgZђ;_0HVk-)Rˑ2@qm7 'qiO)DonD1N\iq_jўb;Z9 /5+kB }ܻP>?Vڵgܤ n@ vT iI{-.+ RfM|40мNTr DZ\ȱ*RdAe9B2G:;ś&ۜӦ,y=9@T( ɯg@2#);RA #|ʟJmzcB@v6њ#mcZ{v`ݒ-/ 5Zd9?4K!^Z͎'R:Dy s V >$VNp5@#WF< LtE9۩Aokw@<轨0,򫱺%G!ގnB fB9kX2jgR&k1WUo fH!]Nà(M;Iܩ|!I'50"Q%RS<.T&b@n-(7c?ئ'w*y?zq> sG&gͧ528p}ν|굌8a  K4k cڳ3Mئ}<ߞ֚QHRC(q`v\2+6p J.<#Η]YNHcTv/@Yw2_MIBh 84cabL4q,iOn0[&z006FB{}*2Pp(nǒQ)r G{;SuO!PHQ밡M~FT5!h }7(Hx1m5m4=vǻh*7AnbdFk| hApBj,4?v.%>ZrG E !_9AY@ZmZRGnB zlZd!.t=--anB"W.\]_{H&Y'hv9&tRq>-q/@*‰k-6Y<u>ɞKWeKhL[SIdr 8M7 ]*izٶB%FNQ=fΧ';ꏺz໏,|*Eq-nt? 1t:FpBv2W6c"f QXOsJ\l՜T2F*SN@Oy;QP̴"[R'+U@ k.⨯'EKU& W@|**mY@N(Z&u:vU$m5O#@*‰m):R yN?][ '9Q} YbJQ2)(Pє꫐/@4/ιY3E-P\ +kC}uWÕ [*GV@qm7]e0-!Wr2R޻'t3mQCUVB"Qgvѵ-NHa]gS?5|QCS>",U- pS=E88gOdk}Uh i@g{@ae9_4N]z2mnɬ{fυg8y[FCw~K:^mar{nicmtDnC pσ6h N\?rQ氢juU) mG]Ӟm-;"D8t*ZcUGOpY}/-'m_h}h$rbzbQ*P׆d:9hO(eQ?o; my;:"{akomc ܮٶ;vZ ׆WȒb6 )R;@{YoP(7!C$6&2ͧ~u pjPHa}*RqwN?ni}9}> O!pƌܝO d6vNXdgɆ l0ʲ8ZY!w1pڧ0ҟX5X!xC:IO*z~b@ -;aϬYLO>{0됗N1^GLgJ*Qϧq؜SOkc.NBL9gsk˂Xʞe-mP\ A5fk\O[ӪAWF"ئ*6E簿5UQ,Ax8{#]zCm3XуrZ( :/5O1KR];k¹]i0Յ.B R'=fQ RT8NNև?.zX#oI ^7R.LRC:C3T`ϋ8!FO֒SsCtS2{Oh"Dʿ:Dx^-kd3 4*Sv{Z℔TkqOU(jC<~NU /2kH!P\ 1kYskڟy܁2UaWض aUWD` XJ4}cdȠUggHCZψ=X(aD4Y5ˬּ`]'}u.9(쎖{>M<ed,bC;i]8/[9N"D([ 4KL5=%[5 BQ^NM3C%gfߎ噵`UNժ(H[ڡ.HIq%i ]z.N#S[v)U7'POD{njq70ihYr6]Xz6GU[p: :N!2,P\ۓUs&R(sCƝ@޴iӦNiN;lO3mk|΃dޏ)B ,G |~{z&"-!Jz$E5ƻ{SrcTUudtVp+P@!Mz7w$z'`5B8mrOok-[ n@`2&$<`壻ImqP[ޞI򎲚 rjPB :/9>C} 3?Pxܞ @qm7j`.C \aͤfNYVjs` jb@ Tݎk@Eu|@5)P X s UMJ+yXI* wHټ' #ϼXST}cw S/,Z}9v~<&n@-7KZW.:!Ӈ.z`/@qm7 w\2(E.3Ɩ35+,]^Fﱺ(<}yi з@qm7 ƎJOR~'Yc9/hZn0(9.c{ WED8 7 |GG+e^U]"E2\ۅYO_{Z}8=`:TUC*oM;`$0M?c9̚kOqИ⨡vOeBJ ;T߮-N &ʘ_fRbmCvc4 Ì6 Nppwz.ֱ0YSQ=@`TeÎNHaQbBqX]@(#=6sr|k~RE8t.!rn m|AƄ4Gt@!=r }]Ps gФZ&gbn蹥m 5{_x( 8BW%@s!d=2iӫP' ׆T^>yBbJ~x*a7ʙc2U`O T'w=3 '8p[2l?n]MABpbn@}&sIXpw7%Tnۻ8>ڿx'UY/?U(B¿^#%_ofE1(I=񋟄/@k"ŏkkq?T,!ݹ.Z-E {r_ xTJy_ej-PmW*Uqpu; 'M&EB>C(r߈orE&-Wl D;Nl H=/`^]1;N\6(&n) T>" &웢"Kظdc=?J!^a>@{/rO# LX)ݏ:+5``ٓ!{kң-}cUA7ܞ@".;q|zψO8[KY  uV<Wyb և%[dZe=/f Om-C!YV稩J}' Scppx)p %Ϛ~0<3SNpsԙ7,ߗ>3.wRn_Buڷذ+RlPxpc\%"FT,(g9lY璣sxgڞe1?7>u}w̤H\̞rXNLC ,H+P\ۓ/2Q6ۅ`Y츤ж5QBS/ڝQB y%'UOzEE8%Ue }T!<$sq\u罜.Cn mOɥ1syA z&=#Fy&b=`3qjxsw@!j!i"e:v8NȐ3KN{'FUTp#W62[@G&\DV :9=yc.&r><sXo9e-sYOioiڞeװ.=MB4TsU79~ڇ!:' <1 7z:m89Lh{- SME8$Gȴ5]** '9XΒ%v.Le BJxЩ"[*(Ƀ2/(J8ky[vYguP ;NFp38MO/Dzt F[zr P5(eJ93B|SS˦iRޓ_vb{l 3nz.Oњ\!^BX6,격 I~GՆWS=!δI1-?H``b06NCXK-J /(1`*{Qde5;w~gd Zb(zn6$V'MQ FncoӖM\Y'ƿeо ˅ e\Y6c̯U5y"/zW( hRq/T[Cc!%.zrc %?潜^(k1܇1w*`23y-[&Ac*ЃpƖ! ^M=!2KdG2ϐ[hG΃s~ebX!2K=ycazz*˾.>z5 ;kG}!Ccfv n^D(ʯFĹsGuG )$7eѦǗkuV. TS[Vld2NBr0Y4rUb%EE*qe8VUm{P0~ `E K% 2ߧW  0SC2{*FB${ ׆@}of >%{j=J>vjt@3ڎ:H$@qmXe[椞.O,r_]~_~ꪛ(nr-Y*[9ך6eKʴ_=ĵݞ@R9M^Sz"X6(Զs'lvn*T>m suңK;]qRthB{y㙋a ?U^xG+' N%} Xj6貌01Pd7{VP{M'pt9u٫܊L1N8Dq.:p%ǖPSB#u5A7Vk](Ӡt3ɜb˧5E8dQwLӓo":h,gh4cbγ9 B BG-` SeE8!EϏÆAhp.S YR s@XFٙ&lB_z T\,:arٟoSޱ;* '_{IAcuyV:"pRۤ9/:tNmNhl5 | G&P)Y*i*'-,(*):oihls dnΗtĵ݀̅|~\$iX2mV:P"pDZɱdVRC{]v>r=BC9+M65G>L-s|1ȟv%HkEdhkg:\?9J猚tZ$h C=_Ї|\E4ΦX*qp2x+kܒrb2sVҏ 6.3q[.6q_g+"DW YU\ʛY,r7_,.,LrўxMUxe}ULu%hM׼-]|鲜T=!JH!_aլ2Ai:JBmijy]ḯ}ȼJ9uP\*$9^E(XEyv\Q2iUZTQ VgXO*Q+VPg'_Մ"곤l/V_1Rj8[_ ĵݞx?Kvn*TRr.,SŔ|5aNO\1a'gQ[TOL8j_OLI:)ĉk=-wY܊P!NH9Mͻy8qm5U:P"\Ki =־ qBHbl\16$-Ӿm!q.B"X5m-4ˬ98{J#R*יp<7USZrGʕ$`J9RBkU->@Q?W&ΒAFMrޖ=)(!%v|8=W&ΰ%Y5)GFZ\y^z(r }P ƚgAzp~}jw⊃\ZZ9'JW'w? qإ:!m()GjHNl H!oQ.K) '74U ë4cWYrPNl HasSf=s+28$wiuN!_;n;\'0ѱf29m,S ttTCJPNp?KqꢖsyȯT4ɿ?Uĵݞ@R'WʉG.\Xj욤/t9T1P\ M"UPXmQ%\@ *V^ETՠzVgU @ԷBYJVb~<F`wWZ,LRbGȕb3 oP<1Tx&uZPB*ì-e p ‹niTd[/N$XpsbZZ^V'k1'uT&VT"}G IG'$sY0o&kJÎBWbKGU/L8)ZV:VgD0[NN$NbrZ΍~Dgjd,i&0%ڎL!Ph,a=.3 PEk5{axt'P!SQ!˺gQ:_jnGpeSEE8qm7][) '7YVj{kc߷vo]}.Ɖk=-({lg94/{Ͻ%Ez}tN*p]=㨗2ɕ{坣2k4D= zʯ$gG.aVҩsc@!y@q].?55wL;N60dlzykI78MKAqnhy-ܐvFh|ms˃]Ge^3/ }&Z!ri+ '?)dNB WE]F% $$|Zf')#qΉ44pp'Zr:9%1 :9fWZWZpo"E8M7 Z猹n:n禽ℓ0Β8ƽu:+={ĵ݀]թˮ z29|Iܓ,8!NHɇn%zeTy+m+6ai\' piHTo-uj-Ty?*D0PS %nZ:3#5$= NE~@!GA&;r*@;+{51^e٨j"p↺S-{qHu$֪ɻe W")ߒrTp>m乀{PpsKC/Os/wp 7>CMwRU\;!ʉP++JP" BZ{˞X@Q l gǘ&Pv;R&^+O pS‹nim^׆洶ўiy侚wFFSfDFoA֤ k,o1Lˇ]>=(L4R@UhkR. {~@ѡմi|[㡡qzexU(İbW:!QFW.Tb*vn禡!Nh)Mig=ӢikvL.DC|xK0i_oN^|C #0 JG~ԛ9]&D #sQ>8(.uh uz_1ltd4(}=_}V݄84ye3]Ȭ( R񾜪p_JUmni{\@*UZW>/.W5CrAP1d˧u5hƌ'`pߞD8]G ;Oש84=<ؐ_~y@BqӤQqqȬ|mb1óJPÊp8 +- pkS\8" O7lxAĎjjl>}gqnON^,䀖{h׆H~Bݶ 8@Г}ځfRBvnPύC'h&;ݹb rWV/%WvE7+qxZy؍/W0Ղ6 /,I!K/O(J\o TڤLB> Jk_*k1lǧns{:~WĊB tiIwZmji (S~9}+nCm9qFYQ#28FjmC"34tS=;D{:\ث)'<_}&pnO>^5teڞt^2C$YYm@n|?h+K f`R=mRVϧűm5"$Y~%뇚ĵ݀Vj}%o|Xt-T@!N}- %[ ؋%مeN ks~2-6KBeOZ?I )7qf`b~e{٫g ݑSe!{$d {?د )* fU6vyo L8)nz+lRBރ+ZZ$,J66*yoMULF[Nd޲8qmtomx9vH`).8FH]w^#{3z{fұacpIN\K8K 2ŵ݀Cϡ~]p(ĸ`qBJ΅7eoaidlCd @.DqV`әŚ5_ ; ^0 *ЃD_}S7*Mw.̀[w~X/ZLm9v.zCK~vhK,<7Oei<;e.|&]*mTxql>-4&e}GJ%m|%v' =~`y-7 ds>E8(|R&(K@{9AA G]u2c _5l9m%aʿEߪU~2<3&؎p@Etv2]@PpИG`LՋ#6\6D㟕pg(qV( $`"=f8״vk(γcqo< -R!cu^^Ꞑfx>E|lV=r]9n/z6=n-!؂ϼauK0($IWT?0G.GX '`\=:&ۦ0fPV3bڢe]5gI'W=ԼX Q"K:Nrw&h>Ԕ.z 8h^yt Pn@a:O5]{%~0=ގhtV]@=9VPBӁ#l蛮[V; /eY nFΪ#->O]%-euݚϵ HET0Mx "z)fiUmz-:ϾPuN9}$a~r,-<^u{@ q&O(W*r;`NC&9'T7@[[mZpx#tGHC1hOV`U)9)ABp{+ '1yvN1RT( oQ~:P&q T5HM1'HOfo]ی'ݨ%cBzPcuY ǟ٢/S kxH'(iB ;{}\zpSv @Rt.>,҂sN"[x0`NL1  0N8LX6@ ܱ[XRtFU㹪vk%}Ó1 %xNZ;c*NP.֩E}(a5f=1Ş#܎Nਯc6u"38MO;:1;yq0l,72u'8M-HLĦt{s5w*;v?l* bxj<{m77&u|_u(ad~H]45li7( WˤY[>-J\ (a\\X%džݳ-„S\k+} 0i(ltZlh8idּ% /LsY²Yȏ'|D(DCwZC޳;mhrx؇j.lU':"6=/~kq‰;vY$@=xw OЁĵ= QnsZ1^!8‹2_EfؿD& &o[Sa08ʍ>ޟooo1P"̡:ٴZԔʼnk{Дݰ Syo ,3)awHkmU$.N^Nry[~}pG3.Mℕ| M\ :P U547b@ja7Fs|\wIcJ{^19LP]s[YV8!P\ &ͺ{-&H 78MžsP㡎}ɾ-P\ۣ}=yװAO B :p: Nq=&T%E8;n̏}NyHoϡı6= 0#G9v.M' '9Iz?6K?;osvJpǷFȎ$v[nsܑpm*~1&Ě^F@Q=Z6üAmnSydb vN^tƠznAYВG]iZB 4.d==pٝ;$:! 퍘5LNa>/MN (DMv[J;uD9݉kn4AaIر6<?h N>J2ŭ?~MZ2C&XɃu;v` BBˡh B u>: i RT`Q}Qv"; wI$c{.kQ G]2Ӄq،--r[==?z2.?2D8(,PHOm(2xE8ssoU~eΑ_.')*k]OAߋe?|e qn@\f6J.},P\XgX} ]:;aB78a m"~ƻ6w''5{nh8!VR+$Յ' R,=ςc|/g6oo[PnK;}N'J/20}k]I0bQ}7mTDX63n_;bD(g}]ۍR'J$P.LUᄓγ{;ܲPGɕ֓1P(5ٶ']{=ia8qmuxvCiAvF aڰ?:|4#&+vXݼ6̊H! l'7Xƃo"9JC dz>N:r"X6(O}/O~6=yEB¼L;N~io[^׀v^N<}k/г+Bj{Jޓ"ԃX%YV} cՉ}D]% B*;3U;9i@EƜԖp@qmXdij 1jA6p@qmX/h8]J~pg9=ڧz~৆Ҟ3].N$Y5݃(cU***y%FA?|c4} IiX=d)@ؒaTc1n<'k''*Jtٗl;D8akȞ@qmOZGKs]RXE}#5cfem]ǚ&‰ma TN*9`,%d mSl:jg,JPBE=e  h̆>%"Kh}b4Nx/Y_Ia3Tv.'@*k1lRCZ K=fpY]J9[8e?.-' Vn1IT;!N8FcB ]5.翃ЭdeXυZY0"LΩ9F`jF^9m2KkG~ eU4,njgh ^D{<{-m|?(_IBpKi/ץt懵r2%_\eMWGlnk'GN5{}>9I˥Ҿ|ona3 yptY~UC92%RXU"ۓm;"c{CIC ' K X=q?LNdY}35KrG-!q<7PNrp{9odKv_+0xi 4C:Fj-QzC;- ݵA UBt+^Yu/b\:M(ZKg]ڵfvB֨UO_keuʲӵ( `C6ym;KIݑ@fsalBޗakڂ ѮUK!z絚WӀRxy]( -|I!3_/p XM(b#V VϏShܪG̪x^׶y~  ]-1vfqBN-(kp[ra_fvffZWWY6ӂh!|7ۆ`Vi=Ŗ-P\^Q˺~h,(r 1 38Mx mo&A|bV\£A/AҺe*ÑҴŵ݀HaSڸ Q EU]_ʸ qgąƑvlTH!,P\kTPץۯ:O{8qm(BY4a`UCvb6廦4ǶEGFu3(KГYMڶªKv㵳彲SÃUo<YM(bm7 *suMVU( HYZ Ф"!G9[E[]`i(: 蓼ཟ OCG6yj6-tt(߻4HJపĵy6̯Yr'uuo:PM(uB9 ޶[Yw-9=8nL0~`,PHuRL2d k/LP&cڞ& q^ -!SjK]^i:_= 0QQz䁔k㏤bWC!CN=L>ݫjhPx]Ǔ A78.Kޣe(عyWSYը(' ud?I 'ʹgi~[XCKk/b˭ӹeJ#'_X/rLiNU(qK 7sؼ4Cڑۙ^PBޙ߄b[q[R_azXoa' ܤaҰ@BTl4w-*lB@S \M5 -|DU7چtXNr_V3~;Kk)WS(Ի%$x_@qm7 ^#}%Mӊܳ:L;Nl H=zG0 m{,Sۘ+ԥpմeamvbSkmlN~s9FaQ]umc9PjkW0 s|s4 5I;^O9?ꥉPgSkSOS[1k3 Wf+؅_/We'\5Ydzjțik~@!G$TwAAw}?>,PH?ʭ>j|]fa}m'| NiنSBg6E Rr=;V*v*5%'JOc75OwwY]&Q/Ku!۴wDdŀs (%ļ %;)oqǿ ''ב͕ts-P;'h_ U8@m!C4VNGm7-g43|ZHJE^XN+FYWQwt?ev4|}e9Wa kv/9;m½M(%.3D|C?)\7_U(ðW33Y ,vXSZ6݀\>*$v̊D!L(hXWKmykWkZüIĵ݀R2/][) 'Q׿2i^g qnOAIY]J$ߝ8z 3ݳYeՁOTa?qDy%#yڥ6W B:rTݙ~4cwv:qD8E?Zw)flU{]@KR-R=?4:[Z4gO\N-M'S-)G LYt/j^{ۂ5 ;U$tHTS!Pxsi R ŵ= zu޵ڞF:(Ѿ_OTMp })3F*ݑWǖb2Z`Ǡ~j"ό2091 |sPPHrs9l7BzNnZٯN흿'~ځnUh+IOO( χhXD0dǨ'yɉmD pb2 7 9 7޿G89gӖ(&έj̊]f:InekS.QLo㰖؂m~P\T0+'DfP4jZh*k1|ר\?3UYU)Uc59"k#"q׮Yƺk.N\ۍ/}Q7acw*#uPuPgu&u4h"=[Q.6} N0?hZ-o6_|p<68a%|ONܧ-R(+Қ,{Q'p?gZ(pInEǟ{C!Zj/UjQq]7ں̀u)CIKj5 [cI["[Kz/@(T4i)eMJ Jڸm+D@+ْ Jz=eDC< QW*OtR)\X/M /;ܒx;ˤRi"GO=ŵ݀^ZYvNی5kZމ]/sz%g7D8qm7kW<9j->azb!okbBӁ5.e#{UB 7n,hwdyT,Q#A+k1FS}M4e|fRS\f)dˤb= +b@!QױJTY!PH9ezHYL]-.-$|ZlmiH)oV>|y^>#1P\ gк`hn@ wٲ\Wu|_jTu<'&+۾Ͷ݀؃,ͳgU( ŅmĶ݀~3$h'q~cR@/lƹ-ŵ["(PP,v*ֿt$c}zmZCM0r.#Va~O+zFZ^{͟6sf6TD0f:~pcٿ'Qf6RÅƩuDGgncpycjZ% -whۊ+ZlSbz{Nۇ7B6x&\_ze%xF~_>'.]@w|JR.o˜ WkLGHպZ6$LIYU{o/B)몝N=3}*Uvb l}c( ):vW6 \Q (u-6= k;8Ew|iNDl^,䛊)b;M%@k7jwfOVg,@ %3|}:թ~| JA\ "w3X ^/_ 0+"8v\^vV*/;"L`ox]W)r_ǩkQ.*]xUw 7 '?]XqJAC(IO>Z" Ϻ<ѽݒ|^X'A+k18ϟK50-|Iޱ;5(P!~4N1jʜ&P\3uBjW_2'9RB8o_1PP]G c~uX(F]T(.4N:BEb1_RrJKXpI5R|Xej` ix_ӳGzoppPlύR%,&z6(%aM0vNNv{RG1[gn^䦰9<-O}Sq*i$A^OsӜS%2#-eZ'IO&?~;ԱyMepx ix>ᄓrP nB`P1 UTj$ϱkYq& X!P\ a\4%zrn]R?q_@qmXaen:}GuҫxZv:T@ZSbEۄ%ۥqQC˷MZqsZT9|b'&SvbxW:~WĊ h姍+XV ׆@y,sM*]>ՅJ6=.Tֿ) cd.㞾%?|e#n@hBcsG"~R-U[Y:itr+cvB*]x5| !0v []fT%ikAĜ3ADa+'wtwm*Sjh:@ۆ'Z:&bӖZ85\?lŋ _P\ Q4P:e,:Rʭ`W-B| >̛ZϭFfˮHJ\)QL6|es@!Syr]F-tlL; tJ(-m۶q Y8MCmm/˷ch z}.i~I]|{ 7j^?fWSM-[=V=G1J\m)埤9>6<ґ0ZHZ i^ɵ3"A vbWs6#mB0zN5a ^5gݥ5o28qm%T(o9I Ll\6bO ٜ"Z#9OZvyn'zL|~pu&5yGǩsu@MޞBWA`Gi)*-J\fp{ \@*SRV\޺]nFjT$%EX5yviᥓky;^ME0bn@uXr=yQfrh4n,H\ۓv{LX4_ABȋ:ggW a+jZ๔.NMMvG"\P1<2&_wo6`ѰrpOP!PvqO֠ EPYud| T.f9>[۬Ίq~7Z 0iz:tseP>@#M'nZZ=YmOȏau+ ROrڵռ?ѤF~w}`/0b{h;#?G롳C⾰ E?Pgp(o2e^du+/+U(a}ҰݸמQI[JlT(Ԗ#Մ mۓ?kp9JhkSRN~rxHQBJ9V0%v[JƴPvuY0o0!BY+=^)]3sLXQ봂|!Eaw.@ݴ5C9|f='vHyPWbf.)-g)CޥdmO-J߶PLwv;:P3'r U c}M@6_4½r饕(hp+ߦ.TpH!PHÍ8!%n`ed5B-/1T'v#=P|j݁D 59Lv~% N8w DUPΦ" gIћgQhY#9KcNn?gGx@~m;G<79ˑ5hbo|60bڶ!lʧyJѣ#=&D hb{?hotzёȧ#+l,;*r[sxro]"V Rxך|O2V c]?VZx}L[C i([e1.f&9Vv`(dߌ!m[֏4jC@6ߐ>q5-!SO[i*ͽ.G *U^aGhR ᆦaf莊%Ց_nG uyra %NPGOPȐӨg^'E{3T&V ~EGXn>?`Fu{sE&Ş?)Zce?F?];UUV<5}!8WЦS 1% ^912@!Kz̯Dݶ`q]amOq)·ΰuy 7>LM7!i0f}Jה˩G%QtʸsӅmp͡ :~b@O$ܼ5ȮH N89ͩGΡaZ q?XݞnAomwzt ˡaTY!_+Pvw_u5.*+ /<@n uzo |tըAʐNd9}C@'Cr *1)7S9ț!(ovVC *[shA=䪸z9 Z2njPשKAl5ʞzh ܥDh;u86]rK[8T 9>Tc86S1gMϙ! 5qt =\@mN\ϥ>=^N@'+`ȹ nMDQxL EJ$>y7pZvv`N8Հ9i@o~DbܯH=6_Č!`fD ?Ը+B̈dLɈO'#,eJNF\ Tz2jMX~O= )|I\5%jJ!Z^В~/ cpɮ;Ph-!OD8, lyXׂ6&]醇6?0ym+ww Caջ+2:Ja?_HM@BIjRjoKQl.˦wnbG40A DEfX]y[jo#-bǖ땘 -/e,צcJ375Fpa(-yӢXR- Y~"RJk}|2_U!>o|Vۛet9TRMNJ/bc` 핰 ԃeZ8pUZ< ai(4MmX/caj娆@ۍU! Csc:+t螮Z髫MGX,,tWM,_)76g|_ޮy|H>Zjkeo$"s `*c\}Ul1L|2+NȌjTԍK. ]b뙦'v#-Gh 8aUnkC| ^X;6&gX ,YrJ(fX+ gTg ( 5,,Y2V"-օ.i4e,zт;N8u?_D aG]]X7 F<:SKTHN.j\ ;̽>ÕlK! F2> PBla(=W ? .j}^=_'E7At}ˋѣ[y/7^@ _ %^ E!]=7bq_F}-hyj*vYfUBwmC-ySh&@ tQp%T eN{V7"[˒*tY[ qdjam@W nI̫҆՝ggc)ARU]Mhssa+Ë{@KݫjBlYT KZRTu}p,{ԛ&W`or<ַܾ{})=s|q(O'g .[ )'>:F"@u21%ВLPρIMPIS`UpfO ]?+ -<Қ|>6 XɸUxMñrsn:[tZ'v;T BUE˶1׷wpT gLB@۷QMi4~VSҔ5:S2nj/@* Hs cDpCI釩]K RYtnۚ@/ _K#S]@!:0i&xZylۍXU͛VsAU(ƫJmv],z`S>@ؿnZ(b1 i-($Ē -xAz"rG#Mw9T7!jχWnqn*TRtטRjy]cr X!Pv]LS B ikLWӖ7b)=- [b,2mڲw K9^3~iYblns&u }hmO}FXӎ.=aWBʎ16C?gSQ9X:9 am7m=Yދٙ!ƎPX9adq+*T9U~Е )Y;\;:{{Q"pk{nrSKqI>Ns,y]F!Ɖ+X57$¸EImmlPü65nE[TSC:2- EY@ۃEWʴX~%}m?HT9+irKB~>;4W{ mC̵5ÚSPnv9ܴBX amoN9Z^Yb+p,%޲Qֹ1ӲmE#@6_>Ʋ!]Z8o':֫_>mROWk[nrSBirfjٵ$)\ Qd"z62CjڕLj;"J "8ke^$%gSvq9vz qGk|>,u#@/75'LZK%ܦ*k=#@*‰mRPjA1;N`B0>>U PBʴqpm`%4y/TrBž$$;ٛ&^ƹ.˹oC@wbbYp0ֳ)-O[~I;p򭱒t5nhsEӣM_]\NTN~vUdz,wVm)y K%v#%y1E;=Ӻo%v;%_V&B;%:v~@!9՟`VB;+9S:5 ?~PHܵ[GşG Y x{N`m7򏿦CaG' 1t;٣<)'kx,9m\_Ico-SKn7׻0[~z&CFQn@?'p=R-PH뮙i.S'׾i+w'a[.҇{fì]^pK@?`W@TBu+7@4_00+,+T&bznj|qmvJ^vdC(ݽcm9s%ã*Vt©{B ZReA+wL FMt蝻]%,s~*VVxNZ:w 3̻mMf8 lËS[b'j7hr4@!ɝwkc.x<:9ex= `m7z0Yߗr) );_d&M+89\(T5a _>8MCAUi [N)WM!:ܒ.nXYRb[Iz@zq妧"k7ِL\uyŸ mO(\UO;78Ar\kqov qy:yU:tkm@!jPG]!/Qz.9F1[ʜ~kIo%Vhbm7|vNް,-x^r D~j6LpKv r PHrbb Ф|v=(Ksbr%m Zb33(2tJ͠F @!u̠cbve@bG͊*&vj@ӆ3~E 1esnn@=QOÄ# p'9.6N89$)dBM,%h{ZN8e;v.@C4~ CҠcCMG-<՛Fւ$JxIn֣T.^5ŭv9ܚe )71rN =vϑDZ xC ?SqR٩pYG'EWF=Xe|.lmH`JX.%3?;R h1`|>1qyV>/l$ hbc]+Ujz%t3̛Y@,G6s݉[r@6TzWNtHs)*A"&aNҎ&Ғ7{L0(r W`+A+n%Pm{: |ZN\--VWG z ]]Ѱaq'׃\<c]2Ad+Iirp*4CsӨ2zfX^Mjp.HQ7zf &RpgX tܲLT)ĉ'8^ʥܲPd4 Wt\)G) 0%Г9~ Mq6* -'@aǨL;)MaBNS\BGSY O"o–<%ƣuhZT ii{].cjDW4(v;yp+5Jݥj¡s*ɥNp!λ\*kW7nrkU^pS{q lMߋ9MJKG;o*)\kr@LlPzdE8=b6'Lae$?Tf]jGk3hR6LڙQ'}r Px--'LE!;o>_w._+(vXt{vـ0TRSLZ''`IK*mY>]Uzc.* /%i\Z*{^ n:K ZѠ-#p]kq_緫kq«Ғ˜''D=k-Q_ R=<J:{Q* 0A[>Bv>n7G r \9mCL\C.&RuvRa/߳ߟ ^G[rQ~-n a19]i+f.ßao׎;e:|W^#@!p`Wws>^WƓ姺 'L%?X0դAq՞A4 ȪAM*gFS)=>lm]v(haz5)^B7lql.F%&;=&QhbQBj]Z6ٙy*{z5w1۴Tעk^cfݸm+ 1qia2)Bx٪%ipT^fH!ϕļ q@dz=ᦺ ‹ +JC žBhqw>ڐ,P i6'P ~r&z.Ar(HA hQyufk>qQ\55(R 6餫lqmCˍqnjm*g%Cͪ@s55[gw9=@!ew^9g:j]´gU{ X!Pv=̒"צbWl{ЖP>0؞_2A'13n҃#"S\mH (v;ĸY 2wf)|&v.ʔ1t Kw҈=뭋aK}\OiCئ!/Sy.QϞۅ܊L1N89EMJb,`ES(+}ўNO{-\T(JA_NNӪY=a]5e|B5iixA0qEIA,IEfz#oҟ >r>]) Fev9TGNhҺU]nlH,PZJ=3l+4B@s +]"U RvoNgp>ۓuc[d`|r1NvhEaXC݇V(g^(65m5qm7r,jNrL 0PƗ1o@!8@GiV}mcG+r BkiMi`d[붋iyн8yT#= (k0o= WӾڪ} _S~rfB N\DO3h YcRdqJnh20ZQ4= uӨ6u~j.Ji mC }bNS}2Km$5emOla@3 )8 #e7]trmFWHgι6_HokZi9!U(v;<+gp7kVHi&ж1? A@T>eY,dh۞\1V *V#SW[4]?+ -|ex&f;c}'(4=Eq]|v4 MOAGn*&D1*DUXDYKirsC_%RX2Vqݹ2MC7*OBWAc3 ۍF"tGA@a~:,<^p>cFc>! 8{n8?7w_'c'$۟j{MZbҸtw$ML:B>^2"Na֣_~zէ.z"[Sb:qeTg? .c>Wړ=Գ+.+T&tZB}/ "89qyvFZԏU-qJwa~%fj$ɥR^m">QAPѓem~yije)m_"ҫmwՔnO! FUlSTru:9^ЩrTB@!x>jp(/ƻA'^_E,'%4^dy> f ~~x'Er0á'u(ֳ!? 20mC̏O'9?D-Pc!Rb1ڮPGm~=KrB B+,L*'eLDEz sr۹& ˿ O4΁%E=3#N3ɗ<Ͱ  f@{p<۹ fs-(gpD ,.0+s9OIXNC90GaPb~縤 9iC C[Wp*# ?>02]>Lj[ c:P[8' ">0RG?4] G19TS-E8618k": vIG9:Wk|(d{003BgF\λkFzTw(%G;1'm8LC%gD`SA׎OuujJ{9;=+ȳR cJM'̓lDcv>4pZNBN^Zhv0(k%&9uilvX#ks ^nÕUw9K`n^ל}uՒ^~U]PW݄@!E]D֕i;[&m喏(v;&W!rlӇ1 mWlxKMB^|/WpL>.zvyPwL4lE\#MM>;x Nn7uj2I2ا왗ߜ燞@5'/=TP4hv\6xx]ȫMNhl9 ==/>aqG]wISQec /`YBr@d2>x]/UR^p'i˾m{,L{ Womz#7Ȏ$؟yϕ\-P.xSrcNrfZFM̥YM,6=mbm2H%au֬r{+c-fB PͶk?k+l[ !ۨ6zFe:c=z)oFlٱF8K& ^T|f9^:8Zp/ ghz"1Xf@2z*᷒sjqzB@ۃ{[{̤߃^-&Ȗbp`Q_v.Df\Mܹ,X8wWijo'v=jEoc(0{v|ʼn+ଉ]p>~yΜy?&s~Q;~>'vsu#$]}R:vî͚Pxف\?"e`n ^mېoۅ46Q_,.){ Ủ+P= E1 $?zp4zQB@{ubf*95NK̕GGECpiPm˂웚B_#GY{= Qn T&>C*8[%g0T̎*]jP7B]4M@6 NC3qnz% ):w+h[:G y+6= 2" 5k.Pܞ2̊H1ο=s7zv?T@eJ;:U37k1VmpzW zoǙ=ׅT'ܮZdo^fuwYhbܯu^ȓ y@~apbG3͡>7,Nq6i٬ =,.! 5zQ6baT&0mz^:k8?fX뜾3i̷u_hb` u4GG'°No-WrtB@!Jyɓ+u/q =x3 +R1S';7+Zj׶& h{wM -?UϠj+S( ߿.?ܖYs=&Os9K<-<Gn4OR&.s9ևPn` BRsd);,G~toJ\ȧ 0Dv砽1åP?VOM'v#-wP̓Q@-N|oƛS_hFqiC$fvtb̀L- S])C]rZ[(v;K幐S@ɿkZK= d E(v;|esL=zЎ%Xza b@Tn$ފ뵘=9&;i]x_ꉁmC]fBYiT3!fߎ^Zx_o H Z%6fa!;tQT .wRxא:~OBg^C h{CTVl7:::KVS K,m{lư::,7[bR^L$m%(mX V@ zG)U8RQ +bũ.yeH h{#RgM2R˜A" N]m^)3\G]h)BWpʁJ]ϲIRCfZ!Pvîð@6عS^_[F9*n'<vZ9a`1@I-(=qc[rsnzzcPB -|,f,k%7Ew=QשDr[ b霂Db_A#Z]Hٶ!0/}p.G *Vj(aZEўP BYKRij^];*r텏s9CG ~G _: Ws1o&nk b7qw~" N8ɽ%m)SE+?ojJTT(6 f?JPfj0v9N+kE9r(D6' -g&֭п6=||>PqILGZg3!PiFrQUNH>dT'unփ 8U ԇY^[˷.G Qjy$Uempúv@|Y2[5ٳ'H+`=:_k]G,u&Ǟ?9Z֏U/İ$uAwaUPnC+s6 Uz{.Ww9Ir:.LoknnH͝M;NlzjG0엿ͱʗ4uՐZ<@unV>~?Y8L/CdX; Z{ǣ?CFrci@,+R xI5rMK]+ʄ@FQ.&r_5Ap:gP!lu"D hb9aNﯜTV*Tz,Ʊ"yQ>j2Tz5\T(Nvs59 .vbRxʴiZ\-δrV?(ڞB"qq:pnVͽ^B@{sTYC>O(iگz5\T[!PHζj5qn؃ٔV0+t[MV웫>hSFoiߜww>_)x}Mgc*VzzAfmlkN5=(1/Pz|ee~W:qnii-N\9[V %[%\nhd]iΌNEkXÉ3l?4l,6W ]D ,q .dz qB <ڭljQN5`ݾ9-R|ܾn-yb\> =Mn+`"h+Kb!][ىOXO\O a҄J75ymkN[ Ф ~Ka1 ,chLf/XW䖫*omCa q:|@mbBXUՠbipi!]/뮩nrS+ 96j!vBps-W@jWi+*5Ԅ +xVRf5Qd9\4#Z89J'_geu< ̚fZܕnu6&ͻCW R&vG EC۳o2E8B_N|an#?Afv΢K526Kì$mCu}`Xrt>so=xEg# CF\*T|!&p7ж1~aT*-\TsV L>(b@!S,PHQa#r:U^̎u[n}CMtrM(Ybu[mȏSZ"u{+;)+ 1W<ׯ3u[M jys;(/W3)}y y[bpsG_GnB zh9d ^[a.{vN{,r0"je.*+ )H7~(L:\^2g(,&L$LѩQP -5,p*uS4O Rk[ri@!o0݀To)+H*';O{XL7QUAPH s'20Rs'‰mR#?oWyJijqGeRU әVcze0-HeN awH/0̦IS$ZYzǘ1ۂ8A .Nw3`c|e r SE R1p,y'xψE >'[8i=`eDUV$ԥ4U4p9PE@S79I5q5X h,>( 7ҜډZ~E}ÂvN;<4eE8wKGQ3qLˏ%Nw3K"o"?yrڱa558$wMzэ25=í; 9~X-PHѵ ApSYY9ǝ姺 w#+);z BxXbaq 9RG RC{v\CI\UQRbgx5ZN-ߴDG?7B@ۍj1 չ[|W#lۿD/u{LD's^M y*TsBℓ:JՅC>ڞ?$if[_8ljzHCS]OV5zC]uhSZ<^aP9rpHjx{; T7!j$oQm=ᦺ B Į\̭V&V&e$ʞ=Ѻbte[.h٣UyDؓYB845mOlBI9AA|oq \7JXfms:v?x'}YJ.ºӅTI!N8~gv9ڱYRrw5Δ~~m* 87(jYk/3 =I}@հqMt>L5dqEmO k*¹%yLzLȍb5鿟wM,N8]BQ.g9uzp,3)o"ݛzRoiIzcHgڞ 8#XSh{G WTK179o$mQN"^&Zfu/(T6v-cnCk.ߚ&v?w9ԤB{A53a @qTP#,9+U,UkMO =yGw`̮p롋Y~Gy y!Ez!̶gi'ĠQ#W}hkK=U^0݌To@gҳ3@!ewܨG=-)s,?UV8Ozv?8((;g8_c\9O / KSO_,NHA=u,6/}QKz#=38w'Z)^9ɝX 6ZsjKtEZ#.X@z"SKy;~ՇUBgv~>7Y@9qQ{Gy$-:ޢ =yv.ŝK3@*˹ 'ƻ {8epILOw,N89)'(?ԣ^X%} Q. =E_'P 1~u X? ] z,r|Ezj+% L#kv\"'vH=XXBrdyBnj!NhɁT.'4+% SY5\շ VCvG޷ה2w@!sUĭ@ss %;!^Zә=bg ]]5‹f΁9%hvcmBOR 6-u*\|Zu0o sn̴G@cw1ж=cC:ǒTaҔE9 s`Gױ-FH =;f8[MY?o3|]0zYvSv>SL8jqmK|B@ۇCo}_%E]=: kuuT[+Y +?󣺹Dj%6~7mqͲ00awA@`BIꭙn]v x8 C'.Q%2W|'n`Zo]ϏaPxفVuTe3"m%pRp]J%]Ȭyfab!.N&d "Քun#R = M:MĸO^4ѥv\Qu;nw9߶qBkṚ]|D@/Sg-enArX!z>Y .p=!ގ'\>6[Ypfv9T-^ƴ#(?u}@6EÞmk) Ѻ"p,Őh/eNk@!.BuC0:oǴp5e21"Ueaizғcړ .G*TRfy'N ahMc\ 'ɗ3#MKiO{)>]LE q& ;만K= 3PNvhy1˟v9܊L!N8M8'e^3$3O3֥-. mC̍폹Gռw9X1Px2 ( ,MFT`<0.Xe)2mϫ1rI1M#< @9{9\vk9˙5M4B@s;gؑSBв#mPB1( 9"m3WĊWujƜ0welK mC쳾šZ4,R%HоL /mC,k͒v^&V'A+ 1wcԈEr۱~&!#hbrW^c6.aRxo̱S|V1#O`EAQ.n؃isn}%<\yۆAX!PvQZRΓύG_\N_!PȎ, c՜lS᧖.ųX^ʚ] :!_ZwȘ QV3O{0']33 ۓ #vh WEF|5(dOS*_M/](uӎn>=?Tp:*ĉmRhbeS+m}wԗ8?f KMiֹonqȣkX>sOay\LlWV_߶4'$i=_$dT~X4t։|qmClKJjeJkꭼu)yy_$mCUj5~||v;ļs42O?ɗ*T39V>Gơ3s@\Bg~O( )ӅcqQl۞pS]@!EwpdZ C v=.3m˙gGMuΣM; ɇ^"UXs>z:/.fT-@6- ӫF> 2k`^qmE AH (U9Oѳ_ saXJU#{]qgUS*]@V@PW PŒFa/}{afԽ|kiyk`_abn҃=G0v0bǩ2V^&%D؋C} 21i7>p9JP"p=(n"֔sSyS{Ǩ8 ur;u[[F<%(O5W-}D8]QDM2,'t,&%zKjY B^"c6weHڽl4}Ir-\Rx&Tr-BЪZUhr] D](H+-r/2&_74n1^ bp{dt ,y_-jB-N!ZG0$"|EZO U)ZoȌ_xj^"!FCܭ5og)YBIݧv4g|`fAzyPhbYAWUen X)] rS S@}TreS@C}F =>&iM,ĞY(Kf-z @TO!@DqπJj~BrةB-J ][E!̞ə};8,9~~& ڬK* ]_>fzw9(@ ӴH!4-K`IsU"{T!Oĸ(SP&:PQ%\T(F e\kV}%+㛦@{wiG/q g'v;tВUWCnX࢒6;8r$޻(v;(ݼyM8G}qlH11ryٰNC36_M#;~(7\. -;*Mryk@'{,ơ!Cn7:kr:m}KnZ,IM{}A$po1PvscX`xGJ{^?DJ-PHÃ%˹gȃR 17mj94'ZZ-M* -?U-%U&K{;VmCOq7>Bz/Ybn0=gnۇه^z9T*”9ٹgpr2pyPAњn#΋n2޹hP5@!`!E5E0d8}ZI\̆ӽnB=mSf׌LV3g{vN#deN.YEr;n|NQp9W+cɌVB( YT^nύ˵8!%wUeޯ)t٦61YE`^)8Qi~ | +VRBb)LvDr]Q&{p7}N:TwRA:,Pi\^tz?׫H94r3w hb}jՂmڻ쩅)rE(v;LI^e̙%k^a^@zZjZ_w( /vO%7{nrksSNr2]n]Í^P!PH˴Ô~/Ƿmb~ι9Gݥ(j/t?#k5I䦚 `B ~L\h|=UJ)J)c@sZN8ۓ,LA 0v|k!@W @LJxYF|y4@41aǻCRv/_ԭ s&nц0 ~\RsSyQ_<%&+M{A: n DNl>Pa4k|8<ԎΩkwTgLC-kŦ5#C@z&!vz`St=F\>F mC`[Fm2,׃7h^Q娡YVRUе%._2x Kv 㸴 (0KG!F: &|_/ E>p4pm78nUy`w9Bв#-!P.Y ;LzKr.nm%!ѩrԠb@3ĥH!(T!n{>&8&p> \eqt2%pt<}s \(v;eLgf] A+ 1.68\5fkmC(Cmb]3.?Vk̑7-Pv%AoBK@@[ ĺv=^ .7sJjp(q憞s )<7 ~79 0 \Sv$B h{Z 8ÚK c-PH]mmV |g>r츹XPAAͣV.) )g:;cz~OuC G~4e-Penw(ڞ,n!ՠөׇgu&=4J%" ݎϰotJ%P!PHbFsQmhf 9BpVdvថRZg"6DmhcejLmmq(4>g"?ill:\TU!PH\2VUNTjT5lPc~RTg^uOkBnmn 7 m{ ;vNU=U6뒛< BR\ /s*Jzari/r/^p(RNNmxEn;#jFDZua;Rϡ|kG8h{r)N-X ą\37۫J7k1ެ,2ww^|9J]>r>ZN e_@u잯m/ .z1WpGk}~)jӻǩ̷ $qmCX;c o#vPi ]c^3'<ǰ?Lz?Y&HD7pNB)Wb6hǹD+aO_A-N89_CJS`ю`yI^@!j/ӏ75Rӏȭm-oxi9] B֮eKݴFx-{kŒ C\+g5${YwFB\hۧNIoe]]"408Mq0EṖFI{u|9߬RE8*)w!տg >5׻w2S3pGq 'S/,ǭitm{ڷ &EjqmCab,R\u^,ʌ!Gžz^=Yr;,-aPVGfs%{d~;&S -:ѷ1KOK~^(2M}M+:n)Uab8*.1S<|\s >X-X!>J~ڶB. 0ߙwF!L뇸r__^SdrS=E8?{J-߻cw9ڕ8%Jp.Ŋ@K9BAD8ªGZcrb]\|iW_>e*Sh{?U fs BG#J%lͽ^ϻ%1#|MMaQ(T~ {u4@un&<8$zj "yr&e,G{I]szB߅ZX!Pva$\~ u79=Ǜ5s(6sK>͖+e.** )MkO4flrx(Ta7o~}W4魿iz( hPzO 85)4_^ΦN/C@'RCB\O{Jrԝ>~pR7|ZVt;TꆮQB7($Q7fQ%z+sC h{C0ɻ/yC3ƹSɹKQpbߨa3|ɛ.ZXnRs'Y{ahPC策?6/D8wHClйl Z*s껅(]= Zx[ԋ1Fxm_:C_8h%b@{Xblaqtr:bhoV1U,P]aR>}\P,;*S0}v?8Vywtaj q8prt>I>5hWB 9,168: 9B '>*1c{|E&X0X!&^59gY{95ͳ%F5{HP N@ősj|^xGk)KK*4)kBdWO W_1%<1Z2^=!P\ _-Wnr;>L\DuU8L( *DF-LL[XCk>82^4&N-c'e0))Dk٩E@Xz]VZT!P\ 8絠#`ȩbՍ?'-%Sl3[ CXbW߬2ޘRX[͓㧑]%<[b/hUyMYTҪᇩ)Vi=;Cs3~|=oC1UTR ].pβi%b<<^<`0 f4&``7k26C6+dMՅqoRE8'`a_EÍ-C ~+9y.ڭ\բ"5bȞ22m9{.ʸ|ƵTzĵu22mZ7o'3UX_ 穆Òߺ^ĵ6eU*y}%42?\Dq#oq%m 1rMC .<6*WL6|$q6X-%4hL+f?׫@NHM"%e_(zawvsNhm͌H`pbRynY)Qw%R rvq**k;1 RӵݕkR/+k;q7ӵ`?]m mVxdk#I8qm'5~g뀒;=Sf󎔍X|TH-X0cYVGKsˮʅn'}|ZP\z`Re0'@Pj( ڐ"cz'jIP:`ֵ;wU' IF=-s qBKnIT49MSTIpڠ ]= +a׆m;GxnY&)ۗc [Z0oz(‰k;-; 7U4%*U)X4+I/0~qbN@48֖P\0(is)uh@}?h`5 qЀ,~,54MwF)6 vZ0HΒo7/ҘMN E qq\r8qmRvN-4.b }:bܯނ۶rG!]d* ?ʯ+1`vX^xGkKR ׆y  kJ~b4-Z׌c~pTB 0(r*l?B@qmif]? S4zqpv^zWs9,mXV(İwJS6W .MKaG_40Ja[N@Ⱥ,8o^}&^lcMkqxzvbx{!#|.pRJ]GC{"bBnyqOvAz'bA}9*_rVЀVAWq;6΁;*]vd:ݖ>Kk;1u2$k;1lXitjw6h_ RvnO3N^w%4-P\ DCgS_S' _z]ͱT V"80~ZnprSe^?\18AbseB% ғ8 zeOF*RӭS&}- h < /~E,hr`w_#f~6[ˎQ>QM8 mV Yǟ3j*z.paA )yW ׾c>2hF@sܗ 5TM!q 켲J~<֫`p+&} pNO vZ`ޫ_V˳B{9e՟ݍLO9@|% 멻Д3 SIʣ^̫눣9T/@qm' f?ӊ!Ws~`4j~08ZD3)w ZO+At0~Z}ӳ4?F5wZ Q}}\Zs TeJ?9I?=QBr${"<ֲ|r3wHˢ߫D9#vZ䩞nJr}8N@פש:}oB 08A~~ )<~#_"ܩԒPs5Ɛ`:pCޛu0;<3( )v<XsP^td[lXC[ 0xB ezdﮞ'kȮN;A^ږ8?-N89}ĸM}mz8rxfo:S׭fs@sWf[;ImO9Э/]{?߯Q 'y/_9h> ئp{zɬz  Eʆ>n*N¡Y0Z%/6Թ=,N\[a۷@ۄupdBno0[8m1U})k;14t^N-))/5/T(hU9vMQƃon/sg=*"@qm' {/~)b1 Nft ੂUئ7E9e8\#C/ߐIE9~Trtin^xaIXwO8qmbdP33M' 喚[ɟk.m@Pٴ\UG(k;1xoi1S>Wv]RxNCϿO!F:C v~\RdB @<=^"U:npZWC_@qmXΐfBZҎ Nlӛ Q^E$M؆-{L_^Bk*T~dŽ&3M. '8 ж~F`u9Tg(B٘ґI%q?RV.gh@E FJGkWװy9,#بkpb68b3FCkՠX͍c[rXET8qm.l%׈m-gOQؑ (ScCZNO\Dޘ؟&3]gqtyx%Ls [-*Sv( {d e[S4oyW@m8  u1CȭWUa4HC٧Xw| Hl wHrd -LuBXpٶW0\p0ӓW6}p>PD0QJ떽b.wF `aڠhIy5Eu+K5WQd|Ӻ3R<܃AU/!P$ZW/;-r8jI*sT"㕾^:,/epb^!BS~Jjs[6&kj}BE8Q!_D@qmXJ"w~*VZ( <搽D5֒Z%<Nl HSHcf+pu"nXQ '2괹x`]4ppabTI눲euVu'؎R9 碝Ek"w%9ĵK8j\J>_9-aJSw)Gr )9bh:(q!W@^(k;18]'R_+Qnw@qmx>q>XR^HV[Ebʴ 6|v\#Ou[=\?UB@fqp 9s%XiKSV/UY!P\ |ߨ~\Gw[s_ŵwM={i걝yP׆ZmXn%W9˨{ |Wka:v8o.,!i{[r(~qwQCu!P\ aO/di@_lW󥵤s{XqI'BKrĸ_vɷmn.˃ϱC9.s g{j` {IAW5@ *VZIbǿ.t~6M ]我]pl2 QZ6+ W.$gOGU-!N89} Ayj*[^"E8{œJ?ڵl8#ljk"Lr}bWO=W"ئSBTxQZyF0n) ]?_ϷOyhB/VMlb@0s(a_O,K}Ӷ|H)\i%08Mo?J?Y1,>^$/cT &0ۗR~أ}ԀĵA%zI=uwTٯ,D0M'2#3m{)/ +ZfU __56ꠜT{ONT a̗Q>aW$l hF8f J(oC.`CLzbt`b^B'N;.vsTd^`N3ˣnTZrC @D`?O[ud=Ζj)쥆M{w.,NT&؞9Dej+hYM>V%370iÊ R8+Lk`x%w E+ĵ)yp߯aTQ LaPRsOM~Fk{{%yM0uxI-k{yPR"[y]S)*O2e&ͼmtvɅf8>mLuAmz2)Hj3Ƕ?\gnT26O:o9l Ll[v y5kìH ];b.ZGujW%/ε8S(֔<7J,ôLv:NP!Nm*tw?zT:n-{S>ˡ'PjK:2,uĵYucخJm@ Di+d%)WF驏'tzJWI~7$mzPĽ@YUx`3ĵAM&%=fv˹?nN@JlKE,P-e/q٫=[$mu\9|}tLD=MV*Q.aC rd[n?D(hBrSps]B RKߟB;Z> /\RޯpܟBȥI`%}>m?P-~<[LҨ(:.,P\˄Bү9m4~O ڰE fR;%*$~P 9〔h9!8/n<#6Ե !!ª(dN@TѪ{S|,P\&/i٥.jjKuP\ʺ7 P\ DYCU).zwpib 6nK XV*)Ƞ,1/劾%WT)꫉dCk:C7_r7PҜ}^hA B4|{@qmrmz2v_k_vEB> 6;M2kc NlӛLi^~)awF:_k̀:U(ptZb;8xJCO@YYnp%P!PHM_(eYKvNex̼斥ImY6^[1Ϋ0t BWop-T!Px:Z)?$e08MX]{=LcϋXn28ꋋ+>I%~j!PxI\}6*N PWE@zu k{b/%vc-P/B@˯= ~ꪉ}# | JŽm@Z}[׆[?b ˃ͬrjY#8ĉk;9+|n/*T^d7?xNN[OpYyH`/31 F '9X_yt8ضʫ-?0U= ͗|c=!P\ .}u2Ezqo4Y?^CϒܢX3loC_'^*T&\㼏vʓ1/-rzbk{|2cµН_3CHܯԔQvbmE Yp#.僌OPץ| +O|x-j@*V:NP}K.8qm8 Qg^(7<[_pN@lhp }΋LsI7^~UEpN@+k{&VcӼcpbN@Zs[*R̍ڵ*!>lVw}&0!jp t|"U"|E砺Y P{UF8xߛ.['.uPR=ŁL (q]{svZ>w(F=gtbw_vJ}YŨZ@k7M-* '8w Z (RJi`%U]aErtm/\]*E_N`qe>*g<['CKݢB 4,BE8|"oZ}k/)UqվevKk\=ז_ℓ2hy%ד(ŗ~:yb*k;1\f6ƥ,Z?f˩3 ѣ)~ ~m#-+drop}I>O'mZ~jQԠb@uh9H!9S(-P@G؆?EST3!˫| /y`[ X!P\ qo.t^8^zuՠbz gXFYG+3ρ"ƪA SӞsXʖةT!Ph=- ) T{Û3}#؇G䭽ҭ-k{{]sܨܓ9艇irm#'zl!@DXm~Ж )u^{Lh-!_ɜdE{E>z iyW}jZP")h`]tʜb\-[Rpq̨>++O WOyWm*N@ BD#;؇ZMxj&k;1qؚ}1`+x"DPQn%Q0#99]D9#G{@ ]o^:ՁJ~t.k[ٿZ ==Ph0ZU%(zT`T<R)Zm{-Ǽvn*TZs]e^-DžUj- `耛%㏹ԑMۃ8 `B Lg3<ѯ~O<t̑`rt7]EŞzkKeßSB6x-CI58Oh(Q. =sXQ}t:t{t[|ܱew8!6~kp:rnxfWSUEpN@ WZqNq?J*wUVeLW7.r Zl^+:v*aaM 88!Yg8::Pfҳz1 WeTkr*jz}(jUR"jF#UML\ HI7F.Q-ܨEZv]lkBy)V8J,P ĵa]Һuǖ+0S_F_~~>(d.5.QQ+/;/Xw=wn30!N\i]E:51Cnd1#BNxTu}X{ی WIQ-08> [4 8$/9vuΖH~e)XDOr;ܰT5f4Y{'R=0>3'E@z pӨ0Q,?hCB2--﨤xK\U<t)&6"IqzZ>(Nz;R@J)w  GG5z8r<`*U,T %V)X{d}KM%\9?rr[7.q.E vb/=heO4Z8T'F&7P:^:kjgą8qm^HY:]oR,N\iVn&+v/Vexb9AvTW!Aœyö8.M}+P;iWyڤ<2%myN@j;ጛnL7Yx[tjr]J8ޅI-m>68R<Z(Sѣ'5v:=(,N\@,bN>_U/d y'kqBklqBJ=|% z3HMJwLZ|gqBiGhm`IpcK *שּׂךzg-EO74(-W˿Z֫hw~*VRx_'9p򲦻4[Zuyϫ7y(ܺ qN@ *yM_Sxo~Dh['{ 褊DpmekUy;$k3o58@O}TBCO%mfNP!N8c '/+j)j Ħ=c2`J'ŔL--5]Yz yRr"E8M' +0E&KྦྷNa[b$XFjYy8qm5Ci~4/q[Aͩ_6r)يz׿K R5E0aNjmP:b!(k0,fT.Ͽ/Z7V*VVmA]cy:nB@EBayn~}5 ʐ/Ws<`xe,B@ -VWFʱ3Mo˒uv=) y>^׿G ׾pB P{%YwK,N\5Pbrlc]_cFЀJᠱze?Yױ[n}ℕ|.kr%~⪗(U)LMDwh%aZm:iz30¶w]Ӛ5q8}T"6 K s3:,(~S PBuq鳹~ܒw{0:<#QNhʜl%L?Xmz%>/Cp{ǝHKIfk!N.--,6ʶ6|| $H-y-hYN87a%qdŵe NS;ۤ{h/fU76вa eֽ/ImYC9dt8dVӂ5_˨J4nBE8[l+MӋB)4nd9saGu8|.2ƱE.[թf ۮ9@רL2\nv nF:ڔ m&`N4n P!8mR hievfwNx-)Š^%nߨaöQ_2GV۠bF&f>;~ջ7[5vF%m WV1bw n{ܾi:TU^bZ~?Y£lH.z[ӽve>Y7fЦ*i{fB lӼ8߉;?b6raOSIý@% LlK8bQ9e]QO~dḌ8ele48Cs9ܦ&C(-CdϪ(TM4KR{YcQ>QSIS׆S[Cr-QiB2S ٭'|:G.!kq^L1)RxF\ĵ$oAГ17J_-iuVr%Y7Kr|w~\ͫEOֺ\hR>o(qm'wݢM0i-iz?ho9tB*?)gO[OEM4E[bE[mўm{h\BKަ[T"jKj3^n{F)UQ>NOGIr 뢴<<ՖH;y/"ݥ<@<-1EE.[7g,~ kL^ _T/?ؔ p& @ouxlגo<$ k;+K^>NݒJƸ](,N\r{U*'9ƪ 87'`,f >gW(~`9b/*USWLێӂ*+!T U*fЈ^5ql}i0d*Qc k*HmWضĠ\v3 {W.(A=B 2=&/cnfmŵٶ1{_חqsGC/1n9Ci~9ƌ=Eť v96z"{(^ >y5 9z%`{M-PGu^BQ^\~০sͨX8wsI4U>Ym96Z[H-o~\nuA&DT{JGo=cAwTj_5tH?p 9RCߨ(NÑ詫n!̉ l,ɗvŵՍ%윶4@}ބX>W!~Q+˼SD3^)ŵ؋͸N/c Ҕk{U;kj+b(~|8Ԁl*'g])kBp=6%r\YX CNH[XӮnp5X!Px:Zrwu7"kB.;Nb բF_wr8U(M}]9/.\X1PB_Mw+ykJjŵaM|mÍTw~*V->뫚Т=Vᣎ|.ocyĵ6}=_skB1@qm' {p[ iͯo.>+a^:b˃!L`ג"DWR"jy?׫H!PHU^SJwg]GX ';^QB9{(`r_TĴ/jڇ9R%#vͧHҾ޻׫_<k;U|Zv`pBn%iȏ-SXL )aɻĵZbtﺂ:"QNl9ʃsՄ)͛ž9=gF8(%0X#Bk+)S҄N-Kab.‰m:=)?ދֶ]:@+jyв'LdtO>tOO,P\[t'5w.=}B >>CC(@Yq lϺmv xۧʨ$X$ ); r.G5gri~}qt qBKH}\Nn׉@eZn?d, uV]/e]5ŵPV ZIRNY~ϙT Ω*|fs+A+gK P^$Zni(莖%v}\jN`oöropwU#ѶylӔWE*|)k+bn>%}V k{Y#'4k* P,]iF8$FP*a67 4moL6gMhq~sfHy.rZK=b"@(0+聦/O-@ u}QAu)JюSuK (-\(β_ .zP8zY>{-`{4V()b6H#xņhR5EXm;1/|Ǩ~t/;ZfQ;^)j/'KJ+dBSC0ǝהk{Ӕ5[v`W qB~W|mVnUHvZ,vRW[ =;jAc{_<\Q5C%(^;@!ep8Wqr΋9=ESXNNˤqLbW2թeX뚫qNO T/ qjZ3Lol臘8Zy"I.sf˻ 6 }90ᙩH!N8{E]Kj4=dE8qmX?Y+^N$;ΊO'^j#Ӭ[n禊 qInl_@Xi5=*SvbƮd˦|^5v`\e[Y:U ئS*roek<$wW @ k;2ӯeDNk_P|qMD1 7gSr`t &=oF uu?!G<~I-PH9 i~p(w1ځC.@G9`}>ܨTY!P:Zn?L(/>:pb~N^:~S6Jި;6RlpȵG޿YZU-i8:r+vUB@5hل -(GB0i(ˏNCy /[ʻ.Unb',K(-Y|kږ>Jg%#G#mo#~3iZPB iyk& ug)\l--{toe,:Q k֎P?=e1[vØ>0w.3?WNJYܴ"puݽp;&v [V#Tӑ@v].̗nhvM /%78}3$O6H}(U|欚[ac^M92̚1Jawvu7;NXR!tX%qstང0%s{?7>/#+K>[TD8qm'UڮR4>uƩ$Qo}٩P:Dezd]kqSsdGĵ>$F>@W!ngΐ.As#[trxhYbܯXA6h2p7:ϝ~?>R@h# H/-7ȋQ_[Zuv:>tRJ(Gi}@BRPUnN>;}| NlҶq-{eC{񅑣e]Ds9ǒ/&kæ]|az(Ej])lZb"ئbWF 7 Nlӛ JLD\+enu̥}+rw|?swAOoC.9~ûJ6F$-~r0Zr1Y"ͻE8A '&Gb9Nwyv.]`!OyQ=Pˍ_Ypr2~x{z{( 1sra7j\pb~ɕv.?H5`o:sZ/ͫ&P1O˘;䇃((*3n۞( )Pu,W߶ץ8q6)AKXIөj(:Ed;H=^prमmpd}q7<(9}שqXl=4x'r#wr=L`'7VZ6#n6MMӨ[ npv)ޱ"0@&o4kz:m`ՓEHtx2}QāqQz*"m#Cm϶vg]N֪ڰZ' ۀ*5yKNyY;}k;1W~d?¯97M+J4]8̨)*>U!6O1 ,qm 36=.7<5P8AI,@`k)kG[#,:>j'/cǪO]}Lv JϷ(6z7St^:+~ªW~/g݄za.XD~\eCNx>};ݮ1N*8&2P|LڦK 4X@95&)r!)dBnA_4 $hӛnk~p\g5bP!N\impӭ Pl%k:=-P\ۛ-|BuJ^m37n&e/]"pNO -uu`8 %.PZCQ.9X|֭JRSw"`bNO V fȤQkXfgVTc<`G[U&Xnm`B R1C`=Ѫoov~VCtU!J8 Sh[fz\F:1~inۀ[mSUF)yaȦw'>YvPJh4\2O&[yݵ8.^G{= pNO dseTGƃbeE-_TXTsZF(c HEY7E5췴8_\~Cj&KW7_(?w029s݇7U!g* lvp9r(:-b} vb8q8c/* m{fЬ)yɿ-jdj(ocvbh$Nr; -yWAiRE8bIQ{Ln2yf2NSJV7($ݡjH[F}4֚vd _{Yɓu'@m:=!7;u)ٯ̿qC450@mX~jH!ox 54n@Ew\I{ Acqkn?5&]w -yQBH4Bp; ^wޖ)m e;dwܖj+'p{.0^U{A$sn; G\NcεYhA['@*‰k;S.5noԒ#p#E;F"2e*%_jѕk_AU J3 R\GFK|:!2˚mFݫBv-ÍS˿l:;Z˚eنJ>*Sv֡r)Mʞ* Axl5HSn06Mÿ0`TNR M/k ιQ//&lڰy#y5h 9>,eI 翋NU'^L}P/a_ṩBВ;Rxw>%ʼnk{!47Ubذna+e]*Ck? @+Vz )AݧC,7 ڭU*jXcI[2Lw-o8U䙦e DզBzԢ 1TU!PHّI|ɛw4kZK6rI]Q ceqH7Vzzru{~VP?mCbUKAm;1؃iSKWJB!s!P~fTrAU(פ\Kl]^cp&N@, 5Wf`]c~KOJP߇ ' ˦rm'}nvuӬQբr|G1RMF)5p"r^)ɵäo,Y]TB=Vz)2(b`=-b9ϫ|/Kޫ2@qm' ӓb ZN5'B^*Ift5"}#oSn!ĸs.oިoQo]؇k'5%mot&C[1J_Qex1V%D\.qrT/u4[9duPpvbxnXKD9䯾@B;Zn^/2&,uufh8}'Хnaڡw1> G?|̂._Q*Vb٨(_Axac pv!{iңRne2حlWͥrު[iWBbL%欈Jom]l0li2" s~gCi Lܡ\@EmQϙ5q,_\&̃GAop﮿ úk*wB5+fdpwДw|$n:穎a,HC3 +To.;؃eb`}26*MZ}6MI@ݚv-/jQ_ e^I7Kun}%}xҪ&ήq5^31rםZqDLa;-3v,N8׉ NQP6ǙЕ3^n6ؒ+b?FWq!.!TDWT"=B)QtjLQvZ/Zsf[+ʄ!>W@*SN\}@08 a ro6n+IHQ}M } ¹ 0zlnXIؖahO(aDJvrܪYJlK=** )<MDg\4pޢIO].lB8Q q>~t@!%'\WW7Z2N\DLʯuo Fyg;fV|AHj|5:^"Q(^NnDws[hv{[px mc>'O\| -aKmp0ϛ<|wPh7lHZ0P--ߪ'^l8*"<V)r?;6|f#rd0ro0CapZ8a^*ʓFFݩ.0M/Y7~ND(pѓT(a$Ƌ/kDql֖qxG.-AU<b5 ˸*Nkm J0"ߞʙ%Wd.|`VU'<䑸 -Kr2Y$˒ؗo9˨pċ%H~Ȏ4(ad #I+˛ZٵVaK1P[b8zxym9) O8'ݲ};;'r{]c*' tGp35ygEΈюT%RaDm]^ƀu*6>(TgT8z.-P\ۛCX|5W܋'=UI'hܠc:B\3VUjHPIѨ}|ljk;-lO!jGwO_Й0jslԮ,\!nnseBܤE3=ۍi\GeV2lp 쬗RuQo]YãH{NU]@PHI}H?ngig@))J#&Ǖ̇>aoku{k^lɉ͘LNZSgS4Wc"FR *SvZ/=7^awvվㄖQI^ֵ-5]\yЪJhA \_+Bp%qǦV̱xI݅K[@qm' {,y-J]\Z0W-@( +sZN/?peRKr ŵ+uMy G-(;jr.j>j"k;+#̵֮ȵ~E}#ɪy5X~W[bxc-жj˕aq Rv\-bV13$W5$:1iH1WL)GsL[5@ ډ!PHBmԧ"~E,SX srYmQImm}ҥF Pԩ_Ve͛!Jvnڅ!PH)I @C u,,s"plUjήpUjW/䊵ER@UjiϜdg(R? }azfGp̆ةB[Z<7'Y |+hְ;"U >Z $BX͑F}c)AX1j0_)vTW!PHaEqi{VWnyŵX9yb _.CUԠ])gYT(eY7bOp\e޴Υ8"Ðg6%1En2@q^4ꨆĵVVq̳B__i[NpE)JT(BQ%yHEU(MY(Ku K!R%}ڶ>ܫ;q"jbzGjGk.ʜ>[~ŵa!ԒGz+b@JԕUbMq(y̫D!P\  )kBJ}:=}^^KFϸN@ bׂ*ǩŘP\&M[֭*kAP?b@qm' @i5IHkyּB ]ܲ<(^.spdrԽ. |uP\ ]]YoV4 ^C8!E>Ś饽SL";b[)*ٯ%σ? '\nɽ}Ӑ7vbbbݤK&ij6|0 Rk!uts]θe]<J|Za/% LHqsW]; "j4p@햙!OWuFL [] hq^yQ9a5~ԗkueiOwVqsk;l*W\2L:L=cc UKҬ8}:FZk{dg"bXbLwE!]ܢ쮾hoM/+V xeh9uߝjn[y@E [y!jr_ suHN~IZSVE5̫D!P\ tuu?nyi4|ާCɏI,}0'B#(yzUk{SwNLt6%}bY_+bB· <Pټ((秺!L>2sUpU[!PQi+5Dkŵ/3nޫ"e޴ݬo)ݫI"3洶nĵނqV-2m' J'"iNO:]|kjpȽN*U׆/Ǔ%0kO=4f>I(İbOi†`eG׻c8\1N\iB,-m )'*&]}r,C.㥹'JncoRE+CP$O{X 4:ҖnyM.W5_3­FB5տLUw~(V*, aڰhlmOk fDi[\b@qm' g\.0WeTB p7,rQ؅a[T]6F%t/ov9֌`*STNzWQ_MN\i9 38S@qmoXR*7 q+iU( [UՐWiZE0o}1,/ڞzm<,Ok6,U?_-n70M'K;d>:byַ3gIzUSvzZI* )L _)yoNFb8sFzc¢e_e N@Ӓ{IQS1P/ t_jБrV"PV!*֊U/tZ~\eL5E|)Mȇi0:,#&D ''^S5OD}W9 i\'u$y91S}|G_j.>sX>%ĖyH"a2k.墛 !D%{'$j̴hPH-Utl?kCˮkWfJH;qlF5Gɚn Yԋ(J;v"U$PvDHqO <( 'AOK6ףqsne4 B@Q<,5uAᰓpHW G,Q] '?lEe_E qdNK˯R8nbw83(kLLjP.k'#hVuԄuwW~ rU.|O-QT#-)[퍲Gp}pd{MibJzyeRseZ T@2mC/1v `?BغhuSV>}p$̾k-VDLiIC/=T (֔UvJ[iה?y/$kW"Rmܤ i} S)bxevi"WjM ՒơZJݞf,uUW]`N#՜:.UU*s-R>Tp8*~ԤkVbH qfb;~Y}5 uQb+ukꢛHv%pD|:V(k_D_iA`_Uȴ[Vӏ4oDOޚNg:Y-JVՄUBiQ ԩ[a}tĆN   -[2ZXplhoeAeae=e!%KcC+n5Z{\G4Z8-T!pZ4*T_\*0,V ľ:Jnh1bԵ&(r5l &B@չês;TFuUFuВظrKHJ *RMs;B@u'C ^e׍׳Yl)N :9Qf6V*5՝\9Wz1teX4V+>#})>|8B i9%1!V@Z@Цm=ih@UqX}uχzBMHtZ~O@BSv.~)EL ] I4ɴ1VwC @2mCQb9\׹0TZ X!L~cՖ8{0Gks0%v+wi,RqdNG0]*NK-9ϿjF *Aۅ|ʒkcǐ8@ Yͯ߇ ?ȯq?گ*k>x qdN_x+RO-e}*?p8J"He24]WVЎƑi;--"QR +dNX[#TV3x@2mbɗmf WK $^oeOL/OH7=[(id7ZNٮS[U_؂в"h ݎbQ0^)LbsN r:vr Zn7Lz)5UwڳbOpIF8$wGU-vP*^y>BltSz/)KH74;)F)馷ѥ8@2ml)`i-%E $ MX̓z+LZ `./"T勮Wy M9bȣ ̆mQZ:^,hYPrf M %y95| oWî4/#zʂOrA-P6"'L̛N&>· Jɴ:9-e"WB~8EH֚Oi ip|Xv8l4-C+-iJBh 6_w!\U;%Վe6]q8]!b@l@&gcL?Ԁ:1>iv*R$v:ȥ.ОҖ3BɴBxg(~W_+b_$"m+K Ww$PxopO{)?V$\xCkd_@2mDݸ߫.r0kO@2mC쥧BzQU95~AH7J0eu3[NmȫUEFݘ*B$v:?<|ƾ:m-!eqzf_QZw:5uKh=ȴmPıΈa' N<]JQ}f;˸ou:T[Ā]E82mC y磌bd`#9''O۝b"*_nA0g/njwjG䘃Ӱ(y[R1Ea&(=ZW>Q/Ӷ^(J d|W.1pӔ;@Ma~)myOMJp1@^t'9t]_{@wׅslXƴe$P[w}>X[ 8֪女)myL9SVXԲ6i 26r4u z-}ɴ1ߤopZ4@Q4SQouA.Ĵp'FV [ aR@2mV7*(2&qY\ LV oKqLʒ$9Ke}44)mDn8')̿qsb*ny&;t7 .c𬭦}Sm5ׁ1fKyjk@2ˮgfH} ޳ >_Nhp H B`!t+KBp5ꉀZ LcjjlZN]mmi5jrA$X6&a!<+11@#QTBL;m,T!LoyC6uQՀ+ӕW:+Pso[}߯o" ҲG'щA?>}$E|*i#%IKZ~OH`wZDLejrؼlȴ_PEu FQ(@_ 5^e;<gxX!4 H𘶒'EjY/@2mo2#գU (tݲ5`ы]^V4nxp #vRŗb{km7X0 /-Eo~M{1u=GጄG蠲i \랟82m寄]/Xh֥~I|ϣHt5N,ᖱ#%5i;bw;n&Cb;璅w zsqn%v:^%Ȓv)ˬQ>/@4^|2MC0 ש{5dN؋Pba֡adڼ//3[]ZK-#~ge~ dNXxCp%leuc'kl!L+W 󂛦@nH*A/`c`b.>m7m~R>iጇzq)b SͣNs~;8 dNc,QECi':DcsmDDwx[ޘs7Vy{I6:Ym] N=K0P ZZGdW_jp4F1 \-?ZkV~kK 폥%i;b%{􄊖G5!1b}bz7ۆ|@2mW K8Xk7n#n‘nzs̍(֊4n;b/GQޔ2QT8󊽲(ӨzimW+/ swM $v:~լ 7o\' ̹ f(lh 68)/D<,֠=/vGCc X!LoYQ9lgX@hi=yj1bhLfcKiZ H 7YQ6JP [[e_/od-߷[5DHN -{  aDo􊢎o>9D3!пc 4i}0M4@v;cUmuTc<Wa `V)-i!Hv`o}W>Nqʕү- r!y#NHt:zV90iv> !Rg\f$Py(P"qNoّ]n-=[[nVw $PtlM\Z>Hmպ1ܿQ ~^]ks߇s $Pxܧt-nGɴg*t"c' ?gzLNnC)jb/2.~ԪdNEBo1Z h`Bk!~=~!q/N9'm}/ȴ)۶M^77ype"Ab;/׼R+y]u}^rMmÒ š};vG䆒yzy^;G h\E<9"U<н1rϫh6oT!L>fy1#k5_^c kZnToyw4lo #Tipw˽ɴ121t ӥ %XG"U$P'mb#&Y 2I%oFpȺq.H7)n۶_˚r;,7YCr,C}T%-yk,#D/!L#{v$';#;eҋݙ0m;x38EwmiXm0PM8ŒnhSUM =8X9rFmHmpVµA浚q-9|_8u{h+i;bEN}sB/V "U#Pհ)Sg=Eɴ)Uq/E 6~]`SS,4>g礣buUHtP/ZKra˱4iC"vjJJ_wVFis{j SyeXnWB !2CՁ !PO[vj85X!pj7 >oU64ʨЮ(2B >=H螮5+fkGM Y<]ibXʭgB ˹%+ #o|-Sƍ_Ew`P{"RCx%taX >8OcnE)!Q7V8MC--)2Ynthy~%nx9X 3j7`tw~nsդIaj(TMn{S`a= ~*Mo9-Q;v{!@ٝJMtJjƍkpHe?=dø4Lc1j!0DUj{wɸ/FH7c[B鮘֧ު+'rS|N:حJ"ӡI&e)PԲ;vGRr D504L/;r)ui_?\Z'ɟ8lV{A0S*Qs&Nu Ce;zQR5 Wokb\xoVv$B 6vԑVrs'0n~B !v/2|2 $tYy.O=pT¬ L;Xa/wXcyԂƑi{җ vx!AZ9s~fmrܫV"ˀ qh m3;qfG:-v b Ko0n~toFqȀ^vTl@kڴV._.~:" "";CzYbv"=-SN% ~7@5*S>|ad|!n,[\w8X1Z.y ' !]w_($)`uU 3zoe*L$v:ȥI":u@2m)9*3?}deD9 '  -{(]tw8D[!@"*_[m[pdNnJ9//J"YB?)iR0|4@Qu(T"5_DKV=NpPk zݱF|PkAm:n_v8DG IV?U[vXnu; pIi8/fpս7`4ˀ tț$_E>AȴWfY<&Hu+.Vy[ A"S#tDdl7G%j6mbVW1S,Qd ,7qe(ڇA>["onKhXֲwHw `pI%`_IBwl(?c0oգao2lZoCW/?%,ą9>,mQK#LN'<|֖0@ɥecX Xmw1V W}G "Uú 6>}wqcV q8QukRa0;fG-"@ۇAӐ!z營ms>v|O#LrGAb)ES!>[p=[fq {\m`:6I'!g㛶U̒MZ΅FHHԆ-U *Bx/^+ ,?P?D($ :Afn%WmiKI6`|NIm(󙓤\|ٯHzpx+k=Lw؊+ 6! _!e,⿭Lpp })aWBB.%78k\*la{4Lr`]F墟D9Kg)jUJ dNG0'*3jJާ!G.kfZyI\(~.>}> @["6ka'z "Ȏ?H#CJ˂=oqW"B !U;m,3"9W2wӟ7|H7)I~&μI&Vi;_*6ݵGzQdA,Iν@2mC̍txa!] uɴ1_[I4-w8j'@4Yx_,He+ 1vfФ0/?*̕ E+@ jkLHIl6k_z,V ľڟq @+3ɖo6ɴ17: N}}TjTMkn;b/K暳fZNs! oCiWKf.^+2.ዥ˯S'ކ2i;b~<O^q"NJ;lbD82mW^Bu `^;o3>];O+\㴸O%DG>Y11\1= ?g\0CL㭠 &x &d>winp=Iϯ`%~YGWg<+ՠ4Ki: kZj…0@> !N&a& *^7"Uövwxž^֢U<7CC*A! - 4mCEUX]z<:UG` =V﯈j:-Pܚi[@{> @#aZ?Ł@2m/\)]QgxJHSx*b! 1}bܰ|;d|3R7us޶XcٕwW_ff)2Z%fa=0, ,_qRo?B=Д03D@32m i?B4 ?fpntm99l$mg4qDH7 vI aV2bv2\̆2lq!7-ؓeWK$kn ;iWiJ"Aw5>gdN < n~ïƹ kZb+aZwV6.ipPvDpæ]9z#@2mNPj|w,$:JNyݟi7a9s!_3qZrC5ߘ=;wB$v:ʙӺr;L2Ml܇;jM@ܹ֠5d^9@jČK~I  $OLi ތ7M= }͊#-b #6`sDȴwݛǭi^q[)saC |+j:9d|s(j( }9M\)+(b5>Xd }/j 'LɴYωc _/QHM\ 1 flB6쮭1Z1 74,:+ !puZIilñjF$А5vrֲv Aei 7e9,u9TPZ(_8;l$Wڇe^P)cs_#E5]{ dNKPo[~q*,$WxM,P9$G)[juي`uocfL{ 8)5<2zָW@2m/z %6 vҿ,Ӄmw@2mC]ɓ ~` a'..N6E(i àBcК쩰_@2mֳsO{ 7@_B10k>wb_EUW!L#Rv-ªUH͏ >\E >H|qTֱ*ބaM"07ldá^oj@Eմo6\!R~@;k_JT{nls]/S1 61rjn(z.diҕ`=OWT >F+}W;>&鉥+ըV 1cl<3jhDWuycWWoue., ?>?HN85S—Z ~зhOi|4@_rrrq=@߸nYK aW!@ٽCٴg|~ q~Nl7>r#LrlTHj!5UHuTy;2m5е\QY1EaŪuZ.$AuY};xg"DtoGqgue3@}+%8g"U\DEPp S"̴׳c^7I y\(Wx/yUxrny 9H@nv5@ݛ@DæݞSjd|sl6PiŖ0A$\po"VJ7N@l^ 7m'D_(2m݋e0yƒ~Ȋ@ L;fg[Qo|?%its\.{pՔH(jiXΚwĀ`#vX#qadކn(;jJf[$Fe3f\%F-UW!L~e{BtGA;)䚛 ן0j4L>jޓ}Rgf aH6el̚@Zqr04@.$p߉_ Ja$/@2mCVYnTp`-4M+ BɴBx6-m: ';b_2¹j :j+bXm[xZ\̺- sb @2mCckiFጐx 2IP#seu߮'>!zTtMIip b@U*v'{ (f²G]e$4Z8-T!=Ul'\0Mp6: ;b_rņd>$GxW㧩<ʏ)\82mC=` s7/'#E`dzXw brob_ny,R#Pnos居'=/I_rZKO}GtHyF\Y#uK$ qto;H7)tqIqcYdm4pFNq aV&[fe&.&7-K7T` hgϩ+ɕ]Ua,;*ߍ9ʛ~~,pt c*Pogt얽ξGtheB-2VVF *QC+x_Ƞp| qzl,١NBjNٵ b{M5#fI>[8z.ڰ;v"T5mNՄm# $fXBU`$kúEzݤۓ ȴud !޲;vYH"Jo|ܒˤ},exAֵ0T1L"M|*9 D082m^wŸv>ݧ;5bNg~,lƱBӮ3!)!~VKUU#vZZ/IQ_Bp"+RkZ:YHȴ"8SkWGg^>,49Ť!$v:qsİ@dSLΝl8 lCLnRu giZ/y9ϰ|s UE8hהT&|íɴY$]K á.oW2P/2(&_o&)+kEaeb޶JYvL)V7^4-TQ>@q (#XM͆2@%5*?q"i9~5uj?+b_5G鳲 Hӟi%W7uw,[!Lst KY9ZǤF!!Yi"A,(Wuʟ/qbqnx/QF_bgqy6HvXnGθ5h`2k]rn 2mn!*Zl'OE3v؏βD 幚e sEۯ>Wf"a3t!̜ 3 2msgVQ!.pxID8[udGܮ%X3~4瘘O?։&Kt*N$v:İ_e Cg?gEnIH͗fR;vY}?V9a'lkm^A#vZZ8AZ'Uj:Rh|G&[x\ȴsGSZM77rj,TmX0*z dNk]ᰓ3H잲MdO<ŏC;ȓ]TQ,7'|$ewZІr hɴlHb} jȯ 4tӛ(YwF9j]fvÿ ɴ1?"%#YPMjv>j$isEΪlP&X9 Ɓ7/^AVsjZN$҄(Bdvb>jU%{b^%pNc,15qvXnYGNuW\v:~wt}Mk6S dNڲfLb$/&4c)b@?fb-H]u+јSH䌗r6S|L`Q,߱!Q ޻/>*"kӮ1K#Vg{P!4L/ Mn&mX7X‡"<1M%6Hu!6!H`< >D4@ѽuL0ək 7CHЏ>FsfG:68R`q~ `݇&*.|گkA L`B4H\X r8ٴOP @i{s8gJau#߁29 1%2wy.Rᨡ :E? <]Prbδ3ޗ$.ejh@dpOӍ&4Ω;G䚒q\Qs!o]n-JLv7ɽi?1sEGŌ}ii{3Н`0>Oê@&[#Lb)i.0;fG؈7!] R'ԃ`P Yn=߰;v5G2>g3jZʩuX^GV`AҘ#$R웆0-E8Ǻ^3g^*MT1U88 */j̈́0RUtiif{F4C;Pe@V8 m{ Hc]B9VX })\76IK؝v+;Krr#{%LiieDì fY"(o:~"ol D{0eՍG٘I`#t:Ack+J_%K6`ˑsV^3ϡq8Cv/0.}7vs`na(nh8\m%_z1@ 49ďZ4Lۋl|Оr`k_ dN]+& R%|gmi6~_$뇶~8.E8`<~syDߒaν,i-/+fxt?)>vT5;j7?e-r856*‘i;Zدl?bPz ]e _G@q ~]Io;)' ݭG^_z)_7Cc kb4֖e^e*]0[A }0lPtHmIɴ)5du'YʽخTZ8-Ԛ)qkT0V.)jѰP C/?vU4y>,mQK#LN2@~dm3Jľuj2[cW~-CwOi$V$v:0]٢b\Vn ;*ZUj:;@F^шW&VrJݺe4@LY_-a' nh2XOyl}Z-á.}#z_]}yB,t,. Grr]>NsoZr0qN +"Q aHK&(;aنr\[iR@ڊ&^[Dp܋p I*X+to_Q0{ *k_dNr,iY dFk'"oӡ2{upxm(E졂ؒE:Х#t:-?kAXb^ڤJz\t"{Ĺ4hy<405a!Yoer\H֨46XŸ E-3.8,)g8'Ohh 7 q\AM 1#pOK9}aiYl; wt`srђI9N~LkL!741W4c mJT$'Bkq`.V_S"f]!F.3(d^̩\?5u܍=,J QM,k>ly(Z9%5rHTm4G\EJ[) j+ǟ{ )p:<Gth (v8DQ0]5%+N}KJMxy>Ϩ9k-á. V(}PKĂm;׹.mrB`e;!3>N38ZykcR; O᳤L2(gEVB.P845͉%mj[^> aUXiv2{>9ϥRw8{$\xCˤ2 Vgl]IDd9AL.)SxmE[nxa_'ao3S+9ƚNȴ0Sԉ)JƴYjX_"Ί})i;bX;H[ e[4:8T!@B?68d ^2AU!]Ee42Ln!@uzA. \ku>׫0ɴgu_<:BhB ԴL]kP#jQsPNiC *mP`mLh8hJ;c)2;,,R#LpxWB !k ~ %~O.(_cEuqXN836ߜP`aEpfh٢P]j|`=ely'?{o9lkP3e|LL$v:1#CՔh ‘n%ԕr_zI18clZsPd{eskWsB !u>D_Ep|#-d f"ӡ$O;E!XAEm鐁p9R\H7%=9itg|s%F=ekU29?O?7w':]{ssB"7 .7j'?5 G!wlZKL+Jv ~-S#vZZΰo;HC6}Ӊ {L~k<GtH3~M؜]Gu۞Z@.C?\ }Ic*d~-^^NE3DZ.b !V$L.,{Cl!_lHtygJmQ$ 6dEEJ \ 4LjW̧Uum =SH>;Q K_8&4l^/[N}j2Zv' $Pvw b &a{ sk~臹=)R`i B6 gnglv:}4Ԡ nyetníĞ$QVGUɍ9H#PNČ\bf-uH #O\ qӯƺ!3Rȴv aV5 \Js~ GŴc /5L{ ߆8A ok4ahJ辜|5Z3 !2B>;!N4juDi+ 82m/Ү&d .CHu!md&V#Z3of+6@2m&1,Ҳ >x@2moƳ׎L}Zt 3Üh}0 $ˣ1jA0T=ŽjԞ^w'ӃVdpyT8/U(l>Lg%-t/}jU(`5&r0un "82;pT41xAuc!0eǏNgc)JoP! =)MnmՃ=քČc^ ~ſ3"ut4j@ѱ:3;:!s pi`&RcA `چ!Z/<+TisPoJWX R̿Y}!48u%moT4=M"& ]曆6@r&}%ljHeGM <۬ tl3YrAd:diZ9v qdN;B*2vظs>bڑRCVa`>.sYCi*UNǴ#S e;ۮvLiiJ| &] PѷNqHP"ڻ< ($(cݚ<7\02>G|82m^g*)w\চN[i_ NBb/5!vL= bL?| *u`X~҇„wp|X[kԵSp \?DZҸ킵wm+ !NĽϝ0>hd&"0cуn'Ɩ|l ]텫v M01aC$v:xO#|4*.KVwuaB 6_McȩyPc> lG "V\ZC&HBU>яs x-; *R$v:ļIs3o'Y֊B ;C;/Y*D X'C2n{yՕi{ӕM2/q~MpB {{/=Dq}IPpNTyLKPajjAPeyq<΄Y"~w)΅?/b !WW5SP\d _#vG>P;tN@ט[}vsTi;b|eggQt SNjfIlKȴ+$KI}XJRhOF!Liin:Y8*v?CJQ51t۫a-w#իkTp8*M@ii=N53aU@<Ʊ/5F@_I:u߲;vGT"h{f D RXy+** d Ydi9iJ6><םHt=!W}ǶIjgIeqmhAе>nDnwm[m_с۩Ƒis+$7zxBpƹlrVv !.8Gg8wgW޴C05LPr\~ Lއn.[ [֪(i;b/wO;)u¯$T6Www*GKtw"LBK"dBKj}H@{s\ǼLȖy}=FίB !楪(?QLW*TTȹ \Lp 4Ö8G@?P{I.Ϋ圍p;n58,es@!9+Z5~~|0 :rJלJt4Liiꜿ SuLT*Z%|VQ5[2.Khs&/~hr4\+K%3|,9N!L5QܚrtBVnz HC:#Xe `ZNP{JX35Zʇ0tX} v:~J5CΗfXΰ"#l6W?g!=*8*ZGS.9 Wjr!i\EtX%i;-)jpi Wˎ]J2I%4ꫜ 'ɴ1v\9-R nfg +nz(siM:蕺x̯u`X_@2mCق~;Bw8X1@&%W3?(Y F*U$v:|e%;'2i w8d@8FyKt+h/ZjR@2mC[IT= a'R@eǦ"kl4@2mo,oiH$l} Gէk'fd͜pV.oCӟZb !*+wR2_q;|k,_{@2mC_8_Z|w8DH0Zוd??GKP dNg0$sr k9W[*. ع Bh 7!Ҟá.S,b$T)N7hƅnb^ʘRS dNi/Y5]*('_~V%X.e!jxM T֜ZN^nPYH Wzo؟b@7Uz^6ˮ幓Nm{yLP7Re!ops}L]xԗ^8-C+UEԔn[K\ff`u8Į LRֵn;b+p:5FwH @g%6[~,|lPo;'H3k-B,1Ỵ{>K2;̲q ^:| i;--rI &,(ƑisEpL y-)UC aN7ח#*%?5jtRɴ181*!^GCO+9f ɴ1? # $PTco󆒇ÞÇ|D3!ft># $\E1+7]Q>-w8d@2kikuM$\)I X8@_Dz*fU(2mCemA~yq2b4L>b8ȃ ~0Ot E뭸 7Q 0: ɝ}7ɧےmLvqhR0TOjzђ3>$O׺ٵ 8m+MOQ|z n};~}!p @BɴBx]zyi2MvvWPAx*'ɩG7X{Ȗǂ^Cq,C݆kgN8G "V$T+ sF[8z*@pP7O6d?chW"!g?i y:xȯP=6_^dßB$o"x?mҫ|9|̓"[J62E\ŖT ľы9_*f >$~C{ࡔk x:^ "PbMD,$v 6>*Q*y7S GI(7p&.GP T{ZODDI!?+^_yȿx> '  XK"Wrs`JRhO=r"AT"PPygc YKs ' 笰;~98ߕLdxļ=nދFJv8DHA *g(U q*KϦɃɻgWo ,S[Щup8:"koc$ocfr^Bd8i2;,3q n}(~g1%ً { GI%{s:1t oʉGk5]r8]"jpv/vGaኜ‘'wA.֓Fzܰ; ϻ'g) &οg(**p/NI:'p:Di{k-b:\:Vr&FrHpZyMX6_8>ԓ0wqCvRZeG3daְ:VqQ trq7-Lb,fdz.P!M%QAi{S-2=Ogsa{ߺECKh)Di;5%w=@SDI+o5iBv$ɴB<バ\c`O1lj!}Ky>OE21׍ؤ6_ `ZN_!Bϗ> at4 r/Z@2m/jnn]~K IRA*UKLJG(NSJݙ%iF)LCs!JE@2m/BԓêbW/v+٢/ØEK\t@pN7CHUSL--&viwQ.$P[d)‘n:RqlS iZ.<Ti{S){-]󽉦@Qÿ ȴ)DqVY(!O 4ZO%DF6Wq'ͼJmCe@b%OA&Q[0ȴ-))Uj:-- b=p*TYýH7)_IA@ͼJlNԋ6YY4AK5:U1u6.5vo,U@.3dgEߊV>HnMQccOޮ-K(*l]Y`‘n)q(SPRI0Zk$9B-pR(t2T?_a@-Ke~ՄWnf/#AetU=WSi:Rh ݶ6aWB !k/:i|ڦZe_e `dN2)ن:.[uc304L/&Xc#67pTը;DO0 湤$ogngCDvׯ|{9E4uRVlۋ%\Eo+J3<`f&Ƞ #\"RĶE_B,mkJ/ӽc+ID qn-׺ B-@5s351oHK^Omoq&ag73_z־, lmQ;1mw6am:u[W-ۏ>v~A/bz,JTgF !bɪ[ní@ѽ`CWѾʬb$v:$<ɳi_jpuL-CqW!ЎdN?kG} 3}F/po,^5W9c R!tI6E1i^fԯcLLbjwnM*&wDk_tlP,T $WtYIXj%pQۺоyUHty֋69Xp;nYH>B9BɴBԡ{ϋR #o.ܦRN1}ɴ1j8QSe$ύR 'lٶsØt1L{V jCk_e51!4L/c Ű~:6v"f0mo50r]~WIxv>|B ֞am 7m;nՐnM7$O؉vPu5vH2ֲ(5DHNe=O1i-pB [Z{/-B⛀B 6_Uom=vyU };7>ǵ/O)(|(Tt?G+y<6JJ3c+RɴHOʽ-qۻf̈́@2m:WϹ睯vƬ9uH7R LsRN~r_Y<4x(=Ƒn:Rw|dMsp6lkb/kͣM{֮@2mC kZ"_f%yȹgwdNX1<@D^4sxgis"c !X97յgXMɴp29!ҼƮk)_my֨ANSֲJ6FLg_H]5ki8v'TlU ݇!^?/dt8"kB6x"CfM^k[ CAmLUxmQ{,^LnjivÞƜ=&Cڌ&]YPv@Sٍ5Z-78%0S5#MB~kUr"QwwGG|M*rѾ~e+,{J}#i;bد{tAw/okv"4\\2m4HI;ԖGфe v[נ+_:%hUu =r5dt  Pp{s [[ЊV0f_Wic7[O0{୦8M~Pڥ4^1x0;,3}/·&E/>{vy $aފG؝8'x䊘 KVl~,Q[5Lˊ]WR?"}umRRGtHͦV,[LD{:#X..ӥ{j wV\pI߅@eRDZ~xƑ+"bu;~~:j vXڗ׾Q:;$đn:Rܷcɏݎ?2M85oP[_Ik{ՍyC&l"*i;b{,Ww@5f#(* KY-YHyfQY%Rٗuºs)o}ԎOp6IW"T$v:7 5 A2P]A@]5GlO ̤TBƦy7Yakpv8$#.e.EB@"!?O3@F=&'Մ8(pIjzu7@ 塗8!`nX$oF*8܌AO?VӾ,WXLdE3%ewGXcFR 8ʯk(CYV7w!U$N^^h;J <4ϳa!S/~C]LnRtuO75Y[>r\-܃t5kWw_˿ߗii_AedÒ<9?//o׿__Y+.9,rwWCRPw/%aO{O!2~ۧh2E6xgR[_J_=G>H^Ye;s_&)QVgAD#9]CWYk-kA l &k}4@1,Q [6i{l`3P& éF4%nB vU"+2@2mC\Z*_ ʗ|ARԗ)-*OssB5)0eVàY ТKӥ"Q#X&u%gj\UGq~Rv9JOV/k,ؒɴ182X:dUiMRgS-UW!L#W60,0s,ݲM>?yo/hx"U#Wg;gl9y@ߙ;o`!w޼sR:yG޽0*zp׆M &{kV|=bh;Z#L_eDx1,ɗ`t8DG!@\ׇdA $Wp/]%8^ Bvdc ]HzʋWcWuf]H7)TZχ?] rZ`z\!e+ȴ59L}yC^q;nYG䞦^婢0rE*‘n:R/*)T UxNV4%| od qdNKX(˝4d9VװtӋL۩}/˜*K;3Ma %Q#t:u9.[aɌ qIn@w(O^ q.m6d,$q-KYiH7)q[9x̵[^%(*ws|'u״\xJQu밦ݢ32.(CR@F=c|ɜʁIDZۺl|b !\_n/clHT\2N*i;bNj/V)VJoB;KPp=,oj6̫8tөx3>40cL|_kڽy>V*nqQL(˭Ht\x.,\t7p \+v8di vm?kߒ.;2ۿ8=5LA8o* !$!@6^ѱRkS5A?皨noԺ#SCd Xtɦ,9ei^N?(%=)+qWo>w~&V RZ^^HXt%MeZU(d"a_@ mX[ f~*jM$'A+Jh;1\]jRiT9PHّ򯉝cbj`{:78pjh)1 :59-kULKMY̨Az(HCGkjz-hIC@ mO2SwLgw~LB f\^-w| 7GE%P;N`W==6|C  9*-{(PxKXּeHZJh{,Н۞:1^\k- >?1R ։] |V9a̴RZVBx6,v8l8~gb@=(PxhhmEI[1Q˛(ZaXn_۴%M87+ќ:( }[G8iW T~՛9Ê(a$N V#^іn/pͩ[+.İ8"CusN]}Q^gmmK*Éo:)_?CIÈo:s BR^ڞ,)Fo9.(Dّ,tN즿'C@ mOR\웚%2d;z-.\omhPU$sT ԇup<8MB4(iIcGAU "M"VBʍ>Z_k`)*Y}VݝAXR@&C1r*E\wXG֪ 7:EMAWԟ1zF^N˵ޛqgR;0ǖGRt>\ZNjEr:̘^ʁN@ 9Rh7XA_eKú욑xO]}xtRpY&ͳtn//s_١c˔$tQijY7(HռՌF P V'ww RІE@}"xo-?ʮ:K$|D¦ [(KpdO>;E_u,=0;/hY(jIZ^'vDz'P( mPOm z0J.bdgU??5o,HjdJFZ+9-a+XUyз= 1;}gRZ8̠3p ZnGfJqIf')Vⅴ)M`T?ƜW ^vO[JoD-# GvOU$~oqvi'qw[aeNrpj*CpfЋ%Vj.T 8DvZxqoV[%)VHXq ۫ϯ98u]WvFZGCxz!~⦘(pJYi][ c-r_auM^_ȱck|:!N%=&]mZ**Nk.W۪'@ m' `œH[zO]~b+'[ .:p܍dI4}ˌ=NH&jdžp)S3&¶ά) /{kBp5}hD8 =ROnzb\oF~6C8Ͷܛ/𔆜xs]krRς_y~u@ m' Or09qWIrwE'JPm=⋛؃U8gdT1Xrݶ׫M*W UبQ:s(y(DDo;U^<ޏ&A)PB kjT/;ve@8bxm,ojaze^TCc8Ih;#4'rs}N~nfB@qw 안:`pZTNB h_hKb2rJzS%"x6,fY:[ 侚!L_PQ |YzI3sM'De+,G(OڗX+GvZRr\0G%|0F@*r0?ib i@86)sA0osxlp%(FdȖDqE}b&!+.Gbzkx4/~􋉔$ԃ`[l&(%qzR( &5ZFMӋ) k,m[ ZE).͒3@1Q\+Z \^4wޟ|٤pR;{]͗7vDn[)N8QYSTťEtEƞ2Qv|i) @*d"Pn@٣dܬtxq޲:"&ДB "*AvnHKJR(DPAOKmԵqXkH3R'ENI|_?YOIG<-b }\ >"PH3[;SV y@v؇)_MN iJN*2J$2p2gIdUpI(|Hr.i:.AR`'r~y3(Gy~+)j^ u'@twVSk5n]K!hBQ HnJq-]ݭvF|;UP@R\q~OԻWr)XZKB ُE:\Q&Tg$ǂs3]]CG]TOV Vi k- V1U[)PB ᷲ(}R?u" -j+Bp٢zjhu3'l>MǙ G(*'GX~ik.0+rF+V,O ϏBʰK׻FtwVjR@ m' yU5>rI rhƞ8mSV,O ȏBDe^1ŎiM5֢Wp{{o&N"LP `Þ{-GݣkŊ)|M{5 'ʏʡ׍iRRrRB9'W<|}h&sʠ'XrQPv:8C}.o"&SvFZTMxHNHpv]5# {KUor3Ң~zZyp'frL\ ^JQ/2Rkrf~ ŕߺ9*O@ m' F֑7 {ªJaQ*PnyyۆFIh-U;qָ,&U 'pe_z/ew ZkpDL)N8eJ2FK1n{i!i῏(LB=4U.@6'q Gpʂ@{V*T^✶G>;r 5[+vNUG)z@sF_;~Ҕ[ߴw 8 m]1\H99u+M^^&}k9!| X8kcj+]G:r)GR8 mKiTݜ_'dpWa׭'}-?f 2dJ8k~.o{ç:{L݂GM?,і^ŪkXu9p9&V --n{{? ){GXam-ڸңa%> Ӏ#C@,j j/fw8)V&O auCA */9nl`uժ7IQVONQ ē@dh;:g]c]1PIQ#v鵤O4_u=&($a:@7)P94^%=(Лcdo"áԙ5s[pp0Rքj;Z;ˎ8xÿZtR[ sMzOޖ԰2e8 m'4|~zm/ZނdaHAM] n~ǃti*Ih;#-K{qNe܍߰AutRzZʗL׿}_Ǯt9i$8;Zly5\z:ЕX{hg-eڞn ȬDhy f zX6h \024|ki$_5 tiU +$ED;1"L"Rp4_2^4$=N~fbBvLbtm^fĢ]Ej*ՠIІm[' 6%$~rq:1PiI~f`E홙L/(6B,Ѣ~D1 N([?_=\+;%=-%Q+Jrca-TнSv8MO GL/ qOk57=!4(iTHгFƇ0hٜةf@U NpTl4T/N߻M~¸jqT$BeaH!{;eX$@n}Yx 6DR^L'=J7L #|;X?#oUEJ><%Kax̓~n m܍v4>?(aCEȝ;6S#FwTIwD:_Yv3tR8P>{;Čo;-֢FZJh{y98[V+by_-{[t n}xVt΂='&1޽¯t5mc몃l;vZ*Dk:Q<<[1i\02$ NB\ 2eƻ"Rp wzp5FKrpliMyy%p O r{MjZQCU4ؽWSt:|j)wL|ӓׁ{&%jZM:.7[& NBig-r'1I3'u}?ӻeX~4#~~c^v<„rp0v%F8 mX\\CkuNj|>onhՋ/y2kD4tQCmgsg;KW=JBۃR_1<p⛰ae&3f2`2E$"Nr3WSRrb0mq)yeEC{zC$ x1{i94T'팴FTݫy W <7* HֲCW m|t#sD2]ˌgQldžqfB\u"6vv]bRSgDT+d[^Uwr{RKxoƉqڰ-$sf֙Z1O1P?yb^vY0Ӈ5p TBٻw׀` @]au:߇!/_02̊ `jOih&d8O*X@6}',hgp'팴|z'cF]n.)E~H wLY%\Hˍ8$rex^WL\vFZ*ƽm} x3 I䉑E<۴'bMt`R@hw_Y 7Ղa.mYWIx2:*Ź7(M1>F%i>0R { uaAU(YlBE ͮoY>ʪ}i1d{KXSm(-ˠ7iU#^IZآGWz % ۟&Kˋe8r}LE!3w[2qk]\j}Kmk2 PBPCI!(j fp鳻~V`ea)4tyu}euV(ua$RQ p3RnSb1 ?&aY^2znr0MN#(=Pot} vHWVY oClrx@ m' zvf)9ZIJm' p*7[-@ &V R@^4'ʵbA{B P0Jh;1VYz(y_ee-YAY(IY`.KQrUp nƲZ X)PB =aj>$r:E{ޯ;5@ =$@!uixZw/@ mr\^NziaLC)}* +JF}47mMTR@ĸ_3݃bzRB8%Tͤ@ m' 0R\ V衶^jLkIR^[^SL+Jh;1nqM*Ĕ5W>Fkv!r B` uu^mQˆΕ!׳z! ÷2:o7H\ZIGĠ]ePB A\cXٲw~(qh\hQ7ǬZ K[WfL_ VRg눼Rpr`M{`@c4* 2c}G )6g9YۚHw8M-tuށ8XIP¸ү~@!yٷ2;9iugGnH vbp^a10UdݵBw4t릢tps bTۃo{ՔB߬)_yo0@bw{(~lNzJtT%T@LgmYZxN7¦nhq]־+`8eqBOw E)QvgAb)Jh;;_}jZɗ.ֹ|~ىwټe І==. -C F/>ۢf1}zX-UvFZI]˻e89RU${4:vT8W'( 0ԤGHK 859&^MZf4>ړVdq؞^-iivq‰L8;v|/ћƣJROi%q͇< __P_]ZroGoLY)$сy!%r^`,{0gb-{lng3&Ih;Q% 9ent7"L-MG8U h;ZCG+\;:rG( 5:< ;)3n 8LZJjF249 jwR vb9n縀o;1u~- Z @&Q R`!VI@X7,O%XKImu}Ƥ "Ѱ} ʁN@ މa+j| =&mP `J\_1vJXk;eM6(0mMǍC˲j]Z*p%=zH 9`5|Jhþ`J@ mZnezPÔ!S1z]j5-(1'5nn{_5= <;__kw9 ׊V7w 3wr j[qBK;裭~ YG ڥ{>$a=$h6r[L|n&9=PBۓg8S;Gw?v˜jPD({˹4ڰ&`TJ}5XJN]'LW)U,jęC'<fP?~]%@w瑺醘8Qci5=5`j2d8jv|譹h}:jx-hvb*[-p */肬.Ʌd'n:7qKbZZK@ mKIUv7뺓.ιhov7oK+ _+3UQ=!J %Bp%J\W͹ #(ĸ"-p3E@!EݗʌHM*&U4B2d-ktRdr9G`_epN@ wU *(B1Huګj?k`*:&hN`gSHʋIh8m(n}}!vrոh%}Ӛ=9uR`H oH`'y977#;w4vb>6/[-(MN@ *^zm{%UJ(b1 9StJ0]sPNUk_ /CRU(IUIE1=R-:)Éoꏘ38&T .v}VQUh'>nkW2<)ny;"7N&̯!luRq4qbcGDR&zk?q-mCO@ mkŠ6GE%vFu4Ԙ"u܉HPxyJ?}d۞$0Yh2L) ҃=cEtiscv:~8#(j' Z&=v!׵АszrGc(3]w/tQB %&mEZԞb@ mOBԋ9QhPw> z6 E|i="<~-ҥvh%=ELإ!]k# 袴a.@ mO^,UW{_B@<X8 l싖B _Lr|0ؓ6|GaEBAf{@_FJhaiPre\b;4QuL;;YdBqw&T &]emJCoO *]+<i&R 䂂WI> "GOQ[5vXI:r!Nނ y[ X$(iN@qbݖS鹩JLfRK4]B5(^~9U6#VCLMv^ƒqPacq>ٴ3531GIh1}MMY(A >L-v(a$&kI\„NZpU(H$mSJ˺ '`~0]8!ÀZW's wp+ye[fNK_2@{bE)P7ٯxg#Iuhr(ZSkzsʴ/x2BmGU*2e8M' F ]RC׽ݏ=RO(IS`hx3]6Ue6c ?xoIh;7le8$#//&)Mm\"߾SUJh{TMA_MXPH} ]ƵSXս8!LC)aXZatF '̞Ҧ5jѤ( -:> 7}{; jG@ m' f`"q}fvz:)Ъ5ڰݻ):0c7'ԋmW/aϨ&ouKpPK)rx @!eGE}W{ֽ(|fNX vFRGkPT{),zCwr=mZO vbR'lZ ʪ%.862~ҵ^G~pM=>9Gw3+6Yq*Lzk_$z+$Komj%{9CLBPf+S&ph}`ln|~eI+JX^?BD)PB qWl .m {edzi+}vFZG%Pi~g;wU ~ 'V ѥP)6lK\GZv?Xut[;NB h=h/KU3+45~X9LBH=K5VF]pN(?۰g)*6ZR`6*jѓ"Ur],R-łV 8 m۪juIii<5A-xO_RpҢY<]jrI^ ' kq z%=PUWL9g8K;٦b=|i'{>tw .'CCj"d8 m'U6to?,a\ĺAOnwDrpgg8 mg/g(I5QHMmtB67@*OF2⴨GKc9һUqAS,(Jh;: -6Q'+T'{y%YRo;1Pt]Vxӝp%T)PHRZ2Rj-F*]?Ysy{t]@ %u2`"@h@PQmc-wZ$b@Aqb-g4- ˈXk?7|o62VmVAz4Dp ]@S{X- Jh;1nibrp6ZpH`̩,WE-_% LQ?J u)7è_NG]\}5oQuQU = 9Dv"[z +կmFn'4,&f* kJxFuapTR v9=R؇:r۱uTe@c=ў!2z1~½ޞiZG&Jh;12vѫQݥV!cmnv\>AXG]c~(erǎNH6F!6U1衩|e_s*b0 Ǒڲ;;s)PxSwA  ء^M ]9(/ V2zX |Ew\3εsAӸviLl2h@ mK46LǠ%=MQ[9.n Y7 dڞb$o9*i`u22>bn.B@ mOR|R}Xsu{ .gÎ#A!!7,2큖Xm|k|SWL"k)>]8!v9U?c) p82%҆ʆg(W;Z_t# Z5fVPvFZZGLĔym:>4աQs>+PZ2 $Pg 9*b?FFXu,H5WrXs Xv9 k9@p]\l4dE$2)'ZYZMf(>`B\lvlƄpIB`M}S Z&?4 R)G%@ m' (V$U$TGJfn/; Z_?"(ʯb-՛{B7Mݼ.<wi(ĬlQ+Ю y_sp~0Rkzk1eIy X)PB 1IMqUS()hb'D'~v`WʁBk餅+6FtU,8J+8tc"rB/<Z9 뺾8ѫRÛU`!h(ZF_43G欮^qWy_iM&bb@PqX>e{c?] =(ިYɚ8:<TgEgM =KYimS?B&U2DJvǿĄ팴U$.˭5xu6ܞԯ<.-Q'V^jggkl39g{ լ3' n%|︾Ι{6ޙCԻyu|Xuz~fZ):qbh0xR3>=$PnF@ mÌ~QWU祐^o;;s PB a>÷s_ Pxc1Bx6,4TBJ;37.bmve2b@ mS:Iǘæ5bvg.es()Sijܔ&{ZQ BW9. @ m8EݿSI@ mnje&E,!A\w0WxVj^*a(Pl-꣩1ɄJ8ƍc:ԉx zzbHW\N2r7]= 98KvĜIOqvMu:IM8-sI>":A'j4uR:ݧMx@фJ\ork-أ}޲gZ ; PB {Q ڿ^lz=XJ‹ǀ|` +jhi7ӍeIʮCܴ";/&II-Sׁ-S OʢD'} *zltA vn_^)^boxqN@qQ?J ȟ C5) LO)mDmUpO"WWnmUZ;+Jh;18rXB]8w_JûS W 9\/־X?.fd^&L'팴PRm*PľqLuOuY"tQvnE'\m~st8Y7A|Q|~u VA)['%(aETF5yijZnPJh;bakзJ6|c{E+ SN[mB5̶릿uE[(I[>˧\Nԁr-@,ciZ'{&@ m' :Z들 3g>Ui "Sk}N jum_CG A!7ڇxi!eaC<=dt^ji[bvZxT8зGvghI'팴pXK;)Ko5{DFu\aȃE~)Phᣳm=PHQC4U —۵\<:ھ/~kk!:kB89ZвSLFiF@aҺl|-vM}pܫH)PB /wO`f.iEvLYuD.No}$:Ÿ@e1l&æJ-vb|G7\; ٛH)PB Y=^ Fbe8Mv$VHš-e`O ~IoԽ:,ljo:)L"UA{皭,DZiԓԯ_Pudn:Vj0@ m' Vp?vJhN*i%:M?A]>8Mbuvl묣/_\ZU(iN@8M3(a$/O^jA\tܫH)PB u)ZL( sWܵ6}D~-DvbpiӪEx#=' Ký$tfȾܚUd4 9> ə>k8{ 54Т1M;}_ STr0Fvn 'ФEcڷa!WʀnјTv;jxȁhjnOVG|&wPMUYzK4_C x%iv,({&NІGh^.G mP=qKw#3[`%OvZ~?yAeWoXl5(i6U/}Fljozxm^^Wܻ{'.yFyu6!'/~2rgdEVyѺ?>֭дm2<NB hqrˍ=N RNTWHQ+PEaOEa.1*r(Jh=8aG#LQK(*#8E]j p*TC+@ uAn:"/( )w$2(ȭ su_q_cĮ^+n☱ϙ)1oz_j:ok 0z= imмۅruq-ѷEww|\å(N+%UwCԃ-7[0D?_ѳ?wmx4r ssn`:zb|i=ֈHvbp8TcAN.S뼭j PH2oq]BNt_uw%v;Ľz7݃u{(lQXΌ>`C JɦKZYdE?x* PH^Ҧ" EwLINHw!!/1z8$f|q",:^d,,:F;y-r[f˨nqF܀mx2Xe:EV2V\?Nm;{2Ew_kh]b"Ih;#-8(UާDKuLq7P1KΜܥ̞QW1i,.c)tW\Ӌ~@+N'~Ѓy}__o '@<Ģ*aͦ_Mx|;?)PHa-RMjٰ^%Phvzx9Aȝ8u'hI"f%.6%.uAzr^q/% uWvvb${i/A(6))о'rŀ}j3!Օ4&5v":5_WKuz҂E:_[T[GPB `ZLCyX3]?=byw Id1I׾焲T7~8q*1dhׁ镫LM~_C$HSM I ]X7ݝi+ /20WԐ1Ѧs%>k;}#'Of5'9r_וqu℗\tJ$O!p5X)PxzZ'u/J@ez} (9g i n F#poN" $IК_? !eז\ї 'K &pN|ӉSpN@!=^W>5\Q3%S0gTp2}EquHw}(#Tp5,Tl{mV)ۊ6ڻo,M ߴ!Zf(P˅(s\\Ebʐ^2-͘zNbv02:[f|lq>8WԄ" 2[e g7nnqͳ!%# ;pI8d-6=PH-+4][z(aKs.1:m"Y '̬ra@!ETm܅nLMR4/ǩ3H JHZ`]v_~}Bϐq0!&[mksS-ve  wRR޲^㺼+ߡyuJt؛%N@,zK}Sm{gO*9N| H@{W^-eze1&{zZNqwuzr+&\8)iײo 8 mg\z:Z[Qnhf1vONp|R|3Ag>' O`z,E-|3{o{b"8 m萞RX@`*s20i ':3×h<2>q}r>1ReH9Bp9(Wܦm ~=*T vbd!G )<;ү]ch[~:twF:tLSQLHG\_JLA)Jtwbc]kcDr =-NIE(rMPC>#D#m1[:;j1QJN@ ^%pG`KrK)kй=+xح%VuzZ]WG_JN@,映t/JȢr %|\LeǗm'۵<x9NBiz냥lp/[΃۵'@*Jh;1wf*J[A;ЖTտ5UJvZ@(>͇w@KYij~@tH˻ %J<";%I( /@.r#%Ú/Mq !po@!wXmoYqfXP)ƙ`I,;~B{p+ZFt›a `pp?,'e'n>Q_3eF Y=GE M ' 1֍7FS06"{9~36(C&kH[%ٙ@)DĖ>am(ާήεqp;Nڼs0D7Cn$!SwHm@YDZWvL-rp0I-p}#qѻA7%=-pfy9 Ppx9iuW&r[ VR`Re8(-)Bp טּnuÞr=!VP zSvPN0XS{sf1S]W%@j 󵿏lL]JӮÉozڳiʇ86(!&c"lfA !5a V̛{ҤF>fk,O z'ezwTvZ0FF w V( δrFvFt'{YVmq0=e8,V:C]¥9&8 `qq7KQn_MlT[vK>.tyY N qBJbvu}pLSN88@0TuJh{:FM')%թ=}gT/oF[YSy"R3zڗ| uؙfR kފ˯x svbjKq[Ykj3[pMg*\3d^EYZRqL3eM]'l ~o޿bڐᚮ M)bgg}v侔5Rp/VC{[ Pxx*m]%Ajm0٪~}*wM)q7MT;.\oK %|H3w9=HO]hBZxe^%J2'TiyP뿄Uu0\0Xu{>A+o' ?̎ȬޣNp N\X^ef.,BUj;/( '5"]D؛R˼ %yJ܍n.tG^vNv G4h5ۻ[VSHʮUJn}j((c_ؼw~}57Ve?7=3†] 6lCHznjVR * &r{{Քsm#HPJN@ ?cWRMnYi_+ ):%gnZn߶RH˿6D )rmXYg@˯2?O}_X|VS7ݤ@!EE\'=1xבḲU4j8Lu@ZW?ڰ~[E Z3X-IN@ъƱwТR,V @!KFV'',Zݔgk"L{Z` ( ۣaV*V s'qyJD7FdLMDh5x-+ .0R> 3~_=PHIL.鸾pM*38 ^[6?L(0IKDb\ 5x{TxO覭gQtp-{= mpLuGy:4ksO>'P)PxZ8;NBp'^p Nx?yz-9X)3Sa+)w>:et{zb).jE0dUBpNJQ_{!c p[3PBq3Ñ[<¬9 a! )8ηi?>4Ee8xN"I.΋—mhgw@/Jh;1,ĵ)gZ'!fh4\vZjeKkh+HH5*%b%ڰUu\|r!=G\f 0͝cu;h~o l_{e?Z] >dIRxeq'9}ry٢% ڕ%Cx0lN~C@£=TF[qSipNWCNa)q/^_nf]=Њ;r܎\ھl}G?Ov6ӽuO?79LF:Nq1^Ory͜= R[= tCÆ )8{8u%7CІ7 g[ԇmnkl$@ՊTeo& /j@ZեKک|#H{hͪsvkADTDI"XbC]O|__U8>$ RqÙo"uo;{pӁ G}0jJv{nGfzJqI%;v`gJBNu_ܪ'۬G=(+nד6쑲-hX=gYh>^~N=e uWK3 '~}~3;3 '܁R,( {]J0>]ێ;;~gfOZ g-F[qÜki+Ǒ ec#m/4`2@hFBχ<]+/J:JM$@!u}-?q!Q߇%V^}a=G}S9k;߻7[s[e=Mby2N@ +:d}E% N*o}zԂKWn]mUUd-vbЃW%vްa_ۂ9PB =cٸJ^~O-])|h.Ba<] 0@ m' hJϸ\(ʰkb(ɰ$M y).)/޺P߷rSւ]{b3Ih;-0j_ם_ԓ\0jILL|)5ZwƪӍ_ #[ ~'{A㾐B1WB\09~;^ֱmݔȴή%kA¸2;PW7r9Nֱa`^&N@aD7v_FUkԠ}g/Jh;1!g!Ís&{4}(:V 'oύwG}7~ô e|MqN@ g̖0wIH N1˂B Jj?vQ:,& -TH{nfB@Eb%2RYK7nW?ܸ^W[;Y-#*Jh;AZFTʐ) Aj˄@"Rzv?xB͗/ZI9$!x~EGeގTI=Ҋ+\Jm^Ϩ˘ }q~'gkS,=p3pBJ{Ƥ"u3izKROܚI.t8Pd(iK{6ZZ%뽷ιѾ 17H*=vqk?Rsp+ct:&{]=EUY9 跔֯(&+?n)9l!44 ^KM*Z")JhB< /~- 䴖kybohEEeuهr$0c2]&팤h[/5ڵ0+W嬛]-"8M' ^\~*;nGfjJqIiheU.}Ve72šZ'=y"TZ@I rMaZ0{mjK5k` cQ{g$pN@ 2(E"I0z=:tcnغY0kO 4IqD8xͷ=(ѬjArjDFRk T`wX^?GMpi_,طϢ T'Gѽ˚/6Tc9R@yzT%<[NW@Y|ID[_吠M)PB _{\TG%<2 E+z4fвCe0M'Dis0i()Ru}pq4 5M%@Ef`#'fTGyӐIh;#-]׺5׏ng3:nBe8M' U~T0׏g}DE'`lLy'z詷V`lf ú*/Vv9qնi3WۈqN@ wZmKuwuي /l|v 3HJ7M~$Aݖ=tכIVQjb<&-Q vzBWH|w}:"QNlJEK 5;dUAڠ!B>zkkyΨk8#m_,:ም`$\oF\! 7-CXR@eMW TA@ mX8EmSIoFyI˵˜v3vn;F_kO}o28 mg'䰨3MJOn}PozPR< |s63z3X|Rsn&il@R b0[ ˳QϾ Ԕ$Z>E~LQ)Px=-=unXN)DJhBgSToy9v`W}3htZctSnN&TvFZzXWY̓ž8J' /'5u'Al8w]U~s9%QW\$ u5 ztRh?5y|v22fTjzz|ϡm!|R'PܱN"s̊HL8cܡW5ZZw*^7%8 mgU~TPi)% )']K1.պ'CeehR]f5O@ m' w0_e ^(.&'"F}ϋ'Y ׉xhEC nτJqBп]QχwE'̠eݭ%L&^K;^kdD( `ٴ݋ǷMw%O_k{z-'ۅx^Fd(8][Y"Q/@ mXWh=\_{u8a#U41n᥃S)4Rm 5͌ f.d Ф2p#G#nVZezXYqʃ}N^&1U'0o%aAC6[54Z&@ȍa Ф2Y] VuW\'DUԔFN&AEuyÒGmo^QN$Z.9z9,<' . l{ێyMa̷uzp/yNGj '*V=^<Ƕ.Nv?M:Z H(mG/Rv4Olj`G9 (HMQω#Nht6Ȭceʝ^ѥEw{}|Y\1WLaZN@qrf pVEKmi7eqgTA3-pYU '5UcWmq0AbÚ-bJE\"7*PZloQnohͰw[~c13.1h өpm6Ԁmo}|jD4R#{-z)mz乽et(PGnHpHawz;OBqֶ *`SS,mC+mR/=6)PHѥٹ}/|ϖ]z|@|#}{{;m'mR+tNЀɔWg*20Ľy/ރoŖ3٭+/޳2FbweO %}ۧṘbRB:<Þ ؃S’OŅp oK{ [!ȨuWf[joaB@=1.ї#?v>\w7;{@&T ^VO ]B+k=YNm'@ m' k ԤEL[)PHᑶr*`sNSoqb '1#N-Ro2F@ mO1bxj+>c(>2R ?bF =bRv*WAʯ+0fTj޶|qN@ y~+[;vb80qьMUC߆ՁѬ u 3cCB4.k5 PK:D]kLU LNz[DɷϽF}/ +5xkFsdvDkh$ZŎYoBGB_QϽ @SY򸾇,%E)P\1%c,{V?,=ڇe_&SV4rh[cHگ Іѽ-:Lq}4,+VfJiB0.Ilkn/v:m]%'.mnmk^كNHņ]ڞT]Ǽ^el!as|]Zvn 'Ȟ6{[#r3=8$z7~Yٙ6߸XƑܿ8+BY"%Pɒ\ Nn$<¾V;hHqڞL \yf@5C}o#$a'Rs\\S>/QfJyR-=NB-STtSkYu nh5p(&Nb"q̕7,oNyTޜpP? o*s,[,ŖȚ*qJe:J0RCsl]W5ࣜMT ycǩN G@!5 ̮ɻqNm~H W ؙ2ВV\/*ڊ}D&AN·5oyyiWTaW܇g`O&zpXz6qo*m7R[+éV)>Y\R N'L@ RtdPZUSt& <-fyQ i6"KcDgi9PS[I.$Jq89)dsݳ=PHa&[EjFVr AC@2rt/ n, )(ӱp ~@=XI&H=>mo >ܬ&䠠DMZB`^@+&BpY.QheP+J=4R )o"?N0} wEQ[= '^ &V GQ0 ==PHRm5R >X=wyjhIN@~eCy v$OڎVNphE{zJ}^nz_)]RyJKΟ>SЎ?Ǽ'lD-ػqm^׀)ȨK8pɀZl)^K{cmZp99Sس}Q_c~R23i= - Lyiǎ(0ٮ.NC ߗW43cO x(#`*[5S`}):! U"(/!zR tVt:*<{ޙ2#ĥk)\pڞ"5I~lϴh뉏NB@bNtUUMWCCcޠ!?SU !$>2821z {.cG@'@:W"-XB  523v6G lT _.2c".3TХrC{aN@ /hcy*~ruD^-OPB}FQڶ І6LnG>mrQ(g[U}IYqxG홱9pbi'N&T>]XAaОR ߄ Ui8Lc.*osgo\S0#fjyRcWY;n`54n68''F.<^E~a9D_:V8ک<+8ԭR ^EQ7jMw 8./g1s#;/~̧Nh+\m:߸^Z;~n @eHuPpzcXh 1ɔТKu' ɂA@ bkaӖw7 -c Ք-LvH0}9}I>2xz,&z%@ -OBj{Qbq/*{@٩S*}^(?{I,5BE[MJH)PB q_lʐ~"iWAUM>$]cwP;\'w|+ID@?vL Hf^vL̙2zdcuyݸgJB  5ּpK]N8~gJ hIK=#*0s"b&T`vFZC[΋y$8[&_gû9bR vb:X$-9w~E(VBx6,8XKuQ>г;;*r )~͵ZuNE,evbx6S;5XWP<\Cg^f-Juꉑ}atF~;Dm@XԵ.jޫ)Jh;x+~U|Ǣ[QfTH9PB;΢>Un`Q(ɢb`L[CNIeR@ m&>WlJK5݄#HqT PB Uu7jPOԛm'@!EE "^%Fm~) +.e(hʛek!W gm7Ș/{^|q}EP3f]ak(Jhá:~z=PHrNreﯳ(jnw>a┫ ?vbEz/-%zu5@zw9΁N@ՠ508ǑN@ e+j&z|n M7V/gCvbPW5yhIAFMȍ]z-S&|vKzu~&D RT Ma .K]ggڢ|.'Ǔ5حL\-x'팴V+)'~&C BkqIY󥻺2f=U St & ֟\VL"d$<7æuǽI#nפWt8M' %R<&E0m:GԿqbO\=>q 9>$iZh Vh:i(1گm7aF;0 ]˓ؑ3uSq"#:L 'W]ļ>]2DpnnOæ mkNjFxJu ϲ?4ӈ-^ -om EL]vn 'R8g3}@Z}~Bx JV&ƫazP~?״B'TC<,z4sEk?-AoP <{(&CY^vdVyULf3$-.3꽽It7ժVJZ_4$6|#-0-ܘ|xLUz71\HSSCY؁CR'[,9 '7aK\gK\>dK M@+v[&gM>ۮ$83_vJgU% mQkE(X]{NW=~ѳ!^g`wvOQvߗv|dg",fL\(vj%@!­<_4ڈwTƔ.gdrg مܙp`̑ m]kL(d?C5ۭ)CZq.LB O{M(~ @ mx^Y+b/^9%=yef?W\A8j"S) .]^.yaf( ןJ U/Kra62luuܛH)PB qQfECN~66;˭fk:V4N'{ @ m' =e шmsn2_ Jh;1 JAo;1=m$fل47^=[[) '9&{`ZPf{aZ?zM ':2OWNF#~&BVi-znދmgM ޸W|K$쓝|J$*]W`7Pw {VkӜmLw?(ĈM;珞4%rzQX=+H|맆%@ mxmji"K4hV[YKM*A?=,.R׋uV})%hJ8ĠV{m;nfJ‹hy"N\ńG^tx;5**2Eo;rsU*ޕzv<r8W/@;=m'4OdDoGVD!QAO|(0ck;1=4ޟP)jJ2]mvZkV=t-zx`wbR*"3 ^j>O}qtRJ:9^RȆCiڰ7P 4 &: !C*QaԃgL1r3M< 3ek=APz8 mwB@N(AmC)МC^)95MaH VVjnֻ<*v>D|CV!V+<+Pn߄J+zblAc+F~Baι`=ךͅ&$~hs =1&8s1=aӲ|TY)=8 m'6ɢWpK~f8Jc/aKcF P˨]Ikɗd,*uF[ JY.==-*"7MC)PB {NdJB S-UM 'W$+8Yг:"PZ@)>L=@(_ezb/@*Jh;1|5[jWYߞX)Ph#Pz%@܎ȭȔ/66ZВAZI%@Z )WJ0 ;kVm V%hb@ m' FV80aǩ)+?'-H=c95{?J o@ mhAa]bC9jRwwWX-3% XHˁngU@n [s8!%G{/_wZO8֭3~`‰]TWS`㖢 0O\֦>g@!~5rdzXm =Cƭ?]ر*s>?ABx˃==:=&L+OQL|TRR@.P8ɿjOc~]-um( S!Hc;jMK{n?K=dxYRqU깵ԿqxQ%G/UO{}iؙPN8Q$‮{yNBѓNnE@yC;M'팴UыR'z;mn1J4ж^^wGz݁PV,O*+)kmUp?;N_* )<|:jSei{{~gJB }vΔ?M ;{6Y[XaW`?y Z S VfGͪtvQ݀_"쒘0Ḿ}1S|"S(y~i*'UŕG;~`S`B@!5 uc:~gb@! +ֵ' kOVXdTWd)+%9.ϙV)o[Z8L(JaqQǯ(U.b@DzԔblRY\l,b.?p-X)PH>Y@!a5-_khZޔ[iqe(`ͲVOX!\n&U دVo?Bd/[ ?k/py% KqQ 6N`E~%= T(NTyt8eсkʣ*Nh4=7c,Qw+|W#̛u` JKyݵ=ޕM(``H4hz)>庢:.V W.V,Adob@%Qy~Wˑj#G~O̎|>11 sj٦׭c__-mt PA{Jz+lkS3JB B\fL*whL+QBp%!J]K*9^]/ZvY-dEvŠxS\UhH0 Bmͅ2FUmm|ۢG[)PB E;eU*tljo:JE_^zUZWՏ(}A @!RV%ʎ:o)sS< 8 m'0'!nj`7l-GU9N| HUA^k} ͏'@a;Po;rX#q[,GCWЎ5 /)z~?ly p w.yq q&V ;.xsχH:>e5kn]\n;GyڭK=#rk[ NXkVWrЏ)Q|r \9bUbzvgu{ %lk_d㜐i{W^l:~6Jh;>r>Ǫf9 뗲r U=1=q%a T`!\?oBc%c|@ mOcd5^ٯqo 2_ٺ>ǎ14Ū)|6O\w= _r /oAs}S\ڞzŃR)>6nJ8L6z~?#Rx40&H\D*2 1p[pa.=~qZ znhRzU"Jh;kռx|in0w>zf?@!%ڋӴahv2Gqf>{?$K{Т^u*]i"]ϣ=F˖^?ڄJh6%z)o$cI SC>9&.p( 輸j],@}́R/9* vFR{CY '\Xԏ,UEU~~H[q{SVxZAP02b ;'ͻ\#Rc/~B {pÁd&V Sn0yÀ1 Lfb7-]R: VrָsM(X]]y7IU'EZiO4=5j '9ɑqfB- 5}m?.R ],&:b~ӻ|vAhlaDImxz(y6<$zb~CWʁWݳ=PH'tY!;w>[vkJAP&;q|w ^E3F-Z̭t@T9$wOe9 ="w@ꨩmwد02M"757ojJW`2e0?c%bZMڹE>=&R vbѡUKf9~g(VUI!X5 X).!-ؘ{nZ0+J0]@+Ҋs7)7wG!wv?j+ ^S'FFRVe)gZΥ}<т(ĸ_Ů0Px/\ǚc9[>+(8~l"~%w8M%6{ ޻T`"QD&,q^K>~N|S<,v)gu0IsGjv8ڰBnTSNj.%qf~qR(IqcLWCǽynM[feS]Y}V_jhJ vbȈrT+Sv\٨W`b@+^{ZGIJ;JWqxJ8kF[OM(V fI!`+=|.fK[,Z^ODǾɔ7.L qʄliy?WgqtqWCdq!ԁ` "# QZ* 4кusfyomk$Y02pk(zc r~8 mO`)Z7 I`֔0v %e>]kVS p]68`KTr~E/yF`6D;qcCR~E/ y Jpoii&ahQ?8ӯ ;PKk\=k1 PHPNsk9 PH$jٶz~gb@!7zYgp' f:b$I7d88G9}呌qLX߄J8y؉?ͱ~c=PH"}ݺ>F$_p G$Q^j-y8R =1r0zƏ8M2꣆yuFN(L}0z 7~5'*rTZu¤pBv+\ewж>L^Jh/S6Iq;nj@ mOSKVj(b1 9r^|ʜOt'brf\?~\{i|e5@.(x/dRGO @kzt޵C&g + iV@b-,2_*+֒bRk8Zn}Swږ5D,a_*izpN@!u>Ni7a +/5Fv 8L'2=)LpڠLW^Ȝ^0Sp~+b*F}L))3֭%YeWt%|HN@UL:&u%sqtB67bB68U`R}ê4&'G3"93B_њEM@Ylh!s mb@NWuv_~A)PxQYH e"!bF]OocJyps5N&&Z>ٻzΐL|Ӄ@$0C& ]Ih{YI89u71Kuz}[yA?Kq05mOkܳF \{4Ee8zZlqlQ} yv:NXu/ Ѯm ѳm} rrg#@jz筣 skc->M(^&wCDIK~y?48JN@a)mqBH]UeiċqڰpZ ؙp+"r6ezSлTOL'LB Ha$OPbe5׍y%kK&_>%J]۪%1R k^Z>$vb歾c1UP}1o\QƬIM=}bvJhˉ{zvzJxV;'42P!"S6hRqڵ؃*pƏ7JȑH>c֔y{'v1~/Oİm' F>2 7:6=$aF~뇁p‰M kJ6V8bGÉoc~%eNyØOq͒~*QRsW歖T}))EIh;=%r>c1;3) -yrײ`X!)DymOXzgs>vىzmN&f~ݴ-з<9C)]ay-TGBQN߽L% 4n~Dքpp#j'})7MxRԏHh4Tw:eMSfwO]"er7i`lA[sy2fUZزM(ʯFgr]N:n7#ǚ(.PWNmW&@E}`$M}HQ3cmg݄`=Po5( J *Kqvlw(r5JVLY)PHQ[tN[4+֐+Ȑ%nKE\OA M3)PPbkG!׭!լϵ^ PC PH"]D#w~։)Px= Jiln( A7Ι7ya7s?7{2opd*Z0T o-k^vv[YoCmХ@ m' ]l"ret`.wRb=24(0N#> iP2?[Azb¸j%Bn B_7RZxV'''Ek t^qw](J:| :zДL5BLGp|^lz~g[!)PH͵X%\ʤ͵bOr+V8n5iy0l9 (;6u,`Mc< 9[û P6Ԓݘ:RH)PXqG na|qkw/4R3M}cN`u4UP[1Hx"R*&W+BYsRWSHSՂIU F>}(YI󡱛s:ͦ8ڞ|h;2B͒{R9ڞ\hs\itF}l)U7j" JhBPՃcՃvElk^ ЂH+##e`! 8AB1V_j-?.:S`@SK vbeR\SX4-j,i&c~Q'P]6t]8d2v4.{t5) +w Ց0aYYpRy&PlT=QDZjJrfy쭒vL&&aA)^XYe(a҅,{І#+~k\}moV`e%0Sz4$+VV'Ih"*}WvnE F}/޾ [5W+ڱo"8 mg)(|u\΋$$M/=q>3پW&pM '*EEn24Ѹc)=e-]=o &qSL&oM5mfmKM % TAm5;Z5KF:8)J8snDw'D˛sZOPZÚO %2T "uyod-eݿ^%XV{or}]`qH ` W; 1 ,n`0 3!w5ꯕhi.%ρN@ e!]sqqi藡pxm2c:ᄓ<ڃ`Ў/L qƍ?19[f(+,309"INW vT.8nRb7yj4fb˗WvTf? =JGwLOIh{,p`juVZ|}Ѿ#fN>;v"w%=MH8W˫Z11D%@ZXEӶ%a!BPSlױT:/wqG;|Rk`"rAݣ)=gP`b@!uiK Ie9G%c"V-z)L)5Q:M)Q=F8}oVGdeݖi(|d{G $=Rn]3):8 mZ | (B(]žSݍjrQLt:ipN@U ER`@{ٹO9Ŧ 'P_mrAQ(IQ~X3Dz}%lBIuDٙ(ײ5=3]@]G:Bx6,0y 檛]*r{lmro9iU][ ] M(Ժʂj_{~WʁB _[W:D[7\88vb]xm-׏Տ%E#Pq6'팴 zuL`Fj"0Ļ*>۾:748Nl@]4oĞ[35 WT?&0&Zr|}8um۱;fㄓ{=s6M˨זLd(PlISy6"1gR`rL$=6JZE}Xh,'A;_4vLSNH4U.m2I}U^^w@T9s&Ih;Mu^]kvxiqki*Ih;#ݔ7a 3tSp4>iVqɉ@2Ly'P'Xuy,הf/erjVQk>f2Z6澃+E(WdgOM(iG`T %E(a$x+e7ԙh)أW_^%hb@ m' *>!C{By^'gWy0*Z0UhI!h?-7~;Z$Ќx~}5e`籽;?V ^@+G AG@݄H7Kd}Yh*Mvb3إ`ǽ rs8 w:}Kp+Rt0] 1 3p jf%::'`ъMW?nH[ NB R(Z`:0Dv *譶djV"^ *Jh$ ]cfEx\ U ދ?>%BPE{~_Fa RxT5!;&)m''xm-4-i -`;w<:YtIhO*DJ#_яp5,%e)zqJh$փd[9;KC1>XDy/TI8ţv{W\A߼:+ -'spedZ_=6-@*Ih;#-GqNyR,(OUBPcאAk$Cg[^} *܊(:|]Ʈ6ΤpBH"LȟJ8x&|sYgkɿ*)Éo:)2gFgxpr-lMKԗci8M8^B!^PZF!meY÷Z[~Xys˥E9204+՞R0Fƴ{9,-,Qkp SWU{鮭{fGdvGR<'Wt>@-M{n/fVbjjuj3J$mWn . |Z b|fN(.7qgVhoraO?[e0'\ Lqw-?V^W)N| HjW 9 5 APc|"hFlݾeXLS)PHc~:nfJBf'/E -hw~(L4$@=H(+>z-us# ʆ iъk{M'zn* <>@)*>){ReenYjq6N("̮T)* +y$_D"@znfF/CLVupZ˒2}&RvFZ%HCʞrвK }n0 p(W=/<jbBXwIP~&D ZTR^/Px<}cOqXO|߆;{Tͦ G] X)+x\e؞!r_]FuyUclΖ,pN@Q<8k㮃i-߄wc0J_&1ni> {Zkz$=z:,Sn5XOTW,~}d2@dX x 8xmrJh{D S [0^mn&nr۾ȯ @ mO7{bzi7 3[+~(gMM Ӷ+1::ㄓX/!@`2@ .Sa{vQUS9U6^Ufpί%)8 ACO6{ c9Fy7Y/2q;ltnt&̈ˊ2Hx`E)2!WD󇠌gi\K.v|W/A[3\7Gus:-pȥm;k-ǥy)VJؓYe'vJzrl1)Ih;-2gǧyp仡ܰ\D7׵B~o/%=;>ㄔuo>Җp izH[KFF}/5Yh@2&QUڎZ<|zn8!%*Ah n fG{Nj>'PO{~{{}ZhWNH941џHCk4FXL}H3taY  "+D'E8P"B{;25k^ӻY2vbp|͚{e iaA{w.d4e6vzJ',w(r -iuq{__A -{7 _Mev~t-׏Jnld8 m'vW7mgus> *rƀU{M|||5 xs#bׄ0ƔA;Zゥ^P1,$=YxT&nzwaN@xN èmQB5ZPW0N|43֭Iht).R'2~E5"߷7lR2쬿rג/6֜jd(,<@^)B"yOY6 lR@M|tRn~ܞRaoRVީveƨ"Omҥ NBJ(r;%U=z󱀈m<װ!Bg% NBLY}Ik_L*A Z'cDR^tTBT!0Qb3gͥ+Z2 ̰B`e߭so9܎AjB`EZ%zT (&hB0D_ۚ0;*V Ծ*KhW8Y݊9tB`lC52t*ikͶ/#дmW"u?PCI NBL~t Ŕȫ}2`Pt)YR%`cYž7iX}:m)q:?ZYi\RSLvb"K5!(-?{} 9G X!0AIuL=Nc 5Rm=-HdfPҫ]ԗ&%QP;pSy8hkPnU5B\i&Gnf!0k64/l8.1lTkν{b2E8`E&qITyըV~{V bB$'3e<.3U=ꞠԃmE~}MzQIʧ!ˋH7{1p:)(@%Idjhֹ&8L"W|x* ªDGjb? L!.il)Rznjۘ/#p I]1'WT6'(*UE=iU2hRZZͤXZ)Znu+V"\к"gLUC~j?Ŏj=lyL,5Ѿ;:*&h; 10ԁٴOS*&JFT5Y:K ^+3k<,5`IV'|*2ē++cJ`7H2/41UlpX.igY, N~!~"z"6b$͆r*m:qj딉܈9ZHEI,;҂ JGuHԟEcdeptUՎg?dɁ[_T `YR\D0y+DJFeäXfWy{}SzSJ~] @ *i(XGҺ7q]levnv#z8oԾ}eX_G~g IhaA=Q A 2!ic`wv攆@:#"VTOEM)O5=S=>+I uj>5`Bsou^K=nVLLvb,_h3t -_VA(K$ЊCz!#$io;%)W,y0"\MvFBFE5U?Ͽn_b !ټ42m'! кG"+|1 2E/m/ KYeO_"עL !0AI}Xa^CgK0|#SwxW><.AۉM;egDt䛮 2NF] 1qebcq}|ΠJJ$.ֽq2yfw6MUp!jJ9-֍oN%rнz`EeO<_ubv@;yQ@#/4b2E8w.`/#4)YRunex{~ıowI>$.bo_d)lB}u8 ĺ~Jy`UjٱͭCXl]!,Vk/aNbijUJ6L/~ןHmE8)bR$ʮM%N˔&h]Bt%^.-gn1ch_?Lefd2ISѕW:eBab$.FnԲA(Tq0Q`-СjKAzyGhuTl?^E1GtB`0ϐ՚-VX_u%tE`(1u_˃e5 L[!0=JPf~舨,ȟTTvQ1N z&Q޽z>-^O q%v\ TLvbKtCXCMH MSb)7˕~W.`Iz!>zLB` т͒HMWb+j-t}uQ<,AۉX&Gr0&QL,㫴ݷZ٭Ը|)5Q\'%t"%L?qI:>^U q NBK4쑝n4qa(n=) }K% k@d}>1:AL @ښR[`3I=IЭ*&h; m2>qi+&]xO6 !>7BHrcirkFA7g{^&TKJlTiHJ,'g5 W |s$} *@R^::ރ?>jj NBL~ !P^D9\ROg,&ILpFzȑ%*'{.=}(voއD=/6";}sf},9‡4w5"/B5lT_idb`k(VOo4lSV*%,Rl}ގvKv"λ?Gm2>3N:%ZjGՁ<#6Kǿˤv"->gi'A Ӥ YtZr`7`עMG~_Dz`³hSE[ jKl`"!Ëi8>R ; ćB`°szNë0ˁk ~wBTSW\o4p5))iMhiMr]WXwrV[ Oy'O{?49CWyj4y}I\ ެj׵ I m'! 0 ') !?-6:-.{Kjmz <㿵ADF[.+HRm'!Fny1azVAZpoR@EXs_MB`҅0IB "Bd^`#X}5|.qmqZ]$h4KBҐPɻcZ$vZv`;A5NAoGBw_Ft <񚹛Kzk ziLi1h0&]EMWb<'Jyp)<);3?Up(D}RTߞ^MW?>uU t"\M'! U=rgU5-Eot tmݞ4~-kb$KQӕN(҂SDSP=!=̈́c{9v3ch?- Bp?b%,p~c1^U<0Q[T%QQڳKLQĢZDkZU^_;@']Q!0AIQD}}\l #P I5T,| AWI~ Dzš%OxYrL=/F젠騅"V()v>x&v>ӬKa}J^}4eR k(׶Tɑ7=7"ʞlX/yK'FJhiRqAсᒮOO ?D^?@p2E0{i?E/5`J^xkT/_M(ľo =.AۉA m/L?㥕ƬGO c`l2X4L3eoVܧ"KPʮ QO[B\7ӭ~K5nm|b%[ݼWay{H,ܚ*{>,K;*UKT $P  VXA(VX1[ݳG! 8P&SSz QBl. 嚣Ywז[5g.5uk})%tR `1;Y>"+j!D%0RZb7fyehHۊ 8SWaA7&hE+DCvAX4^4CK/!$=PPV%cnY4 p3D8/# pIV LQDr󰐅{Z% *SUF5qyx^g\R(Vۋ)̛AY@YLXweL.SK$Zg)i}IľҪ"bgiU8PZA`օd ,]~A`RhaQ`G_@/Voggp7syXfkp3"\RGJX@A+a@#/r=PFH,%31!uC`SG~_${`g)K}l%I%xל NBBG}q( zDlx9r6ۈhrq *&h; b,E%֯H - ?r`o`~+)>neb NBmb*iϘAnbAu!<6vBE[-)-FZ e]0Tjax`cNpz } iE|ٞ̚GE э*&h; 1ԃ㦗z`Ez*o鶿tYn}]Gһ | LvbLOs>y״J%ƆQv,!*)2*=_a}<5v]xOu{Ylvք |Ä{cm;bIWplD MRoN[8W]1-vn2}_|*viVKܳ7y"\4騽)vQ&hjRtRtf˨.q={[)UZɁA;%]pG IhePz$MÄ:An%IRGQ$1Q$YͶp֢ NB20C`g)h7G#0KA,1_S 'WVrݞ$xDU!ZbL؇ZLԇ^~}_vKҥ NBaαq(0{~o, I1+{L+g=ǕcqZrޥ{SKxvbWa5,RXa Z; ktOwҞdШĄͨXN{}#в1ǎ9HǘX!0 NUN"3>fSGm'!vc[{_ Ih++DIL2IL蓘~{YA Q H>( =H6J@ Хp7-~{}@fE$jc'꿆&>2B`j䭧AUb`:>o^&u&hD28elx[j[ʶ '%Z2ާ`a~9i/|iޔMY!0゙dꃗf;{}=@dbm'!b_C$9E@/s'>j Z0B`U5^Dgr GDeiriʚSh\^ &VLJ=-AāA[ %.Q).&>5>v IWE-c7Wm'!V\j,Ӯg_(=kT''X j^t7G<.AIh9$q54.)C@s}61mU#]/χHw@L;z>B6|Tk+}( J0""VIq׊"}nۢu+N& tB8Z!wh veis`vf/&Yr׉BhסF)TBGHmF|@'}[/[jM;FNT%Ӷt7 /b5}fS#/D%쒠>=y|j9MY!#/VDQET23gHk%tACB7moCzͽolp 4Ϣ/b.&-Ě"'OxQ}8\&9*B9.0Ie;*OFk (6wg>.j˨uD^Yk{E}jUMZui<^.%h; /l=i,g9WΥL}+o Ss#/Ɯ&Qvځz[&+/&+r/G&sh#/(fy^jVq .Gxn5! rA>J)F8i_S-Xx$onB`Đ2=r"oӘ3MU!'b:fޭ 1r;7SUL@ yE!|^B}WW4xoanm)FbBif<"(7{IΎW#8Z].f NBBf>'-) RM}olK-Grԯx{]$Ĩb| $U2{KMNсIPZ0Y*7yyVKM>۲gGm'յV|6_j$~}149mu^/G_>x˔ィYT.2<˔3*R]~{5|=?t\?q7TO]5۫Jv#+s~ @xD ItF~t3F6_D3qș(|z`ӏ %ܤ|$KZV"kR( =pE8};\҄ŝ~2,YMs| ˎªץ4%| tC͛_V&hT z ,ǪVoޡ ҉5LSBh,,l&,3P$.:0ġ[ AvEuQG-#vlV,o*&VLN+4;>S$ }6_FYk>J.h Z0B`U րUiD3ҪPC{z.& `ێ: qܴ#/,()Xb@눸?[.[{)Ȼ'!"X{S5(xX 3~hR"4WkΓ4Y'~^))jvb0<)ja1`U(IBKe-<_;+;ؿmg Rtz,.70;Y7d=)QDRPaa,qi(|PuIdMThbRe9pRSS`H)d(kK n FpwlWI=py0&Lc $FHwt%Mrt=YvֻR[Ps*t #/=05ߑƮM>["ާ{B q NENR2Я}P9b?-Kqz ^h'z;rTw]9mD9VtN]A%dfZp=x(i"S٪{W2u@L܎\0ҡ 㽕&>Lm'1x> ?e<m~j'‚9z﨓lSlnyVLvbt׃w2#kILbq tI]Z׬w"~}P[cd/D/SI݊aV&Y8~B{@+[w36v螾7+ZN߅=nZgIX Gdz&h$n)cդp)a 葛>=.i3 cnB 8-H"< >m'!ܾ$NM(a]y )eFnfBE$JN U X!g}J%KBTS~ixLL8,pح^ֻ3&PL.1Z9#/x`RMVfn\27|IH5VkciXZб?TgKvZ{ZR%O oDm\b8sI ϭf)^򬸵$Bm'Ң,P;ILQy,lA4`2Ekӓʾm.~_q ڸV .6GvagBE8鋓zI>>pK5 U)4 L%?oMH(qVvg4gF~++I.!1$}P֮*8 LQUNo;n^CԾ<īMl|Igf 7yzAx5GTҥAg=-B?*]] V6ybQv6!?THU>g\Ҋ¬&7ۨą]+ 6tbEء$T=^~bs/?[ٯm?M#K`j-F_ %uڇqd_qb[Mމ2{@%h#'>5q_seB]p%ّ#&QNj#?+W)R`)y>G:TM'(nNQKIHE(yЭ}$_MZHǒc>P0z*b{NB*Z a įRyn5 Evߌ$&ӑ\-<لpIW'5(N5"/QdG)GC@N-r*yl"-po: )Xw4㡬"\M'!uYE͎h[Kq(ƨ^Q-X /` 3ǃ}aAD;<ށ3S#P0Jy6+GYp7e, >Zۺ+j1"*^E{\熅(sWξr zzJӥz\$;AlkP [GDZ|3Nbn$.ws끃!DejviG3`!vy:]OkρUw`E`tu.iiVx{Zdf=,8BUA^A}xJ]0^@~HpLe{wWQkfpoWtf!PS՝8d$ Ogh3o?P6ڮ_ .y[;|XR)€FlFԆf#/l(:}1R1pFf;0f  9p23?[ -zR Zq3/}xܟ[D;^W?sV?ǿw۲ʣq}f)m_rJD/_kLņrmn__O_GϸS5OikirZ[VU jw}49:gύEl +d=yqXA!A ? FV O͢ rDib|&h; 1fOqhҵ0#񩞘uG0qK)ww5yOM#/1U +}VI^:͋ѓvq 䃞 # ӣ  ?`AMԿpC=0ңxOM5z_-{&p 9c84,fv_I_ֽ: xMG@@==&YxoMw..oj%rMdRW*Yx巀Qv?([40*jކCb–&h; 1i‹.CIwnҕT zy(7#,Riw2 TZVRDP7kM{e_j?-!.JBXò*Vv$VQ5pLTen3UH%yS| S~$*ۨp,ϺٞSÓ=rԷ=$]DZLؕ{+δ3XdmT@ &h; 1յ*u_%h)(< r%@=,Z' A m\ ݶZ-7<.Aۉ ahTb4 OPwW3=ENB f2IgeLȟ1f_\sB`S=1XޅU?l@H|fzGys]E@ \QA h/D?Z>ȾiNǩ^I5>Sсi*%MTQܾ<0Qљw }QW/´Nb9[~kj NBwaþ1] Vt+ctdIӕ5mS+0A тIRE!bLF_8}#rܗ+s3̈́@훹1=0Q:q3~RRTL;}M V&F 9k#M,F5ʶz_l_ D=q@LK;{_'Ѵ?,q$P #!G^_DBzB$f EBz`-ٮj> NBL+#:r;7IkM4dh2JvJjվfaֳB%Ef$` >OJa9?Rxkެ؈(si r?lR|Հɐb\vmPc{'4R'$:B.~1lgm> WaIS0 ԹƁ4~ .S_$gkz5M )38ŝ˦*jjad%/ Dcu|,3fRb2LO&$ ^֏gb؀H(bNuaGA6$ to1KLSuKkOߔy\iYMi |$}q)h$#SF"5ik~m?|WF13a<$9#a5]/\Q.miu8Ǣ\~Tn pa0",<>@mJ y ,#QbsNB frh:_9}?’o'4^"o=}ĂEw"@%EbS5OW=gk~v5z!p;!3.ɒ%L EвPvWʔyݧ@(A+(YOL 389j:h7*%]h"h!(v8J/.254=";wlF: F&^kj| B۴(Oרysc*Z$5#E{ >CS4i)\E?/U#{PG'}%Xpd+Zr m'rbZ-1̣6Kϟ?ׄq<Ѣ!TVtEسַH{7Nx՛L!N`?Ji&#;=(f d}U:mgs! {t>k'Z#\$zܬig df!.ɂ)uERPRÇoXL YGZb=ukPK8U{+oޛ^Ƭ#;<q NE+L@x%3K80^1ϹDc-vH@2y"\bjdLQaeZvusZ`kT;gXI V4<Z{c$_T:$)%AGG칷@K WO1y~a ))8LjfKxb(di1ZKϠpJm=S-0ǣv ܾ[@/J G5UZhkZLhg<{9|VFZ%J4`.2}$|o"$Hc[_rYY.%}E/aJBl'FO]fӔga N ;"{qL"zo#& 9E[.]raG'Z¦J NB"c=ajKiٯ,=<(gv%޶*#/=0{Rɪ\LA:>PyF=)M#/<0S]=Kn8!ACd0H}#IܹE^g:F0Ť <iaI"$m/JΓt/A ~p bsH {QLH /E!z/q97 9|+*{qO;? Ih*t%NzirxGgǽ4(hle`3"\ERĢ(Pd8T̗v 7#.PvQ42SI/sJIĩ?tezZPrQAH$./F`粓T/_Q>8~Fp"2;3ݬg_eX^2$ɐz{# ׏ܾ8@/imǝTe&VL v8(< b/OW^7ۺL"/ݗW/&Szu%foĨNq]- S󪚝7Ǿ.Ki_KJ4ɥg'_>cKD}0X!XRynrX]YY,mjh$̙xxX000,bCP^"n.Aۉ.وkq#&F<0Н#Z &%I\U 6Í .Aⱬ:NsMb.M 8?*L&"Tr9)[oW&P, [4ؐͿ_ż1B`gFv_x`egC/}m_3Yt}yvnpdX10AۥyZ$,LB C!$}a}je3 ڮPM}ka0?L[!!Ryn/H[<0AI]T q=3d0ɞh%ô\<Д&Xc9h0&;;ց>njn+"F7H6OL89jbʣ4u6KvZgKB.ܦYrqkç 8tK͡bAXҟqIHa&'EuqK/BN_\ٞXY@`02y"F"\hm2;ԷN ,'%Mjl=z߶JMsheUN-:So#tၖK?QEO{ix;=)_vÏ݊7naKg `ҦBE>nd&GyXľx;Ʋca!I 72{(8W.s.WLFC3YCPH[y)oT-~S&)DAPS=<pf`wv=h3&]v~Z AdnOr6[7 ;,:OJ-vN8;_Qx9ZW 5Ń&عs}3e\ڦR xV Dm' ng+g1o+*V :^Q٩)Jɴpw@ &VNQ8~$ n<>vPSN1B`61IX@&qLk;ƠC7R?͍&2?SrP!zJ@­'E K (ےI4M> jB"Gv_x}4sRnj{5rpRshB@Vi(#3.&]v5:f_IX6\ "}w7;;*CщLQ-P>Fn_D|xqw_) Ra (=]+q N<ؼ`Xij2%ɏĿ}av=.j/n'Z=*A۟a׭8P?ֲOhnJq=#iQ$INaLX0"^/=yXĖt AMIMVST<G0|ȝ @{Z3LD[S Ea0[y$~_vn&Qt-9<_c<0AyOV3ߓ}O*U$Aa}pI\3 `{{X5uLЦzqv.l㖤xc <-OnSD! b2 #Z%O[qn/r;`3@dbq7}w}~;&W=zݶV3\ $c(QUZU8s3y[ zbm'!Ʀ]c.7.[;#mnud$\v1Y`W#ڕؕRs4NBw<*,FӨsW3팠-iKbڂ3d3b`R@B'o`>3~g}.<œQ-hN|Xy~cg$X|_B%vFqcz'Bha(@BHahDbjfD,9,6"HKRhZQc1G0LBC!XJy w"8l㰑0y{ooGJG%h; %8쑞2cVl͘<.Aە1?$ᨶI`MAا_ҥ qܮ-լL*`'M̦znVL[ɨhd IW'riQ'6W˩)z`rx&6(#% {-R@F^z i_][{oA>+8؀-Jx,7 M-DxmʶFgK`G7#xT$4Ht]Kfy '}Ed{{E>T)Lʳ ;)AU$!ڼԢAF_hg\M|R ~$K>Ķz&h:go?Ѻ߫m\ZEܮSVuv2Hm&QTrv;kyN&S9´Mx\$gSu8yn'mg!͖謊ӥ SVG~_D VRw5B wEѫ[|/z`e>bo3'fۻ|s"\M܍C5M4oWSfP5]5Ÿ$ T#W 5BWD<"(-e2DX^ˍ̚i7 a-o ߩ+=r°=PfaFbMWRW(6.akK/3lt2B#޵|{;@~L줌pR<0cvZ6cc bX wVK^rΤ I] B"!|y, bEM)1LOBLA Nfo̕&SN1#/=07 :wwƀd6B H&J[L8iq髙]͔`Bk{ۧLUbr*پO;?+&QxIy`*!M#9և!0QqӴ-md¸l%4<g/O+ܟӵ!Q7+њeaڔhYZ, qP[ah1vk]HcHZh/IaubiK`(w4)Q-y =.SѺy*oOeٙ@lzwe}M~ Iia(B; vajo:Rm'!Vlҭovnf!0-WƉRj0-M0v=|Q Q HfЈBh4D}Zrm0fi(B2~F*\C#J0B ^!,?=Ȉ~>¤ Z@q1r"(p{>K7x\ҌݍxZ&S^dDLveDdO1Hۇy 56בA!0ɢ% $;{2b2E8Ȉc:%C_l'>^@n6C\%REU@Ծ.^e\vM|c~z\Lv;CP } j*U*,Vvmcp{STM2~_';(?;?3tD2(fLGjl7, B:-,Zus\)I(H7,&IZ$-w{2o_]d q<ٲo07B iBH#Ծoyį =Ƴ@&h; .$+.\&mn&=59^d!pU~vf]Vm&C?P΅l.Hӌ%IHBcB|w(51X/NKAB |B)PP.Gn_\{`Eg'SYl2p%bm'!]ŮQLEٱ+L~pQZ jBA#s4ͳ&wh>i }szPDia(B|]z "yj~Х NBfҔr ,:xQĀ!XDm֧:8LD GB!B'_flc(]Hc(/ a'UBhUaRx*#0AI]v8ӖP aod>_ʰ7o}|KS$D]Ѥ ID&4>yzOB&uƺ}jWb3 Ѕ q4bӢMs;0YMcvf=.jt~ڣkH̐1fՠE@뭝I^I|i+ /1m*z9}m&s9h7ԞxamWg$]u>eAˆ@/[jQmKB󽵺n7֔<K^C-*!CMkntPA`BkhFHBZa0[<̛ڽ,<:z蛃 5 s"u;z@bFUtrCU%lcm?т&<;I3GBǘLm#IK[$-xEۚCQgrk_ȹ$mkȿ _Y٭MdM.zR#"H>2AZԵ)]*U{;'p 63M qBr hA@Z&kO>%+z" ]; ڮi/!!5XW{;zv ?)b`Y7SED `<X}t:gTRed|Ɖ3U )YdV* NڃsyhS8r2rLaL',YƷj3] 羃}&Vf`1FC-Oh)]!Q_<2k5´<0׶[ ({ NBe{>_7tzmB@bhZf1Nv>v|Ŏ'77WB ;K,Ƙ'tFojbfW!P;\WNKŒ@xivyg]iyg֮0J+- 튅A$)i$ ICDBq66>dgV];'lB p)) cDei`LYʝШ/<0*ehO1Ǥ WD/^qqYLOF}qIV{KZ70hWˆ^tiyVscʺѐDS⽞7>C@~cGGH k$*wd>V ܡP-ŷ_Bõ¤ W[xxd ܁OK -}gpOK<06b.k^D&TK6=!ih;9tUލ>>_qX*}H뢣zGvag Ih](vBh;o0q^Zn}( ZW$J }~QG!h}ܝrFT;Ey!?MTU-iD^mEy@TՃ}Az`Zt#K\3ӮsYi υM vȬ0]Kd@g»9hROhl!";ᒍMOZڰdI%h_l#WVxFl4rJ5h0gYsP9y- ڃP5]8dB6'nR@1q!{`Erb6Z72?,W m'b[دXUYUb\i%J k"hEA%|pd&z;_ : !Ȑ- ݤ^WU$oUՄ)A26%=yX6)?Ħ{r.B x6B )AZEGv_DY+\/ "3RH+&mo*&S6ڝbS#/l(Eݦq8Uo- Sa#/=0ɢf#+AU {~Wz\_y/Ep䛸Ag}ǛDNe9/VKDMZ˶i)\"7Ir8ePZAw8Mv8ņ9c|^Bz/w7ǸNB-GV> 38 LR]&SIIPf6w&9e^ǁaBxVvq}?y:OtHw_^7iK`w"]t=aG˭oFnr3B\R%GRj"h! 8##/8{/qt{As3pp,1j<.rR㝖Dwc@.'vǩ݅|.|Kp%T!0Zl$ʠDM?8/z+HdB0Ёj 6o剭⋛hLvac^"7ZݝIC \M1&OylCKmLί ͂.Y!N&B\nd3^޼0A즖=\w=zd]2# I/j[`6)U˿jCFXd7n7L$(T2ZI%lny%;2x\M\zj7v{pOjM6-; *Lxί U؇8&lD}/|/ Y =X:G]?KW r8qhq\@M'//> ڸEX۟C ^Φd,<,ǽn2/t`_b] ˽߫aK2mIᜢM)(b/p+F4bÐܓ[Գ"x\6.Mygps֏3'*z ~Dpb3rӽ&_̺o,Pd[z%QɉkH[VxR@mpԿLìqޯaA &#md<.r&,+j]mjNjJ0ԻF'w"Zۭ[BLƅN%wX}WX!P3>G_LndQc ȨB(]1g?M @ p8xO,v{޺p7ݰWv _U4ꚪNߧoo_2ݧ_?/wu/zr71?3/[i2n/5XVjJ02*py|,ߕ/u}篮_md2~o?wY"ǿ|/$;?~KUbFE5sw׽xLGw?sV)>#uc{d6< r s3x{,5¡L{{f]?Jdbod5:KgpʫeJ<*#&=Ò}"ߖJ_1[Q"_[CEAڷ_=,Oyآd6y\+߷5<O59RB:'/ߛʷ5W {YZqa[o0³~\Rt0ym'jmoR[nU>IّRyO}zO]ͷ)&/G\Z?I]b!>jmoRRQmv?x}zd|:&ܞ=6u؜;tV?)Z/ ٵѩ?nK3_uA@Z{]?ݧU\[V\<^fyuKa{yf)M/' V#X v˭^*Ohd9m.yaϯճغR,#{YD嶔" Y9ypT}|>Vh*|-=R]爵鷨"[t1=s)KнLq  ,syCt+ Sa!GczxCu^Z}G Ӣ]5۞}.M{[W-嵹|ܚ `n|Z9f*+a:rmv~[ C}o1㗽 'ex0u~:}gݳNyl}8D_Ot_W<(I͋^͟NXo VWϿZ.CRJsWUb{#5u#PH$DtK̦(mWBĿZ$ڮlw!4cId٥C-_x_<~A٤ uѲ>z/Y'TK) NB\p.`e.\b͞ 9snGI0׍(}iH*!I'Z3Ŷj0Aە87 n&|{)K`NBL2)f:.A7c { Ӻh*oS T`206֨2ǎaItf{qך U%q窣l{gnY(mWlUP릺ΞfηUrh(L'JԨ4Gv_~Lۭ2{=qL" L@3}r0siO&nQdFr@!HLjHFqISjCߌtLv5TUqm'!unǎ9HǘX!PuV\oY]͊Ѕ! t%Ӭy~Xc:SgIKv5Kb8*Pef&,y4]L^ &U7*TGfqI;gؽ81㾴/Mo} 10AIi3(:<ϫwM+3#/qL|9q-\U..ɲRe m2T~ H1,A 6rby`EՉƌ8mU$W5y.nF*U{bWKɿzX O M5!0q~!jwfn;͢ ڮu(>L17i*i ڮ\ 2B'L[.WtO2fETm׌e^yX6uPjuv_3BTFjumW+uP[YWe%l>x`^ &U:BG^tqI[3n<>o.=j1ckA h!Psk5,ö[췼x`5[UB{1] 4<5TaiS9\M|Uc°_LS1;G<_%8\ [˄ |6=0³*2 IVd+SvlY;$ĸ?3R7$kЭoWQ]LvCl)1A!m+T|B#/"Jq }8_ļXKv1:{2,{@&Sg!N) G,zv0}}CgL&-}y-Z諭ЮTK9U]QZDS5CKML.r{JE LuG]Ծۭ j&TL,8if-Otb$ ٌB^f*^$Xk|Gd#X:vWZ\OKꬰm[LQ!ny3).kQo qtjG&Qt}]kފgJs;|@TSbk+hױ:+3d.V;ϱ A {yJ冟`6"*+#˭Ff#qI[ZQS E)jy%ڱ; 2 /(*qVma qtAM80JmЊDKv1h,ڨ˒~lxyblؗfk;6lB݊M>d%>a(d(!PP]s(#K|AIǽ߷{zބ q<TO=9j"xڿL#b}?ź 0mT%n 66Gs5~| Po^kHf e &#hw}}OjP%=$F?T(ϣ7z@>XJ Goٟ(qy`élaK 5lIG=Bo[ٽ=| a4B |ζS.3PכrɓV&ZSU3l{='᱿ΘȮ1Mg^2|hR{^26^[#/⏭z6wh5B Ǽ2"Mɮ?Z!Dgՙ.2љƟ ORJ|b]whl BWܴ .@t4[3T q{m}{785h&@m?GnrRTZ{լh KD9p=D۵hծJÊx̂+FgNj9zeܳocsIUN4t~Z_@^bPJ M|ˡ f Cs#2q8F|S>mZ8CAօ򭯲@.xe"q" z" ծxO~ ͪ3إ;8w@'»~A\?\n7B+A[y=D;%Ӈ[a]C(ʅc/Vw+l\WTi=.X!@s ŸLf 4A{ebBeW3 ;ii46b>G16`=Z <ʴdڍdlS]4[֋xg=!ۘBaWPhM,NYz6Z 6mlNr5:yUQTG른5-mCE{::yѕc7/߲IpCk_e{ں9if wfS<&ڎV8g$V-060Q6V/KD?A||a_1^^ǙhV'̍z88GxUI}e`{  q1!ÚJ@I~nD?h r kU H(zیxl/z_?|Q!Nzj]#‡=n(ׄ)nz)kW)/KDYr|8m>σ*3Ɂ`~\2Ve|׌p* 鑠Ǚfbx}soR@vR`M[hڻ.̑EyyɎoh[X.9[1@HSL4󟽊3LJ¸F*=_/mx^t.2CSZNԓW&Vn&MVīy35"0Ras\d8կzY_y}{@OlChT{gjm>u`oX EkKhJHM}3G ih ! I8 )4E osB/4]^nkԏwp 彴ϼOԽ2ȸWFVIuРF^`avh.!/fFqZn _C ;&y*|_1@|f%\"qrїhL'.VqF8Y".+ZE ~B˲?OЭ E(&)5.G,ӣeJ7)56x0^?qa`5o5јtјtTgď(NJ2z=$ M0+A)ҁeqi^c@إslZ`f^=ಽ6#"4I᠀ݖa- :45Z<\gsnQ4tc?s3J)uvq(ߒs,}r}Z@Uku`A-2dlf ˰d[YBS5v'2=[~"(2hMR[i]nޣ d?9x?bz5x<{|:N]=|?4ukoOGHg.^G9yAjiͫhaxم~+8: ?ZtoE3@cj{Kq4B IJ!M5je @-@ơ#С(lOP[ax54uk|g02[!ioY# ؔ(jQϲ~@vv⟯bU}p": YHbGi4$ ?9v#&z{ʚ7cG8=5״>z[=[m[=|FX']x#jxҴZ3ư1eȮbnm4@3>㼿¨%"vOHo aC^&i_lڙKdVb/AR2[k@M'k@ bvejc^/ٺ'+&μ*<ن.nLۃY7=cX!E6B *BnB=Dq̨RK2̡JѰ~ PLT-86v#&ZΦTXw-BBFz?Y\bcҌ <ӎG.86w#%&U㩉-]˥EB @f]AŨF4&F챵p5VXjV |%W{{wܤ1[/bTϛOeRCy3]N8,j4۞ǶD dmiZVuwtϫE ?='cg?(h rq006wFmW>SspXK!pbDyBT;c?Z6A#<[ f~S֫ǛQ!P DލDh⸗=d9aq@ٕ?Uu+}hGY"ʎ\W*Q>2JKD؎(wUP qt*T,'ŋ7yg S}쟕mq;0Ɯ[L q2F\|tG7e4RNh3);+|߹~0^TÙ]%;po7 $y&g* r|A.|f|0Z&C^]]$z4o Rw ,eSg Ua D694~J-=HJ=@:'O㛅/M~J+xZּ,]j=;eflkv3/ȯ}˚?  RJ8l=$Y$VZ\*Ok׋Ye3/;6rtF}HI fSԲjnlFM4maWT`IJsmyy 6*SsgSk?x[{"OxaNHx m.~yP`2B x?Ǡc OZxeAp`4RF; jE8ӇԩyaND}! Ŝ9 )q#tby(8; d&E"=R_nK yyB6&؎eL2RIbr\']-H( =h:Æڇ@-xъKR¡Iѣ&^)3L׵~B@SiqrZn*O.G*E洒/Sq.~!)O@-g miqk;SdRT$G/4D0|%و|7=#đ1fd $5])AB\m_)&wZa D]]CG^ؠc,Y*BE;l맸9mkfQVd/߱Òb(gm=2d}gvM6̺wiR:X-ь'}qp 9ȰgBb4yݨ81 8-E^>:Zʌ@vtOLIn!/w#FڏWKL@v5),C3!I\9z@^8s=OnqnsqU!n&Q#h]S>Rt.$Fh3j|N,P9;;WX'HXN咾]2}D&Ϟ#Ubho2$8@u*_,Fs~[K $pB6oE #Yic`nr nuW @Y"jލjh<VzT+MUHS?3L|_Zr"BaiJiS+~#Cm+谾͘F:!:։ E6C l ,ͭ?F+Q> 'Tӎc7ƤL^ƱoAi iOAi$bWE%h{c@aO!P},kNβDӥ,ժ)V j]-{СeWh U) B+͞f=Yҝ_4! @UׯF1 CD i-U#GS3*xh J P Ӽ*`B]ldi»ZgYJ⯞%z| d:$W3jqXh*5`9ܴLq@Uf-vnoOhM{\:d9rlk8zǷz7 dW8tr?c PAo;@aPrL<9ɉܼz=j d,9+SgɳY %<癹P[Oc*TFrL2Q:_Zz2;x-5Cu9xx6$13.EWcsKzHM݃& =g`m&@mg.{K)Df% 4/ھMKyzԥHs 2)ԏD18@y lekZ]$ɇ\@Ӈt5T|%' tjHyWW@Y"hF#Dkv؜V0X}΅@^ʴSTjőN?H )<@vR`rn_~-uCt^R1ǙhV'z8[4tg}}pͨK>XӪu~jNuo޲'c5!N ;yhT~/djj)O9J-c9\Z9[s ZX,n=D:{om E!FӃ43W|V=­fC$6A=m~o<*| D Bl~o_,նGa]["iEyY"xn-J_*eArÙf'%݉ma5aߡnV^ȸ|C WyBG'y ϼ=-kyLi W&j^-nFe!,[=r]/iOɮ*S?ʮ\U2\S[^0ׂ Nϖ8i3;iq͇0Iyeb}rHK3%UyA = (o%f,OIEE~Es7h "̞t|NeލܦhUn,9y⬗yx}[+#yH#[nWFh$^12\ `i{6\N>GYha E#r^e(|XC>h;X4\fVr_nU μ(UC|u>V8rRɡ|oĬXr@R釸|Թ7=DA62/Q;89X)KHs8JW=%W>Q^9j_R3 i0ZŮӊ Ccz L2l1GwRZR)U4qeO}W )ablFM "~1ev[J-|}=W!@2q_4W_hP|rŞl>Bg-^j}};h\ʴ5vny!|Ê+rg\{ $dE+4%"I< RO?QE-ZEWc7W}#vޫm}m/GsI,QOUnTd!]tAJQ&Lx~]>g NeNLSW:fˣXކFJ1@ٕc К4;{1KID< 9}ȏsbFnj3t_($JK485RQ@- 2^K&Z=̋jTr=_y-'JD߱ C-Nf^|G3bgрWQ hCc-x{(*~Kon$q^2مq+1"?_'yi]t`L{Jf0 ;Π!}?Żν5^K˅)kRWVJٱ"qDtiOvpA=4d~݌9Owq:nT1z҇%rSS&gǴJ%ԤkgZo lK~xpҎ;nڗNBK_= ?U36con8?Oݨ:iv>nz)ΊH vR\4- pi5016v0&Z.&K= ^8Y".[U?Ams;]{q^~C։/@ g`5#S:M4\<5Oȃ*V<@2DE'Z9ᏁUgNW|,db)nQx,e+@e{~uMؠ%&e^#{uW2%P'Zs:*iMhR~Z!e(: /J؋q#ULЁ1*yY"46jE#mՒ_ <-~8߂f>hc tC#r!*H=˫БZuG\;(<^]Z:/tdIwg(r$K@pTW=N(Mz2oߟ#q0&\ȔLq){ܱ2mJWޕ;UPFys~&dNU&=Ȓć7}ݒ2sk֡L lpC7ÜDy۾#vzMx[4A;M 8ϳ@΀nUc Py1كi`m/Y[k#Kwʇs`DAiWی׵_ =7B '4T? $GPP y~&*W^^u0D4faHs Vf(goT=DS4<̞գT V<@2)=+? 䱽5{zMk^N̋*8(Z P$% U>lWՃ,QIg KDT~Y/|^sǎ _;?:YyQ'h5)4R}w6(N7B =F*JXɡٮT?|0ӥj1 d u>Qk62ϻ|, bQ=U߇rz]~bN2^ާ,zD_}ռG^;z&Zfm^W*e]ZL 8Z3\&C-<~Hs}@SmG]Сfx*K9%"xuQzeH\pTB^mBcV/EOU@.jB,wCzX?,el`j%h; O*`@2)EW<Yv~8ece:})jlN/ayVIykj%,Q&DbQO}ةZ$8QR{l$^E!P ĸ̵e4xCMsEhB*W]Ow4%"4 q1 (cg I=k9i^ˮ*T=}|U2çTp]sz&rwsЦ~9X8Y"붷S✯V[bT1멮9 @mw6SGfUIuLbV,7.X.1rkž'Nc@2)h-+_Z_? M~wq:l$Fx;"Œ7@ל/x(aa3aa^I{}1^W@Z'Ru]h;]v|q~:7iUMQv` i1][[AqHd녏Rxyj3kuj}M=/2q#b{^F lms~!L6\Lzm(;sT-R=T#y,{ e(QaIiEWFmz 8Y"0j]%d4nLR8Z4ݨ0)0|tlL.zIf*W\>d& @Y"H2*ĠwIacMX;- qZ+2%bq聶nYX.qqU҅$!IR3އũtAx~RsyQ"ІNar0?8sUF8*| UWsi!,e͡wT؞ѸFu?xnIC{IFaV幰4E dk U"]&kޣ]!3&t}cSq&&wy,HtK\3*q$,R1v#@MzuM+ȮhwSc- | p?[z d(I0=@E~RLh KDŀ:Bs^2NXe~,˃-כ u5'SNg&osf,f'1@J;0v @MfPXema=NZ@Ϻ{&≥fN"E ,ȵi|u[?u'4%L4W=ڸ&{H dW&RsQT4]m5OMBcʌg{|<ܸy -wK@0W.!x?_$D]VC/Vؠ沰% *MQY;J,Qy,eb5ASyr 2y Cfd<@igQ؞T΢cTC %_'14jYms&=@2jRg+^KtN3%K{ 3z%fyRTlD]f!Y}FyYB]G\ \F"=SFz_+ꮬ2?7X qeL[ɜgdcMbclL H GX5ڿ`˻vS <坽jR GsYQ@mJ@+De(<@Pھ(g<>2w8hN,uO֑=K;\}~$OʏUy3*_Bkr*Do-ИЂtlɐ»Y`!PnpW?< //G~d-gO)})܎H4MW/;L%b?]Ra KD$ pMI6ߖdGg *~濕bphOkx>QQhR8LU,?{Jφ)F7g/ȯTqSOZ4%L e}ɣč`̋x(<}=X6~qa׹ϵ -q5B"ߑp4WE%r+&evͪ Tza9>pYO*blM4>h8Yx,etR \c!2^Kk0iJ-,ҸzVvFu 4%L{ =7zͽ3U v?cw#7|Rӌ'kZ{o'=!Fs| d uq:ƨMTU<+n޷wO 4% p-t'$lPc~=g<%=<@?Sψh[ zRkw3v g9$4cg/s幾p>W[ׄ@Y":ލ:hR.8*]'h KD}ʂN_˩+f_Y!3pA cs7 hZ0GMȳo뫑R6a$Ma[` /b?i>zV¢R2[Q3@Mږ~^=T>9_Pzj HD7(j{o =DS2)゠%T–֫i1X @Y";H٦РVԪt^w U<@2Oa.3Yu]1s>.7 \hvQju_庬}C,]]5A+ R:!4οMp8\»9$_9GP1iUB7mE˂hB)DrÙ%\BRz?Eiymص1^#8yQBM3y.GfTTkbT@F.+j"?:m.QHRMh6y8:LOp[O9+[D(=F==$n[hW5?{}>֢8.MԔA[)&3l?ӂޥjy;5{9w#{&?G;4d ?M9MZ 8D}Pxw ʇ: N=`%9Ig~&Q[r T8sVMx,eZRm3-%U=@vTUy[x@U,ُ^eC+ښM zhhjCLᅊڅ`'!8)Bzwh424˕be^.J ɿֺ[.8UTiF@BnhƭB#ލ£jgW4E5\}*kէ]S: +J'iG$_̼(MG5fi<_5xq:4nick7ihdGk<}3 :Z٨\ybֳRIʅW:_~̋ѤQit&d4ͥl-̽>h^J"/_2a-z 50ȍ9:(hIcٙ5+4R3h `b}[:*%?$nV4lY0ػcx>ԍ K,!e~&GY$Vμ(UۇQ;;pßx?F|#Ъ蹹B|󣏜PE8YB]C~  \={ ,=Q=@.]-3DiOپ>vĄyjL +<@.>_!Ϳ.BP =.bG=G]'C@NCg3 \Q7{醆 NpgAri]N@U_x DQvʨ\xB[%j姌uFǙh(-l#x =%o[%q~0$"kMfD5i_I" d(e߶G1)/(Z Wʗ'D]!YBj/=M1I|wٓ; d(S;c[juǣLujN"~ r{)rF0ލhRzR<_,x,e̼W°Am')pӾ7Mi|pDtqɴs{<U|*ʘ QcSz!L4[)DM[;\+Dy,]<|>j8:j1Y줡8Y"$JjV$&mnڗ'̝wOWp*R"!BN?[8Cf^}^{O۳MŽ=Z{@.nPxduМv9a*֥Y 9)a/KD]%=eԖ6~bv??O9=H8,'o<4e<8-g 5GG(}{Z=59WփŞMˁ9c%~0r~pMdM/m@NM0ChlM4^"wNu>K,Eh Z]qR3O}Rjd@=2ᱮ3M)QޟP&RkRkH^r[i6E^/o,;ؚξ8,7*Ywv_7h KDT>\޿ԫ4e(Ӳ)i*݋g^tB׭Ũ!:ֲ}qkru:Kuؠ%nί^3&Q`>T4]fd_Gt;'o'MYyW2~Ek:HND Ք_ؚ7 r@ 2.l[Z#,nw*6(* $tH#e uI22 p IJYh23/JMg^xDTwݠ~E+X@2| 0(Y1Vm̐7dԠ];*nS`X̉Q l4דqdr@qz?Һ7FA"jG0$>ffX G')/}C)?0DQ]8'I1]'7f_m ?dœv:izt^Yx,G}S!@5P٫#TY2/Yyh KD%s!Wb:S \f̊ 4Kk;h}4%RpӅ j;:\ti;(0Ǘ N̻iVJGLGDq Q83lN[$2Zooq<μ(UC~K ҙ,S{st̜$E|84ȓqE@M^%#c*r'ڻ(E* d烲ڗ؃@Y"ʚAeҳ}E,c< @ =/@a۵׻hB)߯\w@2)%`-W@B^U]-A9y*pu_QTr3%EkN^RVHS/D#/KK82 78Y"C6Wf{u# ٻ) R9\tK}PKfJ d(Ӟ ]sV.0^gzT d颤F=OOgRw8YB] zl M_kF 9'b !#AWO/@-VZ;0@x Z(HN^JuKgnI懗%EV\qr !Xl[BV:w&Ԧmm\[:&N}DZa& -wT\At1r@-;\M}oArLy>ig^*=pevLQS RU]5ĽNGg^*ڒ ~}b|W8Z)#t' M3h'eqi&yW d~%kD#{c|-5 {f cD{@gz6 g~I~bmٛuahU?BDjP3#5ؚΟ8,gY7݆ӆ.Q&Qn* '[5y@Y"Y%oѥ&DiOA~; ^Juʝ],,±1|hd0!n=Dk5wyyHg[3%E߲U};\? 1s.V]ٖ݅3%K$@$!ZQC͊l L̩9:n Ө3%ŋ'! cSqsRznK~Rq6WMq8 }tPf'c΍.c>_Cc{)F#l#BC%,T,eǍD]jFznyd8  =YqHNsglL>e٘Rcq7GzF6x!|KN8MT]z7Kɟ Poc #qBwɄph:|zMܓ,蜶.S*Jn؜y  Y*md-_oyѥ+dWĈo_ђ%!qCz׍JH1潤 4]9gA]?@M( ƲnNDiOző|&۷8v>.Hcu]3N oz۶W9Kr,wh KD'o0u=DS5"DY,?yY"ʴp ,>A ]|5.ikH@~ $/;6f=D%z>Bϓ =@2RR־Nx,e|b!|{q盕kRi/+9c,eW6B;F\PH3Y98csL &N 1ޭޠFgeE`3Kx5")s,S0eɽc٬ ݋M8w&AU|[;.a3*rv!.K1ŗP;/#7_獈WZR^FYj^UWM݈~\/{Y"*Zy8juD!1 i}$%q"i(Wlk''w!Z*jq"go =DSHWg KD//-Hl C>l9lU dy#ԖJ>u d(Ӟj[%Bva%\SSp3q8~XihL3bV6T̝נ<@PI0 EIy^|~P#na׸=a꾰e|R zQG-b m4'E\ ݢ 4%L{ 7z'`G^ž㦾mQ绥!~ 8~FRycs7xhَ) 𛝈g :C;DѰ,DՂr4~Ͽs@i#2)tt5+YM~.A8z}m?I0 \2vq#]z3o W#Od~&:s-Js++Ҩ/K_`b Q{e*3fl3M4^b_#3,e|ng`~40{&N#0#G➏s3ptG<t?HpjU?B;fTǙ *[*@MVXEXrsyk*@Y".sA-'n5)_=yŽC> 'cD) ۻA<@'mx(z =*Uꩼ;ਪ~f@QIZc{7XZh񴷖ƾks-L ac,e4j@M9K_J9 2ou+x1{*Nꆇ(=KI0^s$Qw߫x څOhc=l9;V|}^ĚY!@vց.wcsn|~/FlDiOaXFPĘG} -r=@2=0z?lO b@CIFf^PJ1zՏfz>Fg^*! :/VkXoPs">,EXX3jA'@M٨( \--x_/8<G/.Py='>V !좯Fy,=# &2'2" {꒨WթWui;8X, W: ;yƓ -lN ;K>ʇjdhȸ3o9<g^*0 J[Gi.agZ7v(:̐`qW}?/'N3x,]F--aK =n dgՎcS7h4(B^aUC  d(Ӟ]BsߪhlGzcH%ixK=K{J32,.})7:eDFxEQƷ;R Ԉ/,w!7xah KD{7aڧ{؞DTx(D+Kق1Jn"i%)`yeg' k7̼(&G( ȅIa9=]y7"v~""jP~{pIǸpj?V|4ϗm$˿+ j9/[2UF/Er֠#L.UC3/zA^o)pFw;v:]>V,eS/N40Jp L_ȏ50;F,uS/^r{{]O:=kqk`62G7xhϩK[/xlK}x91@Pg o0"=P-v8v w~m1UOd޿KF:ʌ(&5ySW b<@vĜg#dXGw #Xo!E]x H4B;F08Kz7IJyeAMlGF盗Xt ْF8Y"T_ _v#9Q<@2!0r r~demCir@%ʫxs] |_=^dDQzڂo@2bf@Q=_12136w#&(/oVoE۝"P+AmIjUk{Y"Zߨz+/·x&|[А1DK]+,J!SǦnP=DR gM#{e[ d(Ӟi,Ayx{DfQ=9ʾ څ|'POf OOÞeՖNM@X,rd4%bB^:,lP4c+nX>}nP45ʺxrTܬ?U競(-ɫ{ӟ)e(MU)g⛽DB '{e6va@MT'GgDUHL[`Fl,pvhՆ}x$e8N5WhnCc7XngtN=3ޅRyyҵq+&.zoJXw͖z3/JD(bck: L|Y_o1#[s_5p:oF!4GFRčt^ioiJrWLXE=Ġ#eRh|';yn?7 &eL#+SpJxY"D7x:h;9O'?ĉԈ}͔aS@} d(Smu:E*qPd&s.6xg8(&P$oQ83Wh_=-̼(&a)T-dC~S b֜g qZeIx8S yO{,eSpz{b(X5C=֓-q@8xZ^߮Gp7]i4m3pWixY"(q K!+ӻvmB geH\^ą(}`DWZgc}s ! X〨,2qhUe1@GVbj8xyVtqDtiOg^q[Iz|e;obsUlS:qB*q\s5*A@- H_o 2Ҁ2\S"R^i1w8G`"y,yM_ C{wS;+Qmʽ߄" d(H8аACsi kǤϚm 8u-PH`Kn'XLANPr0Ē[|l"򲄺rRv O&9yQ"TPOzF@Y"H9.[ؘ=V?]=liPۺ)iTSӱ >>5ԕ=@ O"Y|aV?s]ؽkUYiҶ6f떆Z쎁2N-=-\֧ż/1Ii ٨,"D$벶욮{=j]x5j_0k~U}zo$bߖL"FG3 cf_~uRu=Wv+eK9+ }xߔ#DۙyVv-^<_~F*JJ1/KDyg: Y!i\`d M]bBf e(F-_'] ڽyφll 4l~C 9ϘŎHxJܒi|w`un \BnR3-|(o`ux,eSYPĵ _QvN"n E2j'@Mes9Z {W.SِXuЄs_ZVǵ_zW>NSq)7c[7(7h fz޿qn<@,FOhP+BkdF,e5׳sۏh KD+(Tc~)G d u)Ԥ$4npc&n_ gn+5Qv*8t[' j6i5+hCY`wD"ETL4qB)h܇(M>@2J  h:} Bk[E֐Ù%JzÝB+S.iӚ{6@EzXfܣyU"6 .n>0pD?kFvG?/4]Ӛ:5rF`G,S@J@䇣5`7R"@3X|-[nC@'=8M4$a TQW<[O H#WA{./,e:jy@Mbww2r 0!frSbWWb(͖8~.  thL:ifcױ%<&@~$9jAq@M|_r!pG ɌRj?"UQH^[R:g KDFx}Bj蹙/g)J@ u"@2)*;+.E?('FG4U!V\(*q%=$3[AE$S+#l3(2:"빈Gےy4!!s:^˧J0$h KDD:^xNr=+k4R1>+1o[3*3XS!Suw{zjC dLVHbsmi46f}J18gLy >PzקĕF[߶pݪխ3/bUo[G2SPCO(_X{^ӟlG 1֥ Ϸ'hwuu #~j?<,|{zWgioᶔ(Ԝoרqաx_EƼj_S2u{6?`뵅)ı̄n-uGv\\D ݁s_p|a0Tf[Qi3bfX_ĢSqd!̋8Px6Dr-CV'[<,{;U*"hĉ4k:kz׺[9a2d8F*M ##Bh0#)قLf^2VO1&P[o@ lU5enl~G1W0<Ȓ5Y=%2GZ!V=eh dYHǁ {YB]!?u)z9"Tg KDW3Or`.N1Q3foh10)&{'@-}^̒E=%w$Z:N)fº[OVG*LZh%rW>_4qzR:k+Tex쑿9nO5aTZeLm˞E)aޘUJO\C*,{Zrdž?*Ҿ_SKg (.rU"7 dESq.e*ں=<e(X+S# 1/b)oKͷ6rֱ M>%ӳgxՐ&^ 2k1sʤ,!´D!ktaVTҵw̏.D zjn9Y>%1AĠ20Ú󲄺eu.Yu4wƙ4p@V)ʩԽ|e|@2~@Ey 򷽠jrRUُ{#$6@vh:s@,eSI&hd"D""S62Wszq>')p셯8rЕԄ׭Aivijv;ۺȮt\~@ d4ϢƉxH^rbcؘvyZx4Zx/L-E0|CgI~-rghQv88pzWIΜNqYヘ(t%tV P{2hLo"&̠3}!Foᵽ|rX DiOFPq gȖR}}0 d(XB_ j> %G~]m.t/qDt],!UaJש௭h KD6[v=Lϊl34%b՜/'h=`^g5~ dhҜLAmw)ݥ˒tUG;֐߻8v*QA䉅dRct$I~B\=2Yp"M9Տdvz/qzDLISDThmƌ v!˜8DTE@ߎ Di6ӕقIL9+z8vΗ('\@h)'|('f`m03DiOa,{FPF4pܺ*_w+<%"Ԉ`?۳WQk^Pe7}SB)gvKqoqDtiOaERD8D" d(VGeD|>īq̼(& "r6$ cUeXk<+){ЧJU*~n7lǏaooU"2UH{ª)"A Nݳ "@V2Om.<;' 9qv.@NĩsbǶ.b#Ď߾3Cj koJ¶pu SzhIfZK|9e(k]zs ƞSY翺M}=Cp۸@6/~biy9s1*SC>El0 Q&}|^M-I] "@VJqrV5*# `mγݵ0fQTP?% t8AJڒ\̅JRZBrJ)<ݞ=+h +D+tl:E%J/OӺni(:u gf5MEY!F\L^/ KdlؒL7EUQ|)N ѥ OU W\-<Π1<#@V2rz-mPsgZYm-yp O$+sl5M:7jrslD|ˈ3%PmVJ_tNtjHe[LAB%x痽N?ݜ?@?@{o@˹gU&8Cp/#ĞjWg?i49 OӬom? nR ScaݔfiT˵=ji`E5̦4 %MID\ OXgqBtiB˰jz;^E{Feg1FXʤiЀƹ#[@Y!ʴ_)FPؕ<]sޝPK8GvjDbɣ? gbGhy$ _@Ԏ/q#ĮjWؓ5 d(;}e 6cs,WV[Oƪr=2#նV4LdvΈ3t|oԺ秓 D^ QrӼ8Y>ݮig +K^e+8:k1Np:ԱMe"_nla.M;1o~u|:*DU7h? pc{(thz#ɏnH<6BN0YAUҏrtZWEzuBR4+z?jɺ< ԞZt 4֫ފ\{\S_bSh)q5=pq&_[ŠWγC׉rի@~Trl&v^3 =+;Qb@F̀Dȳ1-B{.?J ox0Û2QV25l fgpUaxs9L1׮S~HKˇqp,ܕiz *qF3QtfQm9]F)|-< L4sX#94Z?DO`d0J4QL"Bt)D#_&o( d(cO봥(ˀ6Gygh4L3H'u~N~!J|a! 9,mxfl)O'].L.h^uneIi^4y2LQikQVPIHS{ԍ4'Hei|p/ՠ"@V2Wnc#|WWBqy{X8éI./68#Nz WWWqh +D+tAPPDucy^)[ 1/ d(xn>nJYog +DWd _SK 3C8c(QS?TP3ר 0] 1b'⍬{. EeJ.`ȹؘ:H>uOy!FeZ.ur#@V2g帚;{9euI?Tb2Q> QҒv)^Td%EQ!atr%"Ѣ< ni=qa$K\(Y>Fq Q }hm\$Cnt'Lome(Uڃ>k>)kgu_@=t&v'fHq<7G=fZ/soxDsx6M`V]dG1g GY!NH)OݽGڠvv_p = : d(~g66zőmӫNE<@yD|8$<+ЖvԲ}Qnk{ Llxe 5M5|E?p2jYk9w{y~15^ Q ->4zżfO c*_H3g1 gZ?I(тe7L1mT6ؘ8:NfC; rҢUї͘QuU2pԄ YVqn#y;j@h@JWٽ Jf8eM)Nt^8MjM7/SBBSX~_8iYQVsjOtWMu!kO.t#@Vp}o,mP[%jy^Ӳ 0B4_Z܎TY*8Qs6xezgLq="^moyƨLdYg !qZcp&(;yH {_3ԥdT~B١T>;55rl žDNLB J\Уd΢U9q(*t|-p Wpuk@FeگR^11qLTqoF iL(+DUum0x(yܺ, j8cS:0L6zw)bkQ d(Sc[hb{x{;($sh OD+]9i=NqϤ}v2>(&]`cF>:~!PA~ln5EiCsvҧ]Ǐ2n2}\F/7#EF#2FdYH(Շ>9;rBiTvl^˭FDq45v^eeu.8VZ] Z:*igD+En檨[3 d(;5FJdCNI[O.x{ k dG:6v&<=4[J>8Y!=RB>5(+DYNmüFэ@Y!-ab07%ysqbCpav!<:`5 dg\ ҎupęQwuD|BioP{;vɳjNWjiy*l4njO}2kú.xr"5, Q%<=3WXƭMl )Qv ](+DvmXC5, j:ye m4՘dOkc^/&^#@V2Wxl#W lY\3K^Ĵhy^ aԌ Q8;:\h!I_J$j-C@q dBw}֌3ڶ>fTwe&@}6KۻK@;sІc4i3Y{?H6 FLUYD`)d鱱 d4~둕PYw~- dgjԅOb''f:fǹ~y"@٩M1Ej)j4Qp7>mc<}O܏f~?=~?p2jΞDwg7QX|W [1 hrW%~/n#\- , jR~]SՂH[ZGsEHvޝS%.#Ğ+,h~%HfQT&nxu׻Ηg_]u-E.N ^n_S5fdbJ<3,g9r:ILr@>BmXΆdh9΢yؒtq~͆tl`AJpZ3*&NYsdhFzMiO옻UsL-6"S%Ј3@,I>˫ ,;a9 D+U0w!A"M}lGwMLo@[@sظ%_`EX7X+x#3VTmP%08~ d|;il o>.qBti ^M沛nqxp&ʅUK?aIh +D9*lm RP_c]%?B2k+AUN@;!r{ɈBy:5@u2@j( Q.#γn~-W I !6\}O&od/F*ou2V2mWI2/nUP&yyIQVJqԖ6\ϣF2̽廬Q ^K%I ;\揻B_<[*7>6Oz=Wy(;Cȶy/j{/o9֭h +D6Cs}\x\ [AW֥9YyU>%߃[ssqRg +XAQ!jO?}T;o!_zgv^.h# duoKY?Vgƙ{Ǭwp2zIq:$cHEh+PF?ucGƠ3@2!xQzR?}~8dӯ*R۾};<®gx G7PVnFWi|m 5+40i`P5!?i(:9DR9$9%҇S};ee,N삘]0wV{}/pElS{~C=kYS9,w/֭˅"Y1)P 4Lۻ&wVسz<qBtip\=z%G"q^׽fNOEQ!¡)=0L4+|z khOOHBTQ4YWj式(*I$=o HJ#P6 Qs#$ ̀4L]G}uֶ5Kxa3eI#lN'G])PWM>Ɲ@Y!zCL*WyQV֥qyJ1|=EY!N sxC9,ycOS @V&?vT&vzt2Pihe~/SY}C{~$G:?s8zH}`{g[%o; 7Kʂ 냕5c{R"mf!~sT'YI`ٯOzd)>, Qs?Sd}2eiƴIdc ~W/+LUS~Ɯhk.$@-I 7`/p#P{Ff\㬮 3YM{mrh +DYʰP۞֣1h 'Ôao2O/graB0LN[L @4F&0jĞVrur[eH'T_(SzpKޝR}DJ$&r.r%FoO_1=;}<e*~l>M ӹL;qw$8c{8hbDD~#h"1i̱6L)wp't!||ۺ*iG)@VP@FMdoXk&e < d(~r!d<^,7}x.5'/a- Qz0xicڹ($r6H|cRlKOWQV2!5Fr<W㇄cÉ\-Q Ak-&_ <|(lZYӊ)֘=q0%(E1A{nvrw,P90Ye +QHx HpAG?kD Q *~%Oa~y=Zk' dg9D+Am1'c=\HSVZ9w"|jpz;IouJ<}f).k&@uzmmmH&niu ІF(kHpi5 BTq*iq*愠BhO*WyЁ?ԡ1ȹ#uxo?3X־sVG L_#Ğpb֫& 6exHϨߤӳhbXf_CM$-ͽSM ĺWWo3j@V.jͪNh +DRj#% /o0ya2%(Hs}K&}No~A3MWIB{ŦhkݾoY}^** y Q 45u{X }`~LB`v٨\Ϟ8NϚaY;&C*QA@Ն[Zɖ]u56]wuC>S"4egonȝ*Jb'H vd}¥~^;e)vh v }cjS]g!mR tARJRbpֻVxbʴ_ . zq{=mY2z @ngEe'{JymH{(MSggt`gga⺣ero^>Vc0vubIxwM=ݙf#ݛ^5" Qv,&#T5_m=:?*`XM@OɝG^=#@ƛߋʹMpРQ#Й'0'7֫tc=(i1MV~Jc 7+,s4Gի@m5%n~w8BT!CKRgje $9hu̝zclfD"y|\#GY!NإP![GeZ%М\p&v]brb;ɩ#TKLM/qq/[*٫h^h +DT[Tm*4(9QQhDW):[ʨR.ޱ7EfΪ@V2WkWB RIt?HqE:Y3Κ iSت8tM Qk G;K0mK3nٛ[ľͷ=+t>\4LO]Y_Z5] ʄTVLb*+i, Q&.0=El(TھRQ(*ɇhסsڨeWC{¦}u;_@܎q ;AX9P&v\Բ؀}L%V 2>4tk Z4ݵM\KЮ]=~`uM d(Z4+l$Ѧ[EY!~zGX..r3m , "Nzԓgٽ~C4XZwDX7T**!v/ӔU5FY!ʴ_J-rҶ@goq[oycsz|ęJLwsxᷔU yԛ\r 9@Y!ʶ[˵_-O3Rnp^5~| )y,5*~%2eRZ}tW-/0 dR(T h +Da0uJ-%5Ϣ|+m5mIfQTPS\[9o5cFٓ M>}Ȯ6p> gLQKq3pfoem @`i[㤸Pr\3[ Ps\NNU@,F4]GKX.M΢U -*y]楛gPB4$B7_I:'ǰ(&$B Qv2N).p:&C;v| BIۓ>1{hmc i#׺Nsj|=ݬ ` AFUd3ZUeI$/ ѥ MH"Wƌro}-es8Y!Nlw}jR$]d H~Ɩ."nG'b"ҍ[Ǒz]gE3$0i BѱaH |*I SbW%Ҷ5 E@Y!99iHE4pNL h9i?<Mv#Me4qIvѶ9AmI ..RJUZcOd_yd樌GHhbW3\Lcϫ׎>ݗDH ?1&516DZ4Ќi=>)]1N>fx`] _@Je} E*L$Rom:w:R.1R[hN&ĮrѫYNm7Gfm}~}EWjGe'G췊|^CQI}~.W0*N9(rQȌ:2q:2p=W֜4W4󶓴cep`I@Y!҅|m-1V[AGS*9 c 3y<~S;LG`sm4w|GFvλ1׃nCvY %y;0UIeJcgi| @8g(Q#cKj$0L3~oNhK5/jY]ح"ο.f3:G#j9jR@y,Myb$;y?0!s 72nϏ/Y"ĮRNk FӦM^QQ 4lSJ߫|abmG,Uh^q6 FY! "?4ĵu"S.ڹ/N7yZzAjRdρ՗IUiotwr0~nñUqCr@NKQkW8Mԅ^kfsMAR=7fvyƍc^ӅIpxͨBrW4 NI ye(z+=b0i ۰@4nVlznxIh Q7irD7tڭh +D9v!3M:{햜z۶ak|7[9 -j/u" ddao^mQSks hGY!ʴQv/vBp;@>+wt#ipgp\4LFYF(+D;^`#]hBj=[ĐeR\(YJ ǖt0L5?{'11tNDIUh}B&z d(YMz8[nzU׭ǫOOבH=6w!:M̏)eF"&O;Rb"P;r 9Ú3F&NWfh.Dgd[6Ǵ-y=y@Y!Njk2O5{Q-I% d(6XB{ZhSK^~,-vf?#@V2v~;Ko89xLB)Yc[jpDk-欰0}]I2 0=L^ATwGlnm?&YCL3s˵m~0enXah7ڋ2nJoޠv['{0T9LV{nWҮe+^W57|Q]QAS?(!jmkm# d(K EYA]ҏpqQKs=sU-!E2YL<>31N+<>*.gvu4q*ҮYxomaٕclk'8Wl];l9Lon-~>u8L]Uw^v Sk]=ֺQsF͓oaZ#X}'<珁;B=knzӕa9.,)̡q5 TE>.=B1E2ޟ<;e[|h ;{qQh.4ٹڼ*}R*.̫4+e[}V?Cݲu-l^k1-Ύ6BQ/gy|Q=ʯ0PFERDvSOj9z4A.%\\d.{QV2μ^7ENSgĉ(*Djx35EQ`ע>/ޑW87Rcshb5Jwcҍ/' QfqZHbj*yJ(8uIoU&lɎP]5 a9hʴѓذBiku*W\NNbңN PKM^|޿g_GF )4 %;w_J28?=1=-Egyɪ ȃk p`iiu~$Q Qs (lL{nr[gp?%@McsľStAlX *~I~"0| g ;slgWAPG;4.HT =n[PdI|zծOhҙ&iM]H҈@-eCxމ2Yˆ@Y!ʴ_#zed+jϕ괯ȑjʭ9s2B_U2;^2}ėck @ʗet9YE'N@;p&q5qGkޟ%Vh'0Z2]`3~8HL H3S@8534|8P ;9wgbo+*e-R@l gd&2 sT"qs: a?6Rié;I~8Ye'Xx1hJ&(aJZwǪ9,wP\]Re6AD{F)Į*{jAV->3)X X g&yZ 8|c+gFV!'@Y!ʸVL}_·wZBfwTn{XE-ΗS#ҥaH7Z*sЩǙA _ 3F:cK#,53gD C,Q!N 5HbQ+.re[M{|+v?G}HZoJB))L-V`]{nFvB8ccХJ=wS¹U 󛹖3sp-}7jP8zNc8X6N)δ+/3w'%7) XGja각Ei]T r܆ d9vk\ӽ/?[?aչe=}8%H-!5knt?DQ%EeIbDY!rq^\--g:s7˶ >9FTV1`4(jWꤚn{9?RrB{,)*~%'81eگ O ]95BQ2Cx}RL Re<gB:ZL QvR~3>S'39#i!YlS) Q6G󟃵ҽi3 Q(}!WlBie4# Bsx2$s]-P2~}3mВ䃈3{/K-I .1U3ݼ"@V6J5<``omi9E?:U-TD2]fim&i)Rsnƃ} Ȁ(*Dw&v7G gMwwUl/1ɯw7΢U$5Ɩ3da-?_Hi[XRq }L9 yx=U˺mYb8 d(w |C9<, |HL@`ht AMұDg!Y1} =i\y}jSʾ@ٙ;+[I(4LdÍD q1ɖ" 11*#ʆzn@1+/򃦍m9~R#8h&}2)Pj*#i. QF|6de W }{uy{'R }eX˴AiOHL6eR=\WJ+達V oTL+e3A mYzs/hm+r?,w3w9 i$@_q>-f 4{#IR߾i 4fF_q$z~zi ľl&!ͬH&I~T^Zniy+W3h +D'kS:qӉ4 կc3`@Y!N c{jAvγcHz6fIQJDYA]ҏj풨6=\8r4W!&ֲC`U&]گjf7>QJcnHKt{I_.YA,=\H/UL/6TJbBe`=?b@Q!kI؉H}|'\>F Geyjg ה됱?!@Y!ZnVh[uTPcۨLaFƢek{9צ_O..ooѺoܩ"l鶹⤰Z"wl4^ 4yHڿ@Y!x=cu{?[SEQ!xfب[ 8IMԡ&m\R~[k3HyJ#!twI:[T׷v<< ѕ; fZYrVD{C=p\ duIckzAę:$+fƸɘjDķ}W?~yj9~l>M8R R_XԾ6g81D"@vo*E-9ZlYkUluz?ެvsikD_|H+_9gHhѷ6N/:?znLŽ\Nqxafۧs_Y0k62ZR Oe''_Ȣ@:DO:{kZ8ʷRI25u%l0 QP6$hȢhO@H<wcZ4}nntT)!f=&LO!v#CoMKMoݥ~knn7\; d(1!pSqWh ^ Z=U[;߿EA6DoR$l/ʸ#CRg5n?ϗf 5<'Q+٥ԏ2٥G*k!NRoLPžэsY;ưz2F]-bdW6RW:3h+"@]m0F)G?٦ixA(vM끫Ԓ#@V2WmA<ف}}i()@V($|ͫQp[)!TkP&T#}/V8Y!4f}\"3B,&AK*=)c U2WP8: 0KJyMKyK,.Jabq&Jnh +DBiݪo]De QV$h +DƇ:TƗ>uGDq;N >a#G_E7DUAG ~AQ-Qjڎs//sFYY^GQZ{׏A~<UԅaZp;!A46;ڤ08z-7yIC5tlӽZ4LzyAr0N63ނ{75c`t3'Y*LiH̤B r[&,Jh +DY /Crδ{8eϹK[ JNw0粛R|3, QE`cq6= cfgAX5#Z 6, Q:PM] uFep1hwiF6-_Gw3!̲o09΢'Q//{s3;*E]گЦ(z@aEQ>ֽ}1W^ QC >:4Gp G] *vA+vOzu|ؠ6h;4?- ?@Nu]\]\DσSCBl*, QlϏW_;%D.G!@k\[6Nc~ҵE^!-Bb. d(3VءTFY@V% ?㔻=駰~ (*D'=ev<ʡ<G!{0E_ZReZQ;IAZ\vΨ[_-&έC)$Hta$TO%=@(q_j޼[gFΓN<;yflB&M8;/ϖMsǺ&LtNg +`1,\/@S{:kjn71 d .l~Rl1Ou R{T>˘q*g"(Gq]BA~MIM٣hÍ?iyaC46mcV Deگa Ab3RNuR_Z-\.n|'WV 4L-;Gk hbh$.,ں%GKL#BA{jw#ݪ7@V>큵2)(ЪWk٪PƏx)1h +DNH@ 8mSziOxk'o4W [PJ;Y7Ӷ" S~Hkx>")@V2*1|kjUb*fO,N,+:UW4q񌋼8̿tqn' N;GȤrnr Bm]'t˼Y5 e8J6" 9kh+LZEJQ(Vh +DZqQa{ڐZ]ߍ4$m1R{iCQY6vq&gS켜ĄOe(S{5w u*ه8giNXj ޟYeklL >6H)@F{k_ 4G!hbov=c\C& L%(߫Ty-Dr=K&xs9$z QF+?9m:}d̻3/+gQT*yGJ<׌.d a@Lj# q؜ۋ8~8=ۧ{hndXQFF(s2uTNOR'x2?83uC~QsMM[5 @٩ȥV _a $*toej@Yw!k `h&(]#uVn4+kV%;r@T^WBSNQItA!"R!"҉?Q1nxz:1/25)Qj0r>sА0_՜zޯei4UAy{aBc>u/Q'e_+} ݓB^{R C^N(,(cm5ô֎{bF Q2 kBcՄcCc@:4%eb0#v0+8'w"X]9sJotUjKa!O~|_oC8@?`A6w -qmqdXύt yDlkÍuGDu5BCR^"#qAY˱12B,) u}R2~DH2t1(HЮ~hbW܁Io3FSfClXDMτHLCZhb`dDHbAiȜc)gD{C!@Y!X\smdt>Uz](:gs2?><X87:*=hLi^9L];]@ DI( BiN75ȽnʽR|1]Qˆ~==w#R= $В{g]n] P[嶽WbPGw/o5gꗺ <|i,R$Nhr9XAYQA/̭G?onk(`.=pN4&_]M#w#r$t߿ Jȳԣ2^ `Oiޢ÷U@vdHQg0/6"ĮJj?}AVP#m\ZQ_A^|䤴d8A\*H=ɦyY5"& d(Sj텚;h NAbSJҔF:r䒷@:@Y!ʨYTsřҾȉG8`OUCUٷ/eA$*C<5.7'ZȈʁ)1Qc&V%L{mv3*;RB *Hqwl~g'p@?@c& FE2GSt;]q", jgONy(wz~M8~mGm`]TL':zѦI4~]g/]1Jy?(+D&?m/w? ^Q dKJ3/ᵳ@r=L<?A9ЎnL Gkh~@{ QfNdjIҘt^tϜK@Y!x6y~Ic_ Fej\926e(SYnayekR`g@V&QHaڜ=V[!ePB)Lm`iTܢR:FkELÜ@k]+>oc rK,*C26eoQ?^ީ%ׄ_viZP(QP3ɴRcK?Lt;Ϳ~>5?4_679ۢ, Q%Hvr@;D'%ɃkWR{Ny qEh,@# o'/^k *E ,甎/f#~=9p>!eJlmBo6M*%+I{ n`L޿qExFQ𲭱?lgZqU\-B֕wكՆ)jG=JLj3'w?}ɂ8Kr~&v5crln?9~ӫ>9AB՞qjЎ<ں0 d'n%pW]#+46B?A ŷcyI̧*cOČ:ŠW?D+䣀(*DFٖj/Pj"@VIv\6(S̆{nGlncs%|& QF>2isoDF;c$Q vs]61$IrȺza@Y!"q4G iДv@'F#yDb:\~j6Hw =Y\^ YSvTy#c{x#=A x]s<^u(YMah&pGC# duI?U/+NjGUwzK7HD tr(Lqx|Aƪ)]u/{uIrE.q2-BLxN>R.h +D%e(gs1NG۵L?JOI/ygE#7M;YX5]o{B@Y!ʴ_ٽz^Zp0_Ht+ ]`i}N 3>yAo6D? dQ>ύ;.#ʂ?94xC.H~Կ/ab0qT#FUccZOU3Hx#ڴg;}2]'F&NԴ#aRP=_nw;^E2 gɍZۻs@!ѫ}]-{guT6CKRIgI-]Ȓ@ B~B<@q<=2( 8I1<PܣF%r;1j@@J?պv1rܣc< sܙQbG4Rp4e1RBic&x*0Y!:|;џ֓v$c|ŜR O`YP/)o󹮮&<y&@0 A|Uex~lnF3 7MQMռ,B%#A `4gmߝn΢Uҏд;r劙nY׈{6CֽW 3#1E.D#K-Nw!pEB >`RMiyOiXd=oeŰv Qy;s+Rj+언ՄۜEfh;9u)vǓ9pO4x8JF8uhbW5:ۺf"@V2WpH Ap57{(D@7‾߾w(+ c9󾷧|y֧/`Ӭ3G‰8YA]ҏ>+L0@Y!`Y_0)Rq Lzxe iVU2mT3pE$mrnUP'9΢Uj~lMGi=Wux^Hw@vr_y1wx.q4U|S\ ރ-Y=JHϞIpǕio/oN"xtda$LDL'Ԙ]yB25$P Z8Zm3Dh +9$HkӋkۺi͵]]M31\O?5 @Yᙘlj1? 0FY(UWG[or>6;F]'GG{̷ fEq[S gSr o@2)o20q= àd!4M| n5<7oKVBR\i(m0 QƋ鎙Uk:DzDM[Bd G/Ҽ$Qw=>P8$EoT~̋ ,QΒ8;JWO~6k]=@y!C"p~&v5g$ޖ@H0Y!qj#Ԁxw}|q\y1r1?Yc3Xhbľ[]=#@VP#\TkWvF(*Dq*Cz+*Lλ3ǏU %2L8$aq2i0 QFt|ΏJyO\=ϼ9sx>=22) Q ?6Dsk#!Ʈ,L؃o}tFY!DV&p8+4iJQ&~t/לz,{1%Z _63"δZv烈Le'٤{Ϫh|leJ uMj mMP(p|g ++t.M1 9b 8Yz=ӺVpª}<B:P&Fekgr!H) mPfi7ilڻ^#dAX?=3R3U>e3}Nw*&@Jctv@SX?FcMf]ӞD3^ADI)+lk9a "e6Y_s/9|N)@v]껁@UѴgmpm=@@xc(#[d}A? Q3Yx1Rq@ Eέzje$G#/ r [%~RVGdgSl;D eگІx^2V`- Q.Fڳ'L *26^"δ~G_Ak'P E/45yg]J: Nb@V2lҵ<=8|l8YA]yN$ɔ$@U)H纠=?ݔ~A58e/ʡ\6@,j#}|Qv#'T/^vG&ؤ@Ȍdi'K tiv+vtDke'Vp ?q̋mRM/DJМ}G[MztGx7QV2>M#޼^FmR (;S"L" Cl9 :+m. Q,DL|õuU툱-p'IB5֞s+$v2މ@!TiDhKA#< u 6TK>['v?ʜ(j#43;hbY +1V6^{>:eFu2Fr'Ntz-|n$YH:ɇԓ ZO?g|VF{GFiGrqRw qww`ߑ<2X'Q),E,]ĮPZjs:&1/>5tR [P@Y!Լ@-o$ d(o5p_G*џPC+δז+8mDY!ʄtM4?(+D Bl :2ƾR57)atf#k5?;ovL\[o3lNs5~Ud_YR;LF6~GRRGϷ}^)] }lRh>mB+ǡkAOA?랸휐[OAW)N:QcPs9hbO܉s'h +DJRy$e(OgsT4,1YVǬxW&e.eδ_;YW'#RF*U،Ill4,eq ՂB0bi?`'Hf.=Eu;Q$ d(~fE ,G{iT3]P.sgbG ޸\E }+BA=#i)aFwT!T wiXp4L,=6%hkjȧv\lNS^v};IaEMlmEY QvLqFIh-JDG)˴5$r\dÚ*2wMLCFV@V@.=Wsj3~@oJqx>¨o>M)v|^ x͍1e@#<EQAMo%U-8K1gK ':"[nˌ4zzJe:hR_FcgXzS g4c-t3d>-0ދ+47/IG|Lj3l~6{n`E42 %vlNj#ĮUӣ ZB"bRk T3,sBiB[/AbX2nR[KJp<L_^F=Ϛs.Kgʊd4,g>ce1 d(3M[,7ob$[ǽ( !squZWe5£q#@V2W,WHӿkq!yd;ϹDP֨\]EeV+eDDo߀V}={L4.Xhb`[5G_0z^-=}@=ʴ_ɱr~L >>-8)H Fet"0|mz i-N? 9NSBXuQӽuޟ[A޺ d0Ws$=xUMh 㧹pM+1m 4@iA6Px _{A0_1*~%ze/B 9Myv}j+fv_ڥۑ98[ 7w2F3ԥ2{.0{#ľK\M_f:*D2j$@Y!Tjyv(H KȈNU6xTxݪ7<Ƣic-75LJU@1=(*gv63.}qJۣm,J&v\GQ68ffi܅ |4cj78Ma X]97o] SchQ#LF}pok43%4=rf#xJB.{$G) dgGWoޕY<_S^TV;n[Tr2,ū5dAvf}R9_ V F:4ql&v G88 \=~Vh +Dv[p@ۼYѓn'lv篋;mg訉ۯ㯪nYO)P2ja5!d/;-$GK9)@ƽ8 sl 3>#U̻_AF]ԕD*t)bW{?aEhRCc:/3L6{ޏgw|_Gӽ_Nd}SG) QsOaoIwgl[^}o)-.GҀg1Y fa[-R=+QD/ۉ2}(teGӬ <%ZI/be0\pIt}&V^`q`6,LXfl`!,5<Ԏcw]/v1Km*@m̞*fҟ}g^UcNy_Ty3aZZL2Z%"s?'b 4DEQ+e֖ d24ɧ@/ۉ2XrvrPxOBi'l'C}y7z'<x (΅!. Әur.G݄+qD w?S_4DYbx uef爤4Rq-0/`h<@e!SZchcE$*aw!0ה0P]E}/>&֚L:2e;upX7gd=S1UqCEt3 ־\ u(2nT+O ƒ_|w2 xc6ie4D+!+)3u%7%jv?kqnMj>LsMJx~㰊jx1 -?ZBL@Np<:,O\4ďGM|_W) {l'ʴ$Ȟ)W*Y%فv^ex߻X wR}lє>ͺf];(v" 8lQɫh ۉ8=|z/dKۑ0[DkJHwJ,9RL΢H‚Cӫfƫ h ۉ22S焢Rfİ:Fxl'ԘU)abh ۉ73 pO4m d;QFnD=Pj3Z+|Iå߅;n_^eL]í5VXq8"cյ6})ivr;ᄺgoFMky,Yﰋ~]V*sY%+!e!eܴK!( Ҝ]V'%pE;QE}ppG\wxGf1 Fji6n#h ۉ21RȰk_TzlUZl4,JĶF/J71wy!rAD/HzUXKmo{;ȝvBmjƁPL&tP@Ni}yviP[șL|M?fJ4̋v-AQq`xc0xh ۉ2W8N*W62BjSUi2+SBB,P#:8y#[2/Tkmg^Yې@ 43Ҭl_AZAB~4C^J kÙ]jJK,/mޓ[ dC!kI~KLLL4i=L6i&ixrץ%tq8sj{/i{+ d{Tޣr9^ . qj5)vk.>mg01j@СN @ӫ,j,N&7,]@P-]+aJ$F%~N\c;V1%{.LRV-fyWپ^ nMj&ve;:3|cym5FHMy%63'"DNrcN,)Y/hb3**ʲbj L᠅r, {l'i[4.6;&y&SC4]PN7 ԒyX%ȤAƲIHO-!V|!*3xl'ʴ_aٚE.%_x&DaYT4v5(~^M_-ܥxFf t2 d;돀^Pvct n~/q;4|8\v [*r$zƊ+\Y9G ` y [T\4h3=Sm'aH,ַ}kȮ,nBc)ҌҚRΕhrdЅ$o U(XamE,/sFVЪ~ZՏSQ -@јhCiQCi,/ۉ2%jy:^[f5@NA 쐶i~\7ի!UCY/RS#5lY<|,j6Iήy )u (Sx4)2meW<lˬҔIJ`rV!h )Gqi[guL ~f,ˮFsGhz,?>j<@vGs2Ô /*Ą^DڥQl[$4D}*?./B9r;.󨕐=1OzJcŞbwJ#:9Eϣ#E8󢝨"`d>i0qJ: _+%j[*UBpX@N%bCs+!w-z ?6h ۉ2m}rCr4E V4C:kJhq|.PB6=7Ƣ%"U% SYZl'Jl mg,|& bLUͫJړcuY(lwґ+R 6fyBdy1ܴ q|"-u) TkZ^G{v}2Mt8 ZX=G'ۉ2V'V8נUKXcl'j jm*oըo(F#9F4Mtˀ+2%_:L"&NK@%ͥ2;& 6C슖B]VBJ l%؈dKclb#J ֢G\#ȎRWBtY ]n2Gv1[H~aBi mt) 6![C;NgCULgWRpPQڠOGAMHo)ta\%}g ۉ.#R۱ JyK;OS (.`Nǻ{Y[n 3/QDc9%Vj"[y R鲕$e{|Dw!ye]BtZ1m_K2Yl'CP;CP4om)^eѺon@;]K)}m\)!d f{|R5mclh ۉ\' @"K}kx;|dU3/ډ*~׭8鍀L(8{Z@~4s{o p5YpԦ(Ħnɦ%{l'衖Caq|rSV8 d;b)yoӽSvv_lʰ@m}'瓍)4扔U@Nip ꥡ&J~Y=zNԨyYΈT=@e17ss.iJe+(gr~h85?+B.K`z͵6/q|j,8D f!k^MA`V(ZJo)/FқXss9LNUj#%[q8!X&iSm4-sVZhf9^sH+8m1D998w5 QfrAqE< "yQQYVjĂDv@&1 mNQiyMةL,W._CiXUn٪,O;| d+ =z`S䣲e`[OZ"A?|q̋vϧKɽl'޺fr=V ӄɜ3bc (2v$*M>]'>ebwj^T =@\jb+°$_`j;+[5sDazsΘ-E5̋h^2>y @!hpuc&֔$w fMK:B39D@oWhXHzJ ^a .wZJvZp a&VS|Fh p6j!,N T{>/$2ѓmZ*S!cOؕZ@~?OTiM9j0z$pWJ>(>Y&;3ǃjzB%a#=U?ʹ?,``i=HZSE2!z $\Qrhp&V[V ΩDk<< dWL<= nrXjTҜ2)$Yt(Zi)ojMvY=;s2@{e"a2yg]t+xNH~a~[ʐ4\鱍Ϗ>"e59X!ھQ6PEYW$ueJ R7NuG@vEiR;ny0.C{}Ku=@Fy]R7aYvˁD@vIBʵ4`7̧ʖ;{kqyA^={igp T^11UBaܛr<370َ2Š_lJ /rIB7@Ni|-hr= 0C VHx:ZnQ,0ʔ/9|L,L36 L'6,|RNvE $E{cdu^4D嗱ni^r=9)j߅@٥l+ `u{/jإ`ٴ1J(yfě)W4e벖 B- dcpZ(L[5z3zeKT7=@M1 ׻Vaqy [N{mba8?)]i73ⴝ.ϥݲ\Thkw\P(~~_ ?Mzcv&ʥCmY4]32ԳwtE?O*@N!os9C˼ʦ$5#v%3j~\JTFnSz'NJi9=xqr Z`|T3Y ,Q?oDh⢠q2i̛%@e_BmC[PvmbϵR-2CPscqq.EPQXr m9#ȏ`[E)5A )b`[msD.j߈ xmVTyydm?!6>K^dhov\4l +/'౯e]|4b[K;Z ۳Ǒ y>Vh&F/K_=δzS2Yg6bf 9lg.qxV*4d뾍 v :iƁThiH>vGY1畩ԟe9jM?3qvcKKӌPB6 ĵR1 {͎ՆeZn{h ۉW֘b,+1;Ұkj:ǜ.ga44ِp7nFzi)D]c'ډ&GXPIQ$)~JT1%Wdn&RaQB/&V= " #D(N4Tr2}9ZI=@ƩdW.JոAwSyD& d*p6#,NH,r/ۣ"+:&Uټư8mAT訛 56Tp1D0]ԳyZ"5(~}q7H?4( ƍmJh? O@N|_9_PZ @~@ +CzOs넄x7>ܢ.sM~_+V;/™VoI=ƁMe;Q5^d+vVxp/i 4q2xӳu@Nut`r0qT)s^Y$ -W;J8n)jk2'_eWdL|h@ۏls4 d߬O xG``c$H $3N]xq?74]XoQ 9a&u&o^U>^{cq^v1TByZZb|uvo77X;sߠ=ĪJlU_d %6p2N?*829w[9yUm.[f_ d$x>luZc2 }^:8[tS P]@0rRl)"5+j*a'v} 7c~6[qbmw/4s>lG]Z~:Sa83-=/֙\ѳ?s !/g&!Ũyow-?-8>Vb<8NtQL4U9J $5(ir49)(Mݗg&OsJUrId-Jx$m%^J-B0(>X&֓g~.{@@vEuTs+Ǿ ]&g#N`J I2X6-5p W) d;Q,gBz7Jc6EUr:BDl,2lmJBȌyDwgͶUw>8xW8*.ŏpG4q)?<qH"3]E`Se=,OsP/U_[Vabf {|*q|Ql.lh ۉ2c\X(c! W J.2hH׶(Q*7GY/rpuq#)<9[3Z%3<_՛/Jdeބ唘زn1D\bnV!h@!zNIl䜁r )v!Ȯ(>Pc`#](KoȆR:GeL1yeil)[ylҗvc @\ǞSao"{C* ̵z0Jv-v [bUve%ї4<δZb1hKafFAhxf@&$6A~un楅9<@eܭHvxV X'sdm8N;]b@4>F37 MP{~.T) qv`ún}gZη<:c6hPǃ;j~W JL/SIx ˙qh ܹ Ic4]0=89mlh[5ηp=Cv+:1tr&c%.ͷǃhjlW ^L9[Ggnn =Ҟ<h_<̾GC3^Zzv;Ҿj8j.Q5l/ۉ.U⃀u҅@΂E)w#&֝Ό9b99ȖF[X?nAZ$+F$L9= Ua=-(T\=2Q3pH88ȰF$󁣞:F{슕W6~yƃ$Yo-g Ol-ϡQ2 n-h Z Tpթm%.aÍ60n]ųdx vϵ{V[٪qRX$?@|W_<Ċ*z\2q0m¼n`eh&9M>jOf _-;`V27"ږm1G;y<@.Nw pjB ` DGxJ O"O^FBzuK=U dKKPGdzWEFCT4qh).y_ VyBSaTZk*4h8EZ`̋vJz(^'ր>>M<&ZydL=L摱s)jK@5*/̱^vŌ+8uv^]2e6~]4P¸e4:&mo$v9(Ec)ͺmMexT%Iq7ë]۳x}q_ʓ@/lG{7aZ_%<]cRxϕhbIRlhB\VJ2PW5|K̋hreɝ%C^G|Zcerh ۉ2 *@*v1l6 m]~'-AmX Ze_`ֶ 2/jk j]R4Ug'ۉ20.D}-/RXmQ&Vp1Med{{L^%!?]Fqcd>ñ^o$A71[L~uPԘ;=~UIl /ۉ.))Bc~Hx@Gs@(#Sڶs#Sh ۉ2In bayǭ:xct.uX_bƠZXzMե'<9Å808=@N:c,ǚ9VqGpE<@LqiZHi%L3I3` BwuL-Pn41ꖓ-\+ o_{>!f)͂;!9jcE8Ϗ!%З<δzk!߼rˮb*(Y ӦH6cv@U"<^x9SHx$ Y.ÿ0xZC}!@etip//ܔ $ (~L]~@cqZXᢝjp ahp<8uuS~cp8IVðrP}ң•7QecA%\}kNRNߤD=vcȞhCȌ@S~v8Imǹ&2;R6J٘SNXoTd\Vp+^#,G6qk+2K %@4\i45՛Ӄï8;lU[Ԫ? ^ӯ6 [iZ+Ic=Pfqju: (]'m@TkfE 9:l=s"M@QJPyI/gHPq$Ӷl\#2^Y؎&۱BV8RuQRX)%ĵNP눋httm,>WɑHnh 9^FȭST2 ٵڇ!@Ʃ:]/p8fSQqj`yj@\q:Y@NGy,DrkMi؟ 銓)LXK%J&uh _eTi,vi:?.pȮ.E8"Λ]8ni}h:K4=N4@2h&>r<%)i]0 ?kAzUe;α 6l E6BO"DkPŏJ rd6W<@Q:;im ɑ8م+)s[˸0O&nZ ,'ukU q2҆9ݖ7U҈U&eWw/.\V]'s<v Sʸk{U\K_wٵdtk}X#9qh r2q-sgZSS;o4(|[J;cuݟ-eO;rf(EY3 'Rjq;ap8fMRMce;A4 dL!.ϥ<ΕO6bѮ <؊^~=ĪK8M4]0bs|tV╱K H1ҾHiuP@cd[˸르6ŶB/K&VT#{َӁ3=xg2Qk~tLy/'*mOr<@&;Q1 6Pwy=2Z0Z7R〸Kk.ԴV[miDA9yх0{=Ħd>4g?_2/-mk-l9yUTi*|u+ sZJ(OȍTJG(6'm\@Im*Т.I9赱B x< ^wWN|pzN`|F>rmerfY dW+{9 z82ey¼jW 94Sb=L9s g0ĭxZ }=斃|_PjB Kqu88\j[ 1lZPT:Uw̼1R̶Qn]xG4<@&mcy+Ҁv+e,hjuL(-϶ndG8 G[=X&™] *h@X ͷy9`42 dW4`+ԣYcx~@yjvO+/<<}3y